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"
85 #include "wine/debug.h"
87 WINE_DEFAULT_DEBUG_CHANNEL(tooltips
);
104 WCHAR szTipText
[INFOTIPSIZE
];
125 #define ID_TIMERSHOW 1 /* show delay timer */
126 #define ID_TIMERPOP 2 /* auto pop timer */
127 #define ID_TIMERLEAVE 3 /* tool leave timer */
130 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
134 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uId
, DWORD_PTR dwRef
);
138 TOOLTIPS_Refresh (HWND hwnd
, HDC hdc
)
140 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr(hwnd
);
145 UINT uFlags
= DT_EXTERNALLEADING
;
147 if (infoPtr
->nMaxTipWidth
> -1)
148 uFlags
|= DT_WORDBREAK
;
149 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
150 uFlags
|= DT_NOPREFIX
;
151 GetClientRect (hwnd
, &rc
);
153 /* fill the background */
154 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
155 FillRect (hdc
, &rc
, hBrush
);
156 DeleteObject (hBrush
);
158 /* calculate text rectangle */
159 rc
.left
+= (2 + infoPtr
->rcMargin
.left
);
160 rc
.top
+= (2 + infoPtr
->rcMargin
.top
);
161 rc
.right
-= (2 + infoPtr
->rcMargin
.right
);
162 rc
.bottom
-= (2 + infoPtr
->rcMargin
.bottom
);
165 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
166 SetTextColor (hdc
, infoPtr
->clrText
);
167 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
168 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
169 SelectObject (hdc
, hOldFont
);
170 if (oldBkMode
!= TRANSPARENT
)
171 SetBkMode (hdc
, oldBkMode
);
174 static void TOOLTIPS_GetDispInfoA(HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, TTTOOL_INFO
*toolPtr
)
176 NMTTDISPINFOA ttnmdi
;
178 /* fill NMHDR struct */
179 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOA
));
180 ttnmdi
.hdr
.hwndFrom
= hwnd
;
181 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
182 ttnmdi
.hdr
.code
= TTN_GETDISPINFOA
;
183 ttnmdi
.lpszText
= (LPSTR
)&ttnmdi
.szText
;
184 ttnmdi
.uFlags
= toolPtr
->uFlags
;
185 ttnmdi
.lParam
= toolPtr
->lParam
;
187 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
188 SendMessageA(toolPtr
->hwnd
, WM_NOTIFY
,
189 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
191 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
192 LoadStringW(ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
193 infoPtr
->szTipText
, INFOTIPSIZE
);
194 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
195 toolPtr
->hinst
= ttnmdi
.hinst
;
196 toolPtr
->lpszText
= (LPWSTR
)ttnmdi
.lpszText
;
199 else if (ttnmdi
.lpszText
== 0) {
200 /* no text available */
201 infoPtr
->szTipText
[0] = '\0';
203 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKA
) {
204 INT max_len
= (ttnmdi
.lpszText
== &ttnmdi
.szText
[0]) ?
205 sizeof(ttnmdi
.szText
)/sizeof(ttnmdi
.szText
[0]) : -1;
206 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, max_len
,
207 infoPtr
->szTipText
, INFOTIPSIZE
);
208 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
209 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
,
212 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
213 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
214 toolPtr
->lpszText
, len
);
218 ERR("recursive text callback!\n");
219 infoPtr
->szTipText
[0] = '\0';
223 static void TOOLTIPS_GetDispInfoW(HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, TTTOOL_INFO
*toolPtr
)
225 NMTTDISPINFOW ttnmdi
;
227 /* fill NMHDR struct */
228 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOW
));
229 ttnmdi
.hdr
.hwndFrom
= hwnd
;
230 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
231 ttnmdi
.hdr
.code
= TTN_GETDISPINFOW
;
232 ttnmdi
.lpszText
= (LPWSTR
)&ttnmdi
.szText
;
233 ttnmdi
.uFlags
= toolPtr
->uFlags
;
234 ttnmdi
.lParam
= toolPtr
->lParam
;
236 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
237 SendMessageW(toolPtr
->hwnd
, WM_NOTIFY
,
238 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
240 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
241 LoadStringW(ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
242 infoPtr
->szTipText
, INFOTIPSIZE
);
243 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
244 toolPtr
->hinst
= ttnmdi
.hinst
;
245 toolPtr
->lpszText
= ttnmdi
.lpszText
;
248 else if (ttnmdi
.lpszText
== 0) {
249 /* no text available */
250 infoPtr
->szTipText
[0] = '\0';
252 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKW
) {
253 INT max_len
= (ttnmdi
.lpszText
== &ttnmdi
.szText
[0]) ?
254 sizeof(ttnmdi
.szText
)/sizeof(ttnmdi
.szText
[0]) : INFOTIPSIZE
-1;
255 strncpyW(infoPtr
->szTipText
, ttnmdi
.lpszText
, max_len
);
256 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
257 INT len
= max(strlenW(ttnmdi
.lpszText
), max_len
);
259 toolPtr
->lpszText
= Alloc ((len
+1) * sizeof(WCHAR
));
260 memcpy(toolPtr
->lpszText
, ttnmdi
.lpszText
, (len
+1) * sizeof(WCHAR
));
264 ERR("recursive text callback!\n");
265 infoPtr
->szTipText
[0] = '\0';
270 TOOLTIPS_GetTipText (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, INT nTool
)
272 TTTOOL_INFO
*toolPtr
= &infoPtr
->tools
[nTool
];
274 if (HIWORD((UINT
)toolPtr
->lpszText
) == 0) {
275 /* load a resource */
276 TRACE("load res string %p %x\n",
277 toolPtr
->hinst
, (int)toolPtr
->lpszText
);
278 LoadStringW (toolPtr
->hinst
, (UINT
)toolPtr
->lpszText
,
279 infoPtr
->szTipText
, INFOTIPSIZE
);
281 else if (toolPtr
->lpszText
) {
282 if (toolPtr
->lpszText
== LPSTR_TEXTCALLBACKW
) {
283 if (toolPtr
->bNotifyUnicode
)
284 TOOLTIPS_GetDispInfoW(hwnd
, infoPtr
, toolPtr
);
286 TOOLTIPS_GetDispInfoA(hwnd
, infoPtr
, toolPtr
);
289 /* the item is a usual (unicode) text */
290 lstrcpynW (infoPtr
->szTipText
, toolPtr
->lpszText
, INFOTIPSIZE
);
294 /* no text available */
295 infoPtr
->szTipText
[0] = L
'\0';
298 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
303 TOOLTIPS_CalcTipSize (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, LPSIZE lpSize
)
307 UINT uFlags
= DT_EXTERNALLEADING
| DT_CALCRECT
;
308 RECT rc
= {0, 0, 0, 0};
310 if (infoPtr
->nMaxTipWidth
> -1) {
311 rc
.right
= infoPtr
->nMaxTipWidth
;
312 uFlags
|= DT_WORDBREAK
;
314 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
315 uFlags
|= DT_NOPREFIX
;
316 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
319 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
320 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
321 SelectObject (hdc
, hOldFont
);
322 ReleaseDC (hwnd
, hdc
);
324 lpSize
->cx
= rc
.right
- rc
.left
+ 4 +
325 infoPtr
->rcMargin
.left
+ infoPtr
->rcMargin
.right
;
326 lpSize
->cy
= rc
.bottom
- rc
.top
+ 4 +
327 infoPtr
->rcMargin
.bottom
+ infoPtr
->rcMargin
.top
;
332 TOOLTIPS_Show (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
334 TTTOOL_INFO
*toolPtr
;
339 if (infoPtr
->nTool
== -1) {
340 TRACE("invalid tool (-1)!\n");
344 infoPtr
->nCurrentTool
= infoPtr
->nTool
;
346 TRACE("Show tooltip pre %d! (%p)\n", infoPtr
->nTool
, hwnd
);
348 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nCurrentTool
);
350 if (infoPtr
->szTipText
[0] == L
'\0') {
351 infoPtr
->nCurrentTool
= -1;
355 TRACE("Show tooltip %d!\n", infoPtr
->nCurrentTool
);
356 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
359 hdr
.idFrom
= toolPtr
->uId
;
361 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
362 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
364 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
366 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
367 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
369 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
372 if (toolPtr
->uFlags
& TTF_IDISHWND
)
373 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
376 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
378 rect
.left
= (rc
.left
+ rc
.right
- size
.cx
) / 2;
379 rect
.top
= rc
.bottom
+ 2;
382 GetCursorPos ((LPPOINT
)&rect
);
386 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
388 rect
.right
= rect
.left
+ size
.cx
;
389 rect
.bottom
= rect
.top
+ size
.cy
;
392 wndrect
.right
= GetSystemMetrics( SM_CXSCREEN
);
393 if( rect
.right
> wndrect
.right
) {
394 rect
.left
-= rect
.right
- wndrect
.right
+ 2;
395 rect
.right
= wndrect
.right
- 2;
397 wndrect
.bottom
= GetSystemMetrics( SM_CYSCREEN
);
398 if( rect
.bottom
> wndrect
.bottom
) {
401 if (toolPtr
->uFlags
& TTF_IDISHWND
)
402 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
405 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
407 rect
.bottom
= rc
.top
- 2;
408 rect
.top
= rect
.bottom
- size
.cy
;
411 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
412 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
414 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
415 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
416 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
418 /* repaint the tooltip */
419 InvalidateRect(hwnd
, NULL
, TRUE
);
422 SetTimer (hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
423 TRACE("timer 2 started!\n");
424 SetTimer (hwnd
, ID_TIMERLEAVE
, infoPtr
->nReshowTime
, 0);
425 TRACE("timer 3 started!\n");
430 TOOLTIPS_Hide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
432 TTTOOL_INFO
*toolPtr
;
435 TRACE("Hide tooltip %d! (%p)\n", infoPtr
->nCurrentTool
, hwnd
);
437 if (infoPtr
->nCurrentTool
== -1)
440 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
441 KillTimer (hwnd
, ID_TIMERPOP
);
444 hdr
.idFrom
= toolPtr
->uId
;
446 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
447 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
449 infoPtr
->nCurrentTool
= -1;
451 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
452 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
457 TOOLTIPS_TrackShow (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
459 TTTOOL_INFO
*toolPtr
;
464 if (infoPtr
->nTrackTool
== -1) {
465 TRACE("invalid tracking tool (-1)!\n");
469 TRACE("show tracking tooltip pre %d!\n", infoPtr
->nTrackTool
);
471 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nTrackTool
);
473 if (infoPtr
->szTipText
[0] == L
'\0') {
474 infoPtr
->nTrackTool
= -1;
478 TRACE("show tracking tooltip %d!\n", infoPtr
->nTrackTool
);
479 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
482 hdr
.idFrom
= toolPtr
->uId
;
484 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
485 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
487 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
489 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
490 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
492 if (toolPtr
->uFlags
& TTF_ABSOLUTE
) {
493 rect
.left
= infoPtr
->xTrackPos
;
494 rect
.top
= infoPtr
->yTrackPos
;
496 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
497 rect
.left
-= (size
.cx
/ 2);
498 rect
.top
-= (size
.cy
/ 2);
504 if (toolPtr
->uFlags
& TTF_IDISHWND
)
505 GetWindowRect ((HWND
)toolPtr
->uId
, &rcTool
);
507 rcTool
= toolPtr
->rect
;
508 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rcTool
, 2);
511 GetCursorPos ((LPPOINT
)&rect
);
514 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
515 rect
.left
-= (size
.cx
/ 2);
516 rect
.top
-= (size
.cy
/ 2);
519 /* smart placement */
520 if ((rect
.left
+ size
.cx
> rcTool
.left
) && (rect
.left
< rcTool
.right
) &&
521 (rect
.top
+ size
.cy
> rcTool
.top
) && (rect
.top
< rcTool
.bottom
))
522 rect
.left
= rcTool
.right
;
525 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
527 rect
.right
= rect
.left
+ size
.cx
;
528 rect
.bottom
= rect
.top
+ size
.cy
;
530 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
531 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
533 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
534 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
535 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
537 InvalidateRect(hwnd
, NULL
, TRUE
);
543 TOOLTIPS_TrackHide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
545 TTTOOL_INFO
*toolPtr
;
548 if (infoPtr
->nTrackTool
== -1)
551 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
552 TRACE("hide tracking tooltip %d!\n", infoPtr
->nTrackTool
);
555 hdr
.idFrom
= toolPtr
->uId
;
557 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
558 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
560 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
561 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
566 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOA lpToolInfo
)
568 TTTOOL_INFO
*toolPtr
;
571 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
572 toolPtr
= &infoPtr
->tools
[nTool
];
574 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
575 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
576 (lpToolInfo
->uId
== toolPtr
->uId
))
580 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
581 toolPtr
= &infoPtr
->tools
[nTool
];
583 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
584 (lpToolInfo
->uId
== toolPtr
->uId
))
593 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOW lpToolInfo
)
595 TTTOOL_INFO
*toolPtr
;
598 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
599 toolPtr
= &infoPtr
->tools
[nTool
];
601 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
602 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
603 (lpToolInfo
->uId
== toolPtr
->uId
))
607 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
608 toolPtr
= &infoPtr
->tools
[nTool
];
610 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
611 (lpToolInfo
->uId
== toolPtr
->uId
))
620 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO
*infoPtr
, HWND hwnd
, LPPOINT lpPt
)
622 TTTOOL_INFO
*toolPtr
;
625 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
626 toolPtr
= &infoPtr
->tools
[nTool
];
628 if (!(toolPtr
->uFlags
& TTF_IDISHWND
)) {
629 if (hwnd
!= toolPtr
->hwnd
)
631 if (!PtInRect (&toolPtr
->rect
, *lpPt
))
637 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
638 toolPtr
= &infoPtr
->tools
[nTool
];
640 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
641 if ((HWND
)toolPtr
->uId
== hwnd
)
651 TOOLTIPS_IsWindowActive (HWND hwnd
)
653 HWND hwndActive
= GetActiveWindow ();
656 if (hwndActive
== hwnd
)
658 return IsChild (hwndActive
, hwnd
);
663 TOOLTIPS_CheckTool (HWND hwnd
, BOOL bShowTest
)
665 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
671 hwndTool
= (HWND
)SendMessageA (hwnd
, TTM_WINDOWFROMPOINT
, 0, (LPARAM
)&pt
);
675 ScreenToClient (hwndTool
, &pt
);
676 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, hwndTool
, &pt
);
680 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_ALWAYSTIP
) && bShowTest
) {
681 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd
, GW_OWNER
)))
685 TRACE("tool %d\n", nTool
);
692 TOOLTIPS_Activate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
694 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
696 infoPtr
->bActive
= (BOOL
)wParam
;
698 if (infoPtr
->bActive
)
699 TRACE("activate!\n");
701 if (!(infoPtr
->bActive
) && (infoPtr
->nCurrentTool
!= -1))
702 TOOLTIPS_Hide (hwnd
, infoPtr
);
709 TOOLTIPS_AddToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
711 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
712 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
713 TTTOOL_INFO
*toolPtr
;
716 if (lpToolInfo
== NULL
)
718 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
721 TRACE("add tool (%p) %p %d%s!\n",
722 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
723 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
725 if (infoPtr
->uNumTools
== 0) {
726 infoPtr
->tools
= Alloc (sizeof(TTTOOL_INFO
));
727 toolPtr
= infoPtr
->tools
;
730 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
732 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
733 memcpy (infoPtr
->tools
, oldTools
,
734 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
736 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
739 infoPtr
->uNumTools
++;
742 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
743 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
744 toolPtr
->uId
= lpToolInfo
->uId
;
745 toolPtr
->rect
= lpToolInfo
->rect
;
746 toolPtr
->hinst
= lpToolInfo
->hinst
;
748 if (HIWORD(lpToolInfo
->lpszText
) == 0) {
749 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
750 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
752 else if (lpToolInfo
->lpszText
) {
753 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
) {
754 TRACE("add CALLBACK!\n");
755 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
758 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
760 TRACE("add text \"%s\"!\n", lpToolInfo
->lpszText
);
761 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
762 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
763 toolPtr
->lpszText
, len
);
767 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
768 toolPtr
->lParam
= lpToolInfo
->lParam
;
770 /* install subclassing hook */
771 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
772 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
773 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
777 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
780 TRACE("subclassing installed!\n");
783 nResult
= (INT
) SendMessageA (toolPtr
->hwnd
, WM_NOTIFYFORMAT
,
784 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
785 if (nResult
== NFR_ANSI
) {
786 toolPtr
->bNotifyUnicode
= FALSE
;
787 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
788 } else if (nResult
== NFR_UNICODE
) {
789 toolPtr
->bNotifyUnicode
= TRUE
;
790 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
792 TRACE (" -- WM_NOTIFYFORMAT returns: error!\n");
800 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
802 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
803 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
804 TTTOOL_INFO
*toolPtr
;
807 if (lpToolInfo
== NULL
)
809 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
812 TRACE("add tool (%p) %p %d%s!\n",
813 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
814 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
816 if (infoPtr
->uNumTools
== 0) {
817 infoPtr
->tools
= Alloc (sizeof(TTTOOL_INFO
));
818 toolPtr
= infoPtr
->tools
;
821 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
823 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
824 memcpy (infoPtr
->tools
, oldTools
,
825 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
827 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
830 infoPtr
->uNumTools
++;
833 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
834 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
835 toolPtr
->uId
= lpToolInfo
->uId
;
836 toolPtr
->rect
= lpToolInfo
->rect
;
837 toolPtr
->hinst
= lpToolInfo
->hinst
;
839 if (HIWORD(lpToolInfo
->lpszText
) == 0) {
840 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
841 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
843 else if (lpToolInfo
->lpszText
) {
844 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
845 TRACE("add CALLBACK!\n");
846 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
849 INT len
= lstrlenW (lpToolInfo
->lpszText
);
850 TRACE("add text %s!\n",
851 debugstr_w(lpToolInfo
->lpszText
));
852 toolPtr
->lpszText
= Alloc ((len
+ 1)*sizeof(WCHAR
));
853 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
857 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
858 toolPtr
->lParam
= lpToolInfo
->lParam
;
860 /* install subclassing hook */
861 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
862 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
863 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
867 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
870 TRACE("subclassing installed!\n");
873 nResult
= (INT
) SendMessageA (toolPtr
->hwnd
, WM_NOTIFYFORMAT
,
874 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
875 if (nResult
== NFR_ANSI
) {
876 toolPtr
->bNotifyUnicode
= FALSE
;
877 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
878 } else if (nResult
== NFR_UNICODE
) {
879 toolPtr
->bNotifyUnicode
= TRUE
;
880 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
882 TRACE (" -- WM_NOTIFYFORMAT returns: error!\n");
890 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
892 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
893 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
894 TTTOOL_INFO
*toolPtr
;
897 if (lpToolInfo
== NULL
)
899 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
901 if (infoPtr
->uNumTools
== 0)
904 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
905 if (nTool
== -1) return 0;
907 TRACE("tool %d\n", nTool
);
909 /* make sure the tooltip has disappeared before deleting it */
910 TOOLTIPS_Hide(hwnd
, infoPtr
);
912 /* delete text string */
913 toolPtr
= &infoPtr
->tools
[nTool
];
914 if (toolPtr
->lpszText
) {
915 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
916 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
917 Free (toolPtr
->lpszText
);
920 /* remove subclassing */
921 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
922 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
923 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
926 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
930 /* delete tool from tool list */
931 if (infoPtr
->uNumTools
== 1) {
932 Free (infoPtr
->tools
);
933 infoPtr
->tools
= NULL
;
936 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
938 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
941 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
942 nTool
* sizeof(TTTOOL_INFO
));
944 if (nTool
< infoPtr
->uNumTools
- 1)
945 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
946 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
951 /* destroying tool that mouse was on on last relayed mouse move */
952 if (infoPtr
->nTool
== nTool
)
954 /* no current tool (0 means first tool) */
958 infoPtr
->uNumTools
--;
965 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
967 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
968 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
969 TTTOOL_INFO
*toolPtr
;
972 if (lpToolInfo
== NULL
)
974 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
976 if (infoPtr
->uNumTools
== 0)
979 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
980 if (nTool
== -1) return 0;
982 TRACE("tool %d\n", nTool
);
984 /* make sure the tooltip has disappeared before deleting it */
985 TOOLTIPS_Hide(hwnd
, infoPtr
);
987 /* delete text string */
988 toolPtr
= &infoPtr
->tools
[nTool
];
989 if (toolPtr
->lpszText
) {
990 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
991 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
992 Free (toolPtr
->lpszText
);
995 /* remove subclassing */
996 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
997 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
998 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
1001 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
1005 /* delete tool from tool list */
1006 if (infoPtr
->uNumTools
== 1) {
1007 Free (infoPtr
->tools
);
1008 infoPtr
->tools
= NULL
;
1011 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
1013 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
1016 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
1017 nTool
* sizeof(TTTOOL_INFO
));
1019 if (nTool
< infoPtr
->uNumTools
- 1)
1020 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
1021 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
1026 /* destroying tool that mouse was on on last relayed mouse move */
1027 if (infoPtr
->nTool
== nTool
)
1029 /* no current tool (0 means first tool) */
1030 infoPtr
->nTool
= -1;
1033 infoPtr
->uNumTools
--;
1040 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1042 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1043 UINT uIndex
= (UINT
)wParam
;
1044 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1045 TTTOOL_INFO
*toolPtr
;
1047 if (lpToolInfo
== NULL
)
1049 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1051 if (uIndex
>= infoPtr
->uNumTools
)
1054 TRACE("index=%u\n", uIndex
);
1056 toolPtr
= &infoPtr
->tools
[uIndex
];
1058 /* copy tool data */
1059 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1060 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1061 lpToolInfo
->uId
= toolPtr
->uId
;
1062 lpToolInfo
->rect
= toolPtr
->rect
;
1063 lpToolInfo
->hinst
= toolPtr
->hinst
;
1064 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1065 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1067 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1068 lpToolInfo
->lParam
= toolPtr
->lParam
;
1075 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1077 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1078 UINT uIndex
= (UINT
)wParam
;
1079 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1080 TTTOOL_INFO
*toolPtr
;
1082 if (lpToolInfo
== NULL
)
1084 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1086 if (uIndex
>= infoPtr
->uNumTools
)
1089 TRACE("index=%u\n", uIndex
);
1091 toolPtr
= &infoPtr
->tools
[uIndex
];
1093 /* copy tool data */
1094 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1095 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1096 lpToolInfo
->uId
= toolPtr
->uId
;
1097 lpToolInfo
->rect
= toolPtr
->rect
;
1098 lpToolInfo
->hinst
= toolPtr
->hinst
;
1099 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1100 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1102 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1103 lpToolInfo
->lParam
= toolPtr
->lParam
;
1109 TOOLTIPS_GetBubbleSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1111 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1112 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1116 if (lpToolInfo
== NULL
)
1118 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1121 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1122 if (nTool
== -1) return 0;
1124 TRACE("tool %d\n", nTool
);
1126 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
1127 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
1129 return MAKELRESULT(size
.cx
, size
.cy
);
1133 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1135 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1136 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1137 TTTOOL_INFO
*toolPtr
;
1139 if (lpToolInfo
== NULL
)
1141 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1145 if (infoPtr
->nCurrentTool
> -1) {
1146 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1148 /* copy tool data */
1149 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1150 lpToolInfo
->rect
= toolPtr
->rect
;
1151 lpToolInfo
->hinst
= toolPtr
->hinst
;
1152 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1153 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1155 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1156 lpToolInfo
->lParam
= toolPtr
->lParam
;
1164 return (infoPtr
->nCurrentTool
!= -1);
1171 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1173 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1174 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1175 TTTOOL_INFO
*toolPtr
;
1177 if (lpToolInfo
== NULL
)
1179 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1183 if (infoPtr
->nCurrentTool
> -1) {
1184 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1186 /* copy tool data */
1187 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1188 lpToolInfo
->rect
= toolPtr
->rect
;
1189 lpToolInfo
->hinst
= toolPtr
->hinst
;
1190 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1191 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1193 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1194 lpToolInfo
->lParam
= toolPtr
->lParam
;
1202 return (infoPtr
->nCurrentTool
!= -1);
1209 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1211 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1215 return infoPtr
->nReshowTime
;
1218 return infoPtr
->nAutoPopTime
;
1221 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1222 return infoPtr
->nInitialTime
;
1225 WARN("Invalid wParam %x\n", wParam
);
1234 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1236 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1237 LPRECT lpRect
= (LPRECT
)lParam
;
1239 lpRect
->left
= infoPtr
->rcMargin
.left
;
1240 lpRect
->right
= infoPtr
->rcMargin
.right
;
1241 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1242 lpRect
->top
= infoPtr
->rcMargin
.top
;
1248 inline static LRESULT
1249 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1251 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1253 return infoPtr
->nMaxTipWidth
;
1258 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1260 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1261 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1264 if (lpToolInfo
== NULL
)
1266 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1269 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1270 if (nTool
== -1) return 0;
1272 /* NB this API is broken, there is no way for the app to determine
1273 what size buffer it requires nor a way to specify how long the
1274 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1276 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1277 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1284 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1286 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1287 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1290 if (lpToolInfo
== NULL
)
1292 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1295 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1296 if (nTool
== -1) return 0;
1298 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1304 inline static LRESULT
1305 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1307 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1308 return infoPtr
->clrBk
;
1312 inline static LRESULT
1313 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1315 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1316 return infoPtr
->clrText
;
1320 inline static LRESULT
1321 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1323 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1324 return infoPtr
->uNumTools
;
1329 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1331 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1332 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1333 TTTOOL_INFO
*toolPtr
;
1336 if (lpToolInfo
== NULL
)
1338 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1340 if (infoPtr
->uNumTools
== 0)
1343 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1347 TRACE("tool %d\n", nTool
);
1349 toolPtr
= &infoPtr
->tools
[nTool
];
1351 /* copy tool data */
1352 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1353 lpToolInfo
->rect
= toolPtr
->rect
;
1354 lpToolInfo
->hinst
= toolPtr
->hinst
;
1355 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1356 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1358 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1359 lpToolInfo
->lParam
= toolPtr
->lParam
;
1366 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1368 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1369 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1370 TTTOOL_INFO
*toolPtr
;
1373 if (lpToolInfo
== NULL
)
1375 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1377 if (infoPtr
->uNumTools
== 0)
1380 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1384 TRACE("tool %d\n", nTool
);
1386 toolPtr
= &infoPtr
->tools
[nTool
];
1388 /* copy tool data */
1389 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1390 lpToolInfo
->rect
= toolPtr
->rect
;
1391 lpToolInfo
->hinst
= toolPtr
->hinst
;
1392 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1393 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1395 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1396 lpToolInfo
->lParam
= toolPtr
->lParam
;
1403 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1405 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1406 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1407 TTTOOL_INFO
*toolPtr
;
1413 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1417 TRACE("tool %d!\n", nTool
);
1419 /* copy tool data */
1420 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1421 toolPtr
= &infoPtr
->tools
[nTool
];
1423 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1424 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1425 lptthit
->ti
.uId
= toolPtr
->uId
;
1426 lptthit
->ti
.rect
= toolPtr
->rect
;
1427 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1428 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1429 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1430 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1438 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1440 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1441 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1442 TTTOOL_INFO
*toolPtr
;
1448 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1452 TRACE("tool %d!\n", nTool
);
1454 /* copy tool data */
1455 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1456 toolPtr
= &infoPtr
->tools
[nTool
];
1458 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1459 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1460 lptthit
->ti
.uId
= toolPtr
->uId
;
1461 lptthit
->ti
.rect
= toolPtr
->rect
;
1462 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1463 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1464 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1465 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1473 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1475 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1476 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1481 if (lpti
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1484 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1485 if (nTool
== -1) return 0;
1487 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1494 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1496 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1497 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1502 if (lpti
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1505 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1506 if (nTool
== -1) return 0;
1508 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1514 inline static LRESULT
1515 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1517 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1518 TOOLTIPS_Hide (hwnd
, infoPtr
);
1525 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1527 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1528 LPMSG lpMsg
= (LPMSG
)lParam
;
1533 ERR("lpMsg == NULL!\n");
1537 switch (lpMsg
->message
) {
1538 case WM_LBUTTONDOWN
:
1540 case WM_MBUTTONDOWN
:
1542 case WM_RBUTTONDOWN
:
1544 TOOLTIPS_Hide (hwnd
, infoPtr
);
1548 pt
.x
= LOWORD(lpMsg
->lParam
);
1549 pt
.y
= HIWORD(lpMsg
->lParam
);
1550 nOldTool
= infoPtr
->nTool
;
1551 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1553 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
1554 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1555 TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1557 if (infoPtr
->nTool
!= nOldTool
) {
1558 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1559 TOOLTIPS_Hide(hwnd
, infoPtr
);
1560 KillTimer(hwnd
, ID_TIMERLEAVE
);
1561 } else if (nOldTool
== -1) { /* Moved from outside */
1562 if(infoPtr
->bActive
) {
1563 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1564 TRACE("timer 1 started!\n");
1566 } else { /* Moved from one to another */
1567 TOOLTIPS_Hide (hwnd
, infoPtr
);
1568 KillTimer(hwnd
, ID_TIMERLEAVE
);
1569 if(infoPtr
->bActive
) {
1570 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1571 TRACE("timer 1 started!\n");
1574 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1575 KillTimer(hwnd
, ID_TIMERPOP
);
1576 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1577 TRACE("timer 2 restarted\n");
1587 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1589 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1590 INT nTime
= (INT
)LOWORD(lParam
);
1593 case TTDT_AUTOMATIC
:
1595 nTime
= GetDoubleClickTime();
1596 infoPtr
->nReshowTime
= nTime
/ 5;
1597 infoPtr
->nAutoPopTime
= nTime
* 10;
1598 infoPtr
->nInitialTime
= nTime
;
1603 nTime
= GetDoubleClickTime() / 5;
1604 infoPtr
->nReshowTime
= nTime
;
1609 nTime
= GetDoubleClickTime() * 10;
1610 infoPtr
->nAutoPopTime
= nTime
;
1615 nTime
= GetDoubleClickTime();
1616 infoPtr
->nInitialTime
= nTime
;
1620 WARN("Invalid wParam %x\n", wParam
);
1629 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1631 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1632 LPRECT lpRect
= (LPRECT
)lParam
;
1634 infoPtr
->rcMargin
.left
= lpRect
->left
;
1635 infoPtr
->rcMargin
.right
= lpRect
->right
;
1636 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1637 infoPtr
->rcMargin
.top
= lpRect
->top
;
1643 inline static LRESULT
1644 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1646 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1647 INT nTemp
= infoPtr
->nMaxTipWidth
;
1649 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1655 inline static LRESULT
1656 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1658 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1660 infoPtr
->clrBk
= (COLORREF
)wParam
;
1666 inline static LRESULT
1667 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1669 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1671 infoPtr
->clrText
= (COLORREF
)wParam
;
1678 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1680 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1681 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1682 TTTOOL_INFO
*toolPtr
;
1685 if (lpToolInfo
== NULL
)
1687 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1690 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1691 if (nTool
== -1) return 0;
1693 TRACE("tool %d\n", nTool
);
1695 toolPtr
= &infoPtr
->tools
[nTool
];
1697 /* copy tool data */
1698 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1699 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1700 toolPtr
->uId
= lpToolInfo
->uId
;
1701 toolPtr
->rect
= lpToolInfo
->rect
;
1702 toolPtr
->hinst
= lpToolInfo
->hinst
;
1704 if (HIWORD(lpToolInfo
->lpszText
) == 0) {
1705 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1706 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1708 else if (lpToolInfo
->lpszText
) {
1709 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1710 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1712 if ( (toolPtr
->lpszText
) &&
1713 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1714 Free (toolPtr
->lpszText
);
1715 toolPtr
->lpszText
= NULL
;
1717 if (lpToolInfo
->lpszText
) {
1718 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1720 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
1721 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1722 toolPtr
->lpszText
, len
);
1727 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1728 toolPtr
->lParam
= lpToolInfo
->lParam
;
1735 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1737 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1738 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1739 TTTOOL_INFO
*toolPtr
;
1742 if (lpToolInfo
== NULL
)
1744 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1747 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1748 if (nTool
== -1) return 0;
1750 TRACE("tool %d\n", nTool
);
1752 toolPtr
= &infoPtr
->tools
[nTool
];
1754 /* copy tool data */
1755 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1756 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1757 toolPtr
->uId
= lpToolInfo
->uId
;
1758 toolPtr
->rect
= lpToolInfo
->rect
;
1759 toolPtr
->hinst
= lpToolInfo
->hinst
;
1761 if (HIWORD(lpToolInfo
->lpszText
) == 0) {
1762 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1763 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1765 else if (lpToolInfo
->lpszText
) {
1766 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1767 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1769 if ( (toolPtr
->lpszText
) &&
1770 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1771 Free (toolPtr
->lpszText
);
1772 toolPtr
->lpszText
= NULL
;
1774 if (lpToolInfo
->lpszText
) {
1775 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1776 toolPtr
->lpszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1777 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1782 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1783 toolPtr
->lParam
= lpToolInfo
->lParam
;
1790 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1792 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1793 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1795 if (lpToolInfo
== NULL
)
1797 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1802 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1803 if (infoPtr
->nTrackTool
!= -1) {
1804 TRACE("activated!\n");
1805 infoPtr
->bTrackActive
= TRUE
;
1806 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1811 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1813 infoPtr
->bTrackActive
= FALSE
;
1814 infoPtr
->nTrackTool
= -1;
1816 TRACE("deactivated!\n");
1824 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1826 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1828 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1829 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1831 if (infoPtr
->bTrackActive
) {
1833 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1835 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1843 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1845 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1847 if (infoPtr
->nCurrentTool
!= -1)
1848 UpdateWindow (hwnd
);
1855 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1857 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1858 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1859 TTTOOL_INFO
*toolPtr
;
1862 if (lpToolInfo
== NULL
)
1864 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1867 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1868 if (nTool
== -1) return 0;
1870 TRACE("tool %d\n", nTool
);
1872 toolPtr
= &infoPtr
->tools
[nTool
];
1874 /* copy tool text */
1875 toolPtr
->hinst
= lpToolInfo
->hinst
;
1877 if (HIWORD(lpToolInfo
->lpszText
) == 0){
1878 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1880 else if (lpToolInfo
->lpszText
) {
1881 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1882 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1884 if ( (toolPtr
->lpszText
) &&
1885 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1886 Free (toolPtr
->lpszText
);
1887 toolPtr
->lpszText
= NULL
;
1889 if (lpToolInfo
->lpszText
) {
1890 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1892 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
1893 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1894 toolPtr
->lpszText
, len
);
1899 if(infoPtr
->nCurrentTool
== -1) return 0;
1901 if (infoPtr
->bActive
)
1902 TOOLTIPS_Show (hwnd
, infoPtr
);
1903 else if (infoPtr
->bTrackActive
)
1904 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1911 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1913 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1914 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1915 TTTOOL_INFO
*toolPtr
;
1918 if (lpToolInfo
== NULL
)
1920 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1923 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1927 TRACE("tool %d\n", nTool
);
1929 toolPtr
= &infoPtr
->tools
[nTool
];
1931 /* copy tool text */
1932 toolPtr
->hinst
= lpToolInfo
->hinst
;
1934 if (HIWORD(lpToolInfo
->lpszText
) == 0){
1935 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1937 else if (lpToolInfo
->lpszText
) {
1938 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1939 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1941 if ( (toolPtr
->lpszText
) &&
1942 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1943 Free (toolPtr
->lpszText
);
1944 toolPtr
->lpszText
= NULL
;
1946 if (lpToolInfo
->lpszText
) {
1947 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1948 toolPtr
->lpszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1949 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1954 if(infoPtr
->nCurrentTool
== -1) return 0;
1956 if (infoPtr
->bActive
)
1957 TOOLTIPS_Show (hwnd
, infoPtr
);
1958 else if (infoPtr
->bTrackActive
)
1959 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1966 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1968 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1974 TOOLTIPS_Create (HWND hwnd
, const CREATESTRUCTW
*lpcs
)
1976 TOOLTIPS_INFO
*infoPtr
;
1977 NONCLIENTMETRICSA nclm
;
1979 /* allocate memory for info structure */
1980 infoPtr
= (TOOLTIPS_INFO
*)Alloc (sizeof(TOOLTIPS_INFO
));
1981 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1983 /* initialize info structure */
1984 infoPtr
->bActive
= TRUE
;
1985 infoPtr
->bTrackActive
= FALSE
;
1986 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1987 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
1989 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
1990 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
1991 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
1993 infoPtr
->nMaxTipWidth
= -1;
1994 infoPtr
->nTool
= -1;
1995 infoPtr
->nCurrentTool
= -1;
1996 infoPtr
->nTrackTool
= -1;
1998 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
2000 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
2007 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2009 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2010 TTTOOL_INFO
*toolPtr
;
2014 if (infoPtr
->tools
) {
2015 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
2016 toolPtr
= &infoPtr
->tools
[i
];
2017 if (toolPtr
->lpszText
) {
2018 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
2019 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
2021 Free (toolPtr
->lpszText
);
2022 toolPtr
->lpszText
= NULL
;
2026 /* remove subclassing */
2027 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
2028 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
2029 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
2032 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
2036 Free (infoPtr
->tools
);
2040 DeleteObject (infoPtr
->hFont
);
2042 /* free tool tips info data */
2044 SetWindowLongA(hwnd
, 0, 0);
2050 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2052 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2056 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2057 GetClientRect (hwnd
, &rect
);
2058 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2059 DeleteObject (hBrush
);
2066 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2068 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2070 return (LRESULT
)infoPtr
->hFont
;
2075 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2077 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2079 TOOLTIPS_Hide (hwnd
, infoPtr
);
2086 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2088 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2089 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2091 dwStyle
&= 0x0000FFFF;
2092 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2093 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2095 dwExStyle
|= WS_EX_TOOLWINDOW
;
2096 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2103 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2105 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2106 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2108 TRACE(" nTool=%d\n", nTool
);
2110 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2111 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2112 TRACE("-- in transparent mode!\n");
2113 return HTTRANSPARENT
;
2117 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2122 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2124 FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2131 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2136 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2137 TOOLTIPS_Refresh (hwnd
, hdc
);
2139 EndPaint (hwnd
, &ps
);
2145 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2147 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2150 if(!GetObjectW((HFONT
)wParam
, sizeof(lf
), &lf
))
2153 if(infoPtr
->hFont
) DeleteObject (infoPtr
->hFont
);
2154 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2156 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2157 FIXME("full redraw needed!\n");
2162 /******************************************************************
2163 * TOOLTIPS_OnWMGetTextLength
2165 * This function is called when the tooltip receive a
2166 * WM_GETTEXTLENGTH message.
2170 * returns the length, in characters, of the tip text
2171 ******************************************************************/
2173 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2175 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2176 return lstrlenW(infoPtr
->szTipText
);
2179 /******************************************************************
2180 * TOOLTIPS_OnWMGetText
2182 * This function is called when the tooltip receive a
2183 * WM_GETTEXT message.
2184 * wParam : specifies the maximum number of characters to be copied
2185 * lParam : is the pointer to the buffer that will receive
2188 * returns the number of characters copied
2189 ******************************************************************/
2191 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2193 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2195 if(!infoPtr
|| !(infoPtr
->szTipText
))
2198 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2199 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2203 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2205 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2208 TRACE("timer %d (%p) expired!\n", wParam
, hwnd
);
2212 KillTimer (hwnd
, ID_TIMERSHOW
);
2213 nOldTool
= infoPtr
->nTool
;
2214 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2215 TOOLTIPS_Show (hwnd
, infoPtr
);
2219 TOOLTIPS_Hide (hwnd
, infoPtr
);
2223 nOldTool
= infoPtr
->nTool
;
2224 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2225 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
2226 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2227 if (infoPtr
->nTool
!= nOldTool
) {
2228 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2229 TOOLTIPS_Hide(hwnd
, infoPtr
);
2230 KillTimer(hwnd
, ID_TIMERLEAVE
);
2231 } else if (nOldTool
== -1) { /* Moved from outside */
2232 ERR("How did this happen?\n");
2233 } else { /* Moved from one to another */
2234 TOOLTIPS_Hide (hwnd
, infoPtr
);
2235 KillTimer(hwnd
, ID_TIMERLEAVE
);
2236 if(infoPtr
->bActive
) {
2237 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2238 TRACE("timer 1 started!\n");
2245 ERR("Unknown timer id %d\n", wParam
);
2253 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2255 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2256 NONCLIENTMETRICSA nclm
;
2258 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2259 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2261 DeleteObject (infoPtr
->hFont
);
2262 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2263 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2264 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2271 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uID
, DWORD_PTR dwRef
)
2277 case WM_LBUTTONDOWN
:
2279 case WM_MBUTTONDOWN
:
2281 case WM_RBUTTONDOWN
:
2285 msg
.wParam
= wParam
;
2286 msg
.lParam
= lParam
;
2287 TOOLTIPS_RelayEvent((HWND
)dwRef
, 0, (LPARAM
)&msg
);
2293 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
2297 static LRESULT CALLBACK
2298 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2300 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2301 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2302 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2306 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2309 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2312 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2315 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2318 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2320 case TTM_ENUMTOOLSA
:
2321 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2323 case TTM_ENUMTOOLSW
:
2324 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2326 case TTM_GETBUBBLESIZE
:
2327 return TOOLTIPS_GetBubbleSize (hwnd
, wParam
, lParam
);
2329 case TTM_GETCURRENTTOOLA
:
2330 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2332 case TTM_GETCURRENTTOOLW
:
2333 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2335 case TTM_GETDELAYTIME
:
2336 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2339 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2341 case TTM_GETMAXTIPWIDTH
:
2342 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2345 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2348 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2350 case TTM_GETTIPBKCOLOR
:
2351 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2353 case TTM_GETTIPTEXTCOLOR
:
2354 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2356 case TTM_GETTOOLCOUNT
:
2357 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2359 case TTM_GETTOOLINFOA
:
2360 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2362 case TTM_GETTOOLINFOW
:
2363 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2366 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2369 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2371 case TTM_NEWTOOLRECTA
:
2372 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2374 case TTM_NEWTOOLRECTW
:
2375 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2378 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2380 case TTM_RELAYEVENT
:
2381 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2383 case TTM_SETDELAYTIME
:
2384 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2387 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2389 case TTM_SETMAXTIPWIDTH
:
2390 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2392 case TTM_SETTIPBKCOLOR
:
2393 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2395 case TTM_SETTIPTEXTCOLOR
:
2396 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2398 case TTM_SETTOOLINFOA
:
2399 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2401 case TTM_SETTOOLINFOW
:
2402 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2404 case TTM_TRACKACTIVATE
:
2405 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2407 case TTM_TRACKPOSITION
:
2408 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2411 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2413 case TTM_UPDATETIPTEXTA
:
2414 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2416 case TTM_UPDATETIPTEXTW
:
2417 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2419 case TTM_WINDOWFROMPOINT
:
2420 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2424 return TOOLTIPS_Create (hwnd
, (LPCREATESTRUCTW
)lParam
);
2427 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2430 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2433 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2436 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2438 case WM_GETTEXTLENGTH
:
2439 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2442 case WM_LBUTTONDOWN
:
2444 case WM_MBUTTONDOWN
:
2446 case WM_RBUTTONDOWN
:
2449 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2452 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2455 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2457 case WM_NOTIFYFORMAT
:
2458 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2461 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2464 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2467 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2469 case WM_WININICHANGE
:
2470 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2473 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2474 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2475 uMsg
, wParam
, lParam
);
2476 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2483 TOOLTIPS_Register (void)
2487 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2488 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2489 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2490 wndClass
.cbClsExtra
= 0;
2491 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2492 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
2493 wndClass
.hbrBackground
= 0;
2494 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2496 RegisterClassA (&wndClass
);
2501 TOOLTIPS_Unregister (void)
2503 UnregisterClassA (TOOLTIPS_CLASSA
, NULL
);