soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SToolTip.cpp
1#include "souistd.h"
2#include "helper/SToolTip.h"
3//增加对多显示器的支持
4#define COMPILE_MULTIMON_STUBS
5#include <multimon.h>
6
7SNSBEGIN
8
9#define TIMERID_DELAY 1
10#define TIMERID_SPAN 2
11
12#define MARGIN_TIP 5
13
15 : m_nDelay(500)
16 , m_nShowSpan(5000)
17 , m_font(0)
18 , m_tipAlign(TA_AUTO)
19 , m_nScale(100)
20{
21 m_id.dwHi = m_id.dwLow = 0;
22 m_id.bNcTip = FALSE;
23}
24
26{
27 if (m_font)
28 DeleteObject(m_font);
29}
30
32{
33 HWND hWnd = SNativeWnd::CreateNative(_T("soui tooltip"), WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOACTIVATE, 0, 0, 0, 0, NULL, 0, NULL);
34 if (!hWnd)
35 return FALSE;
36
37 LOGFONT lf;
38 GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
39 lf.lfHeight = -12;
40 _tcscpy(lf.lfFaceName, _T("宋体"));
41 m_font = CreateFontIndirect(&lf);
42
43 return TRUE;
44}
45
46void STipCtrl::RelayEvent(const MSG *pMsg)
47{
48 if (m_tipAlign != TA_AUTO)
49 return;
50 switch (pMsg->message)
51 {
52 case WM_LBUTTONDOWN:
53 case WM_LBUTTONUP:
54 case WM_RBUTTONDOWN:
55 case WM_RBUTTONUP:
56 case WM_MBUTTONUP:
57 case WM_MBUTTONDOWN:
58
59 case WM_NCLBUTTONDOWN:
60 case WM_NCLBUTTONUP:
61 case WM_NCRBUTTONDOWN:
62 case WM_NCRBUTTONUP:
63 case WM_NCMBUTTONUP:
64 case WM_NCMBUTTONDOWN:
65 OnTimer(TIMERID_SPAN); // hide tip
66 break;
67 case WM_MOUSEMOVE:
68 {
69 CPoint pt(GET_X_LPARAM(pMsg->lParam), GET_Y_LPARAM(pMsg->lParam));
70 if (m_id.bNcTip || !m_rcTarget.PtInRect(pt))
71 {
72 OnTimer(TIMERID_SPAN); // hide tip
73 }
74 else if (!IsWindowVisible() && !m_strTip.IsEmpty())
75 {
76 KillTimer(TIMERID_DELAY);
77 SetTimer(TIMERID_DELAY, m_nDelay);
78 ::ClientToScreen(pMsg->hwnd, &pt);
79 SetWindowPos(0, pt.x, pt.y + 24, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE);
80 }
81 }
82 break;
83 case WM_NCMOUSEMOVE:
84 {
85 CPoint pt(GET_X_LPARAM(pMsg->lParam), GET_Y_LPARAM(pMsg->lParam));
86 CRect rcWnd;
87 ::GetWindowRect(pMsg->hwnd, &rcWnd);
88 CPoint pt2(pt);
89 pt2 -= rcWnd.TopLeft();
90 if (!m_id.bNcTip || !m_rcTarget.PtInRect(pt2))
91 {
92 OnTimer(TIMERID_SPAN); // hide tip
93 }
94 else if (!IsWindowVisible() && !m_strTip.IsEmpty())
95 {
96 KillTimer(TIMERID_DELAY);
97 SetTimer(TIMERID_DELAY, m_nDelay);
98 SetWindowPos(0, pt.x, pt.y + 24, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE);
99 }
100 }
101 break;
102 break;
103 }
104}
105
106void STipCtrl::UpdateFont(int nScale)
107{
108 if (m_nScale != nScale)
109 {
110 if (m_font)
111 DeleteObject(m_font);
112 LOGFONT lf;
113 GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
114 lf.lfHeight = -12 * nScale / 100;
115 _tcscpy(lf.lfFaceName, _T("宋体"));
116 m_font = CreateFontIndirect(&lf);
117 m_nScale = nScale;
118 }
119}
120
121void STipCtrl::SetToolTip(LPCRECT rc, UINT tipAlign, LPCTSTR pszTip, int nScale)
122{
123 if (pszTip)
124 {
125 SSLOGI() << "SetToolTip," << pszTip;
126 SASSERT(tipAlign != TA_AUTO);
127 m_strTip = pszTip;
128 m_strTip.Replace(_T("\\n"), _T("\n"));
129
130 m_tipAlign = tipAlign;
131 m_rcTarget = *rc;
132
133 UpdateFont(nScale);
134 InvalidateRect(NULL, TRUE);
135 ShowTip(TRUE);
136
137 KillTimer(TIMERID_DELAY);
138 KillTimer(TIMERID_SPAN);
139 }
140 else
141 {
142 m_tipAlign = TA_AUTO;
143 ClearTip();
144 }
145}
146
147void STipCtrl::UpdateTip(const TIPID *id, RECT rc, LPCTSTR pszTip, int nScale)
148{
149 if (m_tipAlign != TA_AUTO)
150 return;
151 if (m_id.dwHi == id->dwHi && m_id.dwLow == id->dwLow)
152 return;
153
154 m_id = *id;
155 m_rcTarget = rc;
156 m_strTip = pszTip;
157 m_strTip.Replace(_T("\\n"), _T("\n"));
158
159 UpdateFont(nScale);
160 if (IsWindowVisible())
161 {
162 ShowTip(TRUE);
163 }
164}
165
167{
168 if (m_tipAlign != TA_AUTO)
169 return;
170 m_id.dwHi = m_id.dwLow = 0;
171 ShowTip(FALSE);
172}
173
174void STipCtrl::ShowTip(BOOL bShow)
175{
176 if (!bShow)
177 {
178 ShowWindow(SW_HIDE);
179 m_rcTarget.SetRect(0, 0, 0, 0);
180 m_strTip = _T("");
181 }
182 else if (!m_strTip.IsEmpty())
183 {
184 HDC hdc = ::GetDC(NULL);
185 CRect rcText(0, 0, 500, 1000);
186 HFONT oldFont = (HFONT)SelectObject(hdc, m_font);
187 DrawText(hdc, m_strTip, -1, &rcText, DT_CALCRECT | DT_LEFT | DT_WORDBREAK);
188 SelectObject(hdc, oldFont);
189 ::ReleaseDC(NULL, hdc);
190
191 CRect rcWnd;
192 GetWindowRect(&rcWnd);
193 if (m_tipAlign == TA_AUTO)
194 {
195 //增加对多显示器的支持
196 HMONITOR hMonitor;
197 MONITORINFO mi;
198 hMonitor = MonitorFromRect(&rcWnd, MONITOR_DEFAULTTONEAREST);
199 mi.cbSize = sizeof(mi);
200 GetMonitorInfo(hMonitor, &mi);
201 int cx = mi.rcMonitor.right;
202 int cy = mi.rcMonitor.bottom;
203 /*增加部分结束*/
204
205 rcWnd.right = rcWnd.left + rcText.right + 2 * MARGIN_TIP;
206 rcWnd.bottom = rcWnd.top + rcText.bottom + 2 * MARGIN_TIP;
207 //去掉下面这两行
208 if (rcWnd.right > cx)
209 rcWnd.OffsetRect(cx - rcWnd.right, 0);
210 if (rcWnd.bottom > cy)
211 rcWnd.OffsetRect(0, cy - rcWnd.bottom);
212 }
213 else
214 {
215 rcWnd = rcText;
216 rcWnd.InflateRect(MARGIN_TIP, MARGIN_TIP);
217
218 CPoint pt = m_rcTarget.CenterPoint();
219 switch (m_tipAlign & TA_X_MASK)
220 {
221 case TA_X_LEFT:
222 pt.x = m_rcTarget.left - rcWnd.Width();
223 break;
224 case TA_X_RIGHT:
225 pt.x = m_rcTarget.right;
226 break;
227 case TA_X_CENTER:
228 pt.x -= rcWnd.Width() / 2;
229 break;
230 }
231 switch (m_tipAlign & TA_Y_MASK)
232 {
233 case TA_Y_TOP:
234 pt.y = m_rcTarget.top - rcWnd.Height();
235 break;
236 case TA_Y_BOTTOM:
237 pt.y = m_rcTarget.bottom;
238 break;
239 case TA_Y_CENTER:
240 pt.y -= rcWnd.Height() / 2;
241 break;
242 }
243 rcWnd.MoveToXY(pt);
244 }
245 SetWindowPos(HWND_TOPMOST, rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
246 }
247}
248
249void STipCtrl::OnTimer(UINT_PTR idEvent)
250{
251 switch (idEvent)
252 {
253 case TIMERID_DELAY:
254 KillTimer(TIMERID_DELAY);
255 ShowTip(TRUE);
256 SetTimer(TIMERID_SPAN, m_nShowSpan);
257 break;
258 case TIMERID_SPAN:
259 ShowTip(FALSE);
260 KillTimer(TIMERID_SPAN);
261 break;
262 }
263}
264
266{
267 PAINTSTRUCT ps;
268 dc = ::BeginPaint(m_hWnd, &ps);
269
270 CRect rc;
271 GetClientRect(&rc);
272 HBRUSH br = CreateSolidBrush(GetSysColor(COLOR_INFOBK));
273 HGDIOBJ hOld = SelectObject(dc, br);
274 Rectangle(dc, rc.left, rc.top, rc.right, rc.bottom);
275 SelectObject(dc, hOld);
276 DeleteObject(br);
277
278 rc.DeflateRect(MARGIN_TIP, MARGIN_TIP);
279 SetBkMode(dc, TRANSPARENT);
280 HGDIOBJ hOldFont = SelectObject(dc, m_font);
281 ::DrawText(dc, m_strTip, -1, &rc, DT_WORDBREAK);
282 SelectObject(dc, hOldFont);
283
284 ::EndPaint(m_hWnd, &ps);
285}
286
288{
289 if (m_tipAlign != TA_AUTO)
290 return FALSE;
291 if (IsWindow())
292 RelayEvent(pMsg);
293 return FALSE;
294}
295
297{
299 delete this;
300}
301SNSEND
HDC GetDC() OVERRIDE
Retrieves a device context for the window.
BOOL GetWindowRect(LPRECT lpRect) SCONST OVERRIDE
Retrieves the window rectangle.
BOOL IsWindowVisible() SCONST OVERRIDE
Checks if the window is visible.
BOOL IsWindow() SCONST OVERRIDE
Checks if the handle is a valid window handle.
UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void(CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD)=NULL) OVERRIDE
Sets a timer for the window.
BOOL ClientToScreen(LPPOINT lpPoint) SCONST OVERRIDE
Converts client coordinates to screen coordinates.
BOOL ShowWindow(int nCmdShow) OVERRIDE
Sets the show state of the window.
BOOL KillTimer(UINT_PTR nIDEvent) OVERRIDE
Kills a timer for the window.
HWND m_hWnd
Handle to the window.
Definition SNativeWnd.h:744
BOOL GetClientRect(LPRECT lpRect) SCONST OVERRIDE
Retrieves the client rectangle.
HWND CreateNative(LPCTSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, int nID=0, LPVOID lpParam=0) OVERRIDE
Creates a native window.
BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) OVERRIDE
Sets the window position.
virtual void OnFinalMessage(HWND hWnd)
Handles the final message for the window.
int ReleaseDC(HDC hDC) OVERRIDE
Releases a device context.
BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase=TRUE) OVERRIDE
Invalidates a specified rectangle of the window.
void SetToolTip(LPCRECT rc, UINT tipAlign, LPCTSTR pszTip, int nScale) OVERRIDE
设置提示信息
Definition SToolTip.cpp:121
virtual ~STipCtrl(void)
析构函数
Definition SToolTip.cpp:25
BOOL Create()
创建提示控件
Definition SToolTip.cpp:31
void RelayEvent(const MSG *pMsg) OVERRIDE
传递事件
Definition SToolTip.cpp:46
void ShowTip(BOOL bShow)
显示或隐藏提示
Definition SToolTip.cpp:174
void OnPaint(HDC dc)
处理绘制消息
Definition SToolTip.cpp:265
void UpdateFont(int nScale)
更新字体
Definition SToolTip.cpp:106
void UpdateTip(const TIPID *id, RECT rc, LPCTSTR pszTip, int nScale) OVERRIDE
更新提示信息
Definition SToolTip.cpp:147
BOOL PreTranslateMessage(MSG *pMsg) OVERRIDE
预翻译消息
Definition SToolTip.cpp:287
virtual void OnFinalMessage(HWND hWnd)
处理最终消息
Definition SToolTip.cpp:296
STipCtrl(void)
构造函数
Definition SToolTip.cpp:14
void OnTimer(UINT_PTR idEvent)
处理定时器消息
Definition SToolTip.cpp:249
void ClearTip() OVERRIDE
清除提示信息
Definition SToolTip.cpp:166
@ TA_Y_CENTER
Align center vertically.
Definition stooltip-i.h:47
@ TA_X_MASK
Mask for horizontal alignment.
Definition stooltip-i.h:45
@ TA_AUTO
Automatic alignment.
Definition stooltip-i.h:41
@ TA_Y_MASK
Mask for vertical alignment.
Definition stooltip-i.h:49
@ TA_X_RIGHT
Align right horizontally.
Definition stooltip-i.h:44
@ TA_X_LEFT
Align left horizontally.
Definition stooltip-i.h:42
@ TA_Y_BOTTOM
Align bottom vertically.
Definition stooltip-i.h:48
@ TA_Y_TOP
Align top vertically.
Definition stooltip-i.h:46
@ TA_X_CENTER
Align center horizontally.
Definition stooltip-i.h:43
Identifier for a tooltip.
Definition stooltip-i.h:27
DWORD dwLow
ID2, used to save additional data.
Definition stooltip-i.h:29
DWORD dwHi
ID1, used to save a SWND.
Definition stooltip-i.h:28