4 * Copyright 1998, 1999 Eric Kohl
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * - Unicode support (started).
22 * - Custom draw support.
25 * - Run tests using Waite Group Windows95 API Bible Volume 2.
26 * The second cdrom (chapter 3) contains executables activate.exe,
27 * curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
28 * hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
32 * One important point to remember is that tools don't necessarily get
33 * a WM_MOUSEMOVE once the cursor leaves the tool, an example is when
34 * a tool sets TTF_IDISHWND (i.e. an entire window is a tool) because
35 * here WM_MOUSEMOVEs only get sent when the cursor is inside the
36 * client area. Therefore the only reliable way to know that the
37 * cursor has left a tool is to keep a timer running and check the
38 * position every time it expires. This is the role of timer
42 * On entering a tool (detected in a relayed WM_MOUSEMOVE) we start
43 * ID_TIMERSHOW, if this times out and we're still in the tool we show
44 * the tip. On showing a tip we start both ID_TIMERPOP and
45 * ID_TIMERLEAVE. On hiding a tooltip we kill ID_TIMERPOP.
46 * ID_TIMERPOP is restarted on every relayed WM_MOUSEMOVE. If
47 * ID_TIMERPOP expires the tool is hidden and ID_TIMERPOP is killed.
48 * ID_TIMERLEAVE remains running - this is important as we need to
49 * determine when the cursor leaves the tool.
51 * When ID_TIMERLEAVE expires or on a relayed WM_MOUSEMOVE if we're
52 * still in the tool do nothing (apart from restart ID_TIMERPOP if
53 * this is a WM_MOUSEMOVE) (ID_TIMERLEAVE remains running). If we've
54 * left the tool and entered another one then hide the tip and start
55 * ID_TIMERSHOW with time ReshowTime and kill ID_TIMERLEAVE. If we're
56 * outside all tools hide the tip and kill ID_TIMERLEAVE. On Relayed
57 * mouse button messages hide the tip but leave ID_TIMERLEAVE running,
58 * this again will let us keep track of when the cursor leaves the
62 * infoPtr->nTool is the tool the mouse was on on the last relayed MM
63 * or timer expiry or -1 if the mouse was not on a tool.
65 * infoPtr->nCurrentTool is the tool for which the tip is currently
66 * displaying text for or -1 if the tip is not shown. Actually this
67 * will only ever be infoPtr-nTool or -1, so it could be changed to a
77 #include "wine/unicode.h"
79 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(tooltips
);
97 WCHAR szTipText
[INFOTIPSIZE
];
119 #define ID_TIMERSHOW 1 /* show delay timer */
120 #define ID_TIMERPOP 2 /* auto pop timer */
121 #define ID_TIMERLEAVE 3 /* tool leave timer */
124 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
128 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uId
, DWORD_PTR dwRef
);
132 TOOLTIPS_Refresh (HWND hwnd
, HDC hdc
)
134 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr(hwnd
);
139 UINT uFlags
= DT_EXTERNALLEADING
;
141 if (infoPtr
->nMaxTipWidth
> -1)
142 uFlags
|= DT_WORDBREAK
;
143 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
144 uFlags
|= DT_NOPREFIX
;
145 GetClientRect (hwnd
, &rc
);
147 /* fill the background */
148 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
149 FillRect (hdc
, &rc
, hBrush
);
150 DeleteObject (hBrush
);
152 /* calculate text rectangle */
153 rc
.left
+= (2 + infoPtr
->rcMargin
.left
);
154 rc
.top
+= (2 + infoPtr
->rcMargin
.top
);
155 rc
.right
-= (2 + infoPtr
->rcMargin
.right
);
156 rc
.bottom
-= (2 + infoPtr
->rcMargin
.bottom
);
159 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
160 SetTextColor (hdc
, infoPtr
->clrText
);
161 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
162 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
163 SelectObject (hdc
, hOldFont
);
164 if (oldBkMode
!= TRANSPARENT
)
165 SetBkMode (hdc
, oldBkMode
);
170 TOOLTIPS_GetTipText (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, INT nTool
)
172 TTTOOL_INFO
*toolPtr
= &infoPtr
->tools
[nTool
];
174 if (HIWORD((UINT
)toolPtr
->lpszText
) == 0) {
175 /* load a resource */
176 TRACE("load res string %x %x\n",
177 toolPtr
->hinst
, (int)toolPtr
->lpszText
);
178 LoadStringW (toolPtr
->hinst
, (UINT
)toolPtr
->lpszText
,
179 infoPtr
->szTipText
, INFOTIPSIZE
);
181 else if (toolPtr
->lpszText
) {
182 if (toolPtr
->lpszText
== LPSTR_TEXTCALLBACKW
) {
183 NMTTDISPINFOA ttnmdi
;
185 /* fill NMHDR struct */
186 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOA
));
187 ttnmdi
.hdr
.hwndFrom
= hwnd
;
188 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
189 ttnmdi
.hdr
.code
= TTN_GETDISPINFOA
;
190 ttnmdi
.lpszText
= (LPSTR
)&ttnmdi
.szText
;
191 ttnmdi
.uFlags
= toolPtr
->uFlags
;
192 ttnmdi
.lParam
= toolPtr
->lParam
;
194 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
195 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
196 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
198 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
199 LoadStringW (ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
200 infoPtr
->szTipText
, INFOTIPSIZE
);
201 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
202 toolPtr
->hinst
= ttnmdi
.hinst
;
203 toolPtr
->lpszText
= (LPWSTR
)ttnmdi
.lpszText
;
206 else if (ttnmdi
.szText
[0]) {
207 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
208 infoPtr
->szTipText
, INFOTIPSIZE
);
209 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
210 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
,
213 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
214 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
215 toolPtr
->lpszText
, len
);
218 else if (ttnmdi
.lpszText
== 0) {
219 /* no text available */
220 infoPtr
->szTipText
[0] = L
'\0';
222 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKA
) {
223 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
224 infoPtr
->szTipText
, INFOTIPSIZE
);
225 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
226 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
,
229 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
230 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
231 toolPtr
->lpszText
, len
);
235 ERR("recursive text callback!\n");
236 infoPtr
->szTipText
[0] = '\0';
240 /* the item is a usual (unicode) text */
241 lstrcpynW (infoPtr
->szTipText
, toolPtr
->lpszText
, INFOTIPSIZE
);
245 /* no text available */
246 infoPtr
->szTipText
[0] = L
'\0';
249 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
254 TOOLTIPS_CalcTipSize (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, LPSIZE lpSize
)
258 UINT uFlags
= DT_EXTERNALLEADING
| DT_CALCRECT
;
259 RECT rc
= {0, 0, 0, 0};
261 if (infoPtr
->nMaxTipWidth
> -1) {
262 rc
.right
= infoPtr
->nMaxTipWidth
;
263 uFlags
|= DT_WORDBREAK
;
265 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
266 uFlags
|= DT_NOPREFIX
;
267 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
270 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
271 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
272 SelectObject (hdc
, hOldFont
);
273 ReleaseDC (hwnd
, hdc
);
275 lpSize
->cx
= rc
.right
- rc
.left
+ 4 +
276 infoPtr
->rcMargin
.left
+ infoPtr
->rcMargin
.right
;
277 lpSize
->cy
= rc
.bottom
- rc
.top
+ 4 +
278 infoPtr
->rcMargin
.bottom
+ infoPtr
->rcMargin
.top
;
283 TOOLTIPS_Show (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
285 TTTOOL_INFO
*toolPtr
;
290 if (infoPtr
->nTool
== -1) {
291 TRACE("invalid tool (-1)!\n");
295 infoPtr
->nCurrentTool
= infoPtr
->nTool
;
297 TRACE("Show tooltip pre %d! (%04x)\n", infoPtr
->nTool
, hwnd
);
299 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nCurrentTool
);
301 if (infoPtr
->szTipText
[0] == L
'\0') {
302 infoPtr
->nCurrentTool
= -1;
306 TRACE("Show tooltip %d!\n", infoPtr
->nCurrentTool
);
307 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
310 hdr
.idFrom
= toolPtr
->uId
;
312 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
313 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
315 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
317 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
318 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
320 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
323 if (toolPtr
->uFlags
& TTF_IDISHWND
)
324 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
327 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rc
, 2);
329 rect
.left
= (rc
.left
+ rc
.right
- size
.cx
) / 2;
330 rect
.top
= rc
.bottom
+ 2;
333 GetCursorPos ((LPPOINT
)&rect
);
337 TRACE("pos %d - %d\n", rect
.left
, rect
.top
);
339 rect
.right
= rect
.left
+ size
.cx
;
340 rect
.bottom
= rect
.top
+ size
.cy
;
343 wndrect
.right
= GetSystemMetrics( SM_CXSCREEN
);
344 if( rect
.right
> wndrect
.right
) {
345 rect
.left
-= rect
.right
- wndrect
.right
+ 2;
346 rect
.right
= wndrect
.right
- 2;
348 wndrect
.bottom
= GetSystemMetrics( SM_CYSCREEN
);
349 if( rect
.bottom
> wndrect
.bottom
) {
352 if (toolPtr
->uFlags
& TTF_IDISHWND
)
353 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
356 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rc
, 2);
358 rect
.bottom
= rc
.top
- 2;
359 rect
.top
= rect
.bottom
- size
.cy
;
362 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
363 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
365 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
366 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
367 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
369 /* repaint the tooltip */
370 InvalidateRect(hwnd
, NULL
, TRUE
);
373 SetTimer (hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
374 TRACE("timer 2 started!\n");
375 SetTimer (hwnd
, ID_TIMERLEAVE
, infoPtr
->nReshowTime
, 0);
376 TRACE("timer 3 started!\n");
381 TOOLTIPS_Hide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
383 TTTOOL_INFO
*toolPtr
;
386 TRACE("Hide tooltip %d! (%04x)\n", infoPtr
->nCurrentTool
, hwnd
);
388 if (infoPtr
->nCurrentTool
== -1)
391 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
392 KillTimer (hwnd
, ID_TIMERPOP
);
395 hdr
.idFrom
= toolPtr
->uId
;
397 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
398 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
400 infoPtr
->nCurrentTool
= -1;
402 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
403 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
408 TOOLTIPS_TrackShow (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
410 TTTOOL_INFO
*toolPtr
;
415 if (infoPtr
->nTrackTool
== -1) {
416 TRACE("invalid tracking tool (-1)!\n");
420 TRACE("show tracking tooltip pre %d!\n", infoPtr
->nTrackTool
);
422 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nTrackTool
);
424 if (infoPtr
->szTipText
[0] == L
'\0') {
425 infoPtr
->nTrackTool
= -1;
429 TRACE("show tracking tooltip %d!\n", infoPtr
->nTrackTool
);
430 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
433 hdr
.idFrom
= toolPtr
->uId
;
435 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
436 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
438 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
440 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
441 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
443 if (toolPtr
->uFlags
& TTF_ABSOLUTE
) {
444 rect
.left
= infoPtr
->xTrackPos
;
445 rect
.top
= infoPtr
->yTrackPos
;
447 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
448 rect
.left
-= (size
.cx
/ 2);
449 rect
.top
-= (size
.cy
/ 2);
455 if (toolPtr
->uFlags
& TTF_IDISHWND
)
456 GetWindowRect ((HWND
)toolPtr
->uId
, &rcTool
);
458 rcTool
= toolPtr
->rect
;
459 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rcTool
, 2);
462 GetCursorPos ((LPPOINT
)&rect
);
465 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
466 rect
.left
-= (size
.cx
/ 2);
467 rect
.top
-= (size
.cy
/ 2);
470 /* smart placement */
471 if ((rect
.left
+ size
.cx
> rcTool
.left
) && (rect
.left
< rcTool
.right
) &&
472 (rect
.top
+ size
.cy
> rcTool
.top
) && (rect
.top
< rcTool
.bottom
))
473 rect
.left
= rcTool
.right
;
476 TRACE("pos %d - %d\n", rect
.left
, rect
.top
);
478 rect
.right
= rect
.left
+ size
.cx
;
479 rect
.bottom
= rect
.top
+ size
.cy
;
481 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
482 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
484 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
485 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
486 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
488 InvalidateRect(hwnd
, NULL
, TRUE
);
494 TOOLTIPS_TrackHide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
496 TTTOOL_INFO
*toolPtr
;
499 if (infoPtr
->nTrackTool
== -1)
502 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
503 TRACE("hide tracking tooltip %d!\n", infoPtr
->nTrackTool
);
506 hdr
.idFrom
= toolPtr
->uId
;
508 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
509 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
511 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
512 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
517 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOA lpToolInfo
)
519 TTTOOL_INFO
*toolPtr
;
522 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
523 toolPtr
= &infoPtr
->tools
[nTool
];
525 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
526 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
527 (lpToolInfo
->uId
== toolPtr
->uId
))
531 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
532 toolPtr
= &infoPtr
->tools
[nTool
];
534 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
535 (lpToolInfo
->uId
== toolPtr
->uId
))
544 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOW lpToolInfo
)
546 TTTOOL_INFO
*toolPtr
;
549 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
550 toolPtr
= &infoPtr
->tools
[nTool
];
552 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
553 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
554 (lpToolInfo
->uId
== toolPtr
->uId
))
558 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
559 toolPtr
= &infoPtr
->tools
[nTool
];
561 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
562 (lpToolInfo
->uId
== toolPtr
->uId
))
571 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO
*infoPtr
, HWND hwnd
, LPPOINT lpPt
)
573 TTTOOL_INFO
*toolPtr
;
576 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
577 toolPtr
= &infoPtr
->tools
[nTool
];
579 if (!(toolPtr
->uFlags
& TTF_IDISHWND
)) {
580 if (hwnd
!= toolPtr
->hwnd
)
582 if (!PtInRect (&toolPtr
->rect
, *lpPt
))
588 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
589 toolPtr
= &infoPtr
->tools
[nTool
];
591 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
592 if ((HWND
)toolPtr
->uId
== hwnd
)
602 TOOLTIPS_IsWindowActive (HWND hwnd
)
604 HWND hwndActive
= GetActiveWindow ();
607 if (hwndActive
== hwnd
)
609 return IsChild (hwndActive
, hwnd
);
614 TOOLTIPS_CheckTool (HWND hwnd
, BOOL bShowTest
)
616 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
622 hwndTool
= (HWND
)SendMessageA (hwnd
, TTM_WINDOWFROMPOINT
, 0, (LPARAM
)&pt
);
626 ScreenToClient (hwndTool
, &pt
);
627 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, hwndTool
, &pt
);
631 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_ALWAYSTIP
) && bShowTest
) {
632 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd
, GW_OWNER
)))
636 TRACE("tool %d\n", nTool
);
643 TOOLTIPS_Activate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
645 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
647 infoPtr
->bActive
= (BOOL
)wParam
;
649 if (infoPtr
->bActive
)
650 TRACE("activate!\n");
652 if (!(infoPtr
->bActive
) && (infoPtr
->nCurrentTool
!= -1))
653 TOOLTIPS_Hide (hwnd
, infoPtr
);
660 TOOLTIPS_AddToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
662 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
663 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
664 TTTOOL_INFO
*toolPtr
;
666 if (lpToolInfo
== NULL
)
668 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
671 TRACE("add tool (%x) %x %d%s!\n",
672 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
673 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
675 if (infoPtr
->uNumTools
== 0) {
676 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
677 toolPtr
= infoPtr
->tools
;
680 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
682 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
683 memcpy (infoPtr
->tools
, oldTools
,
684 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
685 COMCTL32_Free (oldTools
);
686 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
689 infoPtr
->uNumTools
++;
692 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
693 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
694 toolPtr
->uId
= lpToolInfo
->uId
;
695 toolPtr
->rect
= lpToolInfo
->rect
;
696 toolPtr
->hinst
= lpToolInfo
->hinst
;
698 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
699 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
700 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
702 else if (lpToolInfo
->lpszText
) {
703 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
) {
704 TRACE("add CALLBACK!\n");
705 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
708 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
710 TRACE("add text \"%s\"!\n", lpToolInfo
->lpszText
);
711 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
712 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
713 toolPtr
->lpszText
, len
);
717 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
718 toolPtr
->lParam
= lpToolInfo
->lParam
;
720 /* install subclassing hook */
721 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
722 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
723 SetWindowSubclass(toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1, hwnd
);
726 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1, hwnd
);
728 TRACE("subclassing installed!\n");
736 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
738 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
739 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
740 TTTOOL_INFO
*toolPtr
;
742 if (lpToolInfo
== NULL
)
744 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
747 TRACE("add tool (%x) %x %d%s!\n",
748 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
749 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
751 if (infoPtr
->uNumTools
== 0) {
752 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
753 toolPtr
= infoPtr
->tools
;
756 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
758 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
759 memcpy (infoPtr
->tools
, oldTools
,
760 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
761 COMCTL32_Free (oldTools
);
762 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
765 infoPtr
->uNumTools
++;
768 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
769 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
770 toolPtr
->uId
= lpToolInfo
->uId
;
771 toolPtr
->rect
= lpToolInfo
->rect
;
772 toolPtr
->hinst
= lpToolInfo
->hinst
;
774 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
775 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
776 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
778 else if (lpToolInfo
->lpszText
) {
779 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
780 TRACE("add CALLBACK!\n");
781 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
784 INT len
= lstrlenW (lpToolInfo
->lpszText
);
785 TRACE("add text %s!\n",
786 debugstr_w(lpToolInfo
->lpszText
));
787 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
788 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
792 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
793 toolPtr
->lParam
= lpToolInfo
->lParam
;
795 /* install subclassing hook */
796 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
797 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
798 SetWindowSubclass(toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1, hwnd
);
801 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1, hwnd
);
803 TRACE("subclassing installed!\n");
811 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
813 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
814 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
815 TTTOOL_INFO
*toolPtr
;
818 if (lpToolInfo
== NULL
)
820 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
822 if (infoPtr
->uNumTools
== 0)
825 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
826 if (nTool
== -1) return 0;
828 TRACE("tool %d\n", nTool
);
830 /* make sure the tooltip has disappeared before deleting it */
831 TOOLTIPS_Hide(hwnd
, infoPtr
);
833 /* delete text string */
834 toolPtr
= &infoPtr
->tools
[nTool
];
835 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
836 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
837 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
838 COMCTL32_Free (toolPtr
->lpszText
);
841 /* remove subclassing */
842 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
843 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
844 RemoveWindowSubclass(toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
847 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
851 /* delete tool from tool list */
852 if (infoPtr
->uNumTools
== 1) {
853 COMCTL32_Free (infoPtr
->tools
);
854 infoPtr
->tools
= NULL
;
857 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
859 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
862 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
863 nTool
* sizeof(TTTOOL_INFO
));
865 if (nTool
< infoPtr
->uNumTools
- 1)
866 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
867 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
869 COMCTL32_Free (oldTools
);
872 /* destroying tool that mouse was on on last relayed mouse move */
873 if (infoPtr
->nTool
== nTool
)
875 /* no current tool (0 means first tool) */
879 infoPtr
->uNumTools
--;
886 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
888 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
889 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
890 TTTOOL_INFO
*toolPtr
;
893 if (lpToolInfo
== NULL
)
895 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
897 if (infoPtr
->uNumTools
== 0)
900 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
901 if (nTool
== -1) return 0;
903 TRACE("tool %d\n", nTool
);
905 /* make sure the tooltip has disappeared before deleting it */
906 TOOLTIPS_Hide(hwnd
, infoPtr
);
908 /* delete text string */
909 toolPtr
= &infoPtr
->tools
[nTool
];
910 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
911 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
912 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
913 COMCTL32_Free (toolPtr
->lpszText
);
916 /* remove subclassing */
917 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
918 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
919 RemoveWindowSubclass(toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
922 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
926 /* delete tool from tool list */
927 if (infoPtr
->uNumTools
== 1) {
928 COMCTL32_Free (infoPtr
->tools
);
929 infoPtr
->tools
= NULL
;
932 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
934 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
937 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
938 nTool
* sizeof(TTTOOL_INFO
));
940 if (nTool
< infoPtr
->uNumTools
- 1)
941 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
942 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
944 COMCTL32_Free (oldTools
);
947 /* destroying tool that mouse was on on last relayed mouse move */
948 if (infoPtr
->nTool
== nTool
)
950 /* no current tool (0 means first tool) */
954 infoPtr
->uNumTools
--;
961 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
963 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
964 UINT uIndex
= (UINT
)wParam
;
965 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
966 TTTOOL_INFO
*toolPtr
;
968 if (lpToolInfo
== NULL
)
970 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
972 if (uIndex
>= infoPtr
->uNumTools
)
975 TRACE("index=%u\n", uIndex
);
977 toolPtr
= &infoPtr
->tools
[uIndex
];
980 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
981 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
982 lpToolInfo
->uId
= toolPtr
->uId
;
983 lpToolInfo
->rect
= toolPtr
->rect
;
984 lpToolInfo
->hinst
= toolPtr
->hinst
;
985 /* lpToolInfo->lpszText = toolPtr->lpszText; */
986 lpToolInfo
->lpszText
= NULL
; /* FIXME */
988 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
989 lpToolInfo
->lParam
= toolPtr
->lParam
;
996 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
998 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
999 UINT uIndex
= (UINT
)wParam
;
1000 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1001 TTTOOL_INFO
*toolPtr
;
1003 if (lpToolInfo
== NULL
)
1005 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1007 if (uIndex
>= infoPtr
->uNumTools
)
1010 TRACE("index=%u\n", uIndex
);
1012 toolPtr
= &infoPtr
->tools
[uIndex
];
1014 /* copy tool data */
1015 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1016 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1017 lpToolInfo
->uId
= toolPtr
->uId
;
1018 lpToolInfo
->rect
= toolPtr
->rect
;
1019 lpToolInfo
->hinst
= toolPtr
->hinst
;
1020 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1021 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1023 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1024 lpToolInfo
->lParam
= toolPtr
->lParam
;
1030 TOOLTIPS_GetBubbleSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1032 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1033 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1037 if (lpToolInfo
== NULL
)
1039 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1042 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1043 if (nTool
== -1) return 0;
1045 TRACE("tool %d\n", nTool
);
1047 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
1048 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
1050 return MAKELRESULT(size
.cx
, size
.cy
);
1054 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1056 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1057 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1058 TTTOOL_INFO
*toolPtr
;
1060 if (lpToolInfo
== NULL
)
1062 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1066 if (infoPtr
->nCurrentTool
> -1) {
1067 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1069 /* copy tool data */
1070 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1071 lpToolInfo
->rect
= toolPtr
->rect
;
1072 lpToolInfo
->hinst
= toolPtr
->hinst
;
1073 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1074 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1076 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1077 lpToolInfo
->lParam
= toolPtr
->lParam
;
1085 return (infoPtr
->nCurrentTool
!= -1);
1092 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1094 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1095 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1096 TTTOOL_INFO
*toolPtr
;
1098 if (lpToolInfo
== NULL
)
1100 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1104 if (infoPtr
->nCurrentTool
> -1) {
1105 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1107 /* copy tool data */
1108 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1109 lpToolInfo
->rect
= toolPtr
->rect
;
1110 lpToolInfo
->hinst
= toolPtr
->hinst
;
1111 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1112 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1114 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1115 lpToolInfo
->lParam
= toolPtr
->lParam
;
1123 return (infoPtr
->nCurrentTool
!= -1);
1130 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1132 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1136 return infoPtr
->nReshowTime
;
1139 return infoPtr
->nAutoPopTime
;
1142 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1143 return infoPtr
->nInitialTime
;
1146 WARN("Invalid wParam %x\n", wParam
);
1155 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1157 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1158 LPRECT lpRect
= (LPRECT
)lParam
;
1160 lpRect
->left
= infoPtr
->rcMargin
.left
;
1161 lpRect
->right
= infoPtr
->rcMargin
.right
;
1162 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1163 lpRect
->top
= infoPtr
->rcMargin
.top
;
1169 inline static LRESULT
1170 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1172 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1174 return infoPtr
->nMaxTipWidth
;
1179 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1181 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1182 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1185 if (lpToolInfo
== NULL
)
1187 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1190 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1191 if (nTool
== -1) return 0;
1193 /* NB this API is broken, there is no way for the app to determine
1194 what size buffer it requires nor a way to specify how long the
1195 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1197 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1198 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1205 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1207 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1208 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1211 if (lpToolInfo
== NULL
)
1213 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1216 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1217 if (nTool
== -1) return 0;
1219 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1225 inline static LRESULT
1226 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1228 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1229 return infoPtr
->clrBk
;
1233 inline static LRESULT
1234 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1236 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1237 return infoPtr
->clrText
;
1241 inline static LRESULT
1242 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1244 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1245 return infoPtr
->uNumTools
;
1250 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1252 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1253 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1254 TTTOOL_INFO
*toolPtr
;
1257 if (lpToolInfo
== NULL
)
1259 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1261 if (infoPtr
->uNumTools
== 0)
1264 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1268 TRACE("tool %d\n", nTool
);
1270 toolPtr
= &infoPtr
->tools
[nTool
];
1272 /* copy tool data */
1273 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1274 lpToolInfo
->rect
= toolPtr
->rect
;
1275 lpToolInfo
->hinst
= toolPtr
->hinst
;
1276 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1277 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1279 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1280 lpToolInfo
->lParam
= toolPtr
->lParam
;
1287 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1289 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1290 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1291 TTTOOL_INFO
*toolPtr
;
1294 if (lpToolInfo
== NULL
)
1296 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1298 if (infoPtr
->uNumTools
== 0)
1301 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1305 TRACE("tool %d\n", nTool
);
1307 toolPtr
= &infoPtr
->tools
[nTool
];
1309 /* copy tool data */
1310 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1311 lpToolInfo
->rect
= toolPtr
->rect
;
1312 lpToolInfo
->hinst
= toolPtr
->hinst
;
1313 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1314 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1316 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1317 lpToolInfo
->lParam
= toolPtr
->lParam
;
1324 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1326 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1327 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1328 TTTOOL_INFO
*toolPtr
;
1334 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1338 TRACE("tool %d!\n", nTool
);
1340 /* copy tool data */
1341 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1342 toolPtr
= &infoPtr
->tools
[nTool
];
1344 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1345 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1346 lptthit
->ti
.uId
= toolPtr
->uId
;
1347 lptthit
->ti
.rect
= toolPtr
->rect
;
1348 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1349 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1350 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1351 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1359 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1361 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1362 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1363 TTTOOL_INFO
*toolPtr
;
1369 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1373 TRACE("tool %d!\n", nTool
);
1375 /* copy tool data */
1376 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1377 toolPtr
= &infoPtr
->tools
[nTool
];
1379 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1380 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1381 lptthit
->ti
.uId
= toolPtr
->uId
;
1382 lptthit
->ti
.rect
= toolPtr
->rect
;
1383 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1384 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1385 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1386 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1394 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1396 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1397 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1402 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1405 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1406 if (nTool
== -1) return 0;
1408 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1415 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1417 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1418 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1423 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1426 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1427 if (nTool
== -1) return 0;
1429 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1435 inline static LRESULT
1436 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1438 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1439 TOOLTIPS_Hide (hwnd
, infoPtr
);
1446 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1448 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1449 LPMSG lpMsg
= (LPMSG
)lParam
;
1454 ERR("lpMsg == NULL!\n");
1458 switch (lpMsg
->message
) {
1459 case WM_LBUTTONDOWN
:
1461 case WM_MBUTTONDOWN
:
1463 case WM_RBUTTONDOWN
:
1465 TOOLTIPS_Hide (hwnd
, infoPtr
);
1469 pt
.x
= LOWORD(lpMsg
->lParam
);
1470 pt
.y
= HIWORD(lpMsg
->lParam
);
1471 nOldTool
= infoPtr
->nTool
;
1472 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1474 TRACE("tool (%x) %d %d %d\n", hwnd
, nOldTool
,
1475 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1476 TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1478 if (infoPtr
->nTool
!= nOldTool
) {
1479 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1480 TOOLTIPS_Hide(hwnd
, infoPtr
);
1481 KillTimer(hwnd
, ID_TIMERLEAVE
);
1482 } else if (nOldTool
== -1) { /* Moved from outside */
1483 if(infoPtr
->bActive
) {
1484 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1485 TRACE("timer 1 started!\n");
1487 } else { /* Moved from one to another */
1488 TOOLTIPS_Hide (hwnd
, infoPtr
);
1489 KillTimer(hwnd
, ID_TIMERLEAVE
);
1490 if(infoPtr
->bActive
) {
1491 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1492 TRACE("timer 1 started!\n");
1495 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1496 KillTimer(hwnd
, ID_TIMERPOP
);
1497 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1498 TRACE("timer 2 restarted\n");
1508 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1510 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1511 INT nTime
= (INT
)LOWORD(lParam
);
1514 case TTDT_AUTOMATIC
:
1516 nTime
= GetDoubleClickTime();
1517 infoPtr
->nReshowTime
= nTime
/ 5;
1518 infoPtr
->nAutoPopTime
= nTime
* 10;
1519 infoPtr
->nInitialTime
= nTime
;
1524 nTime
= GetDoubleClickTime() / 5;
1525 infoPtr
->nReshowTime
= nTime
;
1530 nTime
= GetDoubleClickTime() * 10;
1531 infoPtr
->nAutoPopTime
= nTime
;
1536 nTime
= GetDoubleClickTime();
1537 infoPtr
->nInitialTime
= nTime
;
1541 WARN("Invalid wParam %x\n", wParam
);
1550 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1552 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1553 LPRECT lpRect
= (LPRECT
)lParam
;
1555 infoPtr
->rcMargin
.left
= lpRect
->left
;
1556 infoPtr
->rcMargin
.right
= lpRect
->right
;
1557 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1558 infoPtr
->rcMargin
.top
= lpRect
->top
;
1564 inline static LRESULT
1565 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1567 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1568 INT nTemp
= infoPtr
->nMaxTipWidth
;
1570 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1576 inline static LRESULT
1577 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1579 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1581 infoPtr
->clrBk
= (COLORREF
)wParam
;
1587 inline static LRESULT
1588 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1590 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1592 infoPtr
->clrText
= (COLORREF
)wParam
;
1599 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1601 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1602 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1603 TTTOOL_INFO
*toolPtr
;
1606 if (lpToolInfo
== NULL
)
1608 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1611 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1612 if (nTool
== -1) return 0;
1614 TRACE("tool %d\n", nTool
);
1616 toolPtr
= &infoPtr
->tools
[nTool
];
1618 /* copy tool data */
1619 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1620 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1621 toolPtr
->uId
= lpToolInfo
->uId
;
1622 toolPtr
->rect
= lpToolInfo
->rect
;
1623 toolPtr
->hinst
= lpToolInfo
->hinst
;
1625 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1626 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1627 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1629 else if (lpToolInfo
->lpszText
) {
1630 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1631 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1633 if ( (toolPtr
->lpszText
) &&
1634 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1635 COMCTL32_Free (toolPtr
->lpszText
);
1636 toolPtr
->lpszText
= NULL
;
1638 if (lpToolInfo
->lpszText
) {
1639 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1641 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1642 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1643 toolPtr
->lpszText
, len
);
1648 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1649 toolPtr
->lParam
= lpToolInfo
->lParam
;
1656 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1658 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1659 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1660 TTTOOL_INFO
*toolPtr
;
1663 if (lpToolInfo
== NULL
)
1665 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1668 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1669 if (nTool
== -1) return 0;
1671 TRACE("tool %d\n", nTool
);
1673 toolPtr
= &infoPtr
->tools
[nTool
];
1675 /* copy tool data */
1676 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1677 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1678 toolPtr
->uId
= lpToolInfo
->uId
;
1679 toolPtr
->rect
= lpToolInfo
->rect
;
1680 toolPtr
->hinst
= lpToolInfo
->hinst
;
1682 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1683 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1684 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1686 else if (lpToolInfo
->lpszText
) {
1687 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1688 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1690 if ( (toolPtr
->lpszText
) &&
1691 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1692 COMCTL32_Free (toolPtr
->lpszText
);
1693 toolPtr
->lpszText
= NULL
;
1695 if (lpToolInfo
->lpszText
) {
1696 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1697 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1698 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1703 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1704 toolPtr
->lParam
= lpToolInfo
->lParam
;
1711 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1713 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1714 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1716 if (lpToolInfo
== NULL
)
1718 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1723 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1724 if (infoPtr
->nTrackTool
!= -1) {
1725 TRACE("activated!\n");
1726 infoPtr
->bTrackActive
= TRUE
;
1727 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1732 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1734 infoPtr
->bTrackActive
= FALSE
;
1735 infoPtr
->nTrackTool
= -1;
1737 TRACE("deactivated!\n");
1745 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1747 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1749 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1750 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1752 if (infoPtr
->bTrackActive
) {
1754 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1756 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1764 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1766 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1768 if (infoPtr
->nCurrentTool
!= -1)
1769 UpdateWindow (hwnd
);
1776 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1778 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1779 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1780 TTTOOL_INFO
*toolPtr
;
1783 if (lpToolInfo
== NULL
)
1785 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1788 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1789 if (nTool
== -1) return 0;
1791 TRACE("tool %d\n", nTool
);
1793 toolPtr
= &infoPtr
->tools
[nTool
];
1795 /* copy tool text */
1796 toolPtr
->hinst
= lpToolInfo
->hinst
;
1798 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1799 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1801 else if (lpToolInfo
->lpszText
) {
1802 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1803 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1805 if ( (toolPtr
->lpszText
) &&
1806 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1807 COMCTL32_Free (toolPtr
->lpszText
);
1808 toolPtr
->lpszText
= NULL
;
1810 if (lpToolInfo
->lpszText
) {
1811 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1813 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1814 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1815 toolPtr
->lpszText
, len
);
1820 if(infoPtr
->nCurrentTool
== -1) return 0;
1822 if (infoPtr
->bActive
)
1823 TOOLTIPS_Show (hwnd
, infoPtr
);
1824 else if (infoPtr
->bTrackActive
)
1825 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1832 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1834 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1835 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1836 TTTOOL_INFO
*toolPtr
;
1839 if (lpToolInfo
== NULL
)
1841 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1844 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1848 TRACE("tool %d\n", nTool
);
1850 toolPtr
= &infoPtr
->tools
[nTool
];
1852 /* copy tool text */
1853 toolPtr
->hinst
= lpToolInfo
->hinst
;
1855 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1856 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1858 else if (lpToolInfo
->lpszText
) {
1859 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1860 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1862 if ( (toolPtr
->lpszText
) &&
1863 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1864 COMCTL32_Free (toolPtr
->lpszText
);
1865 toolPtr
->lpszText
= NULL
;
1867 if (lpToolInfo
->lpszText
) {
1868 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1869 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1870 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1875 if(infoPtr
->nCurrentTool
== -1) return 0;
1877 if (infoPtr
->bActive
)
1878 TOOLTIPS_Show (hwnd
, infoPtr
);
1879 else if (infoPtr
->bTrackActive
)
1880 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1887 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1889 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1895 TOOLTIPS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1897 TOOLTIPS_INFO
*infoPtr
;
1898 NONCLIENTMETRICSA nclm
;
1902 /* allocate memory for info structure */
1903 infoPtr
= (TOOLTIPS_INFO
*)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO
));
1904 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1906 /* initialize info structure */
1907 infoPtr
->bActive
= TRUE
;
1908 infoPtr
->bTrackActive
= FALSE
;
1909 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1910 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
1912 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
1913 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
1914 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
1916 infoPtr
->nMaxTipWidth
= -1;
1917 infoPtr
->nTool
= -1;
1918 infoPtr
->nCurrentTool
= -1;
1919 infoPtr
->nTrackTool
= -1;
1921 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
1923 hParent
= GetParent(hwnd
);
1925 nResult
= (INT
) SendMessageA (hParent
, WM_NOTIFYFORMAT
,
1926 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1927 if (nResult
== NFR_ANSI
) {
1928 infoPtr
->bNotifyUnicode
= FALSE
;
1929 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1931 else if (nResult
== NFR_UNICODE
) {
1932 infoPtr
->bNotifyUnicode
= TRUE
;
1933 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1936 ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1940 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
1947 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1949 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1950 TTTOOL_INFO
*toolPtr
;
1954 if (infoPtr
->tools
) {
1955 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
1956 toolPtr
= &infoPtr
->tools
[i
];
1957 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
1958 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
1959 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
1961 COMCTL32_Free (toolPtr
->lpszText
);
1962 toolPtr
->lpszText
= NULL
;
1966 /* remove subclassing */
1967 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
1968 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
1969 RemoveWindowSubclass(toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
1972 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
1976 COMCTL32_Free (infoPtr
->tools
);
1980 DeleteObject (infoPtr
->hFont
);
1982 /* free tool tips info data */
1983 COMCTL32_Free (infoPtr
);
1984 SetWindowLongA(hwnd
, 0, 0);
1990 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1992 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1996 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
1997 GetClientRect (hwnd
, &rect
);
1998 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1999 DeleteObject (hBrush
);
2006 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2008 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2010 return infoPtr
->hFont
;
2015 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2017 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2019 TOOLTIPS_Hide (hwnd
, infoPtr
);
2026 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2028 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2029 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2031 dwStyle
&= 0x0000FFFF;
2032 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2033 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2035 dwExStyle
|= WS_EX_TOOLWINDOW
;
2036 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2043 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2045 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2046 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2048 TRACE(" nTool=%d\n", nTool
);
2050 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2051 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2052 TRACE("-- in transparent mode!\n");
2053 return HTTRANSPARENT
;
2057 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2062 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2064 FIXME ("hwnd=%x wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2071 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2076 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2077 TOOLTIPS_Refresh (hwnd
, hdc
);
2079 EndPaint (hwnd
, &ps
);
2085 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2087 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2090 if(!GetObjectW((HFONT
)wParam
, sizeof lf
, &lf
))
2092 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2094 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2095 FIXME("full redraw needed!\n");
2100 /******************************************************************
2101 * TOOLTIPS_OnWMGetTextLength
2103 * This function is called when the tooltip receive a
2104 * WM_GETTEXTLENGTH message.
2108 * returns the length, in characters, of the tip text
2109 ******************************************************************/
2111 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2113 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2114 return lstrlenW(infoPtr
->szTipText
);
2117 /******************************************************************
2118 * TOOLTIPS_OnWMGetText
2120 * This function is called when the tooltip receive a
2121 * WM_GETTEXT message.
2122 * wParam : specifies the maximum number of characters to be copied
2123 * lParam : is the pointer to the buffer that will receive
2126 * returns the number of characters copied
2127 ******************************************************************/
2129 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2131 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2133 if(!infoPtr
|| !(infoPtr
->szTipText
))
2136 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2137 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2141 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2143 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2146 TRACE("timer %d (%x) expired!\n", wParam
, hwnd
);
2150 KillTimer (hwnd
, ID_TIMERSHOW
);
2151 nOldTool
= infoPtr
->nTool
;
2152 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2153 TOOLTIPS_Show (hwnd
, infoPtr
);
2157 TOOLTIPS_Hide (hwnd
, infoPtr
);
2161 nOldTool
= infoPtr
->nTool
;
2162 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2163 TRACE("tool (%x) %d %d %d\n", hwnd
, nOldTool
,
2164 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2165 if (infoPtr
->nTool
!= nOldTool
) {
2166 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2167 TOOLTIPS_Hide(hwnd
, infoPtr
);
2168 KillTimer(hwnd
, ID_TIMERLEAVE
);
2169 } else if (nOldTool
== -1) { /* Moved from outside */
2170 ERR("How did this happen?\n");
2171 } else { /* Moved from one to another */
2172 TOOLTIPS_Hide (hwnd
, infoPtr
);
2173 KillTimer(hwnd
, ID_TIMERLEAVE
);
2174 if(infoPtr
->bActive
) {
2175 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2176 TRACE("timer 1 started!\n");
2183 ERR("Unknown timer id %d\n", wParam
);
2191 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2193 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2194 NONCLIENTMETRICSA nclm
;
2196 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2197 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2199 DeleteObject (infoPtr
->hFont
);
2200 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2201 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2202 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2209 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uID
, DWORD_PTR dwRef
)
2215 case WM_LBUTTONDOWN
:
2217 case WM_MBUTTONDOWN
:
2219 case WM_RBUTTONDOWN
:
2223 msg
.wParam
= wParam
;
2224 msg
.lParam
= lParam
;
2225 TOOLTIPS_RelayEvent(dwRef
, 0, (LPARAM
)&msg
);
2231 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
2235 static LRESULT CALLBACK
2236 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2238 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2239 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2240 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2244 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2247 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2250 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2253 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2256 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2258 case TTM_ENUMTOOLSA
:
2259 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2261 case TTM_ENUMTOOLSW
:
2262 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2264 case TTM_GETBUBBLESIZE
:
2265 return TOOLTIPS_GetBubbleSize (hwnd
, wParam
, lParam
);
2267 case TTM_GETCURRENTTOOLA
:
2268 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2270 case TTM_GETCURRENTTOOLW
:
2271 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2273 case TTM_GETDELAYTIME
:
2274 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2277 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2279 case TTM_GETMAXTIPWIDTH
:
2280 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2283 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2286 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2288 case TTM_GETTIPBKCOLOR
:
2289 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2291 case TTM_GETTIPTEXTCOLOR
:
2292 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2294 case TTM_GETTOOLCOUNT
:
2295 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2297 case TTM_GETTOOLINFOA
:
2298 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2300 case TTM_GETTOOLINFOW
:
2301 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2304 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2307 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2309 case TTM_NEWTOOLRECTA
:
2310 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2312 case TTM_NEWTOOLRECTW
:
2313 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2316 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2318 case TTM_RELAYEVENT
:
2319 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2321 case TTM_SETDELAYTIME
:
2322 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2325 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2327 case TTM_SETMAXTIPWIDTH
:
2328 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2330 case TTM_SETTIPBKCOLOR
:
2331 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2333 case TTM_SETTIPTEXTCOLOR
:
2334 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2336 case TTM_SETTOOLINFOA
:
2337 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2339 case TTM_SETTOOLINFOW
:
2340 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2342 case TTM_TRACKACTIVATE
:
2343 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2345 case TTM_TRACKPOSITION
:
2346 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2349 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2351 case TTM_UPDATETIPTEXTA
:
2352 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2354 case TTM_UPDATETIPTEXTW
:
2355 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2357 case TTM_WINDOWFROMPOINT
:
2358 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2362 return TOOLTIPS_Create (hwnd
, wParam
, lParam
);
2365 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2368 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2371 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2374 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2376 case WM_GETTEXTLENGTH
:
2377 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2380 case WM_LBUTTONDOWN
:
2382 case WM_MBUTTONDOWN
:
2384 case WM_RBUTTONDOWN
:
2387 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2390 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2393 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2395 case WM_NOTIFYFORMAT
:
2396 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2399 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2402 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2405 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2407 case WM_WININICHANGE
:
2408 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2411 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2412 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2413 uMsg
, wParam
, lParam
);
2414 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2421 TOOLTIPS_Register (void)
2425 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2426 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2427 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2428 wndClass
.cbClsExtra
= 0;
2429 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2430 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
2431 wndClass
.hbrBackground
= 0;
2432 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2434 RegisterClassA (&wndClass
);
2439 TOOLTIPS_Unregister (void)
2441 UnregisterClassA (TOOLTIPS_CLASSA
, (HINSTANCE
)NULL
);