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
);
103 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
);
176 TOOLTIPS_GetTipText (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, INT nTool
)
178 TTTOOL_INFO
*toolPtr
= &infoPtr
->tools
[nTool
];
180 if (HIWORD((UINT
)toolPtr
->lpszText
) == 0) {
181 /* load a resource */
182 TRACE("load res string %p %x\n",
183 toolPtr
->hinst
, (int)toolPtr
->lpszText
);
184 LoadStringW (toolPtr
->hinst
, (UINT
)toolPtr
->lpszText
,
185 infoPtr
->szTipText
, INFOTIPSIZE
);
187 else if (toolPtr
->lpszText
) {
188 if (toolPtr
->lpszText
== LPSTR_TEXTCALLBACKW
) {
189 NMTTDISPINFOA ttnmdi
;
191 /* fill NMHDR struct */
192 ZeroMemory (&ttnmdi
, sizeof(NMTTDISPINFOA
));
193 ttnmdi
.hdr
.hwndFrom
= hwnd
;
194 ttnmdi
.hdr
.idFrom
= toolPtr
->uId
;
195 ttnmdi
.hdr
.code
= TTN_GETDISPINFOA
;
196 ttnmdi
.lpszText
= (LPSTR
)&ttnmdi
.szText
;
197 ttnmdi
.uFlags
= toolPtr
->uFlags
;
198 ttnmdi
.lParam
= toolPtr
->lParam
;
200 TRACE("hdr.idFrom = %x\n", ttnmdi
.hdr
.idFrom
);
201 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
202 (WPARAM
)toolPtr
->uId
, (LPARAM
)&ttnmdi
);
204 if (HIWORD((UINT
)ttnmdi
.lpszText
) == 0) {
205 LoadStringW (ttnmdi
.hinst
, (UINT
)ttnmdi
.lpszText
,
206 infoPtr
->szTipText
, INFOTIPSIZE
);
207 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
208 toolPtr
->hinst
= ttnmdi
.hinst
;
209 toolPtr
->lpszText
= (LPWSTR
)ttnmdi
.lpszText
;
212 else if (ttnmdi
.szText
[0]) {
213 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
214 infoPtr
->szTipText
, INFOTIPSIZE
);
215 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
216 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
,
219 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
220 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.szText
, 80,
221 toolPtr
->lpszText
, len
);
224 else if (ttnmdi
.lpszText
== 0) {
225 /* no text available */
226 infoPtr
->szTipText
[0] = L
'\0';
228 else if (ttnmdi
.lpszText
!= LPSTR_TEXTCALLBACKA
) {
229 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
230 infoPtr
->szTipText
, INFOTIPSIZE
);
231 if (ttnmdi
.uFlags
& TTF_DI_SETITEM
) {
232 INT len
= MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
,
235 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
236 MultiByteToWideChar(CP_ACP
, 0, ttnmdi
.lpszText
, -1,
237 toolPtr
->lpszText
, len
);
241 ERR("recursive text callback!\n");
242 infoPtr
->szTipText
[0] = '\0';
246 /* the item is a usual (unicode) text */
247 lstrcpynW (infoPtr
->szTipText
, toolPtr
->lpszText
, INFOTIPSIZE
);
251 /* no text available */
252 infoPtr
->szTipText
[0] = L
'\0';
255 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
260 TOOLTIPS_CalcTipSize (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
, LPSIZE lpSize
)
264 UINT uFlags
= DT_EXTERNALLEADING
| DT_CALCRECT
;
265 RECT rc
= {0, 0, 0, 0};
267 if (infoPtr
->nMaxTipWidth
> -1) {
268 rc
.right
= infoPtr
->nMaxTipWidth
;
269 uFlags
|= DT_WORDBREAK
;
271 if (GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_NOPREFIX
)
272 uFlags
|= DT_NOPREFIX
;
273 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
276 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
277 DrawTextW (hdc
, infoPtr
->szTipText
, -1, &rc
, uFlags
);
278 SelectObject (hdc
, hOldFont
);
279 ReleaseDC (hwnd
, hdc
);
281 lpSize
->cx
= rc
.right
- rc
.left
+ 4 +
282 infoPtr
->rcMargin
.left
+ infoPtr
->rcMargin
.right
;
283 lpSize
->cy
= rc
.bottom
- rc
.top
+ 4 +
284 infoPtr
->rcMargin
.bottom
+ infoPtr
->rcMargin
.top
;
289 TOOLTIPS_Show (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
291 TTTOOL_INFO
*toolPtr
;
296 if (infoPtr
->nTool
== -1) {
297 TRACE("invalid tool (-1)!\n");
301 infoPtr
->nCurrentTool
= infoPtr
->nTool
;
303 TRACE("Show tooltip pre %d! (%p)\n", infoPtr
->nTool
, hwnd
);
305 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nCurrentTool
);
307 if (infoPtr
->szTipText
[0] == L
'\0') {
308 infoPtr
->nCurrentTool
= -1;
312 TRACE("Show tooltip %d!\n", infoPtr
->nCurrentTool
);
313 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
316 hdr
.idFrom
= toolPtr
->uId
;
318 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
319 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
321 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
323 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
324 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
326 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
329 if (toolPtr
->uFlags
& TTF_IDISHWND
)
330 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
333 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
335 rect
.left
= (rc
.left
+ rc
.right
- size
.cx
) / 2;
336 rect
.top
= rc
.bottom
+ 2;
339 GetCursorPos ((LPPOINT
)&rect
);
343 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
345 rect
.right
= rect
.left
+ size
.cx
;
346 rect
.bottom
= rect
.top
+ size
.cy
;
349 wndrect
.right
= GetSystemMetrics( SM_CXSCREEN
);
350 if( rect
.right
> wndrect
.right
) {
351 rect
.left
-= rect
.right
- wndrect
.right
+ 2;
352 rect
.right
= wndrect
.right
- 2;
354 wndrect
.bottom
= GetSystemMetrics( SM_CYSCREEN
);
355 if( rect
.bottom
> wndrect
.bottom
) {
358 if (toolPtr
->uFlags
& TTF_IDISHWND
)
359 GetWindowRect ((HWND
)toolPtr
->uId
, &rc
);
362 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rc
, 2);
364 rect
.bottom
= rc
.top
- 2;
365 rect
.top
= rect
.bottom
- size
.cy
;
368 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
369 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
371 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
372 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
373 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
375 /* repaint the tooltip */
376 InvalidateRect(hwnd
, NULL
, TRUE
);
379 SetTimer (hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
380 TRACE("timer 2 started!\n");
381 SetTimer (hwnd
, ID_TIMERLEAVE
, infoPtr
->nReshowTime
, 0);
382 TRACE("timer 3 started!\n");
387 TOOLTIPS_Hide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
389 TTTOOL_INFO
*toolPtr
;
392 TRACE("Hide tooltip %d! (%p)\n", infoPtr
->nCurrentTool
, hwnd
);
394 if (infoPtr
->nCurrentTool
== -1)
397 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
398 KillTimer (hwnd
, ID_TIMERPOP
);
401 hdr
.idFrom
= toolPtr
->uId
;
403 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
404 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
406 infoPtr
->nCurrentTool
= -1;
408 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
409 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
414 TOOLTIPS_TrackShow (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
416 TTTOOL_INFO
*toolPtr
;
421 if (infoPtr
->nTrackTool
== -1) {
422 TRACE("invalid tracking tool (-1)!\n");
426 TRACE("show tracking tooltip pre %d!\n", infoPtr
->nTrackTool
);
428 TOOLTIPS_GetTipText (hwnd
, infoPtr
, infoPtr
->nTrackTool
);
430 if (infoPtr
->szTipText
[0] == L
'\0') {
431 infoPtr
->nTrackTool
= -1;
435 TRACE("show tracking tooltip %d!\n", infoPtr
->nTrackTool
);
436 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
439 hdr
.idFrom
= toolPtr
->uId
;
441 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
442 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
444 TRACE("%s\n", debugstr_w(infoPtr
->szTipText
));
446 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
447 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
449 if (toolPtr
->uFlags
& TTF_ABSOLUTE
) {
450 rect
.left
= infoPtr
->xTrackPos
;
451 rect
.top
= infoPtr
->yTrackPos
;
453 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
454 rect
.left
-= (size
.cx
/ 2);
455 rect
.top
-= (size
.cy
/ 2);
461 if (toolPtr
->uFlags
& TTF_IDISHWND
)
462 GetWindowRect ((HWND
)toolPtr
->uId
, &rcTool
);
464 rcTool
= toolPtr
->rect
;
465 MapWindowPoints (toolPtr
->hwnd
, NULL
, (LPPOINT
)&rcTool
, 2);
468 GetCursorPos ((LPPOINT
)&rect
);
471 if (toolPtr
->uFlags
& TTF_CENTERTIP
) {
472 rect
.left
-= (size
.cx
/ 2);
473 rect
.top
-= (size
.cy
/ 2);
476 /* smart placement */
477 if ((rect
.left
+ size
.cx
> rcTool
.left
) && (rect
.left
< rcTool
.right
) &&
478 (rect
.top
+ size
.cy
> rcTool
.top
) && (rect
.top
< rcTool
.bottom
))
479 rect
.left
= rcTool
.right
;
482 TRACE("pos %ld - %ld\n", rect
.left
, rect
.top
);
484 rect
.right
= rect
.left
+ size
.cx
;
485 rect
.bottom
= rect
.top
+ size
.cy
;
487 AdjustWindowRectEx (&rect
, GetWindowLongA (hwnd
, GWL_STYLE
),
488 FALSE
, GetWindowLongA (hwnd
, GWL_EXSTYLE
));
490 SetWindowPos (hwnd
, HWND_TOP
, rect
.left
, rect
.top
,
491 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
492 SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
494 InvalidateRect(hwnd
, NULL
, TRUE
);
500 TOOLTIPS_TrackHide (HWND hwnd
, TOOLTIPS_INFO
*infoPtr
)
502 TTTOOL_INFO
*toolPtr
;
505 if (infoPtr
->nTrackTool
== -1)
508 toolPtr
= &infoPtr
->tools
[infoPtr
->nTrackTool
];
509 TRACE("hide tracking tooltip %d!\n", infoPtr
->nTrackTool
);
512 hdr
.idFrom
= toolPtr
->uId
;
514 SendMessageA (toolPtr
->hwnd
, WM_NOTIFY
,
515 (WPARAM
)toolPtr
->uId
, (LPARAM
)&hdr
);
517 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0,
518 SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
523 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOA lpToolInfo
)
525 TTTOOL_INFO
*toolPtr
;
528 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
529 toolPtr
= &infoPtr
->tools
[nTool
];
531 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
532 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
533 (lpToolInfo
->uId
== toolPtr
->uId
))
537 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
538 toolPtr
= &infoPtr
->tools
[nTool
];
540 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
541 (lpToolInfo
->uId
== toolPtr
->uId
))
550 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO
*infoPtr
, LPTTTOOLINFOW lpToolInfo
)
552 TTTOOL_INFO
*toolPtr
;
555 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
556 toolPtr
= &infoPtr
->tools
[nTool
];
558 if (!(toolPtr
->uFlags
& TTF_IDISHWND
) &&
559 (lpToolInfo
->hwnd
== toolPtr
->hwnd
) &&
560 (lpToolInfo
->uId
== toolPtr
->uId
))
564 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
565 toolPtr
= &infoPtr
->tools
[nTool
];
567 if ((toolPtr
->uFlags
& TTF_IDISHWND
) &&
568 (lpToolInfo
->uId
== toolPtr
->uId
))
577 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO
*infoPtr
, HWND hwnd
, LPPOINT lpPt
)
579 TTTOOL_INFO
*toolPtr
;
582 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
583 toolPtr
= &infoPtr
->tools
[nTool
];
585 if (!(toolPtr
->uFlags
& TTF_IDISHWND
)) {
586 if (hwnd
!= toolPtr
->hwnd
)
588 if (!PtInRect (&toolPtr
->rect
, *lpPt
))
594 for (nTool
= 0; nTool
< infoPtr
->uNumTools
; nTool
++) {
595 toolPtr
= &infoPtr
->tools
[nTool
];
597 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
598 if ((HWND
)toolPtr
->uId
== hwnd
)
608 TOOLTIPS_IsWindowActive (HWND hwnd
)
610 HWND hwndActive
= GetActiveWindow ();
613 if (hwndActive
== hwnd
)
615 return IsChild (hwndActive
, hwnd
);
620 TOOLTIPS_CheckTool (HWND hwnd
, BOOL bShowTest
)
622 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
628 hwndTool
= (HWND
)SendMessageA (hwnd
, TTM_WINDOWFROMPOINT
, 0, (LPARAM
)&pt
);
632 ScreenToClient (hwndTool
, &pt
);
633 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, hwndTool
, &pt
);
637 if (!(GetWindowLongA (hwnd
, GWL_STYLE
) & TTS_ALWAYSTIP
) && bShowTest
) {
638 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd
, GW_OWNER
)))
642 TRACE("tool %d\n", nTool
);
649 TOOLTIPS_Activate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
651 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
653 infoPtr
->bActive
= (BOOL
)wParam
;
655 if (infoPtr
->bActive
)
656 TRACE("activate!\n");
658 if (!(infoPtr
->bActive
) && (infoPtr
->nCurrentTool
!= -1))
659 TOOLTIPS_Hide (hwnd
, infoPtr
);
666 TOOLTIPS_AddToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
668 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
669 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
670 TTTOOL_INFO
*toolPtr
;
672 if (lpToolInfo
== NULL
)
674 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
677 TRACE("add tool (%p) %p %d%s!\n",
678 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
679 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
681 if (infoPtr
->uNumTools
== 0) {
682 infoPtr
->tools
= Alloc (sizeof(TTTOOL_INFO
));
683 toolPtr
= infoPtr
->tools
;
686 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
688 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
689 memcpy (infoPtr
->tools
, oldTools
,
690 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
692 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
695 infoPtr
->uNumTools
++;
698 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
699 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
700 toolPtr
->uId
= lpToolInfo
->uId
;
701 toolPtr
->rect
= lpToolInfo
->rect
;
702 toolPtr
->hinst
= lpToolInfo
->hinst
;
704 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
705 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
706 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
708 else if (lpToolInfo
->lpszText
) {
709 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
) {
710 TRACE("add CALLBACK!\n");
711 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
714 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
716 TRACE("add text \"%s\"!\n", lpToolInfo
->lpszText
);
717 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
718 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
719 toolPtr
->lpszText
, len
);
723 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
724 toolPtr
->lParam
= lpToolInfo
->lParam
;
726 /* install subclassing hook */
727 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
728 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
729 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
733 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
736 TRACE("subclassing installed!\n");
744 TOOLTIPS_AddToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
746 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
747 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
748 TTTOOL_INFO
*toolPtr
;
750 if (lpToolInfo
== NULL
)
752 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
755 TRACE("add tool (%p) %p %d%s!\n",
756 hwnd
, lpToolInfo
->hwnd
, lpToolInfo
->uId
,
757 (lpToolInfo
->uFlags
& TTF_IDISHWND
) ? " TTF_IDISHWND" : "");
759 if (infoPtr
->uNumTools
== 0) {
760 infoPtr
->tools
= Alloc (sizeof(TTTOOL_INFO
));
761 toolPtr
= infoPtr
->tools
;
764 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
766 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
+ 1));
767 memcpy (infoPtr
->tools
, oldTools
,
768 infoPtr
->uNumTools
* sizeof(TTTOOL_INFO
));
770 toolPtr
= &infoPtr
->tools
[infoPtr
->uNumTools
];
773 infoPtr
->uNumTools
++;
776 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
777 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
778 toolPtr
->uId
= lpToolInfo
->uId
;
779 toolPtr
->rect
= lpToolInfo
->rect
;
780 toolPtr
->hinst
= lpToolInfo
->hinst
;
782 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
783 TRACE("add string id %x!\n", (int)lpToolInfo
->lpszText
);
784 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
786 else if (lpToolInfo
->lpszText
) {
787 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
) {
788 TRACE("add CALLBACK!\n");
789 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
792 INT len
= lstrlenW (lpToolInfo
->lpszText
);
793 TRACE("add text %s!\n",
794 debugstr_w(lpToolInfo
->lpszText
));
795 toolPtr
->lpszText
= Alloc ((len
+ 1)*sizeof(WCHAR
));
796 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
800 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
801 toolPtr
->lParam
= lpToolInfo
->lParam
;
803 /* install subclassing hook */
804 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
805 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
806 SetWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1,
810 SetWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1,
813 TRACE("subclassing installed!\n");
821 TOOLTIPS_DelToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
823 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
824 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
825 TTTOOL_INFO
*toolPtr
;
828 if (lpToolInfo
== NULL
)
830 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
832 if (infoPtr
->uNumTools
== 0)
835 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
836 if (nTool
== -1) return 0;
838 TRACE("tool %d\n", nTool
);
840 /* make sure the tooltip has disappeared before deleting it */
841 TOOLTIPS_Hide(hwnd
, infoPtr
);
843 /* delete text string */
844 toolPtr
= &infoPtr
->tools
[nTool
];
845 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
846 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
847 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
848 Free (toolPtr
->lpszText
);
851 /* remove subclassing */
852 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
853 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
854 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
857 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
861 /* delete tool from tool list */
862 if (infoPtr
->uNumTools
== 1) {
863 Free (infoPtr
->tools
);
864 infoPtr
->tools
= NULL
;
867 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
869 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
872 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
873 nTool
* sizeof(TTTOOL_INFO
));
875 if (nTool
< infoPtr
->uNumTools
- 1)
876 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
877 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
882 /* destroying tool that mouse was on on last relayed mouse move */
883 if (infoPtr
->nTool
== nTool
)
885 /* no current tool (0 means first tool) */
889 infoPtr
->uNumTools
--;
896 TOOLTIPS_DelToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
898 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
899 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
900 TTTOOL_INFO
*toolPtr
;
903 if (lpToolInfo
== NULL
)
905 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
907 if (infoPtr
->uNumTools
== 0)
910 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
911 if (nTool
== -1) return 0;
913 TRACE("tool %d\n", nTool
);
915 /* make sure the tooltip has disappeared before deleting it */
916 TOOLTIPS_Hide(hwnd
, infoPtr
);
918 /* delete text string */
919 toolPtr
= &infoPtr
->tools
[nTool
];
920 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
921 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
922 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
923 Free (toolPtr
->lpszText
);
926 /* remove subclassing */
927 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
928 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
929 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
932 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
936 /* delete tool from tool list */
937 if (infoPtr
->uNumTools
== 1) {
938 Free (infoPtr
->tools
);
939 infoPtr
->tools
= NULL
;
942 TTTOOL_INFO
*oldTools
= infoPtr
->tools
;
944 Alloc (sizeof(TTTOOL_INFO
) * (infoPtr
->uNumTools
- 1));
947 memcpy (&infoPtr
->tools
[0], &oldTools
[0],
948 nTool
* sizeof(TTTOOL_INFO
));
950 if (nTool
< infoPtr
->uNumTools
- 1)
951 memcpy (&infoPtr
->tools
[nTool
], &oldTools
[nTool
+ 1],
952 (infoPtr
->uNumTools
- nTool
- 1) * sizeof(TTTOOL_INFO
));
957 /* destroying tool that mouse was on on last relayed mouse move */
958 if (infoPtr
->nTool
== nTool
)
960 /* no current tool (0 means first tool) */
964 infoPtr
->uNumTools
--;
971 TOOLTIPS_EnumToolsA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
973 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
974 UINT uIndex
= (UINT
)wParam
;
975 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
976 TTTOOL_INFO
*toolPtr
;
978 if (lpToolInfo
== NULL
)
980 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
982 if (uIndex
>= infoPtr
->uNumTools
)
985 TRACE("index=%u\n", uIndex
);
987 toolPtr
= &infoPtr
->tools
[uIndex
];
990 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
991 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
992 lpToolInfo
->uId
= toolPtr
->uId
;
993 lpToolInfo
->rect
= toolPtr
->rect
;
994 lpToolInfo
->hinst
= toolPtr
->hinst
;
995 /* lpToolInfo->lpszText = toolPtr->lpszText; */
996 lpToolInfo
->lpszText
= NULL
; /* FIXME */
998 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
999 lpToolInfo
->lParam
= toolPtr
->lParam
;
1006 TOOLTIPS_EnumToolsW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1008 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1009 UINT uIndex
= (UINT
)wParam
;
1010 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1011 TTTOOL_INFO
*toolPtr
;
1013 if (lpToolInfo
== NULL
)
1015 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1017 if (uIndex
>= infoPtr
->uNumTools
)
1020 TRACE("index=%u\n", uIndex
);
1022 toolPtr
= &infoPtr
->tools
[uIndex
];
1024 /* copy tool data */
1025 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1026 lpToolInfo
->hwnd
= toolPtr
->hwnd
;
1027 lpToolInfo
->uId
= toolPtr
->uId
;
1028 lpToolInfo
->rect
= toolPtr
->rect
;
1029 lpToolInfo
->hinst
= toolPtr
->hinst
;
1030 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1031 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1033 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1034 lpToolInfo
->lParam
= toolPtr
->lParam
;
1040 TOOLTIPS_GetBubbleSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1042 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1043 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1047 if (lpToolInfo
== NULL
)
1049 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1052 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1053 if (nTool
== -1) return 0;
1055 TRACE("tool %d\n", nTool
);
1057 TOOLTIPS_CalcTipSize (hwnd
, infoPtr
, &size
);
1058 TRACE("size %ld x %ld\n", size
.cx
, size
.cy
);
1060 return MAKELRESULT(size
.cx
, size
.cy
);
1064 TOOLTIPS_GetCurrentToolA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1066 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1067 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1068 TTTOOL_INFO
*toolPtr
;
1070 if (lpToolInfo
== NULL
)
1072 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1076 if (infoPtr
->nCurrentTool
> -1) {
1077 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1079 /* copy tool data */
1080 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1081 lpToolInfo
->rect
= toolPtr
->rect
;
1082 lpToolInfo
->hinst
= toolPtr
->hinst
;
1083 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1084 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1086 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1087 lpToolInfo
->lParam
= toolPtr
->lParam
;
1095 return (infoPtr
->nCurrentTool
!= -1);
1102 TOOLTIPS_GetCurrentToolW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1104 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1105 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1106 TTTOOL_INFO
*toolPtr
;
1108 if (lpToolInfo
== NULL
)
1110 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1114 if (infoPtr
->nCurrentTool
> -1) {
1115 toolPtr
= &infoPtr
->tools
[infoPtr
->nCurrentTool
];
1117 /* copy tool data */
1118 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1119 lpToolInfo
->rect
= toolPtr
->rect
;
1120 lpToolInfo
->hinst
= toolPtr
->hinst
;
1121 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1122 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1124 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1125 lpToolInfo
->lParam
= toolPtr
->lParam
;
1133 return (infoPtr
->nCurrentTool
!= -1);
1140 TOOLTIPS_GetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1142 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1146 return infoPtr
->nReshowTime
;
1149 return infoPtr
->nAutoPopTime
;
1152 case TTDT_AUTOMATIC
: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1153 return infoPtr
->nInitialTime
;
1156 WARN("Invalid wParam %x\n", wParam
);
1165 TOOLTIPS_GetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1167 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1168 LPRECT lpRect
= (LPRECT
)lParam
;
1170 lpRect
->left
= infoPtr
->rcMargin
.left
;
1171 lpRect
->right
= infoPtr
->rcMargin
.right
;
1172 lpRect
->bottom
= infoPtr
->rcMargin
.bottom
;
1173 lpRect
->top
= infoPtr
->rcMargin
.top
;
1179 inline static LRESULT
1180 TOOLTIPS_GetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1182 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1184 return infoPtr
->nMaxTipWidth
;
1189 TOOLTIPS_GetTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1191 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1192 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1195 if (lpToolInfo
== NULL
)
1197 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1200 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1201 if (nTool
== -1) return 0;
1203 /* NB this API is broken, there is no way for the app to determine
1204 what size buffer it requires nor a way to specify how long the
1205 one it supplies is. We'll assume it's upto INFOTIPSIZE */
1207 WideCharToMultiByte(CP_ACP
, 0, infoPtr
->tools
[nTool
].lpszText
, -1,
1208 lpToolInfo
->lpszText
, INFOTIPSIZE
, NULL
, NULL
);
1215 TOOLTIPS_GetTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1217 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1218 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1221 if (lpToolInfo
== NULL
)
1223 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1226 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1227 if (nTool
== -1) return 0;
1229 strcpyW (lpToolInfo
->lpszText
, infoPtr
->tools
[nTool
].lpszText
);
1235 inline static LRESULT
1236 TOOLTIPS_GetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1238 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1239 return infoPtr
->clrBk
;
1243 inline static LRESULT
1244 TOOLTIPS_GetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1246 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1247 return infoPtr
->clrText
;
1251 inline static LRESULT
1252 TOOLTIPS_GetToolCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1254 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1255 return infoPtr
->uNumTools
;
1260 TOOLTIPS_GetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1262 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1263 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1264 TTTOOL_INFO
*toolPtr
;
1267 if (lpToolInfo
== NULL
)
1269 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1271 if (infoPtr
->uNumTools
== 0)
1274 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1278 TRACE("tool %d\n", nTool
);
1280 toolPtr
= &infoPtr
->tools
[nTool
];
1282 /* copy tool data */
1283 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1284 lpToolInfo
->rect
= toolPtr
->rect
;
1285 lpToolInfo
->hinst
= toolPtr
->hinst
;
1286 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1287 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1289 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1290 lpToolInfo
->lParam
= toolPtr
->lParam
;
1297 TOOLTIPS_GetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1299 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1300 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1301 TTTOOL_INFO
*toolPtr
;
1304 if (lpToolInfo
== NULL
)
1306 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1308 if (infoPtr
->uNumTools
== 0)
1311 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1315 TRACE("tool %d\n", nTool
);
1317 toolPtr
= &infoPtr
->tools
[nTool
];
1319 /* copy tool data */
1320 lpToolInfo
->uFlags
= toolPtr
->uFlags
;
1321 lpToolInfo
->rect
= toolPtr
->rect
;
1322 lpToolInfo
->hinst
= toolPtr
->hinst
;
1323 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1324 lpToolInfo
->lpszText
= NULL
; /* FIXME */
1326 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1327 lpToolInfo
->lParam
= toolPtr
->lParam
;
1334 TOOLTIPS_HitTestA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1336 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1337 LPTTHITTESTINFOA lptthit
= (LPTTHITTESTINFOA
)lParam
;
1338 TTTOOL_INFO
*toolPtr
;
1344 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1348 TRACE("tool %d!\n", nTool
);
1350 /* copy tool data */
1351 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOA
)) {
1352 toolPtr
= &infoPtr
->tools
[nTool
];
1354 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1355 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1356 lptthit
->ti
.uId
= toolPtr
->uId
;
1357 lptthit
->ti
.rect
= toolPtr
->rect
;
1358 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1359 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1360 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1361 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1369 TOOLTIPS_HitTestW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1371 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1372 LPTTHITTESTINFOW lptthit
= (LPTTHITTESTINFOW
)lParam
;
1373 TTTOOL_INFO
*toolPtr
;
1379 nTool
= TOOLTIPS_GetToolFromPoint (infoPtr
, lptthit
->hwnd
, &lptthit
->pt
);
1383 TRACE("tool %d!\n", nTool
);
1385 /* copy tool data */
1386 if (lptthit
->ti
.cbSize
>= sizeof(TTTOOLINFOW
)) {
1387 toolPtr
= &infoPtr
->tools
[nTool
];
1389 lptthit
->ti
.uFlags
= toolPtr
->uFlags
;
1390 lptthit
->ti
.hwnd
= toolPtr
->hwnd
;
1391 lptthit
->ti
.uId
= toolPtr
->uId
;
1392 lptthit
->ti
.rect
= toolPtr
->rect
;
1393 lptthit
->ti
.hinst
= toolPtr
->hinst
;
1394 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1395 lptthit
->ti
.lpszText
= NULL
; /* FIXME */
1396 lptthit
->ti
.lParam
= toolPtr
->lParam
;
1404 TOOLTIPS_NewToolRectA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1406 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1407 LPTTTOOLINFOA lpti
= (LPTTTOOLINFOA
)lParam
;
1412 if (lpti
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1415 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpti
);
1416 if (nTool
== -1) return 0;
1418 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1425 TOOLTIPS_NewToolRectW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1427 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1428 LPTTTOOLINFOW lpti
= (LPTTTOOLINFOW
)lParam
;
1433 if (lpti
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1436 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpti
);
1437 if (nTool
== -1) return 0;
1439 infoPtr
->tools
[nTool
].rect
= lpti
->rect
;
1445 inline static LRESULT
1446 TOOLTIPS_Pop (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1448 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1449 TOOLTIPS_Hide (hwnd
, infoPtr
);
1456 TOOLTIPS_RelayEvent (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1458 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1459 LPMSG lpMsg
= (LPMSG
)lParam
;
1464 ERR("lpMsg == NULL!\n");
1468 switch (lpMsg
->message
) {
1469 case WM_LBUTTONDOWN
:
1471 case WM_MBUTTONDOWN
:
1473 case WM_RBUTTONDOWN
:
1475 TOOLTIPS_Hide (hwnd
, infoPtr
);
1479 pt
.x
= LOWORD(lpMsg
->lParam
);
1480 pt
.y
= HIWORD(lpMsg
->lParam
);
1481 nOldTool
= infoPtr
->nTool
;
1482 infoPtr
->nTool
= TOOLTIPS_GetToolFromPoint(infoPtr
, lpMsg
->hwnd
,
1484 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
1485 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
1486 TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd
, pt
.x
, pt
.y
);
1488 if (infoPtr
->nTool
!= nOldTool
) {
1489 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
1490 TOOLTIPS_Hide(hwnd
, infoPtr
);
1491 KillTimer(hwnd
, ID_TIMERLEAVE
);
1492 } else if (nOldTool
== -1) { /* Moved from outside */
1493 if(infoPtr
->bActive
) {
1494 SetTimer(hwnd
, ID_TIMERSHOW
, infoPtr
->nInitialTime
, 0);
1495 TRACE("timer 1 started!\n");
1497 } else { /* Moved from one to another */
1498 TOOLTIPS_Hide (hwnd
, infoPtr
);
1499 KillTimer(hwnd
, ID_TIMERLEAVE
);
1500 if(infoPtr
->bActive
) {
1501 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
1502 TRACE("timer 1 started!\n");
1505 } else if(infoPtr
->nCurrentTool
!= -1) { /* restart autopop */
1506 KillTimer(hwnd
, ID_TIMERPOP
);
1507 SetTimer(hwnd
, ID_TIMERPOP
, infoPtr
->nAutoPopTime
, 0);
1508 TRACE("timer 2 restarted\n");
1518 TOOLTIPS_SetDelayTime (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1520 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1521 INT nTime
= (INT
)LOWORD(lParam
);
1524 case TTDT_AUTOMATIC
:
1526 nTime
= GetDoubleClickTime();
1527 infoPtr
->nReshowTime
= nTime
/ 5;
1528 infoPtr
->nAutoPopTime
= nTime
* 10;
1529 infoPtr
->nInitialTime
= nTime
;
1534 nTime
= GetDoubleClickTime() / 5;
1535 infoPtr
->nReshowTime
= nTime
;
1540 nTime
= GetDoubleClickTime() * 10;
1541 infoPtr
->nAutoPopTime
= nTime
;
1546 nTime
= GetDoubleClickTime();
1547 infoPtr
->nInitialTime
= nTime
;
1551 WARN("Invalid wParam %x\n", wParam
);
1560 TOOLTIPS_SetMargin (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1562 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1563 LPRECT lpRect
= (LPRECT
)lParam
;
1565 infoPtr
->rcMargin
.left
= lpRect
->left
;
1566 infoPtr
->rcMargin
.right
= lpRect
->right
;
1567 infoPtr
->rcMargin
.bottom
= lpRect
->bottom
;
1568 infoPtr
->rcMargin
.top
= lpRect
->top
;
1574 inline static LRESULT
1575 TOOLTIPS_SetMaxTipWidth (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1577 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1578 INT nTemp
= infoPtr
->nMaxTipWidth
;
1580 infoPtr
->nMaxTipWidth
= (INT
)lParam
;
1586 inline static LRESULT
1587 TOOLTIPS_SetTipBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1589 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1591 infoPtr
->clrBk
= (COLORREF
)wParam
;
1597 inline static LRESULT
1598 TOOLTIPS_SetTipTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1600 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1602 infoPtr
->clrText
= (COLORREF
)wParam
;
1609 TOOLTIPS_SetToolInfoA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1611 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1612 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1613 TTTOOL_INFO
*toolPtr
;
1616 if (lpToolInfo
== NULL
)
1618 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1621 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1622 if (nTool
== -1) return 0;
1624 TRACE("tool %d\n", nTool
);
1626 toolPtr
= &infoPtr
->tools
[nTool
];
1628 /* copy tool data */
1629 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1630 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1631 toolPtr
->uId
= lpToolInfo
->uId
;
1632 toolPtr
->rect
= lpToolInfo
->rect
;
1633 toolPtr
->hinst
= lpToolInfo
->hinst
;
1635 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1636 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1637 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1639 else if (lpToolInfo
->lpszText
) {
1640 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1641 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1643 if ( (toolPtr
->lpszText
) &&
1644 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1645 Free (toolPtr
->lpszText
);
1646 toolPtr
->lpszText
= NULL
;
1648 if (lpToolInfo
->lpszText
) {
1649 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1651 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
1652 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1653 toolPtr
->lpszText
, len
);
1658 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOA
))
1659 toolPtr
->lParam
= lpToolInfo
->lParam
;
1666 TOOLTIPS_SetToolInfoW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1668 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1669 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1670 TTTOOL_INFO
*toolPtr
;
1673 if (lpToolInfo
== NULL
)
1675 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1678 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1679 if (nTool
== -1) return 0;
1681 TRACE("tool %d\n", nTool
);
1683 toolPtr
= &infoPtr
->tools
[nTool
];
1685 /* copy tool data */
1686 toolPtr
->uFlags
= lpToolInfo
->uFlags
;
1687 toolPtr
->hwnd
= lpToolInfo
->hwnd
;
1688 toolPtr
->uId
= lpToolInfo
->uId
;
1689 toolPtr
->rect
= lpToolInfo
->rect
;
1690 toolPtr
->hinst
= lpToolInfo
->hinst
;
1692 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)) {
1693 TRACE("set string id %x!\n", (INT
)lpToolInfo
->lpszText
);
1694 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1696 else if (lpToolInfo
->lpszText
) {
1697 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1698 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1700 if ( (toolPtr
->lpszText
) &&
1701 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1702 Free (toolPtr
->lpszText
);
1703 toolPtr
->lpszText
= NULL
;
1705 if (lpToolInfo
->lpszText
) {
1706 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1707 toolPtr
->lpszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1708 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1713 if (lpToolInfo
->cbSize
>= sizeof(TTTOOLINFOW
))
1714 toolPtr
->lParam
= lpToolInfo
->lParam
;
1721 TOOLTIPS_TrackActivate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1723 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1724 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1726 if (lpToolInfo
== NULL
)
1728 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1733 infoPtr
->nTrackTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1734 if (infoPtr
->nTrackTool
!= -1) {
1735 TRACE("activated!\n");
1736 infoPtr
->bTrackActive
= TRUE
;
1737 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1742 TOOLTIPS_TrackHide (hwnd
, infoPtr
);
1744 infoPtr
->bTrackActive
= FALSE
;
1745 infoPtr
->nTrackTool
= -1;
1747 TRACE("deactivated!\n");
1755 TOOLTIPS_TrackPosition (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1757 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1759 infoPtr
->xTrackPos
= (INT
)LOWORD(lParam
);
1760 infoPtr
->yTrackPos
= (INT
)HIWORD(lParam
);
1762 if (infoPtr
->bTrackActive
) {
1764 infoPtr
->xTrackPos
, infoPtr
->yTrackPos
);
1766 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1774 TOOLTIPS_Update (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1776 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1778 if (infoPtr
->nCurrentTool
!= -1)
1779 UpdateWindow (hwnd
);
1786 TOOLTIPS_UpdateTipTextA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1788 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1789 LPTTTOOLINFOA lpToolInfo
= (LPTTTOOLINFOA
)lParam
;
1790 TTTOOL_INFO
*toolPtr
;
1793 if (lpToolInfo
== NULL
)
1795 if (lpToolInfo
->cbSize
< TTTOOLINFOA_V1_SIZE
)
1798 nTool
= TOOLTIPS_GetToolFromInfoA (infoPtr
, lpToolInfo
);
1799 if (nTool
== -1) return 0;
1801 TRACE("tool %d\n", nTool
);
1803 toolPtr
= &infoPtr
->tools
[nTool
];
1805 /* copy tool text */
1806 toolPtr
->hinst
= lpToolInfo
->hinst
;
1808 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1809 toolPtr
->lpszText
= (LPWSTR
)lpToolInfo
->lpszText
;
1811 else if (lpToolInfo
->lpszText
) {
1812 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKA
)
1813 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1815 if ( (toolPtr
->lpszText
) &&
1816 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1817 Free (toolPtr
->lpszText
);
1818 toolPtr
->lpszText
= NULL
;
1820 if (lpToolInfo
->lpszText
) {
1821 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
,
1823 toolPtr
->lpszText
= Alloc (len
* sizeof(WCHAR
));
1824 MultiByteToWideChar(CP_ACP
, 0, lpToolInfo
->lpszText
, -1,
1825 toolPtr
->lpszText
, len
);
1830 if(infoPtr
->nCurrentTool
== -1) return 0;
1832 if (infoPtr
->bActive
)
1833 TOOLTIPS_Show (hwnd
, infoPtr
);
1834 else if (infoPtr
->bTrackActive
)
1835 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1842 TOOLTIPS_UpdateTipTextW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1844 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1845 LPTTTOOLINFOW lpToolInfo
= (LPTTTOOLINFOW
)lParam
;
1846 TTTOOL_INFO
*toolPtr
;
1849 if (lpToolInfo
== NULL
)
1851 if (lpToolInfo
->cbSize
< TTTOOLINFOW_V1_SIZE
)
1854 nTool
= TOOLTIPS_GetToolFromInfoW (infoPtr
, lpToolInfo
);
1858 TRACE("tool %d\n", nTool
);
1860 toolPtr
= &infoPtr
->tools
[nTool
];
1862 /* copy tool text */
1863 toolPtr
->hinst
= lpToolInfo
->hinst
;
1865 if ((lpToolInfo
->hinst
) && (HIWORD((INT
)lpToolInfo
->lpszText
) == 0)){
1866 toolPtr
->lpszText
= lpToolInfo
->lpszText
;
1868 else if (lpToolInfo
->lpszText
) {
1869 if (lpToolInfo
->lpszText
== LPSTR_TEXTCALLBACKW
)
1870 toolPtr
->lpszText
= LPSTR_TEXTCALLBACKW
;
1872 if ( (toolPtr
->lpszText
) &&
1873 (HIWORD((INT
)toolPtr
->lpszText
) != 0) ) {
1874 Free (toolPtr
->lpszText
);
1875 toolPtr
->lpszText
= NULL
;
1877 if (lpToolInfo
->lpszText
) {
1878 INT len
= lstrlenW (lpToolInfo
->lpszText
);
1879 toolPtr
->lpszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1880 strcpyW (toolPtr
->lpszText
, lpToolInfo
->lpszText
);
1885 if(infoPtr
->nCurrentTool
== -1) return 0;
1887 if (infoPtr
->bActive
)
1888 TOOLTIPS_Show (hwnd
, infoPtr
);
1889 else if (infoPtr
->bTrackActive
)
1890 TOOLTIPS_TrackShow (hwnd
, infoPtr
);
1897 TOOLTIPS_WindowFromPoint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1899 return (LRESULT
)WindowFromPoint (*((LPPOINT
)lParam
));
1905 TOOLTIPS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1907 TOOLTIPS_INFO
*infoPtr
;
1908 NONCLIENTMETRICSA nclm
;
1912 /* allocate memory for info structure */
1913 infoPtr
= (TOOLTIPS_INFO
*)Alloc (sizeof(TOOLTIPS_INFO
));
1914 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1916 /* initialize info structure */
1917 infoPtr
->bActive
= TRUE
;
1918 infoPtr
->bTrackActive
= FALSE
;
1919 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
1920 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
1922 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
1923 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
1924 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
1926 infoPtr
->nMaxTipWidth
= -1;
1927 infoPtr
->nTool
= -1;
1928 infoPtr
->nCurrentTool
= -1;
1929 infoPtr
->nTrackTool
= -1;
1931 TOOLTIPS_SetDelayTime(hwnd
, TTDT_AUTOMATIC
, 0L);
1933 hParent
= GetParent(hwnd
);
1935 nResult
= (INT
) SendMessageA (hParent
, WM_NOTIFYFORMAT
,
1936 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1937 if (nResult
== NFR_ANSI
) {
1938 infoPtr
->bNotifyUnicode
= FALSE
;
1939 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1941 else if (nResult
== NFR_UNICODE
) {
1942 infoPtr
->bNotifyUnicode
= TRUE
;
1943 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1946 ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1950 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_NOACTIVATE
);
1957 TOOLTIPS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1959 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
1960 TTTOOL_INFO
*toolPtr
;
1964 if (infoPtr
->tools
) {
1965 for (i
= 0; i
< infoPtr
->uNumTools
; i
++) {
1966 toolPtr
= &infoPtr
->tools
[i
];
1967 if ((toolPtr
->hinst
) && (toolPtr
->lpszText
)) {
1968 if ( (toolPtr
->lpszText
!= LPSTR_TEXTCALLBACKW
) &&
1969 (HIWORD((INT
)toolPtr
->lpszText
) != 0) )
1971 Free (toolPtr
->lpszText
);
1972 toolPtr
->lpszText
= NULL
;
1976 /* remove subclassing */
1977 if (toolPtr
->uFlags
& TTF_SUBCLASS
) {
1978 if (toolPtr
->uFlags
& TTF_IDISHWND
) {
1979 RemoveWindowSubclass((HWND
)toolPtr
->uId
, TOOLTIPS_SubclassProc
, 1);
1982 RemoveWindowSubclass(toolPtr
->hwnd
, TOOLTIPS_SubclassProc
, 1);
1986 Free (infoPtr
->tools
);
1990 DeleteObject (infoPtr
->hFont
);
1992 /* free tool tips info data */
1994 SetWindowLongA(hwnd
, 0, 0);
2000 TOOLTIPS_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2002 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2006 hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2007 GetClientRect (hwnd
, &rect
);
2008 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2009 DeleteObject (hBrush
);
2016 TOOLTIPS_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2018 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2020 return (LRESULT
)infoPtr
->hFont
;
2025 TOOLTIPS_MouseMessage (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2027 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2029 TOOLTIPS_Hide (hwnd
, infoPtr
);
2036 TOOLTIPS_NCCreate (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2038 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
2039 DWORD dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
2041 dwStyle
&= 0x0000FFFF;
2042 dwStyle
|= (WS_POPUP
| WS_BORDER
| WS_CLIPSIBLINGS
);
2043 SetWindowLongA (hwnd
, GWL_STYLE
, dwStyle
);
2045 dwExStyle
|= WS_EX_TOOLWINDOW
;
2046 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
);
2053 TOOLTIPS_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2055 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2056 INT nTool
= (infoPtr
->bTrackActive
) ? infoPtr
->nTrackTool
: infoPtr
->nTool
;
2058 TRACE(" nTool=%d\n", nTool
);
2060 if ((nTool
> -1) && (nTool
< infoPtr
->uNumTools
)) {
2061 if (infoPtr
->tools
[nTool
].uFlags
& TTF_TRANSPARENT
) {
2062 TRACE("-- in transparent mode!\n");
2063 return HTTRANSPARENT
;
2067 return DefWindowProcA (hwnd
, WM_NCHITTEST
, wParam
, lParam
);
2072 TOOLTIPS_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2074 FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd
, wParam
, lParam
);
2081 TOOLTIPS_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2086 hdc
= (wParam
== 0) ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2087 TOOLTIPS_Refresh (hwnd
, hdc
);
2089 EndPaint (hwnd
, &ps
);
2095 TOOLTIPS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2097 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2100 if(!GetObjectW((HFONT
)wParam
, sizeof(lf
), &lf
))
2103 if(infoPtr
->hFont
) DeleteObject (infoPtr
->hFont
);
2104 infoPtr
->hFont
= CreateFontIndirectW(&lf
);
2106 if ((LOWORD(lParam
)) & (infoPtr
->nCurrentTool
!= -1)) {
2107 FIXME("full redraw needed!\n");
2112 /******************************************************************
2113 * TOOLTIPS_OnWMGetTextLength
2115 * This function is called when the tooltip receive a
2116 * WM_GETTEXTLENGTH message.
2120 * returns the length, in characters, of the tip text
2121 ******************************************************************/
2123 TOOLTIPS_OnWMGetTextLength(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2125 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2126 return lstrlenW(infoPtr
->szTipText
);
2129 /******************************************************************
2130 * TOOLTIPS_OnWMGetText
2132 * This function is called when the tooltip receive a
2133 * WM_GETTEXT message.
2134 * wParam : specifies the maximum number of characters to be copied
2135 * lParam : is the pointer to the buffer that will receive
2138 * returns the number of characters copied
2139 ******************************************************************/
2141 TOOLTIPS_OnWMGetText (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2143 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2145 if(!infoPtr
|| !(infoPtr
->szTipText
))
2148 return WideCharToMultiByte(CP_ACP
, 0, infoPtr
->szTipText
, -1,
2149 (LPSTR
)lParam
, wParam
, NULL
, NULL
);
2153 TOOLTIPS_Timer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2155 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2158 TRACE("timer %d (%p) expired!\n", wParam
, hwnd
);
2162 KillTimer (hwnd
, ID_TIMERSHOW
);
2163 nOldTool
= infoPtr
->nTool
;
2164 if ((infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, TRUE
)) == nOldTool
)
2165 TOOLTIPS_Show (hwnd
, infoPtr
);
2169 TOOLTIPS_Hide (hwnd
, infoPtr
);
2173 nOldTool
= infoPtr
->nTool
;
2174 infoPtr
->nTool
= TOOLTIPS_CheckTool (hwnd
, FALSE
);
2175 TRACE("tool (%p) %d %d %d\n", hwnd
, nOldTool
,
2176 infoPtr
->nTool
, infoPtr
->nCurrentTool
);
2177 if (infoPtr
->nTool
!= nOldTool
) {
2178 if(infoPtr
->nTool
== -1) { /* Moved out of all tools */
2179 TOOLTIPS_Hide(hwnd
, infoPtr
);
2180 KillTimer(hwnd
, ID_TIMERLEAVE
);
2181 } else if (nOldTool
== -1) { /* Moved from outside */
2182 ERR("How did this happen?\n");
2183 } else { /* Moved from one to another */
2184 TOOLTIPS_Hide (hwnd
, infoPtr
);
2185 KillTimer(hwnd
, ID_TIMERLEAVE
);
2186 if(infoPtr
->bActive
) {
2187 SetTimer (hwnd
, ID_TIMERSHOW
, infoPtr
->nReshowTime
, 0);
2188 TRACE("timer 1 started!\n");
2195 ERR("Unknown timer id %d\n", wParam
);
2203 TOOLTIPS_WinIniChange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2205 TOOLTIPS_INFO
*infoPtr
= TOOLTIPS_GetInfoPtr (hwnd
);
2206 NONCLIENTMETRICSA nclm
;
2208 infoPtr
->clrBk
= GetSysColor (COLOR_INFOBK
);
2209 infoPtr
->clrText
= GetSysColor (COLOR_INFOTEXT
);
2211 DeleteObject (infoPtr
->hFont
);
2212 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
2213 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
2214 infoPtr
->hFont
= CreateFontIndirectA (&nclm
.lfStatusFont
);
2221 TOOLTIPS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uID
, DWORD_PTR dwRef
)
2227 case WM_LBUTTONDOWN
:
2229 case WM_MBUTTONDOWN
:
2231 case WM_RBUTTONDOWN
:
2235 msg
.wParam
= wParam
;
2236 msg
.lParam
= lParam
;
2237 TOOLTIPS_RelayEvent((HWND
)dwRef
, 0, (LPARAM
)&msg
);
2243 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
2247 static LRESULT CALLBACK
2248 TOOLTIPS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2250 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
2251 if (!TOOLTIPS_GetInfoPtr(hwnd
) && (uMsg
!= WM_CREATE
) && (uMsg
!= WM_NCCREATE
))
2252 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2256 return TOOLTIPS_Activate (hwnd
, wParam
, lParam
);
2259 return TOOLTIPS_AddToolA (hwnd
, wParam
, lParam
);
2262 return TOOLTIPS_AddToolW (hwnd
, wParam
, lParam
);
2265 return TOOLTIPS_DelToolA (hwnd
, wParam
, lParam
);
2268 return TOOLTIPS_DelToolW (hwnd
, wParam
, lParam
);
2270 case TTM_ENUMTOOLSA
:
2271 return TOOLTIPS_EnumToolsA (hwnd
, wParam
, lParam
);
2273 case TTM_ENUMTOOLSW
:
2274 return TOOLTIPS_EnumToolsW (hwnd
, wParam
, lParam
);
2276 case TTM_GETBUBBLESIZE
:
2277 return TOOLTIPS_GetBubbleSize (hwnd
, wParam
, lParam
);
2279 case TTM_GETCURRENTTOOLA
:
2280 return TOOLTIPS_GetCurrentToolA (hwnd
, wParam
, lParam
);
2282 case TTM_GETCURRENTTOOLW
:
2283 return TOOLTIPS_GetCurrentToolW (hwnd
, wParam
, lParam
);
2285 case TTM_GETDELAYTIME
:
2286 return TOOLTIPS_GetDelayTime (hwnd
, wParam
, lParam
);
2289 return TOOLTIPS_GetMargin (hwnd
, wParam
, lParam
);
2291 case TTM_GETMAXTIPWIDTH
:
2292 return TOOLTIPS_GetMaxTipWidth (hwnd
, wParam
, lParam
);
2295 return TOOLTIPS_GetTextA (hwnd
, wParam
, lParam
);
2298 return TOOLTIPS_GetTextW (hwnd
, wParam
, lParam
);
2300 case TTM_GETTIPBKCOLOR
:
2301 return TOOLTIPS_GetTipBkColor (hwnd
, wParam
, lParam
);
2303 case TTM_GETTIPTEXTCOLOR
:
2304 return TOOLTIPS_GetTipTextColor (hwnd
, wParam
, lParam
);
2306 case TTM_GETTOOLCOUNT
:
2307 return TOOLTIPS_GetToolCount (hwnd
, wParam
, lParam
);
2309 case TTM_GETTOOLINFOA
:
2310 return TOOLTIPS_GetToolInfoA (hwnd
, wParam
, lParam
);
2312 case TTM_GETTOOLINFOW
:
2313 return TOOLTIPS_GetToolInfoW (hwnd
, wParam
, lParam
);
2316 return TOOLTIPS_HitTestA (hwnd
, wParam
, lParam
);
2319 return TOOLTIPS_HitTestW (hwnd
, wParam
, lParam
);
2321 case TTM_NEWTOOLRECTA
:
2322 return TOOLTIPS_NewToolRectA (hwnd
, wParam
, lParam
);
2324 case TTM_NEWTOOLRECTW
:
2325 return TOOLTIPS_NewToolRectW (hwnd
, wParam
, lParam
);
2328 return TOOLTIPS_Pop (hwnd
, wParam
, lParam
);
2330 case TTM_RELAYEVENT
:
2331 return TOOLTIPS_RelayEvent (hwnd
, wParam
, lParam
);
2333 case TTM_SETDELAYTIME
:
2334 return TOOLTIPS_SetDelayTime (hwnd
, wParam
, lParam
);
2337 return TOOLTIPS_SetMargin (hwnd
, wParam
, lParam
);
2339 case TTM_SETMAXTIPWIDTH
:
2340 return TOOLTIPS_SetMaxTipWidth (hwnd
, wParam
, lParam
);
2342 case TTM_SETTIPBKCOLOR
:
2343 return TOOLTIPS_SetTipBkColor (hwnd
, wParam
, lParam
);
2345 case TTM_SETTIPTEXTCOLOR
:
2346 return TOOLTIPS_SetTipTextColor (hwnd
, wParam
, lParam
);
2348 case TTM_SETTOOLINFOA
:
2349 return TOOLTIPS_SetToolInfoA (hwnd
, wParam
, lParam
);
2351 case TTM_SETTOOLINFOW
:
2352 return TOOLTIPS_SetToolInfoW (hwnd
, wParam
, lParam
);
2354 case TTM_TRACKACTIVATE
:
2355 return TOOLTIPS_TrackActivate (hwnd
, wParam
, lParam
);
2357 case TTM_TRACKPOSITION
:
2358 return TOOLTIPS_TrackPosition (hwnd
, wParam
, lParam
);
2361 return TOOLTIPS_Update (hwnd
, wParam
, lParam
);
2363 case TTM_UPDATETIPTEXTA
:
2364 return TOOLTIPS_UpdateTipTextA (hwnd
, wParam
, lParam
);
2366 case TTM_UPDATETIPTEXTW
:
2367 return TOOLTIPS_UpdateTipTextW (hwnd
, wParam
, lParam
);
2369 case TTM_WINDOWFROMPOINT
:
2370 return TOOLTIPS_WindowFromPoint (hwnd
, wParam
, lParam
);
2374 return TOOLTIPS_Create (hwnd
, wParam
, lParam
);
2377 return TOOLTIPS_Destroy (hwnd
, wParam
, lParam
);
2380 return TOOLTIPS_EraseBackground (hwnd
, wParam
, lParam
);
2383 return TOOLTIPS_GetFont (hwnd
, wParam
, lParam
);
2386 return TOOLTIPS_OnWMGetText (hwnd
, wParam
, lParam
);
2388 case WM_GETTEXTLENGTH
:
2389 return TOOLTIPS_OnWMGetTextLength (hwnd
, wParam
, lParam
);
2392 case WM_LBUTTONDOWN
:
2394 case WM_MBUTTONDOWN
:
2396 case WM_RBUTTONDOWN
:
2399 return TOOLTIPS_MouseMessage (hwnd
, uMsg
, wParam
, lParam
);
2402 return TOOLTIPS_NCCreate (hwnd
, wParam
, lParam
);
2405 return TOOLTIPS_NCHitTest (hwnd
, wParam
, lParam
);
2407 case WM_NOTIFYFORMAT
:
2408 return TOOLTIPS_NotifyFormat (hwnd
, wParam
, lParam
);
2411 return TOOLTIPS_Paint (hwnd
, wParam
, lParam
);
2414 return TOOLTIPS_SetFont (hwnd
, wParam
, lParam
);
2417 return TOOLTIPS_Timer (hwnd
, wParam
, lParam
);
2419 case WM_WININICHANGE
:
2420 return TOOLTIPS_WinIniChange (hwnd
, wParam
, lParam
);
2423 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
2424 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2425 uMsg
, wParam
, lParam
);
2426 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
2433 TOOLTIPS_Register (void)
2437 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
2438 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
2439 wndClass
.lpfnWndProc
= (WNDPROC
)TOOLTIPS_WindowProc
;
2440 wndClass
.cbClsExtra
= 0;
2441 wndClass
.cbWndExtra
= sizeof(TOOLTIPS_INFO
*);
2442 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
2443 wndClass
.hbrBackground
= 0;
2444 wndClass
.lpszClassName
= TOOLTIPS_CLASSA
;
2446 RegisterClassA (&wndClass
);
2451 TOOLTIPS_Unregister (void)
2453 UnregisterClassA (TOOLTIPS_CLASSA
, NULL
);