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 %p %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! (%p)\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! (%p)\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 (%p) %p %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((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
727 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
730 TRACE("subclassing installed!\n");
738 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
740 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
741 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
742 TTTOOL_INFO
*toolPtr
;
744 if (lpToolInfo
== NULL
)
746 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
749 TRACE("add tool (%p) %p %d%s!\n",
750 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
751 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
753 if (infoPtr
->uNumTools
== 0) {
754 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
755 toolPtr
= infoPtr
->tools
;
758 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
760 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
761 memcpy (infoPtr
->tools
, oldTools
,
762 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
763 COMCTL32_Free (oldTools
);
764 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
767 infoPtr
->uNumTools
++;
770 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
771 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
772 toolPtr
->uId
= lpToolInfo
->uId
;
773 toolPtr
->rect
= lpToolInfo
->rect
;
774 toolPtr
->hinst
= lpToolInfo
->hinst
;
776 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
777 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
778 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
780 else if (lpToolInfo
->lpszText
) {
781 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
782 TRACE("add CALLBACK!\n");
783 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
786 INT len
= lstrlenW (lpToolInfo
->lpszText
);
787 TRACE("add text %s!\n",
788 debugstr_w(lpToolInfo
->lpszText
));
789 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
790 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
794 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
795 toolPtr
->lParam
= lpToolInfo
->lParam
;
797 /* install subclassing hook */
798 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
799 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
800 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
804 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
807 TRACE("subclassing installed!\n");
815 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
817 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
818 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
819 TTTOOL_INFO
*toolPtr
;
822 if (lpToolInfo
== NULL
)
824 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
826 if (infoPtr
->uNumTools
== 0)
829 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
830 if (nTool
== -1) return 0;
832 TRACE("tool %d\n", nTool
);
834 /* make sure the tooltip has disappeared before deleting it */
835 TOOLTIPS_Hide(hwnd
, infoPtr
);
837 /* delete text string */
838 toolPtr
= &infoPtr
->tools
[nTool
];
839 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
840 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
841 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
842 COMCTL32_Free (toolPtr
->lpszText
);
845 /* remove subclassing */
846 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
847 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
848 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
851 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
855 /* delete tool from tool list */
856 if (infoPtr
->uNumTools
== 1) {
857 COMCTL32_Free (infoPtr
->tools
);
858 infoPtr
->tools
= NULL
;
861 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
863 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
866 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
867 nTool
* sizeof(TTTOOL_INFO
));
869 if (nTool
< infoPtr
->uNumTools
- 1)
870 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
871 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
873 COMCTL32_Free (oldTools
);
876 /* destroying tool that mouse was on on last relayed mouse move */
877 if (infoPtr
->nTool
== nTool
)
879 /* no current tool (0 means first tool) */
883 infoPtr
->uNumTools
--;
890 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
892 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
893 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
894 TTTOOL_INFO
*toolPtr
;
897 if (lpToolInfo
== NULL
)
899 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
901 if (infoPtr
->uNumTools
== 0)
904 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
905 if (nTool
== -1) return 0;
907 TRACE("tool %d\n", nTool
);
909 /* make sure the tooltip has disappeared before deleting it */
910 TOOLTIPS_Hide(hwnd
, infoPtr
);
912 /* delete text string */
913 toolPtr
= &infoPtr
->tools
[nTool
];
914 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
915 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
916 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
917 COMCTL32_Free (toolPtr
->lpszText
);
920 /* remove subclassing */
921 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
922 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
923 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
926 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
930 /* delete tool from tool list */
931 if (infoPtr
->uNumTools
== 1) {
932 COMCTL32_Free (infoPtr
->tools
);
933 infoPtr
->tools
= NULL
;
936 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
938 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
941 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
942 nTool
* sizeof(TTTOOL_INFO
));
944 if (nTool
< infoPtr
->uNumTools
- 1)
945 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
946 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
948 COMCTL32_Free (oldTools
);
951 /* destroying tool that mouse was on on last relayed mouse move */
952 if (infoPtr
->nTool
== nTool
)
954 /* no current tool (0 means first tool) */
958 infoPtr
->uNumTools
--;
965 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
967 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
968 UINT uIndex
= (UINT
)wParam
;
969 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
970 TTTOOL_INFO
*toolPtr
;
972 if (lpToolInfo
== NULL
)
974 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
976 if (uIndex
>= infoPtr
->uNumTools
)
979 TRACE("index=%u\n", uIndex
);
981 toolPtr
= &infoPtr
->tools
[uIndex
];
984 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
985 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
986 lpToolInfo
->uId
= toolPtr
->uId
;
987 lpToolInfo
->rect
= toolPtr
->rect
;
988 lpToolInfo
->hinst
= toolPtr
->hinst
;
989 /* lpToolInfo->lpszText = toolPtr->lpszText; */
990 lpToolInfo
->lpszText
= NULL
; /* FIXME */
992 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
993 lpToolInfo
->lParam
= toolPtr
->lParam
;
1000 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1002 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1003 UINT uIndex
= (UINT
)wParam
;
1004 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1005 TTTOOL_INFO
*toolPtr
;
1007 if (lpToolInfo
== NULL
)
1009 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1011 if (uIndex
>= infoPtr
->uNumTools
)
1014 TRACE("index=%u\n", uIndex
);
1016 toolPtr
= &infoPtr
->tools
[uIndex
];
1018 /* copy tool data */
1019 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1020 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1021 lpToolInfo
->uId
= toolPtr
->uId
;
1022 lpToolInfo
->rect
= toolPtr
->rect
;
1023 lpToolInfo
->hinst
= toolPtr
->hinst
;
1024 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1025 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1027 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1028 lpToolInfo
->lParam
= toolPtr
->lParam
;
1034 TOOLTIPS_GetBubbleSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1036 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1037 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1041 if (lpToolInfo
== NULL
)
1043 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1046 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1047 if (nTool
== -1) return 0;
1049 TRACE("tool %d\n", nTool
);
1051 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
1052 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
1054 return MAKELRESULT(size
.cx
, size
.cy
);
1058 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1060 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1061 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1062 TTTOOL_INFO
*toolPtr
;
1064 if (lpToolInfo
== NULL
)
1066 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1070 if (infoPtr
->nCurrentTool
> -1) {
1071 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1073 /* copy tool data */
1074 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1075 lpToolInfo
->rect
= toolPtr
->rect
;
1076 lpToolInfo
->hinst
= toolPtr
->hinst
;
1077 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1078 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1080 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1081 lpToolInfo
->lParam
= toolPtr
->lParam
;
1089 return (infoPtr
->nCurrentTool
!= -1);
1096 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1098 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1099 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1100 TTTOOL_INFO
*toolPtr
;
1102 if (lpToolInfo
== NULL
)
1104 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1108 if (infoPtr
->nCurrentTool
> -1) {
1109 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1111 /* copy tool data */
1112 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1113 lpToolInfo
->rect
= toolPtr
->rect
;
1114 lpToolInfo
->hinst
= toolPtr
->hinst
;
1115 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1116 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1118 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1119 lpToolInfo
->lParam
= toolPtr
->lParam
;
1127 return (infoPtr
->nCurrentTool
!= -1);
1134 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1136 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1140 return infoPtr
->nReshowTime
;
1143 return infoPtr
->nAutoPopTime
;
1146 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1147 return infoPtr
->nInitialTime
;
1150 WARN("Invalid wParam %x\n", wParam
);
1159 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1161 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1162 LPRECT lpRect
= (LPRECT
)lParam
;
1164 lpRect
->left
= infoPtr
->rcMargin
.left
;
1165 lpRect
->right
= infoPtr
->rcMargin
.right
;
1166 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1167 lpRect
->top
= infoPtr
->rcMargin
.top
;
1173 inline static LRESULT
1174 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1176 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1178 return infoPtr
->nMaxTipWidth
;
1183 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1185 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1186 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1189 if (lpToolInfo
== NULL
)
1191 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1194 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1195 if (nTool
== -1) return 0;
1197 /* NB this API is broken, there is no way for the app to determine
1198 what size buffer it requires nor a way to specify how long the
1199 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1201 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1202 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1209 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1211 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1212 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1215 if (lpToolInfo
== NULL
)
1217 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1220 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1221 if (nTool
== -1) return 0;
1223 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1229 inline static LRESULT
1230 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1232 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1233 return infoPtr
->clrBk
;
1237 inline static LRESULT
1238 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1240 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1241 return infoPtr
->clrText
;
1245 inline static LRESULT
1246 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1248 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1249 return infoPtr
->uNumTools
;
1254 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1256 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1257 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1258 TTTOOL_INFO
*toolPtr
;
1261 if (lpToolInfo
== NULL
)
1263 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1265 if (infoPtr
->uNumTools
== 0)
1268 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1272 TRACE("tool %d\n", nTool
);
1274 toolPtr
= &infoPtr
->tools
[nTool
];
1276 /* copy tool data */
1277 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1278 lpToolInfo
->rect
= toolPtr
->rect
;
1279 lpToolInfo
->hinst
= toolPtr
->hinst
;
1280 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1281 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1283 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1284 lpToolInfo
->lParam
= toolPtr
->lParam
;
1291 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1293 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1294 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1295 TTTOOL_INFO
*toolPtr
;
1298 if (lpToolInfo
== NULL
)
1300 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1302 if (infoPtr
->uNumTools
== 0)
1305 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1309 TRACE("tool %d\n", nTool
);
1311 toolPtr
= &infoPtr
->tools
[nTool
];
1313 /* copy tool data */
1314 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1315 lpToolInfo
->rect
= toolPtr
->rect
;
1316 lpToolInfo
->hinst
= toolPtr
->hinst
;
1317 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1318 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1320 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1321 lpToolInfo
->lParam
= toolPtr
->lParam
;
1328 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1330 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1331 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1332 TTTOOL_INFO
*toolPtr
;
1338 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1342 TRACE("tool %d!\n", nTool
);
1344 /* copy tool data */
1345 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1346 toolPtr
= &infoPtr
->tools
[nTool
];
1348 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1349 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1350 lptthit
->ti
.uId
= toolPtr
->uId
;
1351 lptthit
->ti
.rect
= toolPtr
->rect
;
1352 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1353 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1354 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1355 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1363 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1365 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1366 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1367 TTTOOL_INFO
*toolPtr
;
1373 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1377 TRACE("tool %d!\n", nTool
);
1379 /* copy tool data */
1380 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1381 toolPtr
= &infoPtr
->tools
[nTool
];
1383 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1384 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1385 lptthit
->ti
.uId
= toolPtr
->uId
;
1386 lptthit
->ti
.rect
= toolPtr
->rect
;
1387 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1388 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1389 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1390 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1398 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1400 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1401 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1406 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1409 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1410 if (nTool
== -1) return 0;
1412 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1419 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1421 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1422 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1427 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1430 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1431 if (nTool
== -1) return 0;
1433 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1439 inline static LRESULT
1440 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1442 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1443 TOOLTIPS_Hide (hwnd
, infoPtr
);
1450 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1452 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1453 LPMSG lpMsg
= (LPMSG
)lParam
;
1458 ERR("lpMsg == NULL!\n");
1462 switch (lpMsg
->message
) {
1463 case WM_LBUTTONDOWN
:
1465 case WM_MBUTTONDOWN
:
1467 case WM_RBUTTONDOWN
:
1469 TOOLTIPS_Hide (hwnd
, infoPtr
);
1473 pt
.x
= LOWORD(lpMsg
->lParam
);
1474 pt
.y
= HIWORD(lpMsg
->lParam
);
1475 nOldTool
= infoPtr
->nTool
;
1476 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1478 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
1479 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1480 TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1482 if (infoPtr
->nTool
!= nOldTool
) {
1483 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1484 TOOLTIPS_Hide(hwnd
, infoPtr
);
1485 KillTimer(hwnd
, ID_TIMERLEAVE
);
1486 } else if (nOldTool
== -1) { /* Moved from outside */
1487 if(infoPtr
->bActive
) {
1488 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1489 TRACE("timer 1 started!\n");
1491 } else { /* Moved from one to another */
1492 TOOLTIPS_Hide (hwnd
, infoPtr
);
1493 KillTimer(hwnd
, ID_TIMERLEAVE
);
1494 if(infoPtr
->bActive
) {
1495 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1496 TRACE("timer 1 started!\n");
1499 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1500 KillTimer(hwnd
, ID_TIMERPOP
);
1501 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1502 TRACE("timer 2 restarted\n");
1512 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1514 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1515 INT nTime
= (INT
)LOWORD(lParam
);
1518 case TTDT_AUTOMATIC
:
1520 nTime
= GetDoubleClickTime();
1521 infoPtr
->nReshowTime
= nTime
/ 5;
1522 infoPtr
->nAutoPopTime
= nTime
* 10;
1523 infoPtr
->nInitialTime
= nTime
;
1528 nTime
= GetDoubleClickTime() / 5;
1529 infoPtr
->nReshowTime
= nTime
;
1534 nTime
= GetDoubleClickTime() * 10;
1535 infoPtr
->nAutoPopTime
= nTime
;
1540 nTime
= GetDoubleClickTime();
1541 infoPtr
->nInitialTime
= nTime
;
1545 WARN("Invalid wParam %x\n", wParam
);
1554 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1556 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1557 LPRECT lpRect
= (LPRECT
)lParam
;
1559 infoPtr
->rcMargin
.left
= lpRect
->left
;
1560 infoPtr
->rcMargin
.right
= lpRect
->right
;
1561 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1562 infoPtr
->rcMargin
.top
= lpRect
->top
;
1568 inline static LRESULT
1569 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1571 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1572 INT nTemp
= infoPtr
->nMaxTipWidth
;
1574 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1580 inline static LRESULT
1581 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1583 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1585 infoPtr
->clrBk
= (COLORREF
)wParam
;
1591 inline static LRESULT
1592 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1594 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1596 infoPtr
->clrText
= (COLORREF
)wParam
;
1603 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1605 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1606 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1607 TTTOOL_INFO
*toolPtr
;
1610 if (lpToolInfo
== NULL
)
1612 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1615 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1616 if (nTool
== -1) return 0;
1618 TRACE("tool %d\n", nTool
);
1620 toolPtr
= &infoPtr
->tools
[nTool
];
1622 /* copy tool data */
1623 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1624 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1625 toolPtr
->uId
= lpToolInfo
->uId
;
1626 toolPtr
->rect
= lpToolInfo
->rect
;
1627 toolPtr
->hinst
= lpToolInfo
->hinst
;
1629 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1630 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1631 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1633 else if (lpToolInfo
->lpszText
) {
1634 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1635 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1637 if ( (toolPtr
->lpszText
) &&
1638 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1639 COMCTL32_Free (toolPtr
->lpszText
);
1640 toolPtr
->lpszText
= NULL
;
1642 if (lpToolInfo
->lpszText
) {
1643 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1645 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1646 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1647 toolPtr
->lpszText
, len
);
1652 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1653 toolPtr
->lParam
= lpToolInfo
->lParam
;
1660 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1662 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1663 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1664 TTTOOL_INFO
*toolPtr
;
1667 if (lpToolInfo
== NULL
)
1669 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1672 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1673 if (nTool
== -1) return 0;
1675 TRACE("tool %d\n", nTool
);
1677 toolPtr
= &infoPtr
->tools
[nTool
];
1679 /* copy tool data */
1680 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1681 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1682 toolPtr
->uId
= lpToolInfo
->uId
;
1683 toolPtr
->rect
= lpToolInfo
->rect
;
1684 toolPtr
->hinst
= lpToolInfo
->hinst
;
1686 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1687 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1688 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1690 else if (lpToolInfo
->lpszText
) {
1691 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1692 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1694 if ( (toolPtr
->lpszText
) &&
1695 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1696 COMCTL32_Free (toolPtr
->lpszText
);
1697 toolPtr
->lpszText
= NULL
;
1699 if (lpToolInfo
->lpszText
) {
1700 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1701 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1702 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1707 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1708 toolPtr
->lParam
= lpToolInfo
->lParam
;
1715 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1717 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1718 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1720 if (lpToolInfo
== NULL
)
1722 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1727 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1728 if (infoPtr
->nTrackTool
!= -1) {
1729 TRACE("activated!\n");
1730 infoPtr
->bTrackActive
= TRUE
;
1731 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1736 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1738 infoPtr
->bTrackActive
= FALSE
;
1739 infoPtr
->nTrackTool
= -1;
1741 TRACE("deactivated!\n");
1749 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1751 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1753 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1754 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1756 if (infoPtr
->bTrackActive
) {
1758 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1760 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1768 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1770 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1772 if (infoPtr
->nCurrentTool
!= -1)
1773 UpdateWindow (hwnd
);
1780 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1782 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1783 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1784 TTTOOL_INFO
*toolPtr
;
1787 if (lpToolInfo
== NULL
)
1789 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1792 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1793 if (nTool
== -1) return 0;
1795 TRACE("tool %d\n", nTool
);
1797 toolPtr
= &infoPtr
->tools
[nTool
];
1799 /* copy tool text */
1800 toolPtr
->hinst
= lpToolInfo
->hinst
;
1802 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1803 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1805 else if (lpToolInfo
->lpszText
) {
1806 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1807 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1809 if ( (toolPtr
->lpszText
) &&
1810 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1811 COMCTL32_Free (toolPtr
->lpszText
);
1812 toolPtr
->lpszText
= NULL
;
1814 if (lpToolInfo
->lpszText
) {
1815 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1817 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1818 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1819 toolPtr
->lpszText
, len
);
1824 if(infoPtr
->nCurrentTool
== -1) return 0;
1826 if (infoPtr
->bActive
)
1827 TOOLTIPS_Show (hwnd
, infoPtr
);
1828 else if (infoPtr
->bTrackActive
)
1829 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1836 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1838 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1839 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1840 TTTOOL_INFO
*toolPtr
;
1843 if (lpToolInfo
== NULL
)
1845 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1848 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1852 TRACE("tool %d\n", nTool
);
1854 toolPtr
= &infoPtr
->tools
[nTool
];
1856 /* copy tool text */
1857 toolPtr
->hinst
= lpToolInfo
->hinst
;
1859 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1860 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1862 else if (lpToolInfo
->lpszText
) {
1863 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1864 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1866 if ( (toolPtr
->lpszText
) &&
1867 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1868 COMCTL32_Free (toolPtr
->lpszText
);
1869 toolPtr
->lpszText
= NULL
;
1871 if (lpToolInfo
->lpszText
) {
1872 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1873 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1874 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1879 if(infoPtr
->nCurrentTool
== -1) return 0;
1881 if (infoPtr
->bActive
)
1882 TOOLTIPS_Show (hwnd
, infoPtr
);
1883 else if (infoPtr
->bTrackActive
)
1884 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1891 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1893 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1899 TOOLTIPS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1901 TOOLTIPS_INFO
*infoPtr
;
1902 NONCLIENTMETRICSA nclm
;
1906 /* allocate memory for info structure */
1907 infoPtr
= (TOOLTIPS_INFO
*)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO
));
1908 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1910 /* initialize info structure */
1911 infoPtr
->bActive
= TRUE
;
1912 infoPtr
->bTrackActive
= FALSE
;
1913 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1914 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
1916 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
1917 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
1918 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
1920 infoPtr
->nMaxTipWidth
= -1;
1921 infoPtr
->nTool
= -1;
1922 infoPtr
->nCurrentTool
= -1;
1923 infoPtr
->nTrackTool
= -1;
1925 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
1927 hParent
= GetParent(hwnd
);
1929 nResult
= (INT
) SendMessageA (hParent
, WM_NOTIFYFORMAT
,
1930 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1931 if (nResult
== NFR_ANSI
) {
1932 infoPtr
->bNotifyUnicode
= FALSE
;
1933 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1935 else if (nResult
== NFR_UNICODE
) {
1936 infoPtr
->bNotifyUnicode
= TRUE
;
1937 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1940 ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1944 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
1951 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1953 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1954 TTTOOL_INFO
*toolPtr
;
1958 if (infoPtr
->tools
) {
1959 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
1960 toolPtr
= &infoPtr
->tools
[i
];
1961 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
1962 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
1963 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
1965 COMCTL32_Free (toolPtr
->lpszText
);
1966 toolPtr
->lpszText
= NULL
;
1970 /* remove subclassing */
1971 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
1972 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
1973 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
1976 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
1980 COMCTL32_Free (infoPtr
->tools
);
1984 DeleteObject (infoPtr
->hFont
);
1986 /* free tool tips info data */
1987 COMCTL32_Free (infoPtr
);
1988 SetWindowLongA(hwnd
, 0, 0);
1994 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1996 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2000 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2001 GetClientRect (hwnd
, &rect
);
2002 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2003 DeleteObject (hBrush
);
2010 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2012 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2014 return (LRESULT
)infoPtr
->hFont
;
2019 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2021 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2023 TOOLTIPS_Hide (hwnd
, infoPtr
);
2030 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2032 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2033 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2035 dwStyle
&= 0x0000FFFF;
2036 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2037 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2039 dwExStyle
|= WS_EX_TOOLWINDOW
;
2040 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2047 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2049 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2050 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2052 TRACE(" nTool=%d\n", nTool
);
2054 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2055 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2056 TRACE("-- in transparent mode!\n");
2057 return HTTRANSPARENT
;
2061 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2066 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2068 FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2075 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2080 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2081 TOOLTIPS_Refresh (hwnd
, hdc
);
2083 EndPaint (hwnd
, &ps
);
2089 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2091 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2094 if(!GetObjectW((HFONT
)wParam
, sizeof lf
, &lf
))
2097 if(infoPtr
->hFont
) DeleteObject (infoPtr
->hFont
);
2098 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2100 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2101 FIXME("full redraw needed!\n");
2106 /******************************************************************
2107 * TOOLTIPS_OnWMGetTextLength
2109 * This function is called when the tooltip receive a
2110 * WM_GETTEXTLENGTH message.
2114 * returns the length, in characters, of the tip text
2115 ******************************************************************/
2117 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2119 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2120 return lstrlenW(infoPtr
->szTipText
);
2123 /******************************************************************
2124 * TOOLTIPS_OnWMGetText
2126 * This function is called when the tooltip receive a
2127 * WM_GETTEXT message.
2128 * wParam : specifies the maximum number of characters to be copied
2129 * lParam : is the pointer to the buffer that will receive
2132 * returns the number of characters copied
2133 ******************************************************************/
2135 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2137 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2139 if(!infoPtr
|| !(infoPtr
->szTipText
))
2142 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2143 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2147 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2149 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2152 TRACE("timer %d (%p) expired!\n", wParam
, hwnd
);
2156 KillTimer (hwnd
, ID_TIMERSHOW
);
2157 nOldTool
= infoPtr
->nTool
;
2158 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2159 TOOLTIPS_Show (hwnd
, infoPtr
);
2163 TOOLTIPS_Hide (hwnd
, infoPtr
);
2167 nOldTool
= infoPtr
->nTool
;
2168 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2169 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
2170 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2171 if (infoPtr
->nTool
!= nOldTool
) {
2172 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2173 TOOLTIPS_Hide(hwnd
, infoPtr
);
2174 KillTimer(hwnd
, ID_TIMERLEAVE
);
2175 } else if (nOldTool
== -1) { /* Moved from outside */
2176 ERR("How did this happen?\n");
2177 } else { /* Moved from one to another */
2178 TOOLTIPS_Hide (hwnd
, infoPtr
);
2179 KillTimer(hwnd
, ID_TIMERLEAVE
);
2180 if(infoPtr
->bActive
) {
2181 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2182 TRACE("timer 1 started!\n");
2189 ERR("Unknown timer id %d\n", wParam
);
2197 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2199 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2200 NONCLIENTMETRICSA nclm
;
2202 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2203 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2205 DeleteObject (infoPtr
->hFont
);
2206 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2207 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2208 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2215 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uID
, DWORD_PTR dwRef
)
2221 case WM_LBUTTONDOWN
:
2223 case WM_MBUTTONDOWN
:
2225 case WM_RBUTTONDOWN
:
2229 msg
.wParam
= wParam
;
2230 msg
.lParam
= lParam
;
2231 TOOLTIPS_RelayEvent((HWND
)dwRef
, 0, (LPARAM
)&msg
);
2237 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
2241 static LRESULT CALLBACK
2242 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2244 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2245 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2246 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2250 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2253 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2256 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2259 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2262 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2264 case TTM_ENUMTOOLSA
:
2265 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2267 case TTM_ENUMTOOLSW
:
2268 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2270 case TTM_GETBUBBLESIZE
:
2271 return TOOLTIPS_GetBubbleSize (hwnd
, wParam
, lParam
);
2273 case TTM_GETCURRENTTOOLA
:
2274 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2276 case TTM_GETCURRENTTOOLW
:
2277 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2279 case TTM_GETDELAYTIME
:
2280 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2283 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2285 case TTM_GETMAXTIPWIDTH
:
2286 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2289 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2292 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2294 case TTM_GETTIPBKCOLOR
:
2295 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2297 case TTM_GETTIPTEXTCOLOR
:
2298 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2300 case TTM_GETTOOLCOUNT
:
2301 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2303 case TTM_GETTOOLINFOA
:
2304 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2306 case TTM_GETTOOLINFOW
:
2307 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2310 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2313 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2315 case TTM_NEWTOOLRECTA
:
2316 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2318 case TTM_NEWTOOLRECTW
:
2319 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2322 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2324 case TTM_RELAYEVENT
:
2325 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2327 case TTM_SETDELAYTIME
:
2328 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2331 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2333 case TTM_SETMAXTIPWIDTH
:
2334 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2336 case TTM_SETTIPBKCOLOR
:
2337 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2339 case TTM_SETTIPTEXTCOLOR
:
2340 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2342 case TTM_SETTOOLINFOA
:
2343 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2345 case TTM_SETTOOLINFOW
:
2346 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2348 case TTM_TRACKACTIVATE
:
2349 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2351 case TTM_TRACKPOSITION
:
2352 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2355 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2357 case TTM_UPDATETIPTEXTA
:
2358 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2360 case TTM_UPDATETIPTEXTW
:
2361 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2363 case TTM_WINDOWFROMPOINT
:
2364 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2368 return TOOLTIPS_Create (hwnd
, wParam
, lParam
);
2371 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2374 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2377 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2380 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2382 case WM_GETTEXTLENGTH
:
2383 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2386 case WM_LBUTTONDOWN
:
2388 case WM_MBUTTONDOWN
:
2390 case WM_RBUTTONDOWN
:
2393 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2396 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2399 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2401 case WM_NOTIFYFORMAT
:
2402 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2405 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2408 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2411 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2413 case WM_WININICHANGE
:
2414 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2417 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2418 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2419 uMsg
, wParam
, lParam
);
2420 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2427 TOOLTIPS_Register (void)
2431 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2432 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2433 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2434 wndClass
.cbClsExtra
= 0;
2435 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2436 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
2437 wndClass
.hbrBackground
= 0;
2438 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2440 RegisterClassA (&wndClass
);
2445 TOOLTIPS_Unregister (void)
2447 UnregisterClassA (TOOLTIPS_CLASSA
, (HINSTANCE
)NULL
);