All 19 FileMenu_* functions, some as stubs, some implemented.
[wine/testsucceed.git] / dlls / comctl32 / tooltips.c
bloba8618ebef064c4577fc0ab804eaf5899f8e61afe
1 /*
2 * Tool tip control
4 * Copyright 1998 Eric Kohl
6 * TODO:
7 * - Unicode support.
8 * - Custom draw support.
10 * Testing:
11 * - Run tests using Waite Group Windows95 API Bible Volume 2.
12 * The second cdrom (chapter 3) contains executables activate.exe,
13 * curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
14 * hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
17 #include <string.h>
19 #include "winbase.h"
20 #include "commctrl.h"
21 #include "tooltips.h"
22 #include "debug.h"
24 #define ID_TIMERSHOW 1 /* show delay timer */
25 #define ID_TIMERPOP 2 /* auto pop timer */
26 #define ID_TIMERLEAVE 3 /* tool leave timer */
29 extern LPSTR COMCTL32_aSubclass; /* global subclassing atom */
31 /* property name of tooltip window handle */
32 /*#define TT_SUBCLASS_PROP "CC32SubclassInfo" */
34 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
37 LRESULT CALLBACK
38 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
41 static VOID
42 TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
44 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd);
45 RECT rc;
46 INT oldBkMode;
47 HFONT hOldFont;
48 HBRUSH hBrush;
49 UINT uFlags = DT_EXTERNALLEADING;
51 if (infoPtr->nMaxTipWidth > -1)
52 uFlags |= DT_WORDBREAK;
53 if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
54 uFlags |= DT_NOPREFIX;
55 GetClientRect (hwnd, &rc);
57 /* fill the background */
58 hBrush = CreateSolidBrush (infoPtr->clrBk);
59 FillRect (hdc, &rc, hBrush);
60 DeleteObject (hBrush);
62 /* calculate text rectangle */
63 rc.left += (2 + infoPtr->rcMargin.left);
64 rc.top += (2 + infoPtr->rcMargin.top);
65 rc.right -= (2 + infoPtr->rcMargin.right);
66 rc.bottom -= (2 + infoPtr->rcMargin.bottom);
68 /* draw text */
69 oldBkMode = SetBkMode (hdc, TRANSPARENT);
70 SetTextColor (hdc, infoPtr->clrText);
71 hOldFont = SelectObject (hdc, infoPtr->hFont);
72 DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
73 SelectObject (hdc, hOldFont);
74 if (oldBkMode != TRANSPARENT)
75 SetBkMode (hdc, oldBkMode);
79 static VOID
80 TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
82 TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
84 if ((toolPtr->hinst) && (HIWORD((UINT)toolPtr->lpszText) == 0)) {
85 /* load a resource */
86 TRACE (tooltips, "load res string %x %x\n",
87 toolPtr->hinst, (int)toolPtr->lpszText);
88 LoadStringW (toolPtr->hinst, (UINT)toolPtr->lpszText,
89 infoPtr->szTipText, INFOTIPSIZE);
91 else if (toolPtr->lpszText) {
92 if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
93 NMTTDISPINFOA ttnmdi;
95 /* fill NMHDR struct */
96 ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA));
97 ttnmdi.hdr.hwndFrom = hwnd;
98 ttnmdi.hdr.idFrom = toolPtr->uId;
99 ttnmdi.hdr.code = TTN_GETDISPINFOA;
100 ttnmdi.lpszText = (LPSTR)&ttnmdi.szText;
101 ttnmdi.uFlags = toolPtr->uFlags;
102 ttnmdi.lParam = toolPtr->lParam;
104 TRACE (tooltips, "hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
105 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
106 (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);
108 if ((ttnmdi.hinst) && (HIWORD((UINT)ttnmdi.szText) == 0)) {
109 LoadStringW (ttnmdi.hinst, (UINT)ttnmdi.szText,
110 infoPtr->szTipText, INFOTIPSIZE);
111 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
112 toolPtr->hinst = ttnmdi.hinst;
113 toolPtr->lpszText = (LPWSTR)ttnmdi.szText;
116 else if (ttnmdi.szText[0]) {
117 lstrcpynAtoW (infoPtr->szTipText, ttnmdi.szText, 80);
118 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
119 INT len = lstrlenA (ttnmdi.szText);
120 toolPtr->hinst = 0;
121 toolPtr->lpszText = COMCTL32_Alloc ((len+1)* sizeof(WCHAR));
122 lstrcpyAtoW (toolPtr->lpszText, ttnmdi.szText);
125 else if (ttnmdi.lpszText == 0) {
126 /* no text available */
127 infoPtr->szTipText[0] = L'\0';
129 else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
130 lstrcpynAtoW (infoPtr->szTipText, ttnmdi.lpszText, INFOTIPSIZE);
131 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
132 INT len = lstrlenA (ttnmdi.lpszText);
133 toolPtr->hinst = 0;
134 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
135 lstrcpyAtoW (toolPtr->lpszText, ttnmdi.lpszText);
138 else {
139 ERR (tooltips, "recursive text callback!\n");
140 infoPtr->szTipText[0] = '\0';
143 else {
144 /* the item is a usual (unicode) text */
145 lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
148 else {
149 /* no text available */
150 infoPtr->szTipText[0] = L'\0';
153 TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
157 static VOID
158 TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
160 HDC hdc;
161 HFONT hOldFont;
162 UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
163 RECT rc = {0, 0, 0, 0};
165 if (infoPtr->nMaxTipWidth > -1) {
166 rc.right = infoPtr->nMaxTipWidth;
167 uFlags |= DT_WORDBREAK;
169 if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
170 uFlags |= DT_NOPREFIX;
171 TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
173 hdc = GetDC (hwnd);
174 hOldFont = SelectObject (hdc, infoPtr->hFont);
175 DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
176 SelectObject (hdc, hOldFont);
177 ReleaseDC (hwnd, hdc);
179 lpSize->cx = rc.right - rc.left + 4 +
180 infoPtr->rcMargin.left + infoPtr->rcMargin.right;
181 lpSize->cy = rc.bottom - rc.top + 4 +
182 infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
186 static VOID
187 TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
189 TTTOOL_INFO *toolPtr;
190 RECT rect;
191 SIZE size;
192 HDC hdc;
193 NMHDR hdr;
195 if (infoPtr->nTool == -1) {
196 TRACE (tooltips, "invalid tool (-1)!\n");
197 return;
200 infoPtr->nCurrentTool = infoPtr->nTool;
202 TRACE (tooltips, "Show tooltip pre %d!\n", infoPtr->nTool);
204 TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
206 if (infoPtr->szTipText[0] == L'\0') {
207 infoPtr->nCurrentTool = -1;
208 return;
211 TRACE (tooltips, "Show tooltip %d!\n", infoPtr->nCurrentTool);
212 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
214 hdr.hwndFrom = hwnd;
215 hdr.idFrom = toolPtr->uId;
216 hdr.code = TTN_SHOW;
217 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
218 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
220 TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
222 TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
223 TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
225 if (toolPtr->uFlags & TTF_CENTERTIP) {
226 RECT rc;
228 if (toolPtr->uFlags & TTF_IDISHWND)
229 GetWindowRect ((HWND)toolPtr->uId, &rc);
230 else {
231 rc = toolPtr->rect;
232 MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rc, 2);
234 rect.left = (rc.left + rc.right - size.cx) / 2;
235 rect.top = rc.bottom + 2;
237 else {
238 GetCursorPos ((LPPOINT)&rect);
239 rect.top += 20;
242 /* FIXME: check position */
244 TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
246 rect.right = rect.left + size.cx;
247 rect.bottom = rect.top + size.cy;
249 AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
250 FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
252 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
253 rect.right - rect.left, rect.bottom - rect.top,
254 SWP_SHOWWINDOW);
256 /* repaint the tooltip */
257 hdc = GetDC (hwnd);
258 TOOLTIPS_Refresh (hwnd, hdc);
259 ReleaseDC (hwnd, hdc);
261 SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
265 static VOID
266 TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
268 TTTOOL_INFO *toolPtr;
269 NMHDR hdr;
271 if (infoPtr->nCurrentTool == -1)
272 return;
274 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
275 TRACE (tooltips, "Hide tooltip %d!\n", infoPtr->nCurrentTool);
276 KillTimer (hwnd, ID_TIMERPOP);
278 hdr.hwndFrom = hwnd;
279 hdr.idFrom = toolPtr->uId;
280 hdr.code = TTN_POP;
281 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
282 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
284 infoPtr->nCurrentTool = -1;
286 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
287 SWP_NOZORDER | SWP_HIDEWINDOW);
291 static VOID
292 TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
294 TTTOOL_INFO *toolPtr;
295 RECT rect;
296 SIZE size;
297 HDC hdc;
298 NMHDR hdr;
300 if (infoPtr->nTrackTool == -1) {
301 TRACE (tooltips, "invalid tracking tool (-1)!\n");
302 return;
305 TRACE (tooltips, "show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
307 TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
309 if (infoPtr->szTipText[0] == L'\0') {
310 infoPtr->nTrackTool = -1;
311 return;
314 TRACE (tooltips, "show tracking tooltip %d!\n", infoPtr->nTrackTool);
315 toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
317 hdr.hwndFrom = hwnd;
318 hdr.idFrom = toolPtr->uId;
319 hdr.code = TTN_SHOW;
320 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
321 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
323 TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
325 TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
326 TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
328 if (toolPtr->uFlags & TTF_ABSOLUTE) {
329 rect.left = infoPtr->xTrackPos;
330 rect.top = infoPtr->yTrackPos;
332 if (toolPtr->uFlags & TTF_CENTERTIP) {
333 rect.left -= (size.cx / 2);
334 rect.top -= (size.cy / 2);
337 else {
338 RECT rcTool;
340 if (toolPtr->uFlags & TTF_IDISHWND)
341 GetWindowRect ((HWND)toolPtr->uId, &rcTool);
342 else {
343 rcTool = toolPtr->rect;
344 MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rcTool, 2);
347 GetCursorPos ((LPPOINT)&rect);
348 rect.top += 20;
350 if (toolPtr->uFlags & TTF_CENTERTIP) {
351 rect.left -= (size.cx / 2);
352 rect.top -= (size.cy / 2);
355 /* smart placement */
356 if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
357 (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
358 rect.left = rcTool.right;
361 TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
363 rect.right = rect.left + size.cx;
364 rect.bottom = rect.top + size.cy;
366 AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
367 FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
369 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
370 rect.right - rect.left, rect.bottom - rect.top,
371 SWP_SHOWWINDOW);
373 hdc = GetDC (hwnd);
374 TOOLTIPS_Refresh (hwnd, hdc);
375 ReleaseDC (hwnd, hdc);
379 static VOID
380 TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
382 TTTOOL_INFO *toolPtr;
383 NMHDR hdr;
385 if (infoPtr->nTrackTool == -1)
386 return;
388 toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
389 TRACE (tooltips, "hide tracking tooltip %d!\n", infoPtr->nTrackTool);
391 hdr.hwndFrom = hwnd;
392 hdr.idFrom = toolPtr->uId;
393 hdr.code = TTN_POP;
394 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
395 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
397 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
398 SWP_NOZORDER | SWP_HIDEWINDOW);
402 static INT
403 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
405 TTTOOL_INFO *toolPtr;
406 INT nTool;
408 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
409 toolPtr = &infoPtr->tools[nTool];
411 if (!(toolPtr->uFlags & TTF_IDISHWND) &&
412 (lpToolInfo->hwnd == toolPtr->hwnd) &&
413 (lpToolInfo->uId == toolPtr->uId))
414 return nTool;
417 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
418 toolPtr = &infoPtr->tools[nTool];
420 if ((toolPtr->uFlags & TTF_IDISHWND) &&
421 (lpToolInfo->uId == toolPtr->uId))
422 return nTool;
425 return -1;
429 static INT
430 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
432 TTTOOL_INFO *toolPtr;
433 INT nTool;
435 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
436 toolPtr = &infoPtr->tools[nTool];
438 if (!(toolPtr->uFlags & TTF_IDISHWND) &&
439 (lpToolInfo->hwnd == toolPtr->hwnd) &&
440 (lpToolInfo->uId == toolPtr->uId))
441 return nTool;
444 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
445 toolPtr = &infoPtr->tools[nTool];
447 if ((toolPtr->uFlags & TTF_IDISHWND) &&
448 (lpToolInfo->uId == toolPtr->uId))
449 return nTool;
452 return -1;
456 static INT
457 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
459 TTTOOL_INFO *toolPtr;
460 INT nTool;
462 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
463 toolPtr = &infoPtr->tools[nTool];
465 if (!(toolPtr->uFlags & TTF_IDISHWND)) {
466 if (hwnd != toolPtr->hwnd)
467 continue;
468 if (!PtInRect (&toolPtr->rect, *lpPt))
469 continue;
470 return nTool;
474 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
475 toolPtr = &infoPtr->tools[nTool];
477 if (toolPtr->uFlags & TTF_IDISHWND) {
478 if ((HWND)toolPtr->uId == hwnd)
479 return nTool;
483 return -1;
487 static INT
488 TOOLTIPS_GetToolFromMessage (TOOLTIPS_INFO *infoPtr, HWND hwndTool)
490 DWORD dwPos;
491 POINT pt;
493 dwPos = GetMessagePos ();
494 pt.x = (INT)LOWORD(dwPos);
495 pt.y = (INT)HIWORD(dwPos);
496 ScreenToClient (hwndTool, &pt);
498 return TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
502 static BOOL
503 TOOLTIPS_IsWindowActive (HWND hwnd)
505 HWND hwndActive = GetActiveWindow ();
506 if (!hwndActive)
507 return FALSE;
508 if (hwndActive == hwnd)
509 return TRUE;
510 return IsChild (hwndActive, hwnd);
514 static INT
515 TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest)
517 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
518 POINT pt;
519 HWND hwndTool;
520 INT nTool;
522 GetCursorPos (&pt);
523 hwndTool = SendMessageA (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
524 if (hwndTool == 0)
525 return -1;
527 ScreenToClient (hwndTool, &pt);
528 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
529 if (nTool == -1)
530 return -1;
532 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) {
533 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER)))
534 return -1;
537 TRACE (tooltips, "tool %d\n", nTool);
539 return nTool;
543 static LRESULT
544 TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam)
546 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
548 infoPtr->bActive = (BOOL)wParam;
550 if (infoPtr->bActive)
551 TRACE (tooltips, "activate!\n");
553 if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1))
554 TOOLTIPS_Hide (hwnd, infoPtr);
556 return 0;
560 static LRESULT
561 TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
563 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
564 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
565 TTTOOL_INFO *toolPtr;
567 if (lpToolInfo == NULL)
568 return FALSE;
569 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
570 return FALSE;
572 TRACE (tooltips, "add tool (%x) %x %d%s!\n",
573 hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
574 (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
576 if (infoPtr->uNumTools == 0) {
577 infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
578 toolPtr = infoPtr->tools;
580 else {
581 TTTOOL_INFO *oldTools = infoPtr->tools;
582 infoPtr->tools =
583 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
584 memcpy (infoPtr->tools, oldTools,
585 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
586 COMCTL32_Free (oldTools);
587 toolPtr = &infoPtr->tools[infoPtr->uNumTools];
590 infoPtr->uNumTools++;
592 /* copy tool data */
593 toolPtr->uFlags = lpToolInfo->uFlags;
594 toolPtr->hwnd = lpToolInfo->hwnd;
595 toolPtr->uId = lpToolInfo->uId;
596 toolPtr->rect = lpToolInfo->rect;
597 toolPtr->hinst = lpToolInfo->hinst;
599 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
600 TRACE (tooltips, "add string id %x!\n", (int)lpToolInfo->lpszText);
601 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
603 else if (lpToolInfo->lpszText) {
604 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) {
605 TRACE (tooltips, "add CALLBACK!\n");
606 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
608 else {
609 INT len = lstrlenA (lpToolInfo->lpszText);
610 TRACE (tooltips, "add text \"%s\"!\n", lpToolInfo->lpszText);
611 toolPtr->lpszText = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
612 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
616 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
617 toolPtr->lParam = lpToolInfo->lParam;
619 /* install subclassing hook */
620 if (toolPtr->uFlags & TTF_SUBCLASS) {
621 if (toolPtr->uFlags & TTF_IDISHWND) {
622 LPTT_SUBCLASS_INFO lpttsi =
623 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
624 if (lpttsi == NULL) {
625 lpttsi =
626 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
627 lpttsi->wpOrigProc =
628 (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
629 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
630 lpttsi->hwndToolTip = hwnd;
631 lpttsi->uRefCount++;
632 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
633 (HANDLE)lpttsi);
635 else
636 WARN (tooltips, "A window tool must only be listed once!\n");
638 else {
639 LPTT_SUBCLASS_INFO lpttsi =
640 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
641 if (lpttsi == NULL) {
642 lpttsi =
643 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
644 lpttsi->wpOrigProc =
645 (WNDPROC)SetWindowLongA (toolPtr->hwnd,
646 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
647 lpttsi->hwndToolTip = hwnd;
648 lpttsi->uRefCount++;
649 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
651 else
652 lpttsi->uRefCount++;
654 TRACE (tooltips, "subclassing installed!\n");
657 return TRUE;
661 static LRESULT
662 TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
664 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
665 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
666 TTTOOL_INFO *toolPtr;
668 if (lpToolInfo == NULL)
669 return FALSE;
670 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
671 return FALSE;
673 TRACE (tooltips, "add tool (%x) %x %d%s!\n",
674 hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
675 (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
677 if (infoPtr->uNumTools == 0) {
678 infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
679 toolPtr = infoPtr->tools;
681 else {
682 TTTOOL_INFO *oldTools = infoPtr->tools;
683 infoPtr->tools =
684 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
685 memcpy (infoPtr->tools, oldTools,
686 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
687 COMCTL32_Free (oldTools);
688 toolPtr = &infoPtr->tools[infoPtr->uNumTools];
691 infoPtr->uNumTools++;
693 /* copy tool data */
694 toolPtr->uFlags = lpToolInfo->uFlags;
695 toolPtr->hwnd = lpToolInfo->hwnd;
696 toolPtr->uId = lpToolInfo->uId;
697 toolPtr->rect = lpToolInfo->rect;
698 toolPtr->hinst = lpToolInfo->hinst;
700 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
701 TRACE (tooltips, "add string id %x!\n", (int)lpToolInfo->lpszText);
702 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
704 else if (lpToolInfo->lpszText) {
705 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) {
706 TRACE (tooltips, "add CALLBACK!\n");
707 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
709 else {
710 INT len = lstrlenW (lpToolInfo->lpszText);
711 TRACE (tooltips, "add text \"%s\"!\n",
712 debugstr_w(lpToolInfo->lpszText));
713 toolPtr->lpszText = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
714 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
718 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
719 toolPtr->lParam = lpToolInfo->lParam;
721 /* install subclassing hook */
722 if (toolPtr->uFlags & TTF_SUBCLASS) {
723 if (toolPtr->uFlags & TTF_IDISHWND) {
724 LPTT_SUBCLASS_INFO lpttsi =
725 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
726 if (lpttsi == NULL) {
727 lpttsi =
728 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
729 lpttsi->wpOrigProc =
730 (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
731 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
732 lpttsi->hwndToolTip = hwnd;
733 lpttsi->uRefCount++;
734 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
735 (HANDLE)lpttsi);
737 else
738 WARN (tooltips, "A window tool must only be listed once!\n");
740 else {
741 LPTT_SUBCLASS_INFO lpttsi =
742 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
743 if (lpttsi == NULL) {
744 lpttsi =
745 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
746 lpttsi->wpOrigProc =
747 (WNDPROC)SetWindowLongA (toolPtr->hwnd,
748 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
749 lpttsi->hwndToolTip = hwnd;
750 lpttsi->uRefCount++;
751 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
753 else
754 lpttsi->uRefCount++;
756 TRACE (tooltips, "subclassing installed!\n");
759 return TRUE;
763 static LRESULT
764 TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
766 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
767 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
768 TTTOOL_INFO *toolPtr;
769 INT nTool;
771 if (lpToolInfo == NULL)
772 return 0;
773 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
774 return 0;
775 if (infoPtr->uNumTools == 0)
776 return 0;
778 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
779 if (nTool == -1) return 0;
781 TRACE (tooltips, "tool %d\n", nTool);
783 /* delete text string */
784 toolPtr = &infoPtr->tools[nTool];
785 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
786 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
787 COMCTL32_Free (toolPtr->lpszText);
790 /* remove subclassing */
791 if (toolPtr->uFlags & TTF_SUBCLASS) {
792 if (toolPtr->uFlags & TTF_IDISHWND) {
793 LPTT_SUBCLASS_INFO lpttsi =
794 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
795 if (lpttsi) {
796 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
797 (LONG)lpttsi->wpOrigProc);
798 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
799 COMCTL32_Free (&lpttsi);
801 else
802 ERR (tooltips, "Invalid data handle!\n");
804 else {
805 LPTT_SUBCLASS_INFO lpttsi =
806 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
807 if (lpttsi) {
808 if (lpttsi->uRefCount == 1) {
809 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
810 (LONG)lpttsi->wpOrigProc);
811 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
812 COMCTL32_Free (&lpttsi);
814 else
815 lpttsi->uRefCount--;
817 else
818 ERR (tooltips, "Invalid data handle!\n");
822 /* delete tool from tool list */
823 if (infoPtr->uNumTools == 1) {
824 COMCTL32_Free (infoPtr->tools);
825 infoPtr->tools = NULL;
827 else {
828 TTTOOL_INFO *oldTools = infoPtr->tools;
829 infoPtr->tools =
830 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
832 if (nTool > 0)
833 memcpy (&infoPtr->tools[0], &oldTools[0],
834 nTool * sizeof(TTTOOL_INFO));
836 if (nTool < infoPtr->uNumTools - 1)
837 memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
838 (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
840 COMCTL32_Free (oldTools);
843 infoPtr->uNumTools--;
845 return 0;
849 static LRESULT
850 TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
852 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
853 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
854 TTTOOL_INFO *toolPtr;
855 INT nTool;
857 if (lpToolInfo == NULL)
858 return 0;
859 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
860 return 0;
861 if (infoPtr->uNumTools == 0)
862 return 0;
864 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
865 if (nTool == -1) return 0;
867 TRACE (tooltips, "tool %d\n", nTool);
869 /* delete text string */
870 toolPtr = &infoPtr->tools[nTool];
871 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
872 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
873 COMCTL32_Free (toolPtr->lpszText);
876 /* remove subclassing */
877 if (toolPtr->uFlags & TTF_SUBCLASS) {
878 if (toolPtr->uFlags & TTF_IDISHWND) {
879 LPTT_SUBCLASS_INFO lpttsi =
880 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
881 if (lpttsi) {
882 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
883 (LONG)lpttsi->wpOrigProc);
884 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
885 COMCTL32_Free (&lpttsi);
887 else
888 ERR (tooltips, "Invalid data handle!\n");
890 else {
891 LPTT_SUBCLASS_INFO lpttsi =
892 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
893 if (lpttsi) {
894 if (lpttsi->uRefCount == 1) {
895 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
896 (LONG)lpttsi->wpOrigProc);
897 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
898 COMCTL32_Free (&lpttsi);
900 else
901 lpttsi->uRefCount--;
903 else
904 ERR (tooltips, "Invalid data handle!\n");
908 /* delete tool from tool list */
909 if (infoPtr->uNumTools == 1) {
910 COMCTL32_Free (infoPtr->tools);
911 infoPtr->tools = NULL;
913 else {
914 TTTOOL_INFO *oldTools = infoPtr->tools;
915 infoPtr->tools =
916 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
918 if (nTool > 0)
919 memcpy (&infoPtr->tools[0], &oldTools[0],
920 nTool * sizeof(TTTOOL_INFO));
922 if (nTool < infoPtr->uNumTools - 1)
923 memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
924 (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
926 COMCTL32_Free (oldTools);
929 infoPtr->uNumTools--;
931 return 0;
935 static LRESULT
936 TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
938 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
939 UINT uIndex = (UINT)wParam;
940 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
941 TTTOOL_INFO *toolPtr;
943 if (lpToolInfo == NULL)
944 return FALSE;
945 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
946 return FALSE;
947 if (uIndex >= infoPtr->uNumTools)
948 return FALSE;
950 TRACE (tooltips, "index=%u\n", uIndex);
952 toolPtr = &infoPtr->tools[uIndex];
954 /* copy tool data */
955 lpToolInfo->uFlags = toolPtr->uFlags;
956 lpToolInfo->hwnd = toolPtr->hwnd;
957 lpToolInfo->uId = toolPtr->uId;
958 lpToolInfo->rect = toolPtr->rect;
959 lpToolInfo->hinst = toolPtr->hinst;
960 /* lpToolInfo->lpszText = toolPtr->lpszText; */
961 lpToolInfo->lpszText = NULL; /* FIXME */
963 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
964 lpToolInfo->lParam = toolPtr->lParam;
966 return TRUE;
970 static LRESULT
971 TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
973 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
974 UINT uIndex = (UINT)wParam;
975 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
976 TTTOOL_INFO *toolPtr;
978 if (lpToolInfo == NULL)
979 return FALSE;
980 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
981 return FALSE;
982 if (uIndex >= infoPtr->uNumTools)
983 return FALSE;
985 TRACE (tooltips, "index=%u\n", uIndex);
987 toolPtr = &infoPtr->tools[uIndex];
989 /* copy tool data */
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(TTTOOLINFOW))
999 lpToolInfo->lParam = toolPtr->lParam;
1001 return TRUE;
1005 static LRESULT
1006 TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1008 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1009 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1010 TTTOOL_INFO *toolPtr;
1012 if (lpToolInfo == NULL)
1013 return FALSE;
1014 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1015 return FALSE;
1017 if (lpToolInfo) {
1018 if (infoPtr->nCurrentTool > -1) {
1019 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1021 /* copy tool data */
1022 lpToolInfo->uFlags = toolPtr->uFlags;
1023 lpToolInfo->rect = toolPtr->rect;
1024 lpToolInfo->hinst = toolPtr->hinst;
1025 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1026 lpToolInfo->lpszText = NULL; /* FIXME */
1028 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1029 lpToolInfo->lParam = toolPtr->lParam;
1031 return TRUE;
1033 else
1034 return FALSE;
1036 else
1037 return (infoPtr->nCurrentTool != -1);
1039 return FALSE;
1043 static LRESULT
1044 TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1046 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1047 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1048 TTTOOL_INFO *toolPtr;
1050 if (lpToolInfo == NULL)
1051 return FALSE;
1052 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1053 return FALSE;
1055 if (lpToolInfo) {
1056 if (infoPtr->nCurrentTool > -1) {
1057 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1059 /* copy tool data */
1060 lpToolInfo->uFlags = toolPtr->uFlags;
1061 lpToolInfo->rect = toolPtr->rect;
1062 lpToolInfo->hinst = toolPtr->hinst;
1063 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1064 lpToolInfo->lpszText = NULL; /* FIXME */
1066 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1067 lpToolInfo->lParam = toolPtr->lParam;
1069 return TRUE;
1071 else
1072 return FALSE;
1074 else
1075 return (infoPtr->nCurrentTool != -1);
1077 return FALSE;
1081 static LRESULT
1082 TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1084 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1086 switch (wParam) {
1087 case TTDT_AUTOMATIC:
1088 return infoPtr->nAutomaticTime;
1090 case TTDT_RESHOW:
1091 return infoPtr->nReshowTime;
1093 case TTDT_AUTOPOP:
1094 return infoPtr->nAutoPopTime;
1096 case TTDT_INITIAL:
1097 return infoPtr->nInitialTime;
1100 return 0;
1104 static LRESULT
1105 TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1107 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1108 LPRECT lpRect = (LPRECT)lParam;
1110 lpRect->left = infoPtr->rcMargin.left;
1111 lpRect->right = infoPtr->rcMargin.right;
1112 lpRect->bottom = infoPtr->rcMargin.bottom;
1113 lpRect->top = infoPtr->rcMargin.top;
1115 return 0;
1119 __inline__ static LRESULT
1120 TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1122 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1124 return infoPtr->nMaxTipWidth;
1128 static LRESULT
1129 TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1131 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1132 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1133 INT nTool;
1135 if (lpToolInfo == NULL)
1136 return 0;
1137 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1138 return 0;
1140 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1141 if (nTool == -1) return 0;
1143 lstrcpyWtoA (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1145 return 0;
1149 static LRESULT
1150 TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1152 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1153 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1154 INT nTool;
1156 if (lpToolInfo == NULL)
1157 return 0;
1158 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1159 return 0;
1161 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1162 if (nTool == -1) return 0;
1164 lstrcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1166 return 0;
1170 __inline__ static LRESULT
1171 TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1173 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1174 return infoPtr->clrBk;
1178 __inline__ static LRESULT
1179 TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1181 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1182 return infoPtr->clrText;
1186 __inline__ static LRESULT
1187 TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1189 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1190 return infoPtr->uNumTools;
1194 static LRESULT
1195 TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1197 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1198 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1199 TTTOOL_INFO *toolPtr;
1200 INT nTool;
1202 if (lpToolInfo == NULL)
1203 return FALSE;
1204 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1205 return FALSE;
1206 if (infoPtr->uNumTools == 0)
1207 return FALSE;
1209 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1210 if (nTool == -1)
1211 return FALSE;
1213 TRACE (tooltips, "tool %d\n", nTool);
1215 toolPtr = &infoPtr->tools[nTool];
1217 /* copy tool data */
1218 lpToolInfo->uFlags = toolPtr->uFlags;
1219 lpToolInfo->rect = toolPtr->rect;
1220 lpToolInfo->hinst = toolPtr->hinst;
1221 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1222 lpToolInfo->lpszText = NULL; /* FIXME */
1224 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1225 lpToolInfo->lParam = toolPtr->lParam;
1227 return TRUE;
1231 static LRESULT
1232 TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1234 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1235 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1236 TTTOOL_INFO *toolPtr;
1237 INT nTool;
1239 if (lpToolInfo == NULL)
1240 return FALSE;
1241 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1242 return FALSE;
1243 if (infoPtr->uNumTools == 0)
1244 return FALSE;
1246 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1247 if (nTool == -1)
1248 return FALSE;
1250 TRACE (tooltips, "tool %d\n", nTool);
1252 toolPtr = &infoPtr->tools[nTool];
1254 /* copy tool data */
1255 lpToolInfo->uFlags = toolPtr->uFlags;
1256 lpToolInfo->rect = toolPtr->rect;
1257 lpToolInfo->hinst = toolPtr->hinst;
1258 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1259 lpToolInfo->lpszText = NULL; /* FIXME */
1261 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1262 lpToolInfo->lParam = toolPtr->lParam;
1264 return TRUE;
1268 static LRESULT
1269 TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1271 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1272 LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
1273 TTTOOL_INFO *toolPtr;
1274 INT nTool;
1276 if (lptthit == 0)
1277 return FALSE;
1279 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1280 if (nTool == -1)
1281 return FALSE;
1283 TRACE (tooltips, "tool %d!\n", nTool);
1285 /* copy tool data */
1286 if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1287 toolPtr = &infoPtr->tools[nTool];
1289 lptthit->ti.uFlags = toolPtr->uFlags;
1290 lptthit->ti.hwnd = toolPtr->hwnd;
1291 lptthit->ti.uId = toolPtr->uId;
1292 lptthit->ti.rect = toolPtr->rect;
1293 lptthit->ti.hinst = toolPtr->hinst;
1294 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1295 lptthit->ti.lpszText = NULL; /* FIXME */
1296 lptthit->ti.lParam = toolPtr->lParam;
1299 return TRUE;
1303 static LRESULT
1304 TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1306 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1307 LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1308 TTTOOL_INFO *toolPtr;
1309 INT nTool;
1311 if (lptthit == 0)
1312 return FALSE;
1314 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1315 if (nTool == -1)
1316 return FALSE;
1318 TRACE (tooltips, "tool %d!\n", nTool);
1320 /* copy tool data */
1321 if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1322 toolPtr = &infoPtr->tools[nTool];
1324 lptthit->ti.uFlags = toolPtr->uFlags;
1325 lptthit->ti.hwnd = toolPtr->hwnd;
1326 lptthit->ti.uId = toolPtr->uId;
1327 lptthit->ti.rect = toolPtr->rect;
1328 lptthit->ti.hinst = toolPtr->hinst;
1329 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1330 lptthit->ti.lpszText = NULL; /* FIXME */
1331 lptthit->ti.lParam = toolPtr->lParam;
1334 return TRUE;
1338 static LRESULT
1339 TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1341 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1342 LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
1343 INT nTool;
1345 if (lpti == NULL)
1346 return 0;
1347 if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
1348 return FALSE;
1350 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1351 if (nTool == -1) return 0;
1353 infoPtr->tools[nTool].rect = lpti->rect;
1355 return 0;
1359 static LRESULT
1360 TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1362 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1363 LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
1364 INT nTool;
1366 if (lpti == NULL)
1367 return 0;
1368 if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
1369 return FALSE;
1371 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1372 if (nTool == -1) return 0;
1374 infoPtr->tools[nTool].rect = lpti->rect;
1376 return 0;
1380 __inline__ static LRESULT
1381 TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
1383 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1385 TOOLTIPS_Hide (hwnd, infoPtr);
1387 return 0;
1391 static LRESULT
1392 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1394 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1395 LPMSG lpMsg = (LPMSG)lParam;
1396 POINT pt;
1398 if (lParam == 0) {
1399 ERR (tooltips, "lpMsg == NULL!\n");
1400 return 0;
1403 switch (lpMsg->message) {
1404 case WM_LBUTTONDOWN:
1405 case WM_LBUTTONUP:
1406 case WM_MBUTTONDOWN:
1407 case WM_MBUTTONUP:
1408 case WM_RBUTTONDOWN:
1409 case WM_RBUTTONUP:
1410 pt = lpMsg->pt;
1411 ScreenToClient (lpMsg->hwnd, &pt);
1412 infoPtr->nOldTool = infoPtr->nTool;
1413 infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1414 TRACE (tooltips, "tool (%x) %d %d\n",
1415 hwnd, infoPtr->nOldTool, infoPtr->nTool);
1416 TOOLTIPS_Hide (hwnd, infoPtr);
1417 break;
1419 case WM_MOUSEMOVE:
1420 pt = lpMsg->pt;
1421 ScreenToClient (lpMsg->hwnd, &pt);
1422 infoPtr->nOldTool = infoPtr->nTool;
1423 infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1424 TRACE (tooltips, "tool (%x) %d %d\n",
1425 hwnd, infoPtr->nOldTool, infoPtr->nTool);
1426 TRACE (tooltips, "WM_MOUSEMOVE (%04x %ld %ld)\n",
1427 hwnd, pt.x, pt.y);
1428 if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
1429 if (infoPtr->nOldTool == -1) {
1430 SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1431 TRACE (tooltips, "timer 1 started!\n");
1433 else {
1434 TOOLTIPS_Hide (hwnd, infoPtr);
1435 SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1436 TRACE (tooltips, "timer 2 started!\n");
1439 if (infoPtr->nCurrentTool != -1) {
1440 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
1441 TRACE (tooltips, "timer 3 started!\n");
1443 break;
1446 return 0;
1450 static LRESULT
1451 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1453 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1454 INT nTime = (INT)LOWORD(lParam);
1456 switch (wParam) {
1457 case TTDT_AUTOMATIC:
1458 if (nTime == 0) {
1459 infoPtr->nAutomaticTime = 500;
1460 infoPtr->nReshowTime = 100;
1461 infoPtr->nAutoPopTime = 5000;
1462 infoPtr->nInitialTime = 500;
1464 else {
1465 infoPtr->nAutomaticTime = nTime;
1466 infoPtr->nReshowTime = nTime / 5;
1467 infoPtr->nAutoPopTime = nTime * 10;
1468 infoPtr->nInitialTime = nTime;
1470 break;
1472 case TTDT_RESHOW:
1473 infoPtr->nReshowTime = nTime;
1474 break;
1476 case TTDT_AUTOPOP:
1477 infoPtr->nAutoPopTime = nTime;
1478 break;
1480 case TTDT_INITIAL:
1481 infoPtr->nInitialTime = nTime;
1482 break;
1485 return 0;
1489 static LRESULT
1490 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1492 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1493 LPRECT lpRect = (LPRECT)lParam;
1495 infoPtr->rcMargin.left = lpRect->left;
1496 infoPtr->rcMargin.right = lpRect->right;
1497 infoPtr->rcMargin.bottom = lpRect->bottom;
1498 infoPtr->rcMargin.top = lpRect->top;
1500 return 0;
1504 __inline__ static LRESULT
1505 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1507 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1508 INT nTemp = infoPtr->nMaxTipWidth;
1510 infoPtr->nMaxTipWidth = (INT)lParam;
1512 return nTemp;
1516 __inline__ static LRESULT
1517 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1519 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1521 infoPtr->clrBk = (COLORREF)wParam;
1523 return 0;
1527 __inline__ static LRESULT
1528 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1530 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1532 infoPtr->clrText = (COLORREF)wParam;
1534 return 0;
1538 static LRESULT
1539 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1541 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1542 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1543 TTTOOL_INFO *toolPtr;
1544 INT nTool;
1546 if (lpToolInfo == NULL)
1547 return 0;
1548 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1549 return 0;
1551 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1552 if (nTool == -1) return 0;
1554 TRACE (tooltips, "tool %d\n", nTool);
1556 toolPtr = &infoPtr->tools[nTool];
1558 /* copy tool data */
1559 toolPtr->uFlags = lpToolInfo->uFlags;
1560 toolPtr->hwnd = lpToolInfo->hwnd;
1561 toolPtr->uId = lpToolInfo->uId;
1562 toolPtr->rect = lpToolInfo->rect;
1563 toolPtr->hinst = lpToolInfo->hinst;
1565 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1566 TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
1567 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1569 else if (lpToolInfo->lpszText) {
1570 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1571 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1572 else {
1573 if (toolPtr->lpszText) {
1574 COMCTL32_Free (toolPtr->lpszText);
1575 toolPtr->lpszText = NULL;
1577 if (lpToolInfo->lpszText) {
1578 INT len = lstrlenA (lpToolInfo->lpszText);
1579 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1580 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1585 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1586 toolPtr->lParam = lpToolInfo->lParam;
1588 return 0;
1592 static LRESULT
1593 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1595 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1596 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1597 TTTOOL_INFO *toolPtr;
1598 INT nTool;
1600 if (lpToolInfo == NULL)
1601 return 0;
1602 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1603 return 0;
1605 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1606 if (nTool == -1) return 0;
1608 TRACE (tooltips, "tool %d\n", nTool);
1610 toolPtr = &infoPtr->tools[nTool];
1612 /* copy tool data */
1613 toolPtr->uFlags = lpToolInfo->uFlags;
1614 toolPtr->hwnd = lpToolInfo->hwnd;
1615 toolPtr->uId = lpToolInfo->uId;
1616 toolPtr->rect = lpToolInfo->rect;
1617 toolPtr->hinst = lpToolInfo->hinst;
1619 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1620 TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
1621 toolPtr->lpszText = lpToolInfo->lpszText;
1623 else if (lpToolInfo->lpszText) {
1624 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1625 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1626 else {
1627 if (toolPtr->lpszText) {
1628 COMCTL32_Free (toolPtr->lpszText);
1629 toolPtr->lpszText = NULL;
1631 if (lpToolInfo->lpszText) {
1632 INT len = lstrlenW (lpToolInfo->lpszText);
1633 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1634 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1639 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1640 toolPtr->lParam = lpToolInfo->lParam;
1642 return 0;
1646 static LRESULT
1647 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1649 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1650 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1652 if (lpToolInfo == NULL)
1653 return 0;
1654 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1655 return FALSE;
1657 if ((BOOL)wParam) {
1658 /* activate */
1659 infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1660 if (infoPtr->nTrackTool != -1) {
1661 TRACE (tooltips, "activated!\n");
1662 infoPtr->bTrackActive = TRUE;
1663 TOOLTIPS_TrackShow (hwnd, infoPtr);
1666 else {
1667 /* deactivate */
1668 TOOLTIPS_TrackHide (hwnd, infoPtr);
1670 infoPtr->bTrackActive = FALSE;
1671 infoPtr->nTrackTool = -1;
1673 TRACE (tooltips, "deactivated!\n");
1676 return 0;
1680 static LRESULT
1681 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1683 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1685 infoPtr->xTrackPos = (INT)LOWORD(lParam);
1686 infoPtr->yTrackPos = (INT)HIWORD(lParam);
1688 if (infoPtr->bTrackActive) {
1689 TRACE (tooltips, "[%d %d]\n",
1690 infoPtr->xTrackPos, infoPtr->yTrackPos);
1692 TOOLTIPS_TrackShow (hwnd, infoPtr);
1695 return 0;
1699 static LRESULT
1700 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1702 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1704 if (infoPtr->nCurrentTool != -1)
1705 UpdateWindow (hwnd);
1707 return 0;
1711 static LRESULT
1712 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1714 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1715 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1716 TTTOOL_INFO *toolPtr;
1717 INT nTool;
1719 if (lpToolInfo == NULL)
1720 return 0;
1721 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1722 return FALSE;
1724 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1725 if (nTool == -1) return 0;
1727 TRACE (tooltips, "tool %d\n", nTool);
1729 toolPtr = &infoPtr->tools[nTool];
1731 /* copy tool text */
1732 toolPtr->hinst = lpToolInfo->hinst;
1734 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1735 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1737 else if (lpToolInfo->lpszText) {
1738 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1739 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1740 else {
1741 if (toolPtr->lpszText) {
1742 COMCTL32_Free (toolPtr->lpszText);
1743 toolPtr->lpszText = NULL;
1745 if (lpToolInfo->lpszText) {
1746 INT len = lstrlenA (lpToolInfo->lpszText);
1747 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1748 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1753 /* force repaint */
1754 if (infoPtr->bActive)
1755 TOOLTIPS_Show (hwnd, infoPtr);
1756 else if (infoPtr->bTrackActive)
1757 TOOLTIPS_TrackShow (hwnd, infoPtr);
1759 return 0;
1763 static LRESULT
1764 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1766 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1767 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1768 TTTOOL_INFO *toolPtr;
1769 INT nTool;
1771 if (lpToolInfo == NULL)
1772 return 0;
1773 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1774 return FALSE;
1776 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1777 if (nTool == -1)
1778 return 0;
1780 TRACE (tooltips, "tool %d\n", nTool);
1782 toolPtr = &infoPtr->tools[nTool];
1784 /* copy tool text */
1785 toolPtr->hinst = lpToolInfo->hinst;
1787 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1788 toolPtr->lpszText = lpToolInfo->lpszText;
1790 else if (lpToolInfo->lpszText) {
1791 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1792 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1793 else {
1794 if (toolPtr->lpszText) {
1795 COMCTL32_Free (toolPtr->lpszText);
1796 toolPtr->lpszText = NULL;
1798 if (lpToolInfo->lpszText) {
1799 INT len = lstrlenW (lpToolInfo->lpszText);
1800 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1801 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1806 /* force repaint */
1807 if (infoPtr->bActive)
1808 TOOLTIPS_Show (hwnd, infoPtr);
1809 else if (infoPtr->bTrackActive)
1810 TOOLTIPS_TrackShow (hwnd, infoPtr);
1812 return 0;
1816 static LRESULT
1817 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1819 return WindowFromPoint (*((LPPOINT)lParam));
1824 static LRESULT
1825 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1827 TOOLTIPS_INFO *infoPtr;
1828 NONCLIENTMETRICSA nclm;
1829 INT nResult;
1831 /* allocate memory for info structure */
1832 infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1833 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1835 /* initialize info structure */
1836 infoPtr->bActive = TRUE;
1837 infoPtr->bTrackActive = FALSE;
1838 infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
1839 infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1841 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1842 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1843 infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1845 infoPtr->nMaxTipWidth = -1;
1846 infoPtr->nTool = -1;
1847 infoPtr->nOldTool = -1;
1848 infoPtr->nCurrentTool = -1;
1849 infoPtr->nTrackTool = -1;
1851 infoPtr->nAutomaticTime = 500;
1852 infoPtr->nReshowTime = 100;
1853 infoPtr->nAutoPopTime = 5000;
1854 infoPtr->nInitialTime = 500;
1856 nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
1857 (WPARAM)hwnd, (LPARAM)NF_QUERY);
1858 if (nResult == NFR_ANSI)
1859 FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1860 else if (nResult == NFR_UNICODE)
1861 FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1862 else
1863 FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: error!\n");
1865 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW);
1867 return 0;
1871 static LRESULT
1872 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1874 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1875 TTTOOL_INFO *toolPtr;
1876 INT i;
1878 /* free tools */
1879 if (infoPtr->tools) {
1880 for (i = 0; i < infoPtr->uNumTools; i++) {
1881 toolPtr = &infoPtr->tools[i];
1882 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
1883 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
1884 COMCTL32_Free (toolPtr->lpszText);
1887 /* remove subclassing */
1888 if (toolPtr->uFlags & TTF_SUBCLASS) {
1889 LPTT_SUBCLASS_INFO lpttsi;
1891 if (toolPtr->uFlags & TTF_IDISHWND)
1892 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1893 else
1894 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
1896 if (lpttsi) {
1897 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
1898 (LONG)lpttsi->wpOrigProc);
1899 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1900 COMCTL32_Free (&lpttsi);
1904 COMCTL32_Free (infoPtr->tools);
1907 /* delete font */
1908 DeleteObject (infoPtr->hFont);
1910 /* free tool tips info data */
1911 COMCTL32_Free (infoPtr);
1913 return 0;
1917 static LRESULT
1918 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1920 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1921 RECT rect;
1922 HBRUSH hBrush;
1924 hBrush = CreateSolidBrush (infoPtr->clrBk);
1925 GetClientRect (hwnd, &rect);
1926 FillRect ((HDC)wParam, &rect, hBrush);
1927 DeleteObject (hBrush);
1929 return FALSE;
1933 static LRESULT
1934 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1936 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1938 return infoPtr->hFont;
1942 static LRESULT
1943 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1945 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1947 TOOLTIPS_Hide (hwnd, infoPtr);
1949 return 0;
1953 static LRESULT
1954 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1956 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1958 dwStyle &= 0x0000FFFF;
1959 dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1960 SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
1962 return TRUE;
1966 static LRESULT
1967 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1969 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1970 INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
1972 TRACE (tooltips, " nTool=%d\n", nTool);
1974 if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
1975 if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
1976 TRACE (tooltips, "-- in transparent mode!\n");
1977 return HTTRANSPARENT;
1981 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1985 static LRESULT
1986 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1988 HDC hdc;
1989 PAINTSTRUCT ps;
1991 hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1992 TOOLTIPS_Refresh (hwnd, hdc);
1993 if (!wParam)
1994 EndPaint (hwnd, &ps);
1995 return 0;
1999 static LRESULT
2000 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2002 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2004 infoPtr->hFont = (HFONT)wParam;
2006 if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2007 FIXME (tooltips, "full redraw needed!\n");
2010 return 0;
2014 static LRESULT
2015 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2017 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2019 TRACE (tooltips, "timer %d (%x) expired!\n", wParam, hwnd);
2021 switch (wParam)
2023 case ID_TIMERSHOW:
2024 KillTimer (hwnd, ID_TIMERSHOW);
2025 if (TOOLTIPS_CheckTool (hwnd, TRUE) == infoPtr->nTool)
2026 TOOLTIPS_Show (hwnd, infoPtr);
2027 break;
2029 case ID_TIMERPOP:
2030 TOOLTIPS_Hide (hwnd, infoPtr);
2031 break;
2033 case ID_TIMERLEAVE:
2034 KillTimer (hwnd, ID_TIMERLEAVE);
2035 if (TOOLTIPS_CheckTool (hwnd, FALSE) == -1) {
2036 infoPtr->nTool = -1;
2037 infoPtr->nOldTool = -1;
2038 TOOLTIPS_Hide (hwnd, infoPtr);
2040 break;
2042 return 0;
2046 static LRESULT
2047 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2049 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2050 NONCLIENTMETRICSA nclm;
2052 infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
2053 infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2055 DeleteObject (infoPtr->hFont);
2056 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2057 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2058 infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2060 return 0;
2064 LRESULT CALLBACK
2065 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2067 LPTT_SUBCLASS_INFO lpttsi =
2068 (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2069 TOOLTIPS_INFO *infoPtr;
2070 UINT nTool;
2072 switch (uMsg) {
2073 case WM_LBUTTONDOWN:
2074 case WM_LBUTTONUP:
2075 case WM_MBUTTONDOWN:
2076 case WM_MBUTTONUP:
2077 case WM_RBUTTONDOWN:
2078 case WM_RBUTTONUP:
2079 infoPtr = TOOLTIPS_GetInfoPtr(lpttsi->hwndToolTip);
2080 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2082 TRACE (tooltips, "subclassed mouse message %04x\n", uMsg);
2083 infoPtr->nOldTool = infoPtr->nTool;
2084 infoPtr->nTool = nTool;
2085 TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2086 break;
2088 case WM_MOUSEMOVE:
2089 infoPtr = TOOLTIPS_GetInfoPtr (lpttsi->hwndToolTip);
2090 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2092 TRACE (tooltips, "subclassed WM_MOUSEMOVE\n");
2093 infoPtr->nOldTool = infoPtr->nTool;
2094 infoPtr->nTool = nTool;
2096 if ((infoPtr->bActive) &&
2097 (infoPtr->nTool != infoPtr->nOldTool)) {
2098 if (infoPtr->nOldTool == -1) {
2099 SetTimer (hwnd, ID_TIMERSHOW,
2100 infoPtr->nInitialTime, 0);
2101 TRACE (tooltips, "timer 1 started!\n");
2103 else {
2104 TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2105 SetTimer (hwnd, ID_TIMERSHOW,
2106 infoPtr->nReshowTime, 0);
2107 TRACE (tooltips, "timer 2 started!\n");
2110 if (infoPtr->nCurrentTool != -1) {
2111 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
2112 TRACE (tooltips, "timer 3 started!\n");
2114 break;
2117 return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2121 LRESULT CALLBACK
2122 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2124 switch (uMsg)
2126 case TTM_ACTIVATE:
2127 return TOOLTIPS_Activate (hwnd, wParam, lParam);
2129 case TTM_ADDTOOLA:
2130 return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2132 case TTM_ADDTOOLW:
2133 return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2135 case TTM_DELTOOLA:
2136 return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2138 case TTM_DELTOOLW:
2139 return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2141 case TTM_ENUMTOOLSA:
2142 return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2144 case TTM_ENUMTOOLSW:
2145 return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2147 case TTM_GETCURRENTTOOLA:
2148 return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2150 case TTM_GETCURRENTTOOLW:
2151 return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2153 case TTM_GETDELAYTIME:
2154 return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2156 case TTM_GETMARGIN:
2157 return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2159 case TTM_GETMAXTIPWIDTH:
2160 return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2162 case TTM_GETTEXTA:
2163 return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2165 case TTM_GETTEXTW:
2166 return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2168 case TTM_GETTIPBKCOLOR:
2169 return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2171 case TTM_GETTIPTEXTCOLOR:
2172 return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2174 case TTM_GETTOOLCOUNT:
2175 return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2177 case TTM_GETTOOLINFOA:
2178 return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2180 case TTM_GETTOOLINFOW:
2181 return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2183 case TTM_HITTESTA:
2184 return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2186 case TTM_HITTESTW:
2187 return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2189 case TTM_NEWTOOLRECTA:
2190 return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2192 case TTM_NEWTOOLRECTW:
2193 return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2195 case TTM_POP:
2196 return TOOLTIPS_Pop (hwnd, wParam, lParam);
2198 case TTM_RELAYEVENT:
2199 return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2201 case TTM_SETDELAYTIME:
2202 return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2204 case TTM_SETMARGIN:
2205 return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2207 case TTM_SETMAXTIPWIDTH:
2208 return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2210 case TTM_SETTIPBKCOLOR:
2211 return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2213 case TTM_SETTIPTEXTCOLOR:
2214 return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2216 case TTM_SETTOOLINFOA:
2217 return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2219 case TTM_SETTOOLINFOW:
2220 return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2222 case TTM_TRACKACTIVATE:
2223 return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2225 case TTM_TRACKPOSITION:
2226 return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2228 case TTM_UPDATE:
2229 return TOOLTIPS_Update (hwnd, wParam, lParam);
2231 case TTM_UPDATETIPTEXTA:
2232 return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2234 case TTM_UPDATETIPTEXTW:
2235 return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2237 case TTM_WINDOWFROMPOINT:
2238 return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2241 case WM_CREATE:
2242 return TOOLTIPS_Create (hwnd, wParam, lParam);
2244 case WM_DESTROY:
2245 return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2247 case WM_ERASEBKGND:
2248 return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2250 case WM_GETFONT:
2251 return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2253 case WM_LBUTTONDOWN:
2254 case WM_LBUTTONUP:
2255 case WM_MBUTTONDOWN:
2256 case WM_MBUTTONUP:
2257 case WM_RBUTTONDOWN:
2258 case WM_RBUTTONUP:
2259 case WM_MOUSEMOVE:
2260 return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2262 case WM_NCCREATE:
2263 return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2265 case WM_NCHITTEST:
2266 return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2268 /* case WM_NOTIFYFORMAT: */
2269 /* return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam); */
2271 case WM_PAINT:
2272 return TOOLTIPS_Paint (hwnd, wParam, lParam);
2274 case WM_SETFONT:
2275 return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2277 case WM_TIMER:
2278 return TOOLTIPS_Timer (hwnd, wParam, lParam);
2280 case WM_WININICHANGE:
2281 return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2283 default:
2284 if (uMsg >= WM_USER)
2285 ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
2286 uMsg, wParam, lParam);
2287 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2289 return 0;
2293 VOID
2294 TOOLTIPS_Register (VOID)
2296 WNDCLASSA wndClass;
2298 if (GlobalFindAtomA (TOOLTIPS_CLASSA)) return;
2300 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2301 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2302 wndClass.lpfnWndProc = (WNDPROC)TOOLTIPS_WindowProc;
2303 wndClass.cbClsExtra = 0;
2304 wndClass.cbWndExtra = sizeof(TOOLTIPS_INFO *);
2305 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2306 wndClass.hbrBackground = 0;
2307 wndClass.lpszClassName = TOOLTIPS_CLASSA;
2309 RegisterClassA (&wndClass);
2313 VOID
2314 TOOLTIPS_Unregister (VOID)
2316 if (GlobalFindAtomA (TOOLTIPS_CLASSA))
2317 UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);