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
79 #include "wine/unicode.h"
84 #include "wine/debug.h"
86 WINE_DEFAULT_DEBUG_CHANNEL(tooltips
);
102 WCHAR szTipText
[INFOTIPSIZE
];
124 #define ID_TIMERSHOW 1 /* show delay timer */
125 #define ID_TIMERPOP 2 /* auto pop timer */
126 #define ID_TIMERLEAVE 3 /* tool leave timer */
129 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
133 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uId
, DWORD_PTR dwRef
);
137 TOOLTIPS_Refresh (HWND hwnd
, HDC hdc
)
139 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr(hwnd
);
144 UINT uFlags
= DT_EXTERNALLEADING
;
146 if (infoPtr
->nMaxTipWidth
> -1)
147 uFlags
|= DT_WORDBREAK
;
148 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
149 uFlags
|= DT_NOPREFIX
;
150 GetClientRect (hwnd
, &rc
);
152 /* fill the background */
153 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
154 FillRect (hdc
, &rc
, hBrush
);
155 DeleteObject (hBrush
);
157 /* calculate text rectangle */
158 rc
.left
+= (2 + infoPtr
->rcMargin
.left
);
159 rc
.top
+= (2 + infoPtr
->rcMargin
.top
);
160 rc
.right
-= (2 + infoPtr
->rcMargin
.right
);
161 rc
.bottom
-= (2 + infoPtr
->rcMargin
.bottom
);
164 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
165 SetTextColor (hdc
, infoPtr
->clrText
);
166 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
167 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
168 SelectObject (hdc
, hOldFont
);
169 if (oldBkMode
!= TRANSPARENT
)
170 SetBkMode (hdc
, oldBkMode
);
175 TOOLTIPS_GetTipText (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, INT nTool
)
177 TTTOOL_INFO
*toolPtr
= &infoPtr
->tools
[nTool
];
179 if (HIWORD((UINT
)toolPtr
->lpszText
) == 0) {
180 /* load a resource */
181 TRACE("load res string %p %x\n",
182 toolPtr
->hinst
, (int)toolPtr
->lpszText
);
183 LoadStringW (toolPtr
->hinst
, (UINT
)toolPtr
->lpszText
,
184 infoPtr
->szTipText
, INFOTIPSIZE
);
186 else if (toolPtr
->lpszText
) {
187 if (toolPtr
->lpszText
== LPSTR_TEXTCALLBACKW
) {
188 NMTTDISPINFOA ttnmdi
;
190 /* fill NMHDR struct */
191 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOA
));
192 ttnmdi
.hdr
.hwndFrom
= hwnd
;
193 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
194 ttnmdi
.hdr
.code
= TTN_GETDISPINFOA
;
195 ttnmdi
.lpszText
= (LPSTR
)&ttnmdi
.szText
;
196 ttnmdi
.uFlags
= toolPtr
->uFlags
;
197 ttnmdi
.lParam
= toolPtr
->lParam
;
199 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
200 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
201 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
203 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
204 LoadStringW (ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
205 infoPtr
->szTipText
, INFOTIPSIZE
);
206 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
207 toolPtr
->hinst
= ttnmdi
.hinst
;
208 toolPtr
->lpszText
= (LPWSTR
)ttnmdi
.lpszText
;
211 else if (ttnmdi
.szText
[0]) {
212 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
213 infoPtr
->szTipText
, INFOTIPSIZE
);
214 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
215 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
,
218 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
219 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
220 toolPtr
->lpszText
, len
);
223 else if (ttnmdi
.lpszText
== 0) {
224 /* no text available */
225 infoPtr
->szTipText
[0] = L
'\0';
227 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKA
) {
228 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
229 infoPtr
->szTipText
, INFOTIPSIZE
);
230 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
231 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
,
234 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
235 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
236 toolPtr
->lpszText
, len
);
240 ERR("recursive text callback!\n");
241 infoPtr
->szTipText
[0] = '\0';
245 /* the item is a usual (unicode) text */
246 lstrcpynW (infoPtr
->szTipText
, toolPtr
->lpszText
, INFOTIPSIZE
);
250 /* no text available */
251 infoPtr
->szTipText
[0] = L
'\0';
254 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
259 TOOLTIPS_CalcTipSize (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, LPSIZE lpSize
)
263 UINT uFlags
= DT_EXTERNALLEADING
| DT_CALCRECT
;
264 RECT rc
= {0, 0, 0, 0};
266 if (infoPtr
->nMaxTipWidth
> -1) {
267 rc
.right
= infoPtr
->nMaxTipWidth
;
268 uFlags
|= DT_WORDBREAK
;
270 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
271 uFlags
|= DT_NOPREFIX
;
272 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
275 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
276 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
277 SelectObject (hdc
, hOldFont
);
278 ReleaseDC (hwnd
, hdc
);
280 lpSize
->cx
= rc
.right
- rc
.left
+ 4 +
281 infoPtr
->rcMargin
.left
+ infoPtr
->rcMargin
.right
;
282 lpSize
->cy
= rc
.bottom
- rc
.top
+ 4 +
283 infoPtr
->rcMargin
.bottom
+ infoPtr
->rcMargin
.top
;
288 TOOLTIPS_Show (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
290 TTTOOL_INFO
*toolPtr
;
295 if (infoPtr
->nTool
== -1) {
296 TRACE("invalid tool (-1)!\n");
300 infoPtr
->nCurrentTool
= infoPtr
->nTool
;
302 TRACE("Show tooltip pre %d! (%p)\n", infoPtr
->nTool
, hwnd
);
304 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nCurrentTool
);
306 if (infoPtr
->szTipText
[0] == L
'\0') {
307 infoPtr
->nCurrentTool
= -1;
311 TRACE("Show tooltip %d!\n", infoPtr
->nCurrentTool
);
312 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
315 hdr
.idFrom
= toolPtr
->uId
;
317 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
318 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
320 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
322 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
323 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
325 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
328 if (toolPtr
->uFlags
& TTF_IDISHWND
)
329 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
332 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
334 rect
.left
= (rc
.left
+ rc
.right
- size
.cx
) / 2;
335 rect
.top
= rc
.bottom
+ 2;
338 GetCursorPos ((LPPOINT
)&rect
);
342 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
344 rect
.right
= rect
.left
+ size
.cx
;
345 rect
.bottom
= rect
.top
+ size
.cy
;
348 wndrect
.right
= GetSystemMetrics( SM_CXSCREEN
);
349 if( rect
.right
> wndrect
.right
) {
350 rect
.left
-= rect
.right
- wndrect
.right
+ 2;
351 rect
.right
= wndrect
.right
- 2;
353 wndrect
.bottom
= GetSystemMetrics( SM_CYSCREEN
);
354 if( rect
.bottom
> wndrect
.bottom
) {
357 if (toolPtr
->uFlags
& TTF_IDISHWND
)
358 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
361 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
363 rect
.bottom
= rc
.top
- 2;
364 rect
.top
= rect
.bottom
- size
.cy
;
367 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
368 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
370 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
371 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
372 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
374 /* repaint the tooltip */
375 InvalidateRect(hwnd
, NULL
, TRUE
);
378 SetTimer (hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
379 TRACE("timer 2 started!\n");
380 SetTimer (hwnd
, ID_TIMERLEAVE
, infoPtr
->nReshowTime
, 0);
381 TRACE("timer 3 started!\n");
386 TOOLTIPS_Hide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
388 TTTOOL_INFO
*toolPtr
;
391 TRACE("Hide tooltip %d! (%p)\n", infoPtr
->nCurrentTool
, hwnd
);
393 if (infoPtr
->nCurrentTool
== -1)
396 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
397 KillTimer (hwnd
, ID_TIMERPOP
);
400 hdr
.idFrom
= toolPtr
->uId
;
402 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
403 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
405 infoPtr
->nCurrentTool
= -1;
407 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
408 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
413 TOOLTIPS_TrackShow (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
415 TTTOOL_INFO
*toolPtr
;
420 if (infoPtr
->nTrackTool
== -1) {
421 TRACE("invalid tracking tool (-1)!\n");
425 TRACE("show tracking tooltip pre %d!\n", infoPtr
->nTrackTool
);
427 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nTrackTool
);
429 if (infoPtr
->szTipText
[0] == L
'\0') {
430 infoPtr
->nTrackTool
= -1;
434 TRACE("show tracking tooltip %d!\n", infoPtr
->nTrackTool
);
435 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
438 hdr
.idFrom
= toolPtr
->uId
;
440 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
441 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
443 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
445 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
446 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
448 if (toolPtr
->uFlags
& TTF_ABSOLUTE
) {
449 rect
.left
= infoPtr
->xTrackPos
;
450 rect
.top
= infoPtr
->yTrackPos
;
452 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
453 rect
.left
-= (size
.cx
/ 2);
454 rect
.top
-= (size
.cy
/ 2);
460 if (toolPtr
->uFlags
& TTF_IDISHWND
)
461 GetWindowRect ((HWND
)toolPtr
->uId
, &rcTool
);
463 rcTool
= toolPtr
->rect
;
464 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rcTool
, 2);
467 GetCursorPos ((LPPOINT
)&rect
);
470 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
471 rect
.left
-= (size
.cx
/ 2);
472 rect
.top
-= (size
.cy
/ 2);
475 /* smart placement */
476 if ((rect
.left
+ size
.cx
> rcTool
.left
) && (rect
.left
< rcTool
.right
) &&
477 (rect
.top
+ size
.cy
> rcTool
.top
) && (rect
.top
< rcTool
.bottom
))
478 rect
.left
= rcTool
.right
;
481 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
483 rect
.right
= rect
.left
+ size
.cx
;
484 rect
.bottom
= rect
.top
+ size
.cy
;
486 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
487 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
489 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
490 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
491 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
493 InvalidateRect(hwnd
, NULL
, TRUE
);
499 TOOLTIPS_TrackHide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
501 TTTOOL_INFO
*toolPtr
;
504 if (infoPtr
->nTrackTool
== -1)
507 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
508 TRACE("hide tracking tooltip %d!\n", infoPtr
->nTrackTool
);
511 hdr
.idFrom
= toolPtr
->uId
;
513 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
514 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
516 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
517 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
522 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOA lpToolInfo
)
524 TTTOOL_INFO
*toolPtr
;
527 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
528 toolPtr
= &infoPtr
->tools
[nTool
];
530 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
531 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
532 (lpToolInfo
->uId
== toolPtr
->uId
))
536 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
537 toolPtr
= &infoPtr
->tools
[nTool
];
539 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
540 (lpToolInfo
->uId
== toolPtr
->uId
))
549 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOW lpToolInfo
)
551 TTTOOL_INFO
*toolPtr
;
554 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
555 toolPtr
= &infoPtr
->tools
[nTool
];
557 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
558 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
559 (lpToolInfo
->uId
== toolPtr
->uId
))
563 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
564 toolPtr
= &infoPtr
->tools
[nTool
];
566 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
567 (lpToolInfo
->uId
== toolPtr
->uId
))
576 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO
*infoPtr
, HWND hwnd
, LPPOINT lpPt
)
578 TTTOOL_INFO
*toolPtr
;
581 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
582 toolPtr
= &infoPtr
->tools
[nTool
];
584 if (!(toolPtr
->uFlags
& TTF_IDISHWND
)) {
585 if (hwnd
!= toolPtr
->hwnd
)
587 if (!PtInRect (&toolPtr
->rect
, *lpPt
))
593 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
594 toolPtr
= &infoPtr
->tools
[nTool
];
596 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
597 if ((HWND
)toolPtr
->uId
== hwnd
)
607 TOOLTIPS_IsWindowActive (HWND hwnd
)
609 HWND hwndActive
= GetActiveWindow ();
612 if (hwndActive
== hwnd
)
614 return IsChild (hwndActive
, hwnd
);
619 TOOLTIPS_CheckTool (HWND hwnd
, BOOL bShowTest
)
621 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
627 hwndTool
= (HWND
)SendMessageA (hwnd
, TTM_WINDOWFROMPOINT
, 0, (LPARAM
)&pt
);
631 ScreenToClient (hwndTool
, &pt
);
632 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, hwndTool
, &pt
);
636 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_ALWAYSTIP
) && bShowTest
) {
637 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd
, GW_OWNER
)))
641 TRACE("tool %d\n", nTool
);
648 TOOLTIPS_Activate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
650 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
652 infoPtr
->bActive
= (BOOL
)wParam
;
654 if (infoPtr
->bActive
)
655 TRACE("activate!\n");
657 if (!(infoPtr
->bActive
) && (infoPtr
->nCurrentTool
!= -1))
658 TOOLTIPS_Hide (hwnd
, infoPtr
);
665 TOOLTIPS_AddToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
667 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
668 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
669 TTTOOL_INFO
*toolPtr
;
671 if (lpToolInfo
== NULL
)
673 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
676 TRACE("add tool (%p) %p %d%s!\n",
677 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
678 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
680 if (infoPtr
->uNumTools
== 0) {
681 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
682 toolPtr
= infoPtr
->tools
;
685 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
687 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
688 memcpy (infoPtr
->tools
, oldTools
,
689 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
690 COMCTL32_Free (oldTools
);
691 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
694 infoPtr
->uNumTools
++;
697 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
698 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
699 toolPtr
->uId
= lpToolInfo
->uId
;
700 toolPtr
->rect
= lpToolInfo
->rect
;
701 toolPtr
->hinst
= lpToolInfo
->hinst
;
703 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
704 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
705 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
707 else if (lpToolInfo
->lpszText
) {
708 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
) {
709 TRACE("add CALLBACK!\n");
710 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
713 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
715 TRACE("add text \"%s\"!\n", lpToolInfo
->lpszText
);
716 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
717 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
718 toolPtr
->lpszText
, len
);
722 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
723 toolPtr
->lParam
= lpToolInfo
->lParam
;
725 /* install subclassing hook */
726 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
727 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
728 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
732 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
735 TRACE("subclassing installed!\n");
743 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
745 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
746 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
747 TTTOOL_INFO
*toolPtr
;
749 if (lpToolInfo
== NULL
)
751 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
754 TRACE("add tool (%p) %p %d%s!\n",
755 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
756 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
758 if (infoPtr
->uNumTools
== 0) {
759 infoPtr
->tools
= COMCTL32_Alloc (sizeof(TTTOOL_INFO
));
760 toolPtr
= infoPtr
->tools
;
763 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
765 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
766 memcpy (infoPtr
->tools
, oldTools
,
767 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
768 COMCTL32_Free (oldTools
);
769 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
772 infoPtr
->uNumTools
++;
775 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
776 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
777 toolPtr
->uId
= lpToolInfo
->uId
;
778 toolPtr
->rect
= lpToolInfo
->rect
;
779 toolPtr
->hinst
= lpToolInfo
->hinst
;
781 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
782 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
783 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
785 else if (lpToolInfo
->lpszText
) {
786 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
787 TRACE("add CALLBACK!\n");
788 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
791 INT len
= lstrlenW (lpToolInfo
->lpszText
);
792 TRACE("add text %s!\n",
793 debugstr_w(lpToolInfo
->lpszText
));
794 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+ 1)*sizeof(WCHAR
));
795 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
799 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
800 toolPtr
->lParam
= lpToolInfo
->lParam
;
802 /* install subclassing hook */
803 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
804 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
805 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
809 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
812 TRACE("subclassing installed!\n");
820 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
822 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
823 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
824 TTTOOL_INFO
*toolPtr
;
827 if (lpToolInfo
== NULL
)
829 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
831 if (infoPtr
->uNumTools
== 0)
834 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
835 if (nTool
== -1) return 0;
837 TRACE("tool %d\n", nTool
);
839 /* make sure the tooltip has disappeared before deleting it */
840 TOOLTIPS_Hide(hwnd
, infoPtr
);
842 /* delete text string */
843 toolPtr
= &infoPtr
->tools
[nTool
];
844 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
845 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
846 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
847 COMCTL32_Free (toolPtr
->lpszText
);
850 /* remove subclassing */
851 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
852 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
853 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
856 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
860 /* delete tool from tool list */
861 if (infoPtr
->uNumTools
== 1) {
862 COMCTL32_Free (infoPtr
->tools
);
863 infoPtr
->tools
= NULL
;
866 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
868 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
871 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
872 nTool
* sizeof(TTTOOL_INFO
));
874 if (nTool
< infoPtr
->uNumTools
- 1)
875 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
876 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
878 COMCTL32_Free (oldTools
);
881 /* destroying tool that mouse was on on last relayed mouse move */
882 if (infoPtr
->nTool
== nTool
)
884 /* no current tool (0 means first tool) */
888 infoPtr
->uNumTools
--;
895 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
897 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
898 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
899 TTTOOL_INFO
*toolPtr
;
902 if (lpToolInfo
== NULL
)
904 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
906 if (infoPtr
->uNumTools
== 0)
909 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
910 if (nTool
== -1) return 0;
912 TRACE("tool %d\n", nTool
);
914 /* make sure the tooltip has disappeared before deleting it */
915 TOOLTIPS_Hide(hwnd
, infoPtr
);
917 /* delete text string */
918 toolPtr
= &infoPtr
->tools
[nTool
];
919 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
920 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
921 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
922 COMCTL32_Free (toolPtr
->lpszText
);
925 /* remove subclassing */
926 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
927 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
928 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
931 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
935 /* delete tool from tool list */
936 if (infoPtr
->uNumTools
== 1) {
937 COMCTL32_Free (infoPtr
->tools
);
938 infoPtr
->tools
= NULL
;
941 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
943 COMCTL32_Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
946 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
947 nTool
* sizeof(TTTOOL_INFO
));
949 if (nTool
< infoPtr
->uNumTools
- 1)
950 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
951 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
953 COMCTL32_Free (oldTools
);
956 /* destroying tool that mouse was on on last relayed mouse move */
957 if (infoPtr
->nTool
== nTool
)
959 /* no current tool (0 means first tool) */
963 infoPtr
->uNumTools
--;
970 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
972 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
973 UINT uIndex
= (UINT
)wParam
;
974 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
975 TTTOOL_INFO
*toolPtr
;
977 if (lpToolInfo
== NULL
)
979 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
981 if (uIndex
>= infoPtr
->uNumTools
)
984 TRACE("index=%u\n", uIndex
);
986 toolPtr
= &infoPtr
->tools
[uIndex
];
989 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
990 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
991 lpToolInfo
->uId
= toolPtr
->uId
;
992 lpToolInfo
->rect
= toolPtr
->rect
;
993 lpToolInfo
->hinst
= toolPtr
->hinst
;
994 /* lpToolInfo->lpszText = toolPtr->lpszText; */
995 lpToolInfo
->lpszText
= NULL
; /* FIXME */
997 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
998 lpToolInfo
->lParam
= toolPtr
->lParam
;
1005 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1007 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1008 UINT uIndex
= (UINT
)wParam
;
1009 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1010 TTTOOL_INFO
*toolPtr
;
1012 if (lpToolInfo
== NULL
)
1014 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1016 if (uIndex
>= infoPtr
->uNumTools
)
1019 TRACE("index=%u\n", uIndex
);
1021 toolPtr
= &infoPtr
->tools
[uIndex
];
1023 /* copy tool data */
1024 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1025 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1026 lpToolInfo
->uId
= toolPtr
->uId
;
1027 lpToolInfo
->rect
= toolPtr
->rect
;
1028 lpToolInfo
->hinst
= toolPtr
->hinst
;
1029 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1030 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1032 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1033 lpToolInfo
->lParam
= toolPtr
->lParam
;
1039 TOOLTIPS_GetBubbleSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1041 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1042 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1046 if (lpToolInfo
== NULL
)
1048 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1051 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1052 if (nTool
== -1) return 0;
1054 TRACE("tool %d\n", nTool
);
1056 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
1057 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
1059 return MAKELRESULT(size
.cx
, size
.cy
);
1063 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1065 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1066 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1067 TTTOOL_INFO
*toolPtr
;
1069 if (lpToolInfo
== NULL
)
1071 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1075 if (infoPtr
->nCurrentTool
> -1) {
1076 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1078 /* copy tool data */
1079 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1080 lpToolInfo
->rect
= toolPtr
->rect
;
1081 lpToolInfo
->hinst
= toolPtr
->hinst
;
1082 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1083 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1085 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1086 lpToolInfo
->lParam
= toolPtr
->lParam
;
1094 return (infoPtr
->nCurrentTool
!= -1);
1101 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1103 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1104 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1105 TTTOOL_INFO
*toolPtr
;
1107 if (lpToolInfo
== NULL
)
1109 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1113 if (infoPtr
->nCurrentTool
> -1) {
1114 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1116 /* copy tool data */
1117 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1118 lpToolInfo
->rect
= toolPtr
->rect
;
1119 lpToolInfo
->hinst
= toolPtr
->hinst
;
1120 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1121 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1123 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1124 lpToolInfo
->lParam
= toolPtr
->lParam
;
1132 return (infoPtr
->nCurrentTool
!= -1);
1139 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1141 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1145 return infoPtr
->nReshowTime
;
1148 return infoPtr
->nAutoPopTime
;
1151 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1152 return infoPtr
->nInitialTime
;
1155 WARN("Invalid wParam %x\n", wParam
);
1164 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1166 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1167 LPRECT lpRect
= (LPRECT
)lParam
;
1169 lpRect
->left
= infoPtr
->rcMargin
.left
;
1170 lpRect
->right
= infoPtr
->rcMargin
.right
;
1171 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1172 lpRect
->top
= infoPtr
->rcMargin
.top
;
1178 inline static LRESULT
1179 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1181 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1183 return infoPtr
->nMaxTipWidth
;
1188 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1190 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1191 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1194 if (lpToolInfo
== NULL
)
1196 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1199 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1200 if (nTool
== -1) return 0;
1202 /* NB this API is broken, there is no way for the app to determine
1203 what size buffer it requires nor a way to specify how long the
1204 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1206 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1207 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1214 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1216 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1217 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1220 if (lpToolInfo
== NULL
)
1222 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1225 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1226 if (nTool
== -1) return 0;
1228 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1234 inline static LRESULT
1235 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1237 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1238 return infoPtr
->clrBk
;
1242 inline static LRESULT
1243 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1245 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1246 return infoPtr
->clrText
;
1250 inline static LRESULT
1251 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1253 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1254 return infoPtr
->uNumTools
;
1259 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1261 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1262 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1263 TTTOOL_INFO
*toolPtr
;
1266 if (lpToolInfo
== NULL
)
1268 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1270 if (infoPtr
->uNumTools
== 0)
1273 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1277 TRACE("tool %d\n", nTool
);
1279 toolPtr
= &infoPtr
->tools
[nTool
];
1281 /* copy tool data */
1282 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1283 lpToolInfo
->rect
= toolPtr
->rect
;
1284 lpToolInfo
->hinst
= toolPtr
->hinst
;
1285 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1286 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1288 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1289 lpToolInfo
->lParam
= toolPtr
->lParam
;
1296 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1298 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1299 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1300 TTTOOL_INFO
*toolPtr
;
1303 if (lpToolInfo
== NULL
)
1305 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1307 if (infoPtr
->uNumTools
== 0)
1310 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1314 TRACE("tool %d\n", nTool
);
1316 toolPtr
= &infoPtr
->tools
[nTool
];
1318 /* copy tool data */
1319 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1320 lpToolInfo
->rect
= toolPtr
->rect
;
1321 lpToolInfo
->hinst
= toolPtr
->hinst
;
1322 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1323 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1325 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1326 lpToolInfo
->lParam
= toolPtr
->lParam
;
1333 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1335 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1336 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1337 TTTOOL_INFO
*toolPtr
;
1343 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1347 TRACE("tool %d!\n", nTool
);
1349 /* copy tool data */
1350 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1351 toolPtr
= &infoPtr
->tools
[nTool
];
1353 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1354 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1355 lptthit
->ti
.uId
= toolPtr
->uId
;
1356 lptthit
->ti
.rect
= toolPtr
->rect
;
1357 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1358 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1359 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1360 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1368 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1370 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1371 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1372 TTTOOL_INFO
*toolPtr
;
1378 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1382 TRACE("tool %d!\n", nTool
);
1384 /* copy tool data */
1385 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1386 toolPtr
= &infoPtr
->tools
[nTool
];
1388 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1389 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1390 lptthit
->ti
.uId
= toolPtr
->uId
;
1391 lptthit
->ti
.rect
= toolPtr
->rect
;
1392 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1393 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1394 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1395 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1403 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1405 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1406 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1411 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1414 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1415 if (nTool
== -1) return 0;
1417 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1424 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1426 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1427 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1432 if (lpti
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1435 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1436 if (nTool
== -1) return 0;
1438 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1444 inline static LRESULT
1445 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1447 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1448 TOOLTIPS_Hide (hwnd
, infoPtr
);
1455 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1457 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1458 LPMSG lpMsg
= (LPMSG
)lParam
;
1463 ERR("lpMsg == NULL!\n");
1467 switch (lpMsg
->message
) {
1468 case WM_LBUTTONDOWN
:
1470 case WM_MBUTTONDOWN
:
1472 case WM_RBUTTONDOWN
:
1474 TOOLTIPS_Hide (hwnd
, infoPtr
);
1478 pt
.x
= LOWORD(lpMsg
->lParam
);
1479 pt
.y
= HIWORD(lpMsg
->lParam
);
1480 nOldTool
= infoPtr
->nTool
;
1481 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1483 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
1484 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1485 TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1487 if (infoPtr
->nTool
!= nOldTool
) {
1488 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1489 TOOLTIPS_Hide(hwnd
, infoPtr
);
1490 KillTimer(hwnd
, ID_TIMERLEAVE
);
1491 } else if (nOldTool
== -1) { /* Moved from outside */
1492 if(infoPtr
->bActive
) {
1493 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1494 TRACE("timer 1 started!\n");
1496 } else { /* Moved from one to another */
1497 TOOLTIPS_Hide (hwnd
, infoPtr
);
1498 KillTimer(hwnd
, ID_TIMERLEAVE
);
1499 if(infoPtr
->bActive
) {
1500 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1501 TRACE("timer 1 started!\n");
1504 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1505 KillTimer(hwnd
, ID_TIMERPOP
);
1506 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1507 TRACE("timer 2 restarted\n");
1517 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1519 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1520 INT nTime
= (INT
)LOWORD(lParam
);
1523 case TTDT_AUTOMATIC
:
1525 nTime
= GetDoubleClickTime();
1526 infoPtr
->nReshowTime
= nTime
/ 5;
1527 infoPtr
->nAutoPopTime
= nTime
* 10;
1528 infoPtr
->nInitialTime
= nTime
;
1533 nTime
= GetDoubleClickTime() / 5;
1534 infoPtr
->nReshowTime
= nTime
;
1539 nTime
= GetDoubleClickTime() * 10;
1540 infoPtr
->nAutoPopTime
= nTime
;
1545 nTime
= GetDoubleClickTime();
1546 infoPtr
->nInitialTime
= nTime
;
1550 WARN("Invalid wParam %x\n", wParam
);
1559 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1561 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1562 LPRECT lpRect
= (LPRECT
)lParam
;
1564 infoPtr
->rcMargin
.left
= lpRect
->left
;
1565 infoPtr
->rcMargin
.right
= lpRect
->right
;
1566 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1567 infoPtr
->rcMargin
.top
= lpRect
->top
;
1573 inline static LRESULT
1574 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1576 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1577 INT nTemp
= infoPtr
->nMaxTipWidth
;
1579 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1585 inline static LRESULT
1586 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1588 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1590 infoPtr
->clrBk
= (COLORREF
)wParam
;
1596 inline static LRESULT
1597 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1599 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1601 infoPtr
->clrText
= (COLORREF
)wParam
;
1608 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1610 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1611 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1612 TTTOOL_INFO
*toolPtr
;
1615 if (lpToolInfo
== NULL
)
1617 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1620 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1621 if (nTool
== -1) return 0;
1623 TRACE("tool %d\n", nTool
);
1625 toolPtr
= &infoPtr
->tools
[nTool
];
1627 /* copy tool data */
1628 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1629 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1630 toolPtr
->uId
= lpToolInfo
->uId
;
1631 toolPtr
->rect
= lpToolInfo
->rect
;
1632 toolPtr
->hinst
= lpToolInfo
->hinst
;
1634 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1635 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1636 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1638 else if (lpToolInfo
->lpszText
) {
1639 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1640 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1642 if ( (toolPtr
->lpszText
) &&
1643 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1644 COMCTL32_Free (toolPtr
->lpszText
);
1645 toolPtr
->lpszText
= NULL
;
1647 if (lpToolInfo
->lpszText
) {
1648 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1650 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1651 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1652 toolPtr
->lpszText
, len
);
1657 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1658 toolPtr
->lParam
= lpToolInfo
->lParam
;
1665 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1667 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1668 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1669 TTTOOL_INFO
*toolPtr
;
1672 if (lpToolInfo
== NULL
)
1674 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1677 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1678 if (nTool
== -1) return 0;
1680 TRACE("tool %d\n", nTool
);
1682 toolPtr
= &infoPtr
->tools
[nTool
];
1684 /* copy tool data */
1685 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1686 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1687 toolPtr
->uId
= lpToolInfo
->uId
;
1688 toolPtr
->rect
= lpToolInfo
->rect
;
1689 toolPtr
->hinst
= lpToolInfo
->hinst
;
1691 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1692 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1693 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1695 else if (lpToolInfo
->lpszText
) {
1696 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1697 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1699 if ( (toolPtr
->lpszText
) &&
1700 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1701 COMCTL32_Free (toolPtr
->lpszText
);
1702 toolPtr
->lpszText
= NULL
;
1704 if (lpToolInfo
->lpszText
) {
1705 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1706 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1707 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1712 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1713 toolPtr
->lParam
= lpToolInfo
->lParam
;
1720 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1722 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1723 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1725 if (lpToolInfo
== NULL
)
1727 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1732 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1733 if (infoPtr
->nTrackTool
!= -1) {
1734 TRACE("activated!\n");
1735 infoPtr
->bTrackActive
= TRUE
;
1736 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1741 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1743 infoPtr
->bTrackActive
= FALSE
;
1744 infoPtr
->nTrackTool
= -1;
1746 TRACE("deactivated!\n");
1754 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1756 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1758 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1759 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1761 if (infoPtr
->bTrackActive
) {
1763 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1765 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1773 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1775 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1777 if (infoPtr
->nCurrentTool
!= -1)
1778 UpdateWindow (hwnd
);
1785 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1787 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1788 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1789 TTTOOL_INFO
*toolPtr
;
1792 if (lpToolInfo
== NULL
)
1794 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEA
)
1797 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1798 if (nTool
== -1) return 0;
1800 TRACE("tool %d\n", nTool
);
1802 toolPtr
= &infoPtr
->tools
[nTool
];
1804 /* copy tool text */
1805 toolPtr
->hinst
= lpToolInfo
->hinst
;
1807 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1808 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1810 else if (lpToolInfo
->lpszText
) {
1811 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1812 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1814 if ( (toolPtr
->lpszText
) &&
1815 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1816 COMCTL32_Free (toolPtr
->lpszText
);
1817 toolPtr
->lpszText
= NULL
;
1819 if (lpToolInfo
->lpszText
) {
1820 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1822 toolPtr
->lpszText
= COMCTL32_Alloc (len
* sizeof(WCHAR
));
1823 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1824 toolPtr
->lpszText
, len
);
1829 if(infoPtr
->nCurrentTool
== -1) return 0;
1831 if (infoPtr
->bActive
)
1832 TOOLTIPS_Show (hwnd
, infoPtr
);
1833 else if (infoPtr
->bTrackActive
)
1834 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1841 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1843 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1844 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1845 TTTOOL_INFO
*toolPtr
;
1848 if (lpToolInfo
== NULL
)
1850 if (lpToolInfo
->cbSize
< TTTOOLINFO_V1_SIZEW
)
1853 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1857 TRACE("tool %d\n", nTool
);
1859 toolPtr
= &infoPtr
->tools
[nTool
];
1861 /* copy tool text */
1862 toolPtr
->hinst
= lpToolInfo
->hinst
;
1864 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1865 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1867 else if (lpToolInfo
->lpszText
) {
1868 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1869 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1871 if ( (toolPtr
->lpszText
) &&
1872 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1873 COMCTL32_Free (toolPtr
->lpszText
);
1874 toolPtr
->lpszText
= NULL
;
1876 if (lpToolInfo
->lpszText
) {
1877 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1878 toolPtr
->lpszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1879 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1884 if(infoPtr
->nCurrentTool
== -1) return 0;
1886 if (infoPtr
->bActive
)
1887 TOOLTIPS_Show (hwnd
, infoPtr
);
1888 else if (infoPtr
->bTrackActive
)
1889 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1896 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1898 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1904 TOOLTIPS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1906 TOOLTIPS_INFO
*infoPtr
;
1907 NONCLIENTMETRICSA nclm
;
1911 /* allocate memory for info structure */
1912 infoPtr
= (TOOLTIPS_INFO
*)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO
));
1913 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1915 /* initialize info structure */
1916 infoPtr
->bActive
= TRUE
;
1917 infoPtr
->bTrackActive
= FALSE
;
1918 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1919 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
1921 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
1922 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
1923 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
1925 infoPtr
->nMaxTipWidth
= -1;
1926 infoPtr
->nTool
= -1;
1927 infoPtr
->nCurrentTool
= -1;
1928 infoPtr
->nTrackTool
= -1;
1930 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
1932 hParent
= GetParent(hwnd
);
1934 nResult
= (INT
) SendMessageA (hParent
, WM_NOTIFYFORMAT
,
1935 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1936 if (nResult
== NFR_ANSI
) {
1937 infoPtr
->bNotifyUnicode
= FALSE
;
1938 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1940 else if (nResult
== NFR_UNICODE
) {
1941 infoPtr
->bNotifyUnicode
= TRUE
;
1942 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1945 ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1949 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
1956 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1958 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1959 TTTOOL_INFO
*toolPtr
;
1963 if (infoPtr
->tools
) {
1964 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
1965 toolPtr
= &infoPtr
->tools
[i
];
1966 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
1967 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
1968 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
1970 COMCTL32_Free (toolPtr
->lpszText
);
1971 toolPtr
->lpszText
= NULL
;
1975 /* remove subclassing */
1976 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
1977 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
1978 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
1981 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
1985 COMCTL32_Free (infoPtr
->tools
);
1989 DeleteObject (infoPtr
->hFont
);
1991 /* free tool tips info data */
1992 COMCTL32_Free (infoPtr
);
1993 SetWindowLongA(hwnd
, 0, 0);
1999 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2001 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2005 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2006 GetClientRect (hwnd
, &rect
);
2007 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2008 DeleteObject (hBrush
);
2015 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2017 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2019 return (LRESULT
)infoPtr
->hFont
;
2024 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2026 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2028 TOOLTIPS_Hide (hwnd
, infoPtr
);
2035 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2037 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2038 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2040 dwStyle
&= 0x0000FFFF;
2041 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2042 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2044 dwExStyle
|= WS_EX_TOOLWINDOW
;
2045 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2052 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2054 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2055 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2057 TRACE(" nTool=%d\n", nTool
);
2059 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2060 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2061 TRACE("-- in transparent mode!\n");
2062 return HTTRANSPARENT
;
2066 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2071 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2073 FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2080 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2085 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2086 TOOLTIPS_Refresh (hwnd
, hdc
);
2088 EndPaint (hwnd
, &ps
);
2094 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2096 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2099 if(!GetObjectW((HFONT
)wParam
, sizeof(lf
), &lf
))
2102 if(infoPtr
->hFont
) DeleteObject (infoPtr
->hFont
);
2103 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2105 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2106 FIXME("full redraw needed!\n");
2111 /******************************************************************
2112 * TOOLTIPS_OnWMGetTextLength
2114 * This function is called when the tooltip receive a
2115 * WM_GETTEXTLENGTH message.
2119 * returns the length, in characters, of the tip text
2120 ******************************************************************/
2122 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2124 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2125 return lstrlenW(infoPtr
->szTipText
);
2128 /******************************************************************
2129 * TOOLTIPS_OnWMGetText
2131 * This function is called when the tooltip receive a
2132 * WM_GETTEXT message.
2133 * wParam : specifies the maximum number of characters to be copied
2134 * lParam : is the pointer to the buffer that will receive
2137 * returns the number of characters copied
2138 ******************************************************************/
2140 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2142 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2144 if(!infoPtr
|| !(infoPtr
->szTipText
))
2147 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2148 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2152 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2154 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2157 TRACE("timer %d (%p) expired!\n", wParam
, hwnd
);
2161 KillTimer (hwnd
, ID_TIMERSHOW
);
2162 nOldTool
= infoPtr
->nTool
;
2163 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2164 TOOLTIPS_Show (hwnd
, infoPtr
);
2168 TOOLTIPS_Hide (hwnd
, infoPtr
);
2172 nOldTool
= infoPtr
->nTool
;
2173 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2174 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
2175 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2176 if (infoPtr
->nTool
!= nOldTool
) {
2177 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2178 TOOLTIPS_Hide(hwnd
, infoPtr
);
2179 KillTimer(hwnd
, ID_TIMERLEAVE
);
2180 } else if (nOldTool
== -1) { /* Moved from outside */
2181 ERR("How did this happen?\n");
2182 } else { /* Moved from one to another */
2183 TOOLTIPS_Hide (hwnd
, infoPtr
);
2184 KillTimer(hwnd
, ID_TIMERLEAVE
);
2185 if(infoPtr
->bActive
) {
2186 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2187 TRACE("timer 1 started!\n");
2194 ERR("Unknown timer id %d\n", wParam
);
2202 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2204 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2205 NONCLIENTMETRICSA nclm
;
2207 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2208 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2210 DeleteObject (infoPtr
->hFont
);
2211 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2212 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2213 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2220 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uID
, DWORD_PTR dwRef
)
2226 case WM_LBUTTONDOWN
:
2228 case WM_MBUTTONDOWN
:
2230 case WM_RBUTTONDOWN
:
2234 msg
.wParam
= wParam
;
2235 msg
.lParam
= lParam
;
2236 TOOLTIPS_RelayEvent((HWND
)dwRef
, 0, (LPARAM
)&msg
);
2242 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
2246 static LRESULT CALLBACK
2247 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2249 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2250 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2251 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2255 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2258 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2261 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2264 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2267 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2269 case TTM_ENUMTOOLSA
:
2270 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2272 case TTM_ENUMTOOLSW
:
2273 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2275 case TTM_GETBUBBLESIZE
:
2276 return TOOLTIPS_GetBubbleSize (hwnd
, wParam
, lParam
);
2278 case TTM_GETCURRENTTOOLA
:
2279 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2281 case TTM_GETCURRENTTOOLW
:
2282 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2284 case TTM_GETDELAYTIME
:
2285 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2288 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2290 case TTM_GETMAXTIPWIDTH
:
2291 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2294 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2297 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2299 case TTM_GETTIPBKCOLOR
:
2300 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2302 case TTM_GETTIPTEXTCOLOR
:
2303 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2305 case TTM_GETTOOLCOUNT
:
2306 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2308 case TTM_GETTOOLINFOA
:
2309 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2311 case TTM_GETTOOLINFOW
:
2312 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2315 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2318 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2320 case TTM_NEWTOOLRECTA
:
2321 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2323 case TTM_NEWTOOLRECTW
:
2324 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2327 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2329 case TTM_RELAYEVENT
:
2330 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2332 case TTM_SETDELAYTIME
:
2333 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2336 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2338 case TTM_SETMAXTIPWIDTH
:
2339 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2341 case TTM_SETTIPBKCOLOR
:
2342 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2344 case TTM_SETTIPTEXTCOLOR
:
2345 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2347 case TTM_SETTOOLINFOA
:
2348 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2350 case TTM_SETTOOLINFOW
:
2351 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2353 case TTM_TRACKACTIVATE
:
2354 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2356 case TTM_TRACKPOSITION
:
2357 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2360 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2362 case TTM_UPDATETIPTEXTA
:
2363 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2365 case TTM_UPDATETIPTEXTW
:
2366 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2368 case TTM_WINDOWFROMPOINT
:
2369 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2373 return TOOLTIPS_Create (hwnd
, wParam
, lParam
);
2376 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2379 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2382 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2385 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2387 case WM_GETTEXTLENGTH
:
2388 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2391 case WM_LBUTTONDOWN
:
2393 case WM_MBUTTONDOWN
:
2395 case WM_RBUTTONDOWN
:
2398 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2401 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2404 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2406 case WM_NOTIFYFORMAT
:
2407 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2410 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2413 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2416 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2418 case WM_WININICHANGE
:
2419 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2422 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2423 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2424 uMsg
, wParam
, lParam
);
2425 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2432 TOOLTIPS_Register (void)
2436 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2437 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2438 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2439 wndClass
.cbClsExtra
= 0;
2440 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2441 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
2442 wndClass
.hbrBackground
= 0;
2443 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2445 RegisterClassA (&wndClass
);
2450 TOOLTIPS_Unregister (void)
2452 UnregisterClassA (TOOLTIPS_CLASSA
, NULL
);