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
);
88 } TT_SUBCLASS_INFO
, *LPTT_SUBCLASS_INFO
;
105 WCHAR szTipText
[INFOTIPSIZE
];
127 #define ID_TIMERSHOW 1 /* show delay timer */
128 #define ID_TIMERPOP 2 /* auto pop timer */
129 #define ID_TIMERLEAVE 3 /* tool leave timer */
132 extern LPSTR COMCTL32_aSubclass
; /* global subclassing atom */
134 /* property name of tooltip window handle */
135 /*#define TT_SUBCLASS_PROP "CC32SubclassInfo" */
137 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
141 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
145 TOOLTIPS_Refresh (HWND hwnd
, HDC hdc
)
147 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr(hwnd
);
152 UINT uFlags
= DT_EXTERNALLEADING
;
154 if (infoPtr
->nMaxTipWidth
> -1)
155 uFlags
|= DT_WORDBREAK
;
156 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
157 uFlags
|= DT_NOPREFIX
;
158 GetClientRect (hwnd
, &rc
);
160 /* fill the background */
161 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
162 FillRect (hdc
, &rc
, hBrush
);
163 DeleteObject (hBrush
);
165 /* calculate text rectangle */
166 rc
.left
+= (2 + infoPtr
->rcMargin
.left
);
167 rc
.top
+= (2 + infoPtr
->rcMargin
.top
);
168 rc
.right
-= (2 + infoPtr
->rcMargin
.right
);
169 rc
.bottom
-= (2 + infoPtr
->rcMargin
.bottom
);
172 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
173 SetTextColor (hdc
, infoPtr
->clrText
);
174 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
175 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
176 SelectObject (hdc
, hOldFont
);
177 if (oldBkMode
!= TRANSPARENT
)
178 SetBkMode (hdc
, oldBkMode
);
183 TOOLTIPS_GetTipText (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, INT nTool
)
185 TTTOOL_INFO
*toolPtr
= &infoPtr
->tools
[nTool
];
187 if (HIWORD((UINT
)toolPtr
->lpszText
) == 0) {
188 /* load a resource */
189 TRACE("load res string %x %x\n",
190 toolPtr
->hinst
, (int)toolPtr
->lpszText
);
191 LoadStringW (toolPtr
->hinst
, (UINT
)toolPtr
->lpszText
,
192 infoPtr
->szTipText
, INFOTIPSIZE
);
194 else if (toolPtr
->lpszText
) {
195 if (toolPtr
->lpszText
== LPSTR_TEXTCALLBACKW
) {
196 NMTTDISPINFOA ttnmdi
;
198 /* fill NMHDR struct */
199 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOA
));
200 ttnmdi
.hdr
.hwndFrom
= hwnd
;
201 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
202 ttnmdi
.hdr
.code
= TTN_GETDISPINFOA
;
203 ttnmdi
.lpszText
= (LPSTR
)&ttnmdi
.szText
;
204 ttnmdi
.uFlags
= toolPtr
->uFlags
;
205 ttnmdi
.lParam
= toolPtr
->lParam
;
207 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
208 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
209 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
211 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
212 LoadStringW (ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
213 infoPtr
->szTipText
, INFOTIPSIZE
);
214 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
215 toolPtr
->hinst
= ttnmdi
.hinst
;
216 toolPtr
->lpszText
= (LPWSTR
)ttnmdi
.lpszText
;
219 else if (ttnmdi
.szText
[0]) {
220 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
221 infoPtr
->szTipText
, INFOTIPSIZE
);
222 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
223 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
,
226 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
227 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
228 toolPtr
->lpszText
, len
);
231 else if (ttnmdi
.lpszText
== 0) {
232 /* no text available */
233 infoPtr
->szTipText
[0] = L
'\0';
235 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKA
) {
236 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
237 infoPtr
->szTipText
, INFOTIPSIZE
);
238 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
239 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
,
242 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
243 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
244 toolPtr
->lpszText
, len
);
248 ERR("recursive text callback!\n");
249 infoPtr
->szTipText
[0] = '\0';
253 /* the item is a usual (unicode) text */
254 lstrcpynW (infoPtr
->szTipText
, toolPtr
->lpszText
, INFOTIPSIZE
);
258 /* no text available */
259 infoPtr
->szTipText
[0] = L
'\0';
262 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
267 TOOLTIPS_CalcTipSize (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, LPSIZE lpSize
)
271 UINT uFlags
= DT_EXTERNALLEADING
| DT_CALCRECT
;
272 RECT rc
= {0, 0, 0, 0};
274 if (infoPtr
->nMaxTipWidth
> -1) {
275 rc
.right
= infoPtr
->nMaxTipWidth
;
276 uFlags
|= DT_WORDBREAK
;
278 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
279 uFlags
|= DT_NOPREFIX
;
280 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
283 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
284 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
285 SelectObject (hdc
, hOldFont
);
286 ReleaseDC (hwnd
, hdc
);
288 lpSize
->cx
= rc
.right
- rc
.left
+ 4 +
289 infoPtr
->rcMargin
.left
+ infoPtr
->rcMargin
.right
;
290 lpSize
->cy
= rc
.bottom
- rc
.top
+ 4 +
291 infoPtr
->rcMargin
.bottom
+ infoPtr
->rcMargin
.top
;
296 TOOLTIPS_Show (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
298 TTTOOL_INFO
*toolPtr
;
303 if (infoPtr
->nTool
== -1) {
304 TRACE("invalid tool (-1)!\n");
308 infoPtr
->nCurrentTool
= infoPtr
->nTool
;
310 TRACE("Show tooltip pre %d! (%04x)\n", infoPtr
->nTool
, hwnd
);
312 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nCurrentTool
);
314 if (infoPtr
->szTipText
[0] == L
'\0') {
315 infoPtr
->nCurrentTool
= -1;
319 TRACE("Show tooltip %d!\n", infoPtr
->nCurrentTool
);
320 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
323 hdr
.idFrom
= toolPtr
->uId
;
325 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
326 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
328 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
330 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
331 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
333 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
336 if (toolPtr
->uFlags
& TTF_IDISHWND
)
337 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
340 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rc
, 2);
342 rect
.left
= (rc
.left
+ rc
.right
- size
.cx
) / 2;
343 rect
.top
= rc
.bottom
+ 2;
346 GetCursorPos ((LPPOINT
)&rect
);
350 TRACE("pos %d - %d\n", rect
.left
, rect
.top
);
352 rect
.right
= rect
.left
+ size
.cx
;
353 rect
.bottom
= rect
.top
+ size
.cy
;
356 wndrect
.right
= GetSystemMetrics( SM_CXSCREEN
);
357 if( rect
.right
> wndrect
.right
) {
358 rect
.left
-= rect
.right
- wndrect
.right
+ 2;
359 rect
.right
= wndrect
.right
- 2;
361 wndrect
.bottom
= GetSystemMetrics( SM_CYSCREEN
);
362 if( rect
.bottom
> wndrect
.bottom
) {
365 if (toolPtr
->uFlags
& TTF_IDISHWND
)
366 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
369 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rc
, 2);
371 rect
.bottom
= rc
.top
- 2;
372 rect
.top
= rect
.bottom
- size
.cy
;
375 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
376 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
378 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
379 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
380 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
382 /* repaint the tooltip */
383 InvalidateRect(hwnd
, NULL
, TRUE
);
386 SetTimer (hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
387 TRACE("timer 2 started!\n");
388 SetTimer (hwnd
, ID_TIMERLEAVE
, infoPtr
->nReshowTime
, 0);
389 TRACE("timer 3 started!\n");
394 TOOLTIPS_Hide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
396 TTTOOL_INFO
*toolPtr
;
399 TRACE("Hide tooltip %d! (%04x)\n", infoPtr
->nCurrentTool
, hwnd
);
401 if (infoPtr
->nCurrentTool
== -1)
404 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
405 KillTimer (hwnd
, ID_TIMERPOP
);
408 hdr
.idFrom
= toolPtr
->uId
;
410 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
411 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
413 infoPtr
->nCurrentTool
= -1;
415 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
416 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
421 TOOLTIPS_TrackShow (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
423 TTTOOL_INFO
*toolPtr
;
428 if (infoPtr
->nTrackTool
== -1) {
429 TRACE("invalid tracking tool (-1)!\n");
433 TRACE("show tracking tooltip pre %d!\n", infoPtr
->nTrackTool
);
435 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nTrackTool
);
437 if (infoPtr
->szTipText
[0] == L
'\0') {
438 infoPtr
->nTrackTool
= -1;
442 TRACE("show tracking tooltip %d!\n", infoPtr
->nTrackTool
);
443 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
446 hdr
.idFrom
= toolPtr
->uId
;
448 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
449 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
451 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
453 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
454 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
456 if (toolPtr
->uFlags
& TTF_ABSOLUTE
) {
457 rect
.left
= infoPtr
->xTrackPos
;
458 rect
.top
= infoPtr
->yTrackPos
;
460 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
461 rect
.left
-= (size
.cx
/ 2);
462 rect
.top
-= (size
.cy
/ 2);
468 if (toolPtr
->uFlags
& TTF_IDISHWND
)
469 GetWindowRect ((HWND
)toolPtr
->uId
, &rcTool
);
471 rcTool
= toolPtr
->rect
;
472 MapWindowPoints (toolPtr
->hwnd
, (HWND
)0, (LPPOINT
)&rcTool
, 2);
475 GetCursorPos ((LPPOINT
)&rect
);
478 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
479 rect
.left
-= (size
.cx
/ 2);
480 rect
.top
-= (size
.cy
/ 2);
483 /* smart placement */
484 if ((rect
.left
+ size
.cx
> rcTool
.left
) && (rect
.left
< rcTool
.right
) &&
485 (rect
.top
+ size
.cy
> rcTool
.top
) && (rect
.top
< rcTool
.bottom
))
486 rect
.left
= rcTool
.right
;
489 TRACE("pos %d - %d\n", rect
.left
, rect
.top
);
491 rect
.right
= rect
.left
+ size
.cx
;
492 rect
.bottom
= rect
.top
+ size
.cy
;
494 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
495 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
497 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
498 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
499 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
501 InvalidateRect(hwnd
, NULL
, TRUE
);
507 TOOLTIPS_TrackHide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
509 TTTOOL_INFO
*toolPtr
;
512 if (infoPtr
->nTrackTool
== -1)
515 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
516 TRACE("hide tracking tooltip %d!\n", infoPtr
->nTrackTool
);
519 hdr
.idFrom
= toolPtr
->uId
;
521 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
522 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
524 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
525 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
530 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOA lpToolInfo
)
532 TTTOOL_INFO
*toolPtr
;
535 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
536 toolPtr
= &infoPtr
->tools
[nTool
];
538 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
539 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
540 (lpToolInfo
->uId
== toolPtr
->uId
))
544 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
545 toolPtr
= &infoPtr
->tools
[nTool
];
547 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
548 (lpToolInfo
->uId
== toolPtr
->uId
))
557 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOW lpToolInfo
)
559 TTTOOL_INFO
*toolPtr
;
562 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
563 toolPtr
= &infoPtr
->tools
[nTool
];
565 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
566 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
567 (lpToolInfo
->uId
== toolPtr
->uId
))
571 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
572 toolPtr
= &infoPtr
->tools
[nTool
];
574 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
575 (lpToolInfo
->uId
== toolPtr
->uId
))
584 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO
*infoPtr
, HWND hwnd
, LPPOINT lpPt
)
586 TTTOOL_INFO
*toolPtr
;
589 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
590 toolPtr
= &infoPtr
->tools
[nTool
];
592 if (!(toolPtr
->uFlags
& TTF_IDISHWND
)) {
593 if (hwnd
!= toolPtr
->hwnd
)
595 if (!PtInRect (&toolPtr
->rect
, *lpPt
))
601 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
602 toolPtr
= &infoPtr
->tools
[nTool
];
604 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
605 if ((HWND
)toolPtr
->uId
== hwnd
)
615 TOOLTIPS_IsWindowActive (HWND hwnd
)
617 HWND hwndActive
= GetActiveWindow ();
620 if (hwndActive
== hwnd
)
622 return IsChild (hwndActive
, hwnd
);
627 TOOLTIPS_CheckTool (HWND hwnd
, BOOL bShowTest
)
629 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
635 hwndTool
= (HWND
)SendMessageA (hwnd
, TTM_WINDOWFROMPOINT
, 0, (LPARAM
)&pt
);
639 ScreenToClient (hwndTool
, &pt
);
640 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, hwndTool
, &pt
);
644 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_ALWAYSTIP
) && bShowTest
) {
645 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd
, GW_OWNER
)))
649 TRACE("tool %d\n", nTool
);
656 TOOLTIPS_Activate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
658 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
660 infoPtr
->bActive
= (BOOL
)wParam
;
662 if (infoPtr
->bActive
)
663 TRACE("activate!\n");
665 if (!(infoPtr
->bActive
) && (infoPtr
->nCurrentTool
!= -1))
666 TOOLTIPS_Hide (hwnd
, infoPtr
);
673 TOOLTIPS_AddToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
675 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
676 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
677 TTTOOL_INFO
*toolPtr
;
679 if (lpToolInfo
== NULL
)
681 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
684 TRACE("add tool (%x) %x %d%s!\n",
685 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
686 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
688 if (infoPtr
->uNumTools
== 0) {
689 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
690 toolPtr
= infoPtr
->tools
;
693 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
695 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
696 memcpy (infoPtr
->tools
, oldTools
,
697 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
698 COMCTL32_Free (oldTools
);
699 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
702 infoPtr
->uNumTools
++;
705 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
706 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
707 toolPtr
->uId
= lpToolInfo
->uId
;
708 toolPtr
->rect
= lpToolInfo
->rect
;
709 toolPtr
->hinst
= lpToolInfo
->hinst
;
711 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
712 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
713 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
715 else if (lpToolInfo
->lpszText
) {
716 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
) {
717 TRACE("add CALLBACK!\n");
718 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
721 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
723 TRACE("add text \"%s\"!\n", lpToolInfo
->lpszText
);
724 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
725 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
726 toolPtr
->lpszText
, len
);
730 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
731 toolPtr
->lParam
= lpToolInfo
->lParam
;
733 /* install subclassing hook */
734 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
735 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
736 LPTT_SUBCLASS_INFO lpttsi
=
737 (LPTT_SUBCLASS_INFO
)GetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
738 if (lpttsi
== NULL
) {
740 (LPTT_SUBCLASS_INFO
)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO
));
742 (WNDPROC
)SetWindowLongA ((HWND
)toolPtr
->uId
,
743 GWL_WNDPROC
,(LONG
)TOOLTIPS_SubclassProc
);
744 lpttsi
->hwndToolTip
= hwnd
;
746 SetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
,
750 WARN("A window tool must only be listed once!\n");
753 LPTT_SUBCLASS_INFO lpttsi
=
754 (LPTT_SUBCLASS_INFO
)GetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
);
755 if (lpttsi
== NULL
) {
757 (LPTT_SUBCLASS_INFO
)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO
));
759 (WNDPROC
)SetWindowLongA (toolPtr
->hwnd
,
760 GWL_WNDPROC
,(LONG
)TOOLTIPS_SubclassProc
);
761 lpttsi
->hwndToolTip
= hwnd
;
763 SetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
, (HANDLE
)lpttsi
);
768 TRACE("subclassing installed!\n");
776 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
778 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
779 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
780 TTTOOL_INFO
*toolPtr
;
782 if (lpToolInfo
== NULL
)
784 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
787 TRACE("add tool (%x) %x %d%s!\n",
788 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
789 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
791 if (infoPtr
->uNumTools
== 0) {
792 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
793 toolPtr
= infoPtr
->tools
;
796 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
798 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
799 memcpy (infoPtr
->tools
, oldTools
,
800 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
801 COMCTL32_Free (oldTools
);
802 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
805 infoPtr
->uNumTools
++;
808 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
809 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
810 toolPtr
->uId
= lpToolInfo
->uId
;
811 toolPtr
->rect
= lpToolInfo
->rect
;
812 toolPtr
->hinst
= lpToolInfo
->hinst
;
814 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
815 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
816 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
818 else if (lpToolInfo
->lpszText
) {
819 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
820 TRACE("add CALLBACK!\n");
821 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
824 INT len
= lstrlenW (lpToolInfo
->lpszText
);
825 TRACE("add text %s!\n",
826 debugstr_w(lpToolInfo
->lpszText
));
827 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
828 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
832 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
833 toolPtr
->lParam
= lpToolInfo
->lParam
;
835 /* install subclassing hook */
836 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
837 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
838 LPTT_SUBCLASS_INFO lpttsi
=
839 (LPTT_SUBCLASS_INFO
)GetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
840 if (lpttsi
== NULL
) {
842 (LPTT_SUBCLASS_INFO
)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO
));
844 (WNDPROC
)SetWindowLongA ((HWND
)toolPtr
->uId
,
845 GWL_WNDPROC
,(LONG
)TOOLTIPS_SubclassProc
);
846 lpttsi
->hwndToolTip
= hwnd
;
848 SetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
,
852 WARN("A window tool must only be listed once!\n");
855 LPTT_SUBCLASS_INFO lpttsi
=
856 (LPTT_SUBCLASS_INFO
)GetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
);
857 if (lpttsi
== NULL
) {
859 (LPTT_SUBCLASS_INFO
)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO
));
861 (WNDPROC
)SetWindowLongA (toolPtr
->hwnd
,
862 GWL_WNDPROC
,(LONG
)TOOLTIPS_SubclassProc
);
863 lpttsi
->hwndToolTip
= hwnd
;
865 SetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
, (HANDLE
)lpttsi
);
870 TRACE("subclassing installed!\n");
878 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
880 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
881 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
882 TTTOOL_INFO
*toolPtr
;
885 if (lpToolInfo
== NULL
)
887 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
889 if (infoPtr
->uNumTools
== 0)
892 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
893 if (nTool
== -1) return 0;
895 TRACE("tool %d\n", nTool
);
897 /* make sure the tooltip has disappeared before deleting it */
898 TOOLTIPS_Hide(hwnd
, infoPtr
);
900 /* delete text string */
901 toolPtr
= &infoPtr
->tools
[nTool
];
902 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
903 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
904 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
905 COMCTL32_Free (toolPtr
->lpszText
);
908 /* remove subclassing */
909 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
910 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
911 LPTT_SUBCLASS_INFO lpttsi
=
912 (LPTT_SUBCLASS_INFO
)GetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
914 SetWindowLongA ((HWND
)toolPtr
->uId
, GWL_WNDPROC
,
915 (LONG
)lpttsi
->wpOrigProc
);
916 RemovePropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
917 COMCTL32_Free (lpttsi
);
920 ERR("Invalid data handle!\n");
923 LPTT_SUBCLASS_INFO lpttsi
=
924 (LPTT_SUBCLASS_INFO
)GetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
);
926 if (lpttsi
->uRefCount
== 1) {
927 SetWindowLongA ((HWND
)toolPtr
->hwnd
, GWL_WNDPROC
,
928 (LONG
)lpttsi
->wpOrigProc
);
929 RemovePropA ((HWND
)toolPtr
->hwnd
, COMCTL32_aSubclass
);
930 COMCTL32_Free (lpttsi
);
936 ERR("Invalid data handle!\n");
940 /* delete tool from tool list */
941 if (infoPtr
->uNumTools
== 1) {
942 COMCTL32_Free (infoPtr
->tools
);
943 infoPtr
->tools
= NULL
;
946 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
948 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
951 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
952 nTool
* sizeof(TTTOOL_INFO
));
954 if (nTool
< infoPtr
->uNumTools
- 1)
955 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
956 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
958 COMCTL32_Free (oldTools
);
961 /* destroying tool that mouse was on on last relayed mouse move */
962 if (infoPtr
->nTool
== nTool
)
964 /* no current tool (0 means first tool) */
968 infoPtr
->uNumTools
--;
975 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
977 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
978 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
979 TTTOOL_INFO
*toolPtr
;
982 if (lpToolInfo
== NULL
)
984 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
986 if (infoPtr
->uNumTools
== 0)
989 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
990 if (nTool
== -1) return 0;
992 TRACE("tool %d\n", nTool
);
994 /* make sure the tooltip has disappeared before deleting it */
995 TOOLTIPS_Hide(hwnd
, infoPtr
);
997 /* delete text string */
998 toolPtr
= &infoPtr
->tools
[nTool
];
999 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
1000 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
1001 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
1002 COMCTL32_Free (toolPtr
->lpszText
);
1005 /* remove subclassing */
1006 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
1007 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
1008 LPTT_SUBCLASS_INFO lpttsi
=
1009 (LPTT_SUBCLASS_INFO
)GetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
1011 SetWindowLongA ((HWND
)toolPtr
->uId
, GWL_WNDPROC
,
1012 (LONG
)lpttsi
->wpOrigProc
);
1013 RemovePropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
1014 COMCTL32_Free (lpttsi
);
1017 ERR("Invalid data handle!\n");
1020 LPTT_SUBCLASS_INFO lpttsi
=
1021 (LPTT_SUBCLASS_INFO
)GetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
);
1023 if (lpttsi
->uRefCount
== 1) {
1024 SetWindowLongA ((HWND
)toolPtr
->hwnd
, GWL_WNDPROC
,
1025 (LONG
)lpttsi
->wpOrigProc
);
1026 RemovePropA ((HWND
)toolPtr
->hwnd
, COMCTL32_aSubclass
);
1027 COMCTL32_Free (lpttsi
);
1030 lpttsi
->uRefCount
--;
1033 ERR("Invalid data handle!\n");
1037 /* delete tool from tool list */
1038 if (infoPtr
->uNumTools
== 1) {
1039 COMCTL32_Free (infoPtr
->tools
);
1040 infoPtr
->tools
= NULL
;
1043 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
1045 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
1048 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
1049 nTool
* sizeof(TTTOOL_INFO
));
1051 if (nTool
< infoPtr
->uNumTools
- 1)
1052 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
1053 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
1055 COMCTL32_Free (oldTools
);
1058 /* destroying tool that mouse was on on last relayed mouse move */
1059 if (infoPtr
->nTool
== nTool
)
1061 /* no current tool (0 means first tool) */
1062 infoPtr
->nTool
= -1;
1065 infoPtr
->uNumTools
--;
1072 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1074 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1075 UINT uIndex
= (UINT
)wParam
;
1076 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1077 TTTOOL_INFO
*toolPtr
;
1079 if (lpToolInfo
== NULL
)
1081 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1083 if (uIndex
>= infoPtr
->uNumTools
)
1086 TRACE("index=%u\n", uIndex
);
1088 toolPtr
= &infoPtr
->tools
[uIndex
];
1090 /* copy tool data */
1091 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1092 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1093 lpToolInfo
->uId
= toolPtr
->uId
;
1094 lpToolInfo
->rect
= toolPtr
->rect
;
1095 lpToolInfo
->hinst
= toolPtr
->hinst
;
1096 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1097 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1099 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1100 lpToolInfo
->lParam
= toolPtr
->lParam
;
1107 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1109 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1110 UINT uIndex
= (UINT
)wParam
;
1111 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1112 TTTOOL_INFO
*toolPtr
;
1114 if (lpToolInfo
== NULL
)
1116 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1118 if (uIndex
>= infoPtr
->uNumTools
)
1121 TRACE("index=%u\n", uIndex
);
1123 toolPtr
= &infoPtr
->tools
[uIndex
];
1125 /* copy tool data */
1126 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1127 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1128 lpToolInfo
->uId
= toolPtr
->uId
;
1129 lpToolInfo
->rect
= toolPtr
->rect
;
1130 lpToolInfo
->hinst
= toolPtr
->hinst
;
1131 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1132 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1134 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1135 lpToolInfo
->lParam
= toolPtr
->lParam
;
1142 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1144 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1145 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1146 TTTOOL_INFO
*toolPtr
;
1148 if (lpToolInfo
== NULL
)
1150 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1154 if (infoPtr
->nCurrentTool
> -1) {
1155 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1157 /* copy tool data */
1158 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1159 lpToolInfo
->rect
= toolPtr
->rect
;
1160 lpToolInfo
->hinst
= toolPtr
->hinst
;
1161 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1162 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1164 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1165 lpToolInfo
->lParam
= toolPtr
->lParam
;
1173 return (infoPtr
->nCurrentTool
!= -1);
1180 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1182 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1183 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1184 TTTOOL_INFO
*toolPtr
;
1186 if (lpToolInfo
== NULL
)
1188 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1192 if (infoPtr
->nCurrentTool
> -1) {
1193 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1195 /* copy tool data */
1196 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1197 lpToolInfo
->rect
= toolPtr
->rect
;
1198 lpToolInfo
->hinst
= toolPtr
->hinst
;
1199 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1200 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1202 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1203 lpToolInfo
->lParam
= toolPtr
->lParam
;
1211 return (infoPtr
->nCurrentTool
!= -1);
1218 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1220 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1224 return infoPtr
->nReshowTime
;
1227 return infoPtr
->nAutoPopTime
;
1230 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1231 return infoPtr
->nInitialTime
;
1234 WARN("Invalid wParam %x\n", wParam
);
1243 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1245 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1246 LPRECT lpRect
= (LPRECT
)lParam
;
1248 lpRect
->left
= infoPtr
->rcMargin
.left
;
1249 lpRect
->right
= infoPtr
->rcMargin
.right
;
1250 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1251 lpRect
->top
= infoPtr
->rcMargin
.top
;
1257 inline static LRESULT
1258 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1260 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1262 return infoPtr
->nMaxTipWidth
;
1267 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1269 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1270 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1273 if (lpToolInfo
== NULL
)
1275 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1278 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1279 if (nTool
== -1) return 0;
1281 /* NB this API is broken, there is no way for the app to determine
1282 what size buffer it requires nor a way to specify how long the
1283 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1285 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1286 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1293 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1295 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1296 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1299 if (lpToolInfo
== NULL
)
1301 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1304 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1305 if (nTool
== -1) return 0;
1307 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1313 inline static LRESULT
1314 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1316 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1317 return infoPtr
->clrBk
;
1321 inline static LRESULT
1322 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1324 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1325 return infoPtr
->clrText
;
1329 inline static LRESULT
1330 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1332 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1333 return infoPtr
->uNumTools
;
1338 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1340 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1341 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1342 TTTOOL_INFO
*toolPtr
;
1345 if (lpToolInfo
== NULL
)
1347 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1349 if (infoPtr
->uNumTools
== 0)
1352 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1356 TRACE("tool %d\n", nTool
);
1358 toolPtr
= &infoPtr
->tools
[nTool
];
1360 /* copy tool data */
1361 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1362 lpToolInfo
->rect
= toolPtr
->rect
;
1363 lpToolInfo
->hinst
= toolPtr
->hinst
;
1364 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1365 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1367 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1368 lpToolInfo
->lParam
= toolPtr
->lParam
;
1375 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1377 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1378 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1379 TTTOOL_INFO
*toolPtr
;
1382 if (lpToolInfo
== NULL
)
1384 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1386 if (infoPtr
->uNumTools
== 0)
1389 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1393 TRACE("tool %d\n", nTool
);
1395 toolPtr
= &infoPtr
->tools
[nTool
];
1397 /* copy tool data */
1398 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1399 lpToolInfo
->rect
= toolPtr
->rect
;
1400 lpToolInfo
->hinst
= toolPtr
->hinst
;
1401 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1402 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1404 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1405 lpToolInfo
->lParam
= toolPtr
->lParam
;
1412 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1414 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1415 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1416 TTTOOL_INFO
*toolPtr
;
1422 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1426 TRACE("tool %d!\n", nTool
);
1428 /* copy tool data */
1429 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1430 toolPtr
= &infoPtr
->tools
[nTool
];
1432 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1433 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1434 lptthit
->ti
.uId
= toolPtr
->uId
;
1435 lptthit
->ti
.rect
= toolPtr
->rect
;
1436 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1437 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1438 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1439 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1447 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1449 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1450 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1451 TTTOOL_INFO
*toolPtr
;
1457 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1461 TRACE("tool %d!\n", nTool
);
1463 /* copy tool data */
1464 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1465 toolPtr
= &infoPtr
->tools
[nTool
];
1467 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1468 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1469 lptthit
->ti
.uId
= toolPtr
->uId
;
1470 lptthit
->ti
.rect
= toolPtr
->rect
;
1471 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1472 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1473 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1474 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1482 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1484 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1485 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1490 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1493 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1494 if (nTool
== -1) return 0;
1496 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1503 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1505 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1506 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1511 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1514 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1515 if (nTool
== -1) return 0;
1517 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1523 inline static LRESULT
1524 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1526 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1527 TOOLTIPS_Hide (hwnd
, infoPtr
);
1534 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1536 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1537 LPMSG lpMsg
= (LPMSG
)lParam
;
1542 ERR("lpMsg == NULL!\n");
1546 switch (lpMsg
->message
) {
1547 case WM_LBUTTONDOWN
:
1549 case WM_MBUTTONDOWN
:
1551 case WM_RBUTTONDOWN
:
1553 TOOLTIPS_Hide (hwnd
, infoPtr
);
1557 pt
.x
= LOWORD(lpMsg
->lParam
);
1558 pt
.y
= HIWORD(lpMsg
->lParam
);
1559 nOldTool
= infoPtr
->nTool
;
1560 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1562 TRACE("tool (%x) %d %d %d\n", hwnd
, nOldTool
,
1563 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1564 TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1566 if (infoPtr
->nTool
!= nOldTool
) {
1567 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1568 TOOLTIPS_Hide(hwnd
, infoPtr
);
1569 KillTimer(hwnd
, ID_TIMERLEAVE
);
1570 } else if (nOldTool
== -1) { /* Moved from outside */
1571 if(infoPtr
->bActive
) {
1572 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1573 TRACE("timer 1 started!\n");
1575 } else { /* Moved from one to another */
1576 TOOLTIPS_Hide (hwnd
, infoPtr
);
1577 KillTimer(hwnd
, ID_TIMERLEAVE
);
1578 if(infoPtr
->bActive
) {
1579 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1580 TRACE("timer 1 started!\n");
1583 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1584 KillTimer(hwnd
, ID_TIMERPOP
);
1585 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1586 TRACE("timer 2 restarted\n");
1596 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1598 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1599 INT nTime
= (INT
)LOWORD(lParam
);
1602 case TTDT_AUTOMATIC
:
1604 nTime
= GetDoubleClickTime();
1605 infoPtr
->nReshowTime
= nTime
/ 5;
1606 infoPtr
->nAutoPopTime
= nTime
* 10;
1607 infoPtr
->nInitialTime
= nTime
;
1612 nTime
= GetDoubleClickTime() / 5;
1613 infoPtr
->nReshowTime
= nTime
;
1618 nTime
= GetDoubleClickTime() * 10;
1619 infoPtr
->nAutoPopTime
= nTime
;
1624 nTime
= GetDoubleClickTime();
1625 infoPtr
->nInitialTime
= nTime
;
1629 WARN("Invalid wParam %x\n", wParam
);
1638 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1640 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1641 LPRECT lpRect
= (LPRECT
)lParam
;
1643 infoPtr
->rcMargin
.left
= lpRect
->left
;
1644 infoPtr
->rcMargin
.right
= lpRect
->right
;
1645 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1646 infoPtr
->rcMargin
.top
= lpRect
->top
;
1652 inline static LRESULT
1653 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1655 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1656 INT nTemp
= infoPtr
->nMaxTipWidth
;
1658 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1664 inline static LRESULT
1665 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1667 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1669 infoPtr
->clrBk
= (COLORREF
)wParam
;
1675 inline static LRESULT
1676 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1678 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1680 infoPtr
->clrText
= (COLORREF
)wParam
;
1687 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1689 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1690 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1691 TTTOOL_INFO
*toolPtr
;
1694 if (lpToolInfo
== NULL
)
1696 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1699 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1700 if (nTool
== -1) return 0;
1702 TRACE("tool %d\n", nTool
);
1704 toolPtr
= &infoPtr
->tools
[nTool
];
1706 /* copy tool data */
1707 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1708 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1709 toolPtr
->uId
= lpToolInfo
->uId
;
1710 toolPtr
->rect
= lpToolInfo
->rect
;
1711 toolPtr
->hinst
= lpToolInfo
->hinst
;
1713 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1714 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1715 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1717 else if (lpToolInfo
->lpszText
) {
1718 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1719 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1721 if ( (toolPtr
->lpszText
) &&
1722 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1723 COMCTL32_Free (toolPtr
->lpszText
);
1724 toolPtr
->lpszText
= NULL
;
1726 if (lpToolInfo
->lpszText
) {
1727 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1729 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1730 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1731 toolPtr
->lpszText
, len
);
1736 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1737 toolPtr
->lParam
= lpToolInfo
->lParam
;
1744 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1746 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1747 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1748 TTTOOL_INFO
*toolPtr
;
1751 if (lpToolInfo
== NULL
)
1753 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1756 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1757 if (nTool
== -1) return 0;
1759 TRACE("tool %d\n", nTool
);
1761 toolPtr
= &infoPtr
->tools
[nTool
];
1763 /* copy tool data */
1764 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1765 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1766 toolPtr
->uId
= lpToolInfo
->uId
;
1767 toolPtr
->rect
= lpToolInfo
->rect
;
1768 toolPtr
->hinst
= lpToolInfo
->hinst
;
1770 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1771 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1772 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1774 else if (lpToolInfo
->lpszText
) {
1775 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1776 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1778 if ( (toolPtr
->lpszText
) &&
1779 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1780 COMCTL32_Free (toolPtr
->lpszText
);
1781 toolPtr
->lpszText
= NULL
;
1783 if (lpToolInfo
->lpszText
) {
1784 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1785 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1786 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1791 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1792 toolPtr
->lParam
= lpToolInfo
->lParam
;
1799 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1801 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1802 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1804 if (lpToolInfo
== NULL
)
1806 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1811 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1812 if (infoPtr
->nTrackTool
!= -1) {
1813 TRACE("activated!\n");
1814 infoPtr
->bTrackActive
= TRUE
;
1815 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1820 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1822 infoPtr
->bTrackActive
= FALSE
;
1823 infoPtr
->nTrackTool
= -1;
1825 TRACE("deactivated!\n");
1833 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1835 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1837 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1838 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1840 if (infoPtr
->bTrackActive
) {
1842 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1844 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1852 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1854 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1856 if (infoPtr
->nCurrentTool
!= -1)
1857 UpdateWindow (hwnd
);
1864 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1866 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1867 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1868 TTTOOL_INFO
*toolPtr
;
1871 if (lpToolInfo
== NULL
)
1873 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1876 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1877 if (nTool
== -1) return 0;
1879 TRACE("tool %d\n", nTool
);
1881 toolPtr
= &infoPtr
->tools
[nTool
];
1883 /* copy tool text */
1884 toolPtr
->hinst
= lpToolInfo
->hinst
;
1886 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1887 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1889 else if (lpToolInfo
->lpszText
) {
1890 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1891 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1893 if ( (toolPtr
->lpszText
) &&
1894 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1895 COMCTL32_Free (toolPtr
->lpszText
);
1896 toolPtr
->lpszText
= NULL
;
1898 if (lpToolInfo
->lpszText
) {
1899 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1901 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1902 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1903 toolPtr
->lpszText
, len
);
1908 if(infoPtr
->nCurrentTool
== -1) return 0;
1910 if (infoPtr
->bActive
)
1911 TOOLTIPS_Show (hwnd
, infoPtr
);
1912 else if (infoPtr
->bTrackActive
)
1913 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1920 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1922 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1923 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1924 TTTOOL_INFO
*toolPtr
;
1927 if (lpToolInfo
== NULL
)
1929 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1932 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1936 TRACE("tool %d\n", nTool
);
1938 toolPtr
= &infoPtr
->tools
[nTool
];
1940 /* copy tool text */
1941 toolPtr
->hinst
= lpToolInfo
->hinst
;
1943 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1944 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1946 else if (lpToolInfo
->lpszText
) {
1947 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1948 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1950 if ( (toolPtr
->lpszText
) &&
1951 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1952 COMCTL32_Free (toolPtr
->lpszText
);
1953 toolPtr
->lpszText
= NULL
;
1955 if (lpToolInfo
->lpszText
) {
1956 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1957 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1958 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1963 if(infoPtr
->nCurrentTool
== -1) return 0;
1965 if (infoPtr
->bActive
)
1966 TOOLTIPS_Show (hwnd
, infoPtr
);
1967 else if (infoPtr
->bTrackActive
)
1968 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1975 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1977 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1983 TOOLTIPS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1985 TOOLTIPS_INFO
*infoPtr
;
1986 NONCLIENTMETRICSA nclm
;
1990 /* allocate memory for info structure */
1991 infoPtr
= (TOOLTIPS_INFO
*)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO
));
1992 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1994 /* initialize info structure */
1995 infoPtr
->bActive
= TRUE
;
1996 infoPtr
->bTrackActive
= FALSE
;
1997 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1998 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2000 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2001 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2002 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2004 infoPtr
->nMaxTipWidth
= -1;
2005 infoPtr
->nTool
= -1;
2006 infoPtr
->nCurrentTool
= -1;
2007 infoPtr
->nTrackTool
= -1;
2009 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
2011 hParent
= GetParent(hwnd
);
2013 nResult
= (INT
) SendMessageA (hParent
, WM_NOTIFYFORMAT
,
2014 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
2015 if (nResult
== NFR_ANSI
) {
2016 infoPtr
->bNotifyUnicode
= FALSE
;
2017 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
2019 else if (nResult
== NFR_UNICODE
) {
2020 infoPtr
->bNotifyUnicode
= TRUE
;
2021 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
2024 ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
2028 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
2035 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2037 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2038 TTTOOL_INFO
*toolPtr
;
2042 if (infoPtr
->tools
) {
2043 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
2044 toolPtr
= &infoPtr
->tools
[i
];
2045 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
2046 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
2047 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
2049 COMCTL32_Free (toolPtr
->lpszText
);
2050 toolPtr
->lpszText
= NULL
;
2054 /* remove subclassing */
2055 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
2056 LPTT_SUBCLASS_INFO lpttsi
;
2058 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
2059 lpttsi
= (LPTT_SUBCLASS_INFO
)GetPropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
2061 SetWindowLongA ((HWND
)toolPtr
->uId
, GWL_WNDPROC
,
2062 (LONG
)lpttsi
->wpOrigProc
);
2063 RemovePropA ((HWND
)toolPtr
->uId
, COMCTL32_aSubclass
);
2064 COMCTL32_Free (lpttsi
);
2068 lpttsi
= (LPTT_SUBCLASS_INFO
)GetPropA (toolPtr
->hwnd
, COMCTL32_aSubclass
);
2070 SetWindowLongA ((HWND
)toolPtr
->hwnd
, GWL_WNDPROC
,
2071 (LONG
)lpttsi
->wpOrigProc
);
2072 RemovePropA ((HWND
)toolPtr
->hwnd
, COMCTL32_aSubclass
);
2073 COMCTL32_Free (lpttsi
);
2078 COMCTL32_Free (infoPtr
->tools
);
2082 DeleteObject (infoPtr
->hFont
);
2084 /* free tool tips info data */
2085 COMCTL32_Free (infoPtr
);
2086 SetWindowLongA(hwnd
, 0, 0);
2092 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2094 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2098 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2099 GetClientRect (hwnd
, &rect
);
2100 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2101 DeleteObject (hBrush
);
2108 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2110 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2112 return infoPtr
->hFont
;
2117 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2119 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2121 TOOLTIPS_Hide (hwnd
, infoPtr
);
2128 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2130 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2131 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2133 dwStyle
&= 0x0000FFFF;
2134 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2135 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2137 dwExStyle
|= WS_EX_TOOLWINDOW
;
2138 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2145 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2147 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2148 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2150 TRACE(" nTool=%d\n", nTool
);
2152 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2153 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2154 TRACE("-- in transparent mode!\n");
2155 return HTTRANSPARENT
;
2159 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2164 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2166 FIXME ("hwnd=%x wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2173 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2178 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2179 TOOLTIPS_Refresh (hwnd
, hdc
);
2181 EndPaint (hwnd
, &ps
);
2187 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2189 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2192 if(!GetObjectW((HFONT
)wParam
, sizeof lf
, &lf
))
2194 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2196 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2197 FIXME("full redraw needed!\n");
2202 /******************************************************************
2203 * TOOLTIPS_OnWMGetTextLength
2205 * This function is called when the tooltip receive a
2206 * WM_GETTEXTLENGTH message.
2210 * returns the length, in characters, of the tip text
2211 ******************************************************************/
2213 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2215 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2216 return lstrlenW(infoPtr
->szTipText
);
2219 /******************************************************************
2220 * TOOLTIPS_OnWMGetText
2222 * This function is called when the tooltip receive a
2223 * WM_GETTEXT message.
2224 * wParam : specifies the maximum number of characters to be copied
2225 * lParam : is the pointer to the buffer that will receive
2228 * returns the number of characters copied
2229 ******************************************************************/
2231 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2233 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2235 if(!infoPtr
|| !(infoPtr
->szTipText
))
2238 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2239 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2243 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2245 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2248 TRACE("timer %d (%x) expired!\n", wParam
, hwnd
);
2252 KillTimer (hwnd
, ID_TIMERSHOW
);
2253 nOldTool
= infoPtr
->nTool
;
2254 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2255 TOOLTIPS_Show (hwnd
, infoPtr
);
2259 TOOLTIPS_Hide (hwnd
, infoPtr
);
2263 nOldTool
= infoPtr
->nTool
;
2264 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2265 TRACE("tool (%x) %d %d %d\n", hwnd
, nOldTool
,
2266 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2267 if (infoPtr
->nTool
!= nOldTool
) {
2268 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2269 TOOLTIPS_Hide(hwnd
, infoPtr
);
2270 KillTimer(hwnd
, ID_TIMERLEAVE
);
2271 } else if (nOldTool
== -1) { /* Moved from outside */
2272 ERR("How did this happen?\n");
2273 } else { /* Moved from one to another */
2274 TOOLTIPS_Hide (hwnd
, infoPtr
);
2275 KillTimer(hwnd
, ID_TIMERLEAVE
);
2276 if(infoPtr
->bActive
) {
2277 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2278 TRACE("timer 1 started!\n");
2285 ERR("Unknown timer id %d\n", wParam
);
2293 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2295 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2296 NONCLIENTMETRICSA nclm
;
2298 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2299 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2301 DeleteObject (infoPtr
->hFont
);
2302 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2303 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2304 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2311 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2313 LPTT_SUBCLASS_INFO lpttsi
=
2314 (LPTT_SUBCLASS_INFO
)GetPropA (hwnd
, COMCTL32_aSubclass
);
2319 case WM_LBUTTONDOWN
:
2321 case WM_MBUTTONDOWN
:
2323 case WM_RBUTTONDOWN
:
2327 msg
.wParam
= wParam
;
2328 msg
.lParam
= lParam
;
2329 TOOLTIPS_RelayEvent(lpttsi
->hwndToolTip
, 0, (LPARAM
)&msg
);
2335 return CallWindowProcA (lpttsi
->wpOrigProc
, hwnd
, uMsg
, wParam
, lParam
);
2339 static LRESULT CALLBACK
2340 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2342 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2343 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2344 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2348 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2351 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2354 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2357 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2360 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2362 case TTM_ENUMTOOLSA
:
2363 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2365 case TTM_ENUMTOOLSW
:
2366 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2368 case TTM_GETCURRENTTOOLA
:
2369 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2371 case TTM_GETCURRENTTOOLW
:
2372 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2374 case TTM_GETDELAYTIME
:
2375 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2378 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2380 case TTM_GETMAXTIPWIDTH
:
2381 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2384 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2387 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2389 case TTM_GETTIPBKCOLOR
:
2390 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2392 case TTM_GETTIPTEXTCOLOR
:
2393 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2395 case TTM_GETTOOLCOUNT
:
2396 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2398 case TTM_GETTOOLINFOA
:
2399 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2401 case TTM_GETTOOLINFOW
:
2402 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2405 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2408 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2410 case TTM_NEWTOOLRECTA
:
2411 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2413 case TTM_NEWTOOLRECTW
:
2414 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2417 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2419 case TTM_RELAYEVENT
:
2420 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2422 case TTM_SETDELAYTIME
:
2423 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2426 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2428 case TTM_SETMAXTIPWIDTH
:
2429 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2431 case TTM_SETTIPBKCOLOR
:
2432 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2434 case TTM_SETTIPTEXTCOLOR
:
2435 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2437 case TTM_SETTOOLINFOA
:
2438 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2440 case TTM_SETTOOLINFOW
:
2441 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2443 case TTM_TRACKACTIVATE
:
2444 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2446 case TTM_TRACKPOSITION
:
2447 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2450 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2452 case TTM_UPDATETIPTEXTA
:
2453 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2455 case TTM_UPDATETIPTEXTW
:
2456 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2458 case TTM_WINDOWFROMPOINT
:
2459 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2463 return TOOLTIPS_Create (hwnd
, wParam
, lParam
);
2466 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2469 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2472 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2475 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2477 case WM_GETTEXTLENGTH
:
2478 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2481 case WM_LBUTTONDOWN
:
2483 case WM_MBUTTONDOWN
:
2485 case WM_RBUTTONDOWN
:
2488 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2491 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2494 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2496 case WM_NOTIFYFORMAT
:
2497 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2500 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2503 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2506 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2508 case WM_WININICHANGE
:
2509 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2512 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2513 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2514 uMsg
, wParam
, lParam
);
2515 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2522 TOOLTIPS_Register (void)
2526 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2527 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2528 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2529 wndClass
.cbClsExtra
= 0;
2530 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2531 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
2532 wndClass
.hbrBackground
= 0;
2533 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2535 RegisterClassA (&wndClass
);
2540 TOOLTIPS_Unregister (void)
2542 UnregisterClassA (TOOLTIPS_CLASSA
, (HINSTANCE
)NULL
);