Converted to the new debug interface, using script written by Patrik
[wine/testsucceed.git] / dlls / comctl32 / tooltips.c
blob6b6fcd6734b84e3bdbab34eb7ec9c88264b82186
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 "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(tooltips)
26 #define ID_TIMERSHOW 1 /* show delay timer */
27 #define ID_TIMERPOP 2 /* auto pop timer */
28 #define ID_TIMERLEAVE 3 /* tool leave timer */
31 extern LPSTR COMCTL32_aSubclass; /* global subclassing atom */
33 /* property name of tooltip window handle */
34 /*#define TT_SUBCLASS_PROP "CC32SubclassInfo" */
36 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
39 LRESULT CALLBACK
40 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
43 static VOID
44 TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
46 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd);
47 RECT rc;
48 INT oldBkMode;
49 HFONT hOldFont;
50 HBRUSH hBrush;
51 UINT uFlags = DT_EXTERNALLEADING;
53 if (infoPtr->nMaxTipWidth > -1)
54 uFlags |= DT_WORDBREAK;
55 if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
56 uFlags |= DT_NOPREFIX;
57 GetClientRect (hwnd, &rc);
59 /* fill the background */
60 hBrush = CreateSolidBrush (infoPtr->clrBk);
61 FillRect (hdc, &rc, hBrush);
62 DeleteObject (hBrush);
64 /* calculate text rectangle */
65 rc.left += (2 + infoPtr->rcMargin.left);
66 rc.top += (2 + infoPtr->rcMargin.top);
67 rc.right -= (2 + infoPtr->rcMargin.right);
68 rc.bottom -= (2 + infoPtr->rcMargin.bottom);
70 /* draw text */
71 oldBkMode = SetBkMode (hdc, TRANSPARENT);
72 SetTextColor (hdc, infoPtr->clrText);
73 hOldFont = SelectObject (hdc, infoPtr->hFont);
74 DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
75 SelectObject (hdc, hOldFont);
76 if (oldBkMode != TRANSPARENT)
77 SetBkMode (hdc, oldBkMode);
81 static VOID
82 TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
84 TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
86 if ((toolPtr->hinst) && (HIWORD((UINT)toolPtr->lpszText) == 0)) {
87 /* load a resource */
88 TRACE("load res string %x %x\n",
89 toolPtr->hinst, (int)toolPtr->lpszText);
90 LoadStringW (toolPtr->hinst, (UINT)toolPtr->lpszText,
91 infoPtr->szTipText, INFOTIPSIZE);
93 else if (toolPtr->lpszText) {
94 if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
95 NMTTDISPINFOA ttnmdi;
97 /* fill NMHDR struct */
98 ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA));
99 ttnmdi.hdr.hwndFrom = hwnd;
100 ttnmdi.hdr.idFrom = toolPtr->uId;
101 ttnmdi.hdr.code = TTN_GETDISPINFOA;
102 ttnmdi.lpszText = (LPSTR)&ttnmdi.szText;
103 ttnmdi.uFlags = toolPtr->uFlags;
104 ttnmdi.lParam = toolPtr->lParam;
106 TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
107 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
108 (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);
110 if ((ttnmdi.hinst) && (HIWORD((UINT)ttnmdi.lpszText) == 0)) {
111 LoadStringW (ttnmdi.hinst, (UINT)ttnmdi.lpszText,
112 infoPtr->szTipText, INFOTIPSIZE);
113 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
114 toolPtr->hinst = ttnmdi.hinst;
115 toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText;
118 else if (ttnmdi.szText[0]) {
119 lstrcpynAtoW (infoPtr->szTipText, ttnmdi.szText, 80);
120 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
121 INT len = lstrlenA (ttnmdi.szText);
122 toolPtr->hinst = 0;
123 toolPtr->lpszText = COMCTL32_Alloc ((len+1)* sizeof(WCHAR));
124 lstrcpyAtoW (toolPtr->lpszText, ttnmdi.szText);
127 else if (ttnmdi.lpszText == 0) {
128 /* no text available */
129 infoPtr->szTipText[0] = L'\0';
131 else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
132 lstrcpynAtoW (infoPtr->szTipText, ttnmdi.lpszText, INFOTIPSIZE);
133 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
134 INT len = lstrlenA (ttnmdi.lpszText);
135 toolPtr->hinst = 0;
136 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
137 lstrcpyAtoW (toolPtr->lpszText, ttnmdi.lpszText);
140 else {
141 ERR("recursive text callback!\n");
142 infoPtr->szTipText[0] = '\0';
145 else {
146 /* the item is a usual (unicode) text */
147 lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
150 else {
151 /* no text available */
152 infoPtr->szTipText[0] = L'\0';
155 TRACE("\"%s\"\n", debugstr_w(infoPtr->szTipText));
159 static VOID
160 TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
162 HDC hdc;
163 HFONT hOldFont;
164 UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
165 RECT rc = {0, 0, 0, 0};
167 if (infoPtr->nMaxTipWidth > -1) {
168 rc.right = infoPtr->nMaxTipWidth;
169 uFlags |= DT_WORDBREAK;
171 if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
172 uFlags |= DT_NOPREFIX;
173 TRACE("\"%s\"\n", debugstr_w(infoPtr->szTipText));
175 hdc = GetDC (hwnd);
176 hOldFont = SelectObject (hdc, infoPtr->hFont);
177 DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
178 SelectObject (hdc, hOldFont);
179 ReleaseDC (hwnd, hdc);
181 lpSize->cx = rc.right - rc.left + 4 +
182 infoPtr->rcMargin.left + infoPtr->rcMargin.right;
183 lpSize->cy = rc.bottom - rc.top + 4 +
184 infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
188 static VOID
189 TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
191 TTTOOL_INFO *toolPtr;
192 RECT rect;
193 SIZE size;
194 HDC hdc;
195 NMHDR hdr;
197 if (infoPtr->nTool == -1) {
198 TRACE("invalid tool (-1)!\n");
199 return;
202 infoPtr->nCurrentTool = infoPtr->nTool;
204 TRACE("Show tooltip pre %d!\n", infoPtr->nTool);
206 TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
208 if (infoPtr->szTipText[0] == L'\0') {
209 infoPtr->nCurrentTool = -1;
210 return;
213 TRACE("Show tooltip %d!\n", infoPtr->nCurrentTool);
214 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
216 hdr.hwndFrom = hwnd;
217 hdr.idFrom = toolPtr->uId;
218 hdr.code = TTN_SHOW;
219 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
220 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
222 TRACE("\"%s\"\n", debugstr_w(infoPtr->szTipText));
224 TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
225 TRACE("size %d - %d\n", size.cx, size.cy);
227 if (toolPtr->uFlags & TTF_CENTERTIP) {
228 RECT rc;
230 if (toolPtr->uFlags & TTF_IDISHWND)
231 GetWindowRect ((HWND)toolPtr->uId, &rc);
232 else {
233 rc = toolPtr->rect;
234 MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rc, 2);
236 rect.left = (rc.left + rc.right - size.cx) / 2;
237 rect.top = rc.bottom + 2;
239 else {
240 GetCursorPos ((LPPOINT)&rect);
241 rect.top += 20;
244 /* FIXME: check position */
246 TRACE("pos %d - %d\n", rect.left, rect.top);
248 rect.right = rect.left + size.cx;
249 rect.bottom = rect.top + size.cy;
251 AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
252 FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
254 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
255 rect.right - rect.left, rect.bottom - rect.top,
256 SWP_SHOWWINDOW | SWP_NOACTIVATE);
258 /* repaint the tooltip */
259 hdc = GetDC (hwnd);
260 TOOLTIPS_Refresh (hwnd, hdc);
261 ReleaseDC (hwnd, hdc);
263 SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
267 static VOID
268 TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
270 TTTOOL_INFO *toolPtr;
271 NMHDR hdr;
273 if (infoPtr->nCurrentTool == -1)
274 return;
276 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
277 TRACE("Hide tooltip %d!\n", infoPtr->nCurrentTool);
278 KillTimer (hwnd, ID_TIMERPOP);
280 hdr.hwndFrom = hwnd;
281 hdr.idFrom = toolPtr->uId;
282 hdr.code = TTN_POP;
283 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
284 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
286 infoPtr->nCurrentTool = -1;
288 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
289 SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
293 static VOID
294 TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
296 TTTOOL_INFO *toolPtr;
297 RECT rect;
298 SIZE size;
299 HDC hdc;
300 NMHDR hdr;
302 if (infoPtr->nTrackTool == -1) {
303 TRACE("invalid tracking tool (-1)!\n");
304 return;
307 TRACE("show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
309 TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
311 if (infoPtr->szTipText[0] == L'\0') {
312 infoPtr->nTrackTool = -1;
313 return;
316 TRACE("show tracking tooltip %d!\n", infoPtr->nTrackTool);
317 toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
319 hdr.hwndFrom = hwnd;
320 hdr.idFrom = toolPtr->uId;
321 hdr.code = TTN_SHOW;
322 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
323 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
325 TRACE("\"%s\"\n", debugstr_w(infoPtr->szTipText));
327 TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
328 TRACE("size %d - %d\n", size.cx, size.cy);
330 if (toolPtr->uFlags & TTF_ABSOLUTE) {
331 rect.left = infoPtr->xTrackPos;
332 rect.top = infoPtr->yTrackPos;
334 if (toolPtr->uFlags & TTF_CENTERTIP) {
335 rect.left -= (size.cx / 2);
336 rect.top -= (size.cy / 2);
339 else {
340 RECT rcTool;
342 if (toolPtr->uFlags & TTF_IDISHWND)
343 GetWindowRect ((HWND)toolPtr->uId, &rcTool);
344 else {
345 rcTool = toolPtr->rect;
346 MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rcTool, 2);
349 GetCursorPos ((LPPOINT)&rect);
350 rect.top += 20;
352 if (toolPtr->uFlags & TTF_CENTERTIP) {
353 rect.left -= (size.cx / 2);
354 rect.top -= (size.cy / 2);
357 /* smart placement */
358 if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
359 (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
360 rect.left = rcTool.right;
363 TRACE("pos %d - %d\n", rect.left, rect.top);
365 rect.right = rect.left + size.cx;
366 rect.bottom = rect.top + 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 hdc = GetDC (hwnd);
376 TOOLTIPS_Refresh (hwnd, hdc);
377 ReleaseDC (hwnd, hdc);
381 static VOID
382 TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
384 TTTOOL_INFO *toolPtr;
385 NMHDR hdr;
387 if (infoPtr->nTrackTool == -1)
388 return;
390 toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
391 TRACE("hide tracking tooltip %d!\n", infoPtr->nTrackTool);
393 hdr.hwndFrom = hwnd;
394 hdr.idFrom = toolPtr->uId;
395 hdr.code = TTN_POP;
396 SendMessageA (toolPtr->hwnd, WM_NOTIFY,
397 (WPARAM)toolPtr->uId, (LPARAM)&hdr);
399 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
400 SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
404 static INT
405 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
407 TTTOOL_INFO *toolPtr;
408 INT nTool;
410 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
411 toolPtr = &infoPtr->tools[nTool];
413 if (!(toolPtr->uFlags & TTF_IDISHWND) &&
414 (lpToolInfo->hwnd == toolPtr->hwnd) &&
415 (lpToolInfo->uId == toolPtr->uId))
416 return nTool;
419 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
420 toolPtr = &infoPtr->tools[nTool];
422 if ((toolPtr->uFlags & TTF_IDISHWND) &&
423 (lpToolInfo->uId == toolPtr->uId))
424 return nTool;
427 return -1;
431 static INT
432 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
434 TTTOOL_INFO *toolPtr;
435 INT nTool;
437 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
438 toolPtr = &infoPtr->tools[nTool];
440 if (!(toolPtr->uFlags & TTF_IDISHWND) &&
441 (lpToolInfo->hwnd == toolPtr->hwnd) &&
442 (lpToolInfo->uId == toolPtr->uId))
443 return nTool;
446 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
447 toolPtr = &infoPtr->tools[nTool];
449 if ((toolPtr->uFlags & TTF_IDISHWND) &&
450 (lpToolInfo->uId == toolPtr->uId))
451 return nTool;
454 return -1;
458 static INT
459 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
461 TTTOOL_INFO *toolPtr;
462 INT nTool;
464 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
465 toolPtr = &infoPtr->tools[nTool];
467 if (!(toolPtr->uFlags & TTF_IDISHWND)) {
468 if (hwnd != toolPtr->hwnd)
469 continue;
470 if (!PtInRect (&toolPtr->rect, *lpPt))
471 continue;
472 return nTool;
476 for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
477 toolPtr = &infoPtr->tools[nTool];
479 if (toolPtr->uFlags & TTF_IDISHWND) {
480 if ((HWND)toolPtr->uId == hwnd)
481 return nTool;
485 return -1;
489 static INT
490 TOOLTIPS_GetToolFromMessage (TOOLTIPS_INFO *infoPtr, HWND hwndTool)
492 DWORD dwPos;
493 POINT pt;
495 dwPos = GetMessagePos ();
496 pt.x = (INT)LOWORD(dwPos);
497 pt.y = (INT)HIWORD(dwPos);
498 ScreenToClient (hwndTool, &pt);
500 return TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
504 static BOOL
505 TOOLTIPS_IsWindowActive (HWND hwnd)
507 HWND hwndActive = GetActiveWindow ();
508 if (!hwndActive)
509 return FALSE;
510 if (hwndActive == hwnd)
511 return TRUE;
512 return IsChild (hwndActive, hwnd);
516 static INT
517 TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest)
519 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
520 POINT pt;
521 HWND hwndTool;
522 INT nTool;
524 GetCursorPos (&pt);
525 hwndTool = SendMessageA (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
526 if (hwndTool == 0)
527 return -1;
529 ScreenToClient (hwndTool, &pt);
530 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
531 if (nTool == -1)
532 return -1;
534 if (!(GetWindowLongA (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) {
535 if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER)))
536 return -1;
539 TRACE("tool %d\n", nTool);
541 return nTool;
545 static LRESULT
546 TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam)
548 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
550 infoPtr->bActive = (BOOL)wParam;
552 if (infoPtr->bActive)
553 TRACE("activate!\n");
555 if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1))
556 TOOLTIPS_Hide (hwnd, infoPtr);
558 return 0;
562 static LRESULT
563 TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
565 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
566 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
567 TTTOOL_INFO *toolPtr;
569 if (lpToolInfo == NULL)
570 return FALSE;
571 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
572 return FALSE;
574 TRACE("add tool (%x) %x %d%s!\n",
575 hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
576 (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
578 if (infoPtr->uNumTools == 0) {
579 infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
580 toolPtr = infoPtr->tools;
582 else {
583 TTTOOL_INFO *oldTools = infoPtr->tools;
584 infoPtr->tools =
585 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
586 memcpy (infoPtr->tools, oldTools,
587 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
588 COMCTL32_Free (oldTools);
589 toolPtr = &infoPtr->tools[infoPtr->uNumTools];
592 infoPtr->uNumTools++;
594 /* copy tool data */
595 toolPtr->uFlags = lpToolInfo->uFlags;
596 toolPtr->hwnd = lpToolInfo->hwnd;
597 toolPtr->uId = lpToolInfo->uId;
598 toolPtr->rect = lpToolInfo->rect;
599 toolPtr->hinst = lpToolInfo->hinst;
601 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
602 TRACE("add string id %x!\n", (int)lpToolInfo->lpszText);
603 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
605 else if (lpToolInfo->lpszText) {
606 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) {
607 TRACE("add CALLBACK!\n");
608 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
610 else {
611 INT len = lstrlenA (lpToolInfo->lpszText);
612 TRACE("add text \"%s\"!\n", lpToolInfo->lpszText);
613 toolPtr->lpszText = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
614 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
618 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
619 toolPtr->lParam = lpToolInfo->lParam;
621 /* install subclassing hook */
622 if (toolPtr->uFlags & TTF_SUBCLASS) {
623 if (toolPtr->uFlags & TTF_IDISHWND) {
624 LPTT_SUBCLASS_INFO lpttsi =
625 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
626 if (lpttsi == NULL) {
627 lpttsi =
628 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
629 lpttsi->wpOrigProc =
630 (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
631 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
632 lpttsi->hwndToolTip = hwnd;
633 lpttsi->uRefCount++;
634 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
635 (HANDLE)lpttsi);
637 else
638 WARN("A window tool must only be listed once!\n");
640 else {
641 LPTT_SUBCLASS_INFO lpttsi =
642 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
643 if (lpttsi == NULL) {
644 lpttsi =
645 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
646 lpttsi->wpOrigProc =
647 (WNDPROC)SetWindowLongA (toolPtr->hwnd,
648 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
649 lpttsi->hwndToolTip = hwnd;
650 lpttsi->uRefCount++;
651 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
653 else
654 lpttsi->uRefCount++;
656 TRACE("subclassing installed!\n");
659 return TRUE;
663 static LRESULT
664 TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
666 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
667 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
668 TTTOOL_INFO *toolPtr;
670 if (lpToolInfo == NULL)
671 return FALSE;
672 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
673 return FALSE;
675 TRACE("add tool (%x) %x %d%s!\n",
676 hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
677 (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
679 if (infoPtr->uNumTools == 0) {
680 infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
681 toolPtr = infoPtr->tools;
683 else {
684 TTTOOL_INFO *oldTools = infoPtr->tools;
685 infoPtr->tools =
686 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
687 memcpy (infoPtr->tools, oldTools,
688 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
689 COMCTL32_Free (oldTools);
690 toolPtr = &infoPtr->tools[infoPtr->uNumTools];
693 infoPtr->uNumTools++;
695 /* copy tool data */
696 toolPtr->uFlags = lpToolInfo->uFlags;
697 toolPtr->hwnd = lpToolInfo->hwnd;
698 toolPtr->uId = lpToolInfo->uId;
699 toolPtr->rect = lpToolInfo->rect;
700 toolPtr->hinst = lpToolInfo->hinst;
702 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
703 TRACE("add string id %x!\n", (int)lpToolInfo->lpszText);
704 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
706 else if (lpToolInfo->lpszText) {
707 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) {
708 TRACE("add CALLBACK!\n");
709 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
711 else {
712 INT len = lstrlenW (lpToolInfo->lpszText);
713 TRACE("add text \"%s\"!\n",
714 debugstr_w(lpToolInfo->lpszText));
715 toolPtr->lpszText = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
716 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
720 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
721 toolPtr->lParam = lpToolInfo->lParam;
723 /* install subclassing hook */
724 if (toolPtr->uFlags & TTF_SUBCLASS) {
725 if (toolPtr->uFlags & TTF_IDISHWND) {
726 LPTT_SUBCLASS_INFO lpttsi =
727 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
728 if (lpttsi == NULL) {
729 lpttsi =
730 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
731 lpttsi->wpOrigProc =
732 (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
733 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
734 lpttsi->hwndToolTip = hwnd;
735 lpttsi->uRefCount++;
736 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
737 (HANDLE)lpttsi);
739 else
740 WARN("A window tool must only be listed once!\n");
742 else {
743 LPTT_SUBCLASS_INFO lpttsi =
744 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
745 if (lpttsi == NULL) {
746 lpttsi =
747 (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
748 lpttsi->wpOrigProc =
749 (WNDPROC)SetWindowLongA (toolPtr->hwnd,
750 GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
751 lpttsi->hwndToolTip = hwnd;
752 lpttsi->uRefCount++;
753 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
755 else
756 lpttsi->uRefCount++;
758 TRACE("subclassing installed!\n");
761 return TRUE;
765 static LRESULT
766 TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
768 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
769 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
770 TTTOOL_INFO *toolPtr;
771 INT nTool;
773 if (lpToolInfo == NULL)
774 return 0;
775 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
776 return 0;
777 if (infoPtr->uNumTools == 0)
778 return 0;
780 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
781 if (nTool == -1) return 0;
783 TRACE("tool %d\n", nTool);
785 /* delete text string */
786 toolPtr = &infoPtr->tools[nTool];
787 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
788 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
789 COMCTL32_Free (toolPtr->lpszText);
792 /* remove subclassing */
793 if (toolPtr->uFlags & TTF_SUBCLASS) {
794 if (toolPtr->uFlags & TTF_IDISHWND) {
795 LPTT_SUBCLASS_INFO lpttsi =
796 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
797 if (lpttsi) {
798 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
799 (LONG)lpttsi->wpOrigProc);
800 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
801 COMCTL32_Free (&lpttsi);
803 else
804 ERR("Invalid data handle!\n");
806 else {
807 LPTT_SUBCLASS_INFO lpttsi =
808 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
809 if (lpttsi) {
810 if (lpttsi->uRefCount == 1) {
811 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
812 (LONG)lpttsi->wpOrigProc);
813 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
814 COMCTL32_Free (&lpttsi);
816 else
817 lpttsi->uRefCount--;
819 else
820 ERR("Invalid data handle!\n");
824 /* delete tool from tool list */
825 if (infoPtr->uNumTools == 1) {
826 COMCTL32_Free (infoPtr->tools);
827 infoPtr->tools = NULL;
829 else {
830 TTTOOL_INFO *oldTools = infoPtr->tools;
831 infoPtr->tools =
832 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
834 if (nTool > 0)
835 memcpy (&infoPtr->tools[0], &oldTools[0],
836 nTool * sizeof(TTTOOL_INFO));
838 if (nTool < infoPtr->uNumTools - 1)
839 memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
840 (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
842 COMCTL32_Free (oldTools);
845 infoPtr->uNumTools--;
847 return 0;
851 static LRESULT
852 TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
854 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
855 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
856 TTTOOL_INFO *toolPtr;
857 INT nTool;
859 if (lpToolInfo == NULL)
860 return 0;
861 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
862 return 0;
863 if (infoPtr->uNumTools == 0)
864 return 0;
866 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
867 if (nTool == -1) return 0;
869 TRACE("tool %d\n", nTool);
871 /* delete text string */
872 toolPtr = &infoPtr->tools[nTool];
873 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
874 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
875 COMCTL32_Free (toolPtr->lpszText);
878 /* remove subclassing */
879 if (toolPtr->uFlags & TTF_SUBCLASS) {
880 if (toolPtr->uFlags & TTF_IDISHWND) {
881 LPTT_SUBCLASS_INFO lpttsi =
882 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
883 if (lpttsi) {
884 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
885 (LONG)lpttsi->wpOrigProc);
886 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
887 COMCTL32_Free (&lpttsi);
889 else
890 ERR("Invalid data handle!\n");
892 else {
893 LPTT_SUBCLASS_INFO lpttsi =
894 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
895 if (lpttsi) {
896 if (lpttsi->uRefCount == 1) {
897 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
898 (LONG)lpttsi->wpOrigProc);
899 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
900 COMCTL32_Free (&lpttsi);
902 else
903 lpttsi->uRefCount--;
905 else
906 ERR("Invalid data handle!\n");
910 /* delete tool from tool list */
911 if (infoPtr->uNumTools == 1) {
912 COMCTL32_Free (infoPtr->tools);
913 infoPtr->tools = NULL;
915 else {
916 TTTOOL_INFO *oldTools = infoPtr->tools;
917 infoPtr->tools =
918 COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
920 if (nTool > 0)
921 memcpy (&infoPtr->tools[0], &oldTools[0],
922 nTool * sizeof(TTTOOL_INFO));
924 if (nTool < infoPtr->uNumTools - 1)
925 memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
926 (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
928 COMCTL32_Free (oldTools);
931 infoPtr->uNumTools--;
933 return 0;
937 static LRESULT
938 TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
940 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
941 UINT uIndex = (UINT)wParam;
942 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
943 TTTOOL_INFO *toolPtr;
945 if (lpToolInfo == NULL)
946 return FALSE;
947 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
948 return FALSE;
949 if (uIndex >= infoPtr->uNumTools)
950 return FALSE;
952 TRACE("index=%u\n", uIndex);
954 toolPtr = &infoPtr->tools[uIndex];
956 /* copy tool data */
957 lpToolInfo->uFlags = toolPtr->uFlags;
958 lpToolInfo->hwnd = toolPtr->hwnd;
959 lpToolInfo->uId = toolPtr->uId;
960 lpToolInfo->rect = toolPtr->rect;
961 lpToolInfo->hinst = toolPtr->hinst;
962 /* lpToolInfo->lpszText = toolPtr->lpszText; */
963 lpToolInfo->lpszText = NULL; /* FIXME */
965 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
966 lpToolInfo->lParam = toolPtr->lParam;
968 return TRUE;
972 static LRESULT
973 TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
975 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
976 UINT uIndex = (UINT)wParam;
977 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
978 TTTOOL_INFO *toolPtr;
980 if (lpToolInfo == NULL)
981 return FALSE;
982 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
983 return FALSE;
984 if (uIndex >= infoPtr->uNumTools)
985 return FALSE;
987 TRACE("index=%u\n", uIndex);
989 toolPtr = &infoPtr->tools[uIndex];
991 /* copy tool data */
992 lpToolInfo->uFlags = toolPtr->uFlags;
993 lpToolInfo->hwnd = toolPtr->hwnd;
994 lpToolInfo->uId = toolPtr->uId;
995 lpToolInfo->rect = toolPtr->rect;
996 lpToolInfo->hinst = toolPtr->hinst;
997 /* lpToolInfo->lpszText = toolPtr->lpszText; */
998 lpToolInfo->lpszText = NULL; /* FIXME */
1000 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1001 lpToolInfo->lParam = toolPtr->lParam;
1003 return TRUE;
1007 static LRESULT
1008 TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1010 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1011 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1012 TTTOOL_INFO *toolPtr;
1014 if (lpToolInfo == NULL)
1015 return FALSE;
1016 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1017 return FALSE;
1019 if (lpToolInfo) {
1020 if (infoPtr->nCurrentTool > -1) {
1021 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1023 /* copy tool data */
1024 lpToolInfo->uFlags = toolPtr->uFlags;
1025 lpToolInfo->rect = toolPtr->rect;
1026 lpToolInfo->hinst = toolPtr->hinst;
1027 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1028 lpToolInfo->lpszText = NULL; /* FIXME */
1030 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1031 lpToolInfo->lParam = toolPtr->lParam;
1033 return TRUE;
1035 else
1036 return FALSE;
1038 else
1039 return (infoPtr->nCurrentTool != -1);
1041 return FALSE;
1045 static LRESULT
1046 TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1048 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1049 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1050 TTTOOL_INFO *toolPtr;
1052 if (lpToolInfo == NULL)
1053 return FALSE;
1054 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1055 return FALSE;
1057 if (lpToolInfo) {
1058 if (infoPtr->nCurrentTool > -1) {
1059 toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1061 /* copy tool data */
1062 lpToolInfo->uFlags = toolPtr->uFlags;
1063 lpToolInfo->rect = toolPtr->rect;
1064 lpToolInfo->hinst = toolPtr->hinst;
1065 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1066 lpToolInfo->lpszText = NULL; /* FIXME */
1068 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1069 lpToolInfo->lParam = toolPtr->lParam;
1071 return TRUE;
1073 else
1074 return FALSE;
1076 else
1077 return (infoPtr->nCurrentTool != -1);
1079 return FALSE;
1083 static LRESULT
1084 TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1086 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1088 switch (wParam) {
1089 case TTDT_AUTOMATIC:
1090 return infoPtr->nAutomaticTime;
1092 case TTDT_RESHOW:
1093 return infoPtr->nReshowTime;
1095 case TTDT_AUTOPOP:
1096 return infoPtr->nAutoPopTime;
1098 case TTDT_INITIAL:
1099 return infoPtr->nInitialTime;
1102 return 0;
1106 static LRESULT
1107 TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1109 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1110 LPRECT lpRect = (LPRECT)lParam;
1112 lpRect->left = infoPtr->rcMargin.left;
1113 lpRect->right = infoPtr->rcMargin.right;
1114 lpRect->bottom = infoPtr->rcMargin.bottom;
1115 lpRect->top = infoPtr->rcMargin.top;
1117 return 0;
1121 inline static LRESULT
1122 TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1124 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1126 return infoPtr->nMaxTipWidth;
1130 static LRESULT
1131 TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1133 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1134 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1135 INT nTool;
1137 if (lpToolInfo == NULL)
1138 return 0;
1139 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1140 return 0;
1142 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1143 if (nTool == -1) return 0;
1145 lstrcpyWtoA (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1147 return 0;
1151 static LRESULT
1152 TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1154 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1155 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1156 INT nTool;
1158 if (lpToolInfo == NULL)
1159 return 0;
1160 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1161 return 0;
1163 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1164 if (nTool == -1) return 0;
1166 lstrcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1168 return 0;
1172 inline static LRESULT
1173 TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1175 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1176 return infoPtr->clrBk;
1180 inline static LRESULT
1181 TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1183 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1184 return infoPtr->clrText;
1188 inline static LRESULT
1189 TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1191 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1192 return infoPtr->uNumTools;
1196 static LRESULT
1197 TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1199 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1200 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1201 TTTOOL_INFO *toolPtr;
1202 INT nTool;
1204 if (lpToolInfo == NULL)
1205 return FALSE;
1206 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1207 return FALSE;
1208 if (infoPtr->uNumTools == 0)
1209 return FALSE;
1211 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1212 if (nTool == -1)
1213 return FALSE;
1215 TRACE("tool %d\n", nTool);
1217 toolPtr = &infoPtr->tools[nTool];
1219 /* copy tool data */
1220 lpToolInfo->uFlags = toolPtr->uFlags;
1221 lpToolInfo->rect = toolPtr->rect;
1222 lpToolInfo->hinst = toolPtr->hinst;
1223 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1224 lpToolInfo->lpszText = NULL; /* FIXME */
1226 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1227 lpToolInfo->lParam = toolPtr->lParam;
1229 return TRUE;
1233 static LRESULT
1234 TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1236 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1237 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1238 TTTOOL_INFO *toolPtr;
1239 INT nTool;
1241 if (lpToolInfo == NULL)
1242 return FALSE;
1243 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1244 return FALSE;
1245 if (infoPtr->uNumTools == 0)
1246 return FALSE;
1248 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1249 if (nTool == -1)
1250 return FALSE;
1252 TRACE("tool %d\n", nTool);
1254 toolPtr = &infoPtr->tools[nTool];
1256 /* copy tool data */
1257 lpToolInfo->uFlags = toolPtr->uFlags;
1258 lpToolInfo->rect = toolPtr->rect;
1259 lpToolInfo->hinst = toolPtr->hinst;
1260 /* lpToolInfo->lpszText = toolPtr->lpszText; */
1261 lpToolInfo->lpszText = NULL; /* FIXME */
1263 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1264 lpToolInfo->lParam = toolPtr->lParam;
1266 return TRUE;
1270 static LRESULT
1271 TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1273 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1274 LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
1275 TTTOOL_INFO *toolPtr;
1276 INT nTool;
1278 if (lptthit == 0)
1279 return FALSE;
1281 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1282 if (nTool == -1)
1283 return FALSE;
1285 TRACE("tool %d!\n", nTool);
1287 /* copy tool data */
1288 if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1289 toolPtr = &infoPtr->tools[nTool];
1291 lptthit->ti.uFlags = toolPtr->uFlags;
1292 lptthit->ti.hwnd = toolPtr->hwnd;
1293 lptthit->ti.uId = toolPtr->uId;
1294 lptthit->ti.rect = toolPtr->rect;
1295 lptthit->ti.hinst = toolPtr->hinst;
1296 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1297 lptthit->ti.lpszText = NULL; /* FIXME */
1298 lptthit->ti.lParam = toolPtr->lParam;
1301 return TRUE;
1305 static LRESULT
1306 TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1308 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1309 LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1310 TTTOOL_INFO *toolPtr;
1311 INT nTool;
1313 if (lptthit == 0)
1314 return FALSE;
1316 nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1317 if (nTool == -1)
1318 return FALSE;
1320 TRACE("tool %d!\n", nTool);
1322 /* copy tool data */
1323 if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1324 toolPtr = &infoPtr->tools[nTool];
1326 lptthit->ti.uFlags = toolPtr->uFlags;
1327 lptthit->ti.hwnd = toolPtr->hwnd;
1328 lptthit->ti.uId = toolPtr->uId;
1329 lptthit->ti.rect = toolPtr->rect;
1330 lptthit->ti.hinst = toolPtr->hinst;
1331 /* lptthit->ti.lpszText = toolPtr->lpszText; */
1332 lptthit->ti.lpszText = NULL; /* FIXME */
1333 lptthit->ti.lParam = toolPtr->lParam;
1336 return TRUE;
1340 static LRESULT
1341 TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1343 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1344 LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
1345 INT nTool;
1347 if (lpti == NULL)
1348 return 0;
1349 if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
1350 return FALSE;
1352 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1353 if (nTool == -1) return 0;
1355 infoPtr->tools[nTool].rect = lpti->rect;
1357 return 0;
1361 static LRESULT
1362 TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1364 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1365 LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
1366 INT nTool;
1368 if (lpti == NULL)
1369 return 0;
1370 if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
1371 return FALSE;
1373 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1374 if (nTool == -1) return 0;
1376 infoPtr->tools[nTool].rect = lpti->rect;
1378 return 0;
1382 inline static LRESULT
1383 TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
1385 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1387 TOOLTIPS_Hide (hwnd, infoPtr);
1389 return 0;
1393 static LRESULT
1394 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1396 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1397 LPMSG lpMsg = (LPMSG)lParam;
1398 POINT pt;
1400 if (lParam == 0) {
1401 ERR("lpMsg == NULL!\n");
1402 return 0;
1405 switch (lpMsg->message) {
1406 case WM_LBUTTONDOWN:
1407 case WM_LBUTTONUP:
1408 case WM_MBUTTONDOWN:
1409 case WM_MBUTTONUP:
1410 case WM_RBUTTONDOWN:
1411 case WM_RBUTTONUP:
1412 pt = lpMsg->pt;
1413 ScreenToClient (lpMsg->hwnd, &pt);
1414 infoPtr->nOldTool = infoPtr->nTool;
1415 infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1416 TRACE("tool (%x) %d %d\n",
1417 hwnd, infoPtr->nOldTool, infoPtr->nTool);
1418 TOOLTIPS_Hide (hwnd, infoPtr);
1419 break;
1421 case WM_MOUSEMOVE:
1422 pt = lpMsg->pt;
1423 ScreenToClient (lpMsg->hwnd, &pt);
1424 infoPtr->nOldTool = infoPtr->nTool;
1425 infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1426 TRACE("tool (%x) %d %d\n",
1427 hwnd, infoPtr->nOldTool, infoPtr->nTool);
1428 TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n",
1429 hwnd, pt.x, pt.y);
1430 if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
1431 if (infoPtr->nOldTool == -1) {
1432 SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1433 TRACE("timer 1 started!\n");
1435 else {
1436 TOOLTIPS_Hide (hwnd, infoPtr);
1437 SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1438 TRACE("timer 2 started!\n");
1441 if (infoPtr->nCurrentTool != -1) {
1442 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
1443 TRACE("timer 3 started!\n");
1445 break;
1448 return 0;
1452 static LRESULT
1453 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1455 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1456 INT nTime = (INT)LOWORD(lParam);
1458 switch (wParam) {
1459 case TTDT_AUTOMATIC:
1460 if (nTime == 0) {
1461 infoPtr->nAutomaticTime = 500;
1462 infoPtr->nReshowTime = 100;
1463 infoPtr->nAutoPopTime = 5000;
1464 infoPtr->nInitialTime = 500;
1466 else {
1467 infoPtr->nAutomaticTime = nTime;
1468 infoPtr->nReshowTime = nTime / 5;
1469 infoPtr->nAutoPopTime = nTime * 10;
1470 infoPtr->nInitialTime = nTime;
1472 break;
1474 case TTDT_RESHOW:
1475 infoPtr->nReshowTime = nTime;
1476 break;
1478 case TTDT_AUTOPOP:
1479 infoPtr->nAutoPopTime = nTime;
1480 break;
1482 case TTDT_INITIAL:
1483 infoPtr->nInitialTime = nTime;
1484 break;
1487 return 0;
1491 static LRESULT
1492 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1494 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1495 LPRECT lpRect = (LPRECT)lParam;
1497 infoPtr->rcMargin.left = lpRect->left;
1498 infoPtr->rcMargin.right = lpRect->right;
1499 infoPtr->rcMargin.bottom = lpRect->bottom;
1500 infoPtr->rcMargin.top = lpRect->top;
1502 return 0;
1506 inline static LRESULT
1507 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1509 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1510 INT nTemp = infoPtr->nMaxTipWidth;
1512 infoPtr->nMaxTipWidth = (INT)lParam;
1514 return nTemp;
1518 inline static LRESULT
1519 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1521 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1523 infoPtr->clrBk = (COLORREF)wParam;
1525 return 0;
1529 inline static LRESULT
1530 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1532 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1534 infoPtr->clrText = (COLORREF)wParam;
1536 return 0;
1540 static LRESULT
1541 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1543 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1544 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1545 TTTOOL_INFO *toolPtr;
1546 INT nTool;
1548 if (lpToolInfo == NULL)
1549 return 0;
1550 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1551 return 0;
1553 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1554 if (nTool == -1) return 0;
1556 TRACE("tool %d\n", nTool);
1558 toolPtr = &infoPtr->tools[nTool];
1560 /* copy tool data */
1561 toolPtr->uFlags = lpToolInfo->uFlags;
1562 toolPtr->hwnd = lpToolInfo->hwnd;
1563 toolPtr->uId = lpToolInfo->uId;
1564 toolPtr->rect = lpToolInfo->rect;
1565 toolPtr->hinst = lpToolInfo->hinst;
1567 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1568 TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1569 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1571 else if (lpToolInfo->lpszText) {
1572 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1573 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1574 else {
1575 if (toolPtr->lpszText) {
1576 COMCTL32_Free (toolPtr->lpszText);
1577 toolPtr->lpszText = NULL;
1579 if (lpToolInfo->lpszText) {
1580 INT len = lstrlenA (lpToolInfo->lpszText);
1581 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1582 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1587 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1588 toolPtr->lParam = lpToolInfo->lParam;
1590 return 0;
1594 static LRESULT
1595 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1597 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1598 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1599 TTTOOL_INFO *toolPtr;
1600 INT nTool;
1602 if (lpToolInfo == NULL)
1603 return 0;
1604 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1605 return 0;
1607 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1608 if (nTool == -1) return 0;
1610 TRACE("tool %d\n", nTool);
1612 toolPtr = &infoPtr->tools[nTool];
1614 /* copy tool data */
1615 toolPtr->uFlags = lpToolInfo->uFlags;
1616 toolPtr->hwnd = lpToolInfo->hwnd;
1617 toolPtr->uId = lpToolInfo->uId;
1618 toolPtr->rect = lpToolInfo->rect;
1619 toolPtr->hinst = lpToolInfo->hinst;
1621 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1622 TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1623 toolPtr->lpszText = lpToolInfo->lpszText;
1625 else if (lpToolInfo->lpszText) {
1626 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1627 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1628 else {
1629 if (toolPtr->lpszText) {
1630 COMCTL32_Free (toolPtr->lpszText);
1631 toolPtr->lpszText = NULL;
1633 if (lpToolInfo->lpszText) {
1634 INT len = lstrlenW (lpToolInfo->lpszText);
1635 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1636 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1641 if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1642 toolPtr->lParam = lpToolInfo->lParam;
1644 return 0;
1648 static LRESULT
1649 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1651 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1652 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1654 if (lpToolInfo == NULL)
1655 return 0;
1656 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1657 return FALSE;
1659 if ((BOOL)wParam) {
1660 /* activate */
1661 infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1662 if (infoPtr->nTrackTool != -1) {
1663 TRACE("activated!\n");
1664 infoPtr->bTrackActive = TRUE;
1665 TOOLTIPS_TrackShow (hwnd, infoPtr);
1668 else {
1669 /* deactivate */
1670 TOOLTIPS_TrackHide (hwnd, infoPtr);
1672 infoPtr->bTrackActive = FALSE;
1673 infoPtr->nTrackTool = -1;
1675 TRACE("deactivated!\n");
1678 return 0;
1682 static LRESULT
1683 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1685 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1687 infoPtr->xTrackPos = (INT)LOWORD(lParam);
1688 infoPtr->yTrackPos = (INT)HIWORD(lParam);
1690 if (infoPtr->bTrackActive) {
1691 TRACE("[%d %d]\n",
1692 infoPtr->xTrackPos, infoPtr->yTrackPos);
1694 TOOLTIPS_TrackShow (hwnd, infoPtr);
1697 return 0;
1701 static LRESULT
1702 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1704 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1706 if (infoPtr->nCurrentTool != -1)
1707 UpdateWindow (hwnd);
1709 return 0;
1713 static LRESULT
1714 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1716 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1717 LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1718 TTTOOL_INFO *toolPtr;
1719 INT nTool;
1721 if (lpToolInfo == NULL)
1722 return 0;
1723 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1724 return FALSE;
1726 nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1727 if (nTool == -1) return 0;
1729 TRACE("tool %d\n", nTool);
1731 toolPtr = &infoPtr->tools[nTool];
1733 /* copy tool text */
1734 toolPtr->hinst = lpToolInfo->hinst;
1736 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1737 toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1739 else if (lpToolInfo->lpszText) {
1740 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1741 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1742 else {
1743 if (toolPtr->lpszText) {
1744 COMCTL32_Free (toolPtr->lpszText);
1745 toolPtr->lpszText = NULL;
1747 if (lpToolInfo->lpszText) {
1748 INT len = lstrlenA (lpToolInfo->lpszText);
1749 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1750 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1755 /* force repaint */
1756 if (infoPtr->bActive)
1757 TOOLTIPS_Show (hwnd, infoPtr);
1758 else if (infoPtr->bTrackActive)
1759 TOOLTIPS_TrackShow (hwnd, infoPtr);
1761 return 0;
1765 static LRESULT
1766 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1768 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1769 LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1770 TTTOOL_INFO *toolPtr;
1771 INT nTool;
1773 if (lpToolInfo == NULL)
1774 return 0;
1775 if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1776 return FALSE;
1778 nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1779 if (nTool == -1)
1780 return 0;
1782 TRACE("tool %d\n", nTool);
1784 toolPtr = &infoPtr->tools[nTool];
1786 /* copy tool text */
1787 toolPtr->hinst = lpToolInfo->hinst;
1789 if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1790 toolPtr->lpszText = lpToolInfo->lpszText;
1792 else if (lpToolInfo->lpszText) {
1793 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1794 toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1795 else {
1796 if (toolPtr->lpszText) {
1797 COMCTL32_Free (toolPtr->lpszText);
1798 toolPtr->lpszText = NULL;
1800 if (lpToolInfo->lpszText) {
1801 INT len = lstrlenW (lpToolInfo->lpszText);
1802 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1803 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1808 /* force repaint */
1809 if (infoPtr->bActive)
1810 TOOLTIPS_Show (hwnd, infoPtr);
1811 else if (infoPtr->bTrackActive)
1812 TOOLTIPS_TrackShow (hwnd, infoPtr);
1814 return 0;
1818 static LRESULT
1819 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1821 return WindowFromPoint (*((LPPOINT)lParam));
1826 static LRESULT
1827 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1829 TOOLTIPS_INFO *infoPtr;
1830 NONCLIENTMETRICSA nclm;
1831 INT nResult;
1833 /* allocate memory for info structure */
1834 infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1835 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1837 /* initialize info structure */
1838 infoPtr->bActive = TRUE;
1839 infoPtr->bTrackActive = FALSE;
1840 infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
1841 infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1843 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1844 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1845 infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1847 infoPtr->nMaxTipWidth = -1;
1848 infoPtr->nTool = -1;
1849 infoPtr->nOldTool = -1;
1850 infoPtr->nCurrentTool = -1;
1851 infoPtr->nTrackTool = -1;
1853 infoPtr->nAutomaticTime = 500;
1854 infoPtr->nReshowTime = 100;
1855 infoPtr->nAutoPopTime = 5000;
1856 infoPtr->nInitialTime = 500;
1858 nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
1859 (WPARAM)hwnd, (LPARAM)NF_QUERY);
1860 if (nResult == NFR_ANSI)
1861 TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1862 else if (nResult == NFR_UNICODE)
1863 FIXME(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1864 else
1865 FIXME(" -- WM_NOTIFYFORMAT returns: error!\n");
1867 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
1869 return 0;
1873 static LRESULT
1874 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1876 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1877 TTTOOL_INFO *toolPtr;
1878 INT i;
1880 /* free tools */
1881 if (infoPtr->tools) {
1882 for (i = 0; i < infoPtr->uNumTools; i++) {
1883 toolPtr = &infoPtr->tools[i];
1884 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
1885 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
1886 COMCTL32_Free (toolPtr->lpszText);
1889 /* remove subclassing */
1890 if (toolPtr->uFlags & TTF_SUBCLASS) {
1891 LPTT_SUBCLASS_INFO lpttsi;
1893 if (toolPtr->uFlags & TTF_IDISHWND)
1894 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1895 else
1896 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
1898 if (lpttsi) {
1899 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
1900 (LONG)lpttsi->wpOrigProc);
1901 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1902 COMCTL32_Free (&lpttsi);
1906 COMCTL32_Free (infoPtr->tools);
1909 /* delete font */
1910 DeleteObject (infoPtr->hFont);
1912 /* free tool tips info data */
1913 COMCTL32_Free (infoPtr);
1915 return 0;
1919 static LRESULT
1920 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1922 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1923 RECT rect;
1924 HBRUSH hBrush;
1926 hBrush = CreateSolidBrush (infoPtr->clrBk);
1927 GetClientRect (hwnd, &rect);
1928 FillRect ((HDC)wParam, &rect, hBrush);
1929 DeleteObject (hBrush);
1931 return FALSE;
1935 static LRESULT
1936 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1938 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1940 return infoPtr->hFont;
1944 static LRESULT
1945 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1947 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1949 TOOLTIPS_Hide (hwnd, infoPtr);
1951 return 0;
1955 static LRESULT
1956 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1958 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1960 dwStyle &= 0x0000FFFF;
1961 dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1962 SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
1964 return TRUE;
1968 static LRESULT
1969 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1971 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1972 INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
1974 TRACE(" nTool=%d\n", nTool);
1976 if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
1977 if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
1978 TRACE("-- in transparent mode!\n");
1979 return HTTRANSPARENT;
1983 return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1987 static LRESULT
1988 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1990 HDC hdc;
1991 PAINTSTRUCT ps;
1993 hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1994 TOOLTIPS_Refresh (hwnd, hdc);
1995 if (!wParam)
1996 EndPaint (hwnd, &ps);
1997 return 0;
2001 static LRESULT
2002 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2004 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2006 infoPtr->hFont = (HFONT)wParam;
2008 if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2009 FIXME("full redraw needed!\n");
2012 return 0;
2014 /******************************************************************
2015 * TOOLTIPS_OnWMGetTextLength
2017 * This function is called when the tooltip receive a
2018 * WM_GETTEXTLENGTH message.
2019 * wParam : not used
2020 * lParam : not used
2022 * returns the length, in characters, of the tip text
2023 ******************************************************************/
2024 static LRESULT
2025 TOOLTIPS_OnWMGetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2027 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2028 return lstrlenW(infoPtr->szTipText);
2030 /******************************************************************
2031 * TOOLTIPS_OnWMGetText
2033 * This function is called when the tooltip receive a
2034 * WM_GETTEXT message.
2035 * wParam : specifies the maximum number of characters to be copied
2036 * lParam : is the pointer to the buffer that will receive
2037 * the tip text
2039 * returns the number of characters copied
2040 ******************************************************************/
2041 static LRESULT
2042 TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
2044 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2045 INT length;
2047 if(!infoPtr || !(infoPtr->szTipText))
2048 return 0;
2050 length = lstrlenW(infoPtr->szTipText);
2051 /* When wParam is smaller than the lenght of the tip text
2052 copy wParam characters of the tip text and return wParam */
2053 if(wParam < length)
2055 lstrcpynWtoA((LPSTR)lParam, infoPtr->szTipText,(UINT)wParam);
2056 return wParam;
2058 lstrcpyWtoA((LPSTR)lParam, infoPtr->szTipText);
2059 return length;
2063 static LRESULT
2064 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2066 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2068 TRACE("timer %d (%x) expired!\n", wParam, hwnd);
2070 switch (wParam)
2072 case ID_TIMERSHOW:
2073 KillTimer (hwnd, ID_TIMERSHOW);
2074 if (TOOLTIPS_CheckTool (hwnd, TRUE) == infoPtr->nTool)
2075 TOOLTIPS_Show (hwnd, infoPtr);
2076 break;
2078 case ID_TIMERPOP:
2079 TOOLTIPS_Hide (hwnd, infoPtr);
2080 break;
2082 case ID_TIMERLEAVE:
2083 KillTimer (hwnd, ID_TIMERLEAVE);
2084 if (TOOLTIPS_CheckTool (hwnd, FALSE) == -1) {
2085 infoPtr->nTool = -1;
2086 infoPtr->nOldTool = -1;
2087 TOOLTIPS_Hide (hwnd, infoPtr);
2089 break;
2091 return 0;
2095 static LRESULT
2096 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2098 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2099 NONCLIENTMETRICSA nclm;
2101 infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
2102 infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2104 DeleteObject (infoPtr->hFont);
2105 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2106 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2107 infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2109 return 0;
2113 LRESULT CALLBACK
2114 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2116 LPTT_SUBCLASS_INFO lpttsi =
2117 (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2118 TOOLTIPS_INFO *infoPtr;
2119 UINT nTool;
2121 switch (uMsg) {
2122 case WM_LBUTTONDOWN:
2123 case WM_LBUTTONUP:
2124 case WM_MBUTTONDOWN:
2125 case WM_MBUTTONUP:
2126 case WM_RBUTTONDOWN:
2127 case WM_RBUTTONUP:
2128 infoPtr = TOOLTIPS_GetInfoPtr(lpttsi->hwndToolTip);
2129 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2131 TRACE("subclassed mouse message %04x\n", uMsg);
2132 infoPtr->nOldTool = infoPtr->nTool;
2133 infoPtr->nTool = nTool;
2134 TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2135 break;
2137 case WM_MOUSEMOVE:
2138 infoPtr = TOOLTIPS_GetInfoPtr (lpttsi->hwndToolTip);
2139 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2141 TRACE("subclassed WM_MOUSEMOVE\n");
2142 infoPtr->nOldTool = infoPtr->nTool;
2143 infoPtr->nTool = nTool;
2145 if ((infoPtr->bActive) &&
2146 (infoPtr->nTool != infoPtr->nOldTool)) {
2147 if (infoPtr->nOldTool == -1) {
2148 SetTimer (hwnd, ID_TIMERSHOW,
2149 infoPtr->nInitialTime, 0);
2150 TRACE("timer 1 started!\n");
2152 else {
2153 TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2154 SetTimer (hwnd, ID_TIMERSHOW,
2155 infoPtr->nReshowTime, 0);
2156 TRACE("timer 2 started!\n");
2159 if (infoPtr->nCurrentTool != -1) {
2160 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
2161 TRACE("timer 3 started!\n");
2163 break;
2166 return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2170 LRESULT CALLBACK
2171 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2173 switch (uMsg)
2175 case TTM_ACTIVATE:
2176 return TOOLTIPS_Activate (hwnd, wParam, lParam);
2178 case TTM_ADDTOOLA:
2179 return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2181 case TTM_ADDTOOLW:
2182 return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2184 case TTM_DELTOOLA:
2185 return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2187 case TTM_DELTOOLW:
2188 return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2190 case TTM_ENUMTOOLSA:
2191 return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2193 case TTM_ENUMTOOLSW:
2194 return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2196 case TTM_GETCURRENTTOOLA:
2197 return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2199 case TTM_GETCURRENTTOOLW:
2200 return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2202 case TTM_GETDELAYTIME:
2203 return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2205 case TTM_GETMARGIN:
2206 return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2208 case TTM_GETMAXTIPWIDTH:
2209 return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2211 case TTM_GETTEXTA:
2212 return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2214 case TTM_GETTEXTW:
2215 return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2217 case TTM_GETTIPBKCOLOR:
2218 return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2220 case TTM_GETTIPTEXTCOLOR:
2221 return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2223 case TTM_GETTOOLCOUNT:
2224 return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2226 case TTM_GETTOOLINFOA:
2227 return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2229 case TTM_GETTOOLINFOW:
2230 return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2232 case TTM_HITTESTA:
2233 return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2235 case TTM_HITTESTW:
2236 return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2238 case TTM_NEWTOOLRECTA:
2239 return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2241 case TTM_NEWTOOLRECTW:
2242 return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2244 case TTM_POP:
2245 return TOOLTIPS_Pop (hwnd, wParam, lParam);
2247 case TTM_RELAYEVENT:
2248 return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2250 case TTM_SETDELAYTIME:
2251 return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2253 case TTM_SETMARGIN:
2254 return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2256 case TTM_SETMAXTIPWIDTH:
2257 return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2259 case TTM_SETTIPBKCOLOR:
2260 return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2262 case TTM_SETTIPTEXTCOLOR:
2263 return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2265 case TTM_SETTOOLINFOA:
2266 return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2268 case TTM_SETTOOLINFOW:
2269 return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2271 case TTM_TRACKACTIVATE:
2272 return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2274 case TTM_TRACKPOSITION:
2275 return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2277 case TTM_UPDATE:
2278 return TOOLTIPS_Update (hwnd, wParam, lParam);
2280 case TTM_UPDATETIPTEXTA:
2281 return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2283 case TTM_UPDATETIPTEXTW:
2284 return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2286 case TTM_WINDOWFROMPOINT:
2287 return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2290 case WM_CREATE:
2291 return TOOLTIPS_Create (hwnd, wParam, lParam);
2293 case WM_DESTROY:
2294 return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2296 case WM_ERASEBKGND:
2297 return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2299 case WM_GETFONT:
2300 return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2302 case WM_GETTEXT:
2303 return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2305 case WM_GETTEXTLENGTH:
2306 return TOOLTIPS_OnWMGetTextLength (hwnd, wParam, lParam);
2309 case WM_LBUTTONDOWN:
2310 case WM_LBUTTONUP:
2311 case WM_MBUTTONDOWN:
2312 case WM_MBUTTONUP:
2313 case WM_RBUTTONDOWN:
2314 case WM_RBUTTONUP:
2315 case WM_MOUSEMOVE:
2316 return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2318 case WM_NCCREATE:
2319 return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2321 case WM_NCHITTEST:
2322 return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2324 /* case WM_NOTIFYFORMAT: */
2325 /* return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam); */
2327 case WM_PAINT:
2328 return TOOLTIPS_Paint (hwnd, wParam, lParam);
2330 case WM_SETFONT:
2331 return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2333 case WM_TIMER:
2334 return TOOLTIPS_Timer (hwnd, wParam, lParam);
2336 case WM_WININICHANGE:
2337 return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2339 default:
2340 if (uMsg >= WM_USER)
2341 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2342 uMsg, wParam, lParam);
2343 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2345 return 0;
2349 VOID
2350 TOOLTIPS_Register (void)
2352 WNDCLASSA wndClass;
2354 if (GlobalFindAtomA (TOOLTIPS_CLASSA)) return;
2356 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2357 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2358 wndClass.lpfnWndProc = (WNDPROC)TOOLTIPS_WindowProc;
2359 wndClass.cbClsExtra = 0;
2360 wndClass.cbWndExtra = sizeof(TOOLTIPS_INFO *);
2361 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2362 wndClass.hbrBackground = 0;
2363 wndClass.lpszClassName = TOOLTIPS_CLASSA;
2365 RegisterClassA (&wndClass);
2369 VOID
2370 TOOLTIPS_Unregister (void)
2372 if (GlobalFindAtomA (TOOLTIPS_CLASSA))
2373 UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);