source: trunk/src/helpers/cctl_tooltip.c@ 19

Last change on this file since 19 was 19, checked in by umoeller, 25 years ago

Reworked tooltip.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 60.9 KB
Line 
1
2/*
3 *@@sourcefile cctl_tooltip.c:
4 * implementation for the "tooltip" common control.
5 * See comctl.c for an overview.
6 *
7 * This has been extracted from comctl.c with V0.9.3 (2000-05-21) [umoeller].
8 *
9 * Note: Version numbering in this file relates to XWorkplace version
10 * numbering.
11 *
12 *@@header "helpers\comctl.h"
13 *@@added V0.9.3 (2000-05-21) [umoeller].
14 */
15
16/*
17 * Copyright (C) 1997-2000 Ulrich M”ller.
18 * This file is part of the "XWorkplace helpers" source package.
19 * This is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published
21 * by the Free Software Foundation, in version 2 as it comes in the
22 * "COPYING" file of the XWorkplace main distribution.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 */
28
29#define OS2EMX_PLAIN_CHAR
30 // this is needed for "os2emx.h"; if this is defined,
31 // emx will define PSZ as _signed_ char, otherwise
32 // as unsigned char
33
34#define INCL_DOSEXCEPTIONS
35#define INCL_DOSPROCESS
36#define INCL_DOSSEMAPHORES
37#define INCL_DOSERRORS
38
39#define INCL_WINWINDOWMGR
40#define INCL_WINFRAMEMGR
41#define INCL_WINMESSAGEMGR
42#define INCL_WININPUT
43#define INCL_WINPOINTERS
44#define INCL_WINTRACKRECT
45#define INCL_WINTIMER
46#define INCL_WINSYS
47
48#define INCL_WINRECTANGLES /// xxx temporary
49
50#define INCL_WINMENUS
51#define INCL_WINSTATICS
52#define INCL_WINBUTTONS
53#define INCL_WINSTDCNR
54
55#define INCL_GPIPRIMITIVES
56#define INCL_GPILOGCOLORTABLE
57#define INCL_GPILCIDS
58#define INCL_GPIPATHS
59#define INCL_GPIREGIONS
60#define INCL_GPIBITMAPS // added V0.9.1 (2000-01-04) [umoeller]: needed for EMX headers
61#include <os2.h>
62
63#include <stdlib.h>
64#include <stdio.h>
65#include <string.h>
66#include <setjmp.h> // needed for except.h
67#include <assert.h> // needed for except.h
68
69#include "setup.h" // code generation and debugging options
70
71#include "helpers\cnrh.h"
72#include "helpers\except.h" // exception handling
73#include "helpers\gpih.h"
74#include "helpers\linklist.h"
75#include "helpers\winh.h"
76
77#include "helpers\comctl.h"
78
79#pragma hdrstop
80
81/*
82 *@@category: Helpers\PM helpers\Window classes\Tooltips
83 */
84
85/* ******************************************************************
86 *
87 * Global variables
88 *
89 ********************************************************************/
90
91// screen size
92LONG G_cxScreen = 0,
93 G_cyScreen = 0;
94
95// linked list of all tools which were subclassed for tooltip
96HMTX G_hmtxSubclassedTools = NULLHANDLE;
97PLINKLIST G_pllSubclassedTools = NULL; // linked list of SUBCLASSEDTOOL items
98
99/* ******************************************************************
100 *
101 * "Tooltip" control
102 *
103 ********************************************************************/
104
105/*
106 *@@ ctlRegisterTooltip:
107 * this registers the Tooltip window class (ctl_fnwpTooltip)
108 * for an application. This is required before the tooltip
109 * control can be used.
110 *
111 *@@added V0.9.0 [umoeller]
112 */
113
114BOOL ctlRegisterTooltip(HAB hab)
115{
116 return (WinRegisterClass(hab,
117 COMCTL_TOOLTIP_CLASS,
118 ctl_fnwpTooltip,
119 CS_HITTEST, // class styles;
120 // CS_FRAME not working,
121 // CS_CLIPSIBLINGS not working
122 sizeof(PVOID)*2)); // addt'l bytes to reserve:
123 // one pointer for QWL_USER,
124 // one more for instance data
125}
126
127/*
128 *@@ SUBCLASSEDTOOL:
129 * structure created for each control which is
130 * subclassed by the tooltip control (ctl_fnwpTooltip).
131 *
132 *@@added V0.9.0 [umoeller]
133 */
134
135typedef struct _SUBCLASSEDTOOL
136{
137 HWND hwndTool;
138 PFNWP pfnwpOrig;
139 HWND hwndTooltip;
140 HAB hab;
141} SUBCLASSEDTOOL, *PSUBCLASSEDTOOL;
142
143/*
144 *@@ ctl_fnwpSubclassedTool:
145 * window procedure for tools which were subclassed
146 * to support tooltips.
147 *
148 *@@added V0.9.0 [umoeller]
149 */
150
151MRESULT EXPENTRY ctl_fnwpSubclassedTool(HWND hwndTool, ULONG msg, MPARAM mp1, MPARAM mp2)
152{
153 MRESULT mrc = 0;
154
155 PSUBCLASSEDTOOL pst = NULL;
156
157 PLISTNODE pNode = lstQueryFirstNode(G_pllSubclassedTools);
158 while (pNode)
159 {
160 PSUBCLASSEDTOOL pstThis = (PSUBCLASSEDTOOL)pNode->pItemData;
161 if (pstThis->hwndTool == hwndTool)
162 {
163 pst = pstThis;
164 break;
165 }
166 pNode = pNode->pNext;
167 }
168
169 switch (msg)
170 {
171 case WM_MOUSEMOVE:
172 case WM_BUTTON1DOWN:
173 case WM_BUTTON1UP:
174 case WM_BUTTON2DOWN:
175 case WM_BUTTON2UP:
176 case WM_BUTTON3DOWN:
177 case WM_BUTTON3UP:
178 {
179 QMSG qmsg;
180 qmsg.hwnd = hwndTool;
181 qmsg.msg = msg;
182 qmsg.mp1 = mp1;
183 qmsg.mp2 = mp2;
184 _Pmpf((__FUNCTION__ ": sending TTM_RELAYEVENT"));
185 WinSendMsg(pst->hwndTooltip,
186 TTM_RELAYEVENT,
187 (MPARAM)0,
188 (MPARAM)&qmsg);
189 mrc = (pst->pfnwpOrig)(hwndTool, msg, mp1, mp2);
190 break; }
191
192 case WM_DESTROY:
193 lstRemoveItem(G_pllSubclassedTools, pst); // this frees the item
194 if (lstCountItems(G_pllSubclassedTools) == 0)
195 {
196 // last item: destroy list
197 lstFree(G_pllSubclassedTools);
198 G_pllSubclassedTools = NULL;
199 _Pmpf((__FUNCTION__ ": removed hwnd 0x%lX", hwndTool));
200 }
201 mrc = (pst->pfnwpOrig)(hwndTool, msg, mp1, mp2);
202 break;
203
204 default:
205 mrc = (pst->pfnwpOrig)(hwndTool, msg, mp1, mp2);
206 }
207
208 return (mrc);
209}
210
211/*
212 *@@ SubclassToolForToolinfo:
213 * this gets called from ctl_fnwpTooltip if a control
214 * is to be subclassed to support mouse messaging
215 * (TTF_SUBCLASS flag).
216 *
217 *@@added V0.9.0 [umoeller]
218 */
219
220BOOL SubclassToolForToolinfo(HWND hwndTooltip,
221 HWND hwndTool)
222{
223 BOOL brc = FALSE;
224 PFNWP pfnwpOrig = WinSubclassWindow(hwndTool,
225 ctl_fnwpSubclassedTool);
226 if (pfnwpOrig)
227 {
228 PSUBCLASSEDTOOL pst = (PSUBCLASSEDTOOL)malloc(sizeof(SUBCLASSEDTOOL));
229 if (pst)
230 {
231 pst->pfnwpOrig = pfnwpOrig;
232 pst->hwndTooltip = hwndTooltip;
233 pst->hwndTool = hwndTool;
234 pst->hab = WinQueryAnchorBlock(hwndTool);
235
236 if (G_pllSubclassedTools == NULL)
237 G_pllSubclassedTools = lstCreate(TRUE); // auto-free items
238
239 lstAppendItem(G_pllSubclassedTools, pst);
240 _Pmpf((__FUNCTION__ ": subclassed hwnd 0x%lX", hwndTool));
241 }
242 }
243 return (brc);
244}
245
246/*
247 *@@ TOOLTIPDATA:
248 * private data structure stored in the window
249 * words of ctl_fnwpTooltip to hold information for
250 * a tooltip instance.
251 *
252 *@@added V0.9.0 [umoeller]
253 */
254
255typedef struct _TOOLTIPDATA
256{
257 HWND hwndOwner; // from WM_CREATE
258 HAB hab; // from WM_CREATE
259 ULONG ulTooltipID; // from WM_CREATE
260
261 BOOL fIsActive; // TRUE per default; changed by TTM_ACTIVATE
262
263 ULONG idTimerInitial, // if != 0, "initial" timer is running
264 idTimerAutopop; // if != 0, "autopop" (hide) timer is running
265
266 ULONG ulTimeoutInitial, // "initial" timer timeout (ms)
267 ulTimeoutAutopop, // "autopop" (hide) timer timeout (ms)
268 ulTimeoutReshow; // "reshow" timer timeout (ms)
269
270 LINKLIST llTools; // linked list of TOOLINFO structures
271 // containing the tools
272 FONTMETRICS fontmetrics; // current font
273 LONG lForeColor, // current foreground color
274 lBackColor, // current background color
275 l3DHiColor, // 3D border light color
276 l3DLoColor; // 3D border dark color
277 PSZ pszPaintText; // text to paint (new buffer)
278
279 POINTL ptlPointerLast; // last mouse pointer position
280
281 PTOOLINFO ptiMouseOver; // tool info over which the mouse resides
282
283 BOOL fIsVisible; // TRUE if tooltip is visible
284
285 // CHAR szTextBuf[256]; // static buffer for copying/loading strings
286} TOOLTIPDATA, *PTOOLTIPDATA;
287
288// timer IDs
289#define TOOLTIP_ID_TIMER_INITIAL 1
290#define TOOLTIP_ID_TIMER_AUTOPOP 2
291
292// tooltip window border (free spaces)
293#define TOOLTIP_CX_BORDER 5
294#define TOOLTIP_CY_BORDER 3
295
296/*
297 *@@ UpdateTooltipPresColors:
298 * this gets called during WM_CREATE and WM_PRESPARAMCHANGED
299 * in ctl_fnwpTooltip to set the colors in TOOLTIPDATA according
300 * to the control's presparams.
301 */
302
303VOID UpdateTooltipPresColors(HWND hwndTooltip, // in: tooltip control
304 PTOOLTIPDATA pttd) // in/out: tooltip data struct (QWL_USER) with color fields
305{
306 // tooltip background color:
307 pttd->lBackColor = winhQueryPresColor(hwndTooltip,
308 PP_MENUBACKGROUNDCOLOR,
309 FALSE, // no inherit
310 SYSCLR_ENTRYFIELD);
311 // tooltip text color:
312 pttd->lForeColor = winhQueryPresColor(hwndTooltip,
313 PP_MENUFOREGROUNDCOLOR,
314 FALSE, // no inherit
315 SYSCLR_WINDOWTEXT);
316 // 3D border light color:
317 pttd->l3DHiColor = winhQueryPresColor(hwndTooltip,
318 PP_MENUHILITEFGNDCOLOR,
319 FALSE, // no inherit
320 SYSCLR_WINDOWTEXT);
321 // 3D border dark color:
322 pttd->l3DLoColor = winhQueryPresColor(hwndTooltip,
323 PP_MENUHILITEBGNDCOLOR,
324 FALSE, // no inherit
325 SYSCLR_WINDOWTEXT);
326}
327
328/*
329 *@@ PaintTooltip:
330 * this gets called from ctl_fnwpTooltip upon WM_PAINT.
331 *
332 *@@added V0.9.1 (99-11-30) [umoeller]
333 */
334
335VOID PaintTooltip(HWND hwndTooltip,
336 PTOOLTIPDATA pttd)
337{
338 HPS hps = WinBeginPaint(hwndTooltip, NULLHANDLE, NULL);
339 POINTL ptl = {0, 0};
340 RECTL rclWindow,
341 rclWindowBak;
342 ULONG ulStyle = WinQueryWindowULong(hwndTooltip, QWL_STYLE);
343
344 ULONG ulRounding = 0;
345 if (ulStyle & TTS_ROUNDED)
346 ulRounding = TT_ROUNDING;
347
348
349 gpihSwitchToRGB(hps);
350
351 // get tooltip size; this has been properly calculated
352 // by TTM_SHOWTOOLTIPNOW earlier
353 WinQueryWindowRect(hwndTooltip, &rclWindow);
354 memcpy(&rclWindowBak, &rclWindow, sizeof(RECTL));
355
356 if (ulStyle & TTS_SHADOW)
357 {
358 // if shadows are on, the window is too large;
359 // make rectl smaller for rest of paint
360 rclWindow.xRight -= TT_SHADOWOFS;
361 rclWindow.yBottom += TT_SHADOWOFS;
362 // restore old pattern
363 GpiSetPattern(hps, PATSYM_DEFAULT);
364 }
365
366 // draw shadow
367 if (ulStyle & TTS_SHADOW)
368 {
369 GpiSetColor(hps, CLR_BLACK);
370 GpiSetPattern(hps, PATSYM_HALFTONE);
371 ptl.x = rclWindowBak.xLeft + TT_SHADOWOFS;
372 ptl.y = rclWindowBak.yBottom;
373 GpiMove(hps, &ptl);
374 ptl.x = rclWindowBak.xRight - 1;
375 ptl.y = rclWindowBak.yTop - TT_SHADOWOFS;
376 GpiBox(hps,
377 DRO_FILL,
378 &ptl,
379 ulRounding, ulRounding);
380 // restore pattern
381 GpiSetPattern(hps, PATSYM_DEFAULT);
382 }
383
384 // draw "real" rectangle
385 ptl.x = rclWindow.xLeft;
386 ptl.y = rclWindow.yBottom;
387 GpiMove(hps, &ptl);
388 ptl.x = rclWindow.xRight - 1;
389 ptl.y = rclWindow.yTop - 1;
390 GpiSetColor(hps, pttd->lBackColor);
391 GpiBox(hps,
392 DRO_FILL,
393 &ptl,
394 6, 6);
395
396 GpiSetColor(hps, pttd->lForeColor);
397 GpiBox(hps,
398 DRO_OUTLINE,
399 &ptl,
400 ulRounding, ulRounding);
401
402 if (pttd->pszPaintText)
403 {
404 RECTL rclText;
405 GpiSetColor(hps, pttd->lForeColor);
406 GpiSetBackColor(hps, pttd->lBackColor);
407 rclText.xLeft = rclWindow.xLeft + TOOLTIP_CX_BORDER;
408 rclText.xRight = rclWindow.xRight - TOOLTIP_CX_BORDER;
409 rclText.yBottom = rclWindow.yBottom + TOOLTIP_CY_BORDER;
410 rclText.yTop = rclWindow.yTop - TOOLTIP_CY_BORDER;
411 winhDrawFormattedText(hps,
412 &rclText,
413 pttd->pszPaintText,
414 DT_LEFT | DT_TOP | DT_WORDBREAK);
415 }
416
417 WinEndPaint(hps);
418}
419
420/*
421 *@@ TtmShowTooltip:
422 * implementation for TTM_SHOW_TOOLTIP.
423 *
424 * Depending on fShow, this shows or hides the
425 * tool tip at the position specified by the
426 * current tool or the mouse pointer (specified
427 * by the tool's style flags).
428 *
429 *@@added V0.9.1 (2000-02-04) [umoeller]
430 */
431
432VOID TtmShowTooltip(HWND hwndTooltip,
433 PTOOLTIPDATA pttd,
434 BOOL fShow) // if TRUE: show, else: HIDE
435{
436 _Pmpf((__FUNCTION__ ": fShow %d", fShow));
437 if (fShow)
438 {
439 /*
440 * show tooltip::
441 *
442 */
443
444 POINTL ptlPointer;
445 HPS hps;
446
447 // free old text
448 if (pttd->pszPaintText)
449 {
450 free(pttd->pszPaintText);
451 pttd->pszPaintText = NULL;
452 }
453
454 WinQueryPointerPos(HWND_DESKTOP, &ptlPointer);
455
456 if ( (ptlPointer.x == pttd->ptlPointerLast.x)
457 && (ptlPointer.y == pttd->ptlPointerLast.y)
458 )
459 {
460 // mouse not moved since timer was started:
461 // find the current TOOLINFO
462 _Pmpf((__FUNCTION__ ": mouse not moved... pttd->ptiMouseOver 0x%lX", pttd->ptiMouseOver));
463 if (pttd->ptiMouseOver)
464 {
465 TOOLINFO tiTemp;
466 memcpy(&tiTemp, pttd->ptiMouseOver, sizeof(TOOLINFO));
467 // get the text for the TOOLINFO
468 WinSendMsg(hwndTooltip,
469 TTM_GETTEXT,
470 (MPARAM)0,
471 (MPARAM)&tiTemp);
472 if (tiTemp.pszText)
473 pttd->pszPaintText = strdup(tiTemp.pszText);
474 else
475 pttd->pszPaintText = NULL;
476 }
477
478 _Pmpf((__FUNCTION__ ": pttd->pszPaintText %s",
479 (pttd->pszPaintText) ? pttd->pszPaintText : "NULL"));
480
481 if (pttd->pszPaintText)
482 {
483 // find out how much space we need
484 RECTL rcl = { 0, 0, 300, 1000 };
485 POINTL ptlTooltip;
486 LONG cx, cy;
487 ULONG ulStyle = WinQueryWindowULong(hwndTooltip, QWL_STYLE);
488
489 G_cxScreen = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN),
490 G_cyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
491
492 hps = WinGetPS(hwndTooltip);
493 winhDrawFormattedText(hps,
494 &rcl,
495 pttd->pszPaintText,
496 DT_LEFT | DT_TOP | DT_WORDBREAK | DT_QUERYEXTENT);
497 WinReleasePS(hps);
498
499 // calc width and height of tooltip
500 cx = rcl.xRight + 2*TOOLTIP_CX_BORDER;
501 cy = (rcl.yTop - rcl.yBottom) + 2*TOOLTIP_CY_BORDER;
502
503 // calc x and y pos of tooltip
504 if ( (pttd->ptiMouseOver->ulFlags & TTF_CENTERBELOW)
505 || (pttd->ptiMouseOver->ulFlags & TTF_CENTERABOVE)
506 )
507 {
508 // center below control:
509 SWP swpTool;
510 WinQueryWindowPos(pttd->ptiMouseOver->hwndTool, &swpTool);
511 ptlTooltip.x = swpTool.x;
512 ptlTooltip.y = swpTool.y;
513 // convert x, y to desktop points
514 WinMapWindowPoints(WinQueryWindow(pttd->ptiMouseOver->hwndTool,
515 QW_PARENT), // hwndFrom
516 HWND_DESKTOP, // hwndTo
517 &ptlTooltip,
518 1);
519 ptlTooltip.x += ((swpTool.cx - cx) / 2L);
520 if (pttd->ptiMouseOver->ulFlags & TTF_CENTERBELOW)
521 ptlTooltip.y -= cy;
522 else
523 ptlTooltip.y += swpTool.cy;
524 }
525 else
526 {
527 // use pointer pos:
528 ptlTooltip.x = ptlPointer.x - cx/2;
529 ptlTooltip.y = ptlPointer.y - cy;
530 }
531
532 // if "shy mouse" is enabled, make
533 // sure the tool tip is not under the
534 // mouse pointer
535 if (ulStyle & TTF_SHYMOUSE)
536 {
537 // we need to subtract the current mouse
538 // pointer's hot spot from the current
539 // pointer position
540 HPOINTER hptr = WinQueryPointer(HWND_DESKTOP);
541 POINTERINFO pi;
542 if (WinQueryPointerInfo(hptr, &pi))
543 {
544 /* ULONG cyPointer = WinQuerySysValue(HWND_DESKTOP,
545 SV_CYPOINTER); */
546 // calc bottom edge of mouse pointer rect
547 ULONG yBottomPointer = (ptlPointer.y - pi.yHotspot);
548 // _Pmpf(("yHotspot: %d", pi.yHotspot));
549 if ( (ptlTooltip.y + cy) // top edge of tool tip
550 > yBottomPointer
551 )
552 {
553 ptlTooltip.y = ptlPointer.y - cy - pi.yHotspot;
554 }
555 }
556 }
557
558 // constrain to screen
559 if (ptlTooltip.x < 0)
560 ptlTooltip.x = 0;
561 if (ptlTooltip.y < 0)
562 ptlTooltip.y = 0;
563 if (ptlTooltip.x + cx > G_cxScreen)
564 ptlTooltip.x = G_cxScreen-cx;
565 if (ptlTooltip.y + cy > G_cyScreen)
566 ptlTooltip.y = G_cyScreen-cy;
567
568 // if shadow is enabled,
569 // enlarge; the shadow might by
570 // off-screen now, but that's OK
571 if (ulStyle & TTS_SHADOW)
572 {
573 cx += TT_SHADOWOFS;
574 cy += TT_SHADOWOFS;
575 ptlTooltip.y -= TT_SHADOWOFS;
576 }
577
578 // notify owner
579 WinSendMsg(pttd->hwndOwner,
580 WM_CONTROL,
581 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
582 TTN_SHOW),
583 0);
584
585 // set tooltip position at the pos we calculated
586 // and show tooltip
587 WinSetWindowPos(hwndTooltip,
588 HWND_TOP,
589 ptlTooltip.x,
590 ptlTooltip.y,
591 cx, cy,
592 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW);
593 pttd->fIsVisible = TRUE;
594
595 // start autopop timer
596 pttd->idTimerAutopop = WinStartTimer(pttd->hab,
597 hwndTooltip,
598 TOOLTIP_ID_TIMER_AUTOPOP,
599 pttd->ulTimeoutAutopop);
600 } // end if (pttd->pszPaintText)
601 } // end if ( (ptlPointer.x == pttd->ptlPointerLast.x)...
602 } // end if (mp1)
603 else
604 {
605 /*
606 * hide tooltip::
607 *
608 */
609
610 if (pttd->fIsVisible)
611 {
612 WinSendMsg(pttd->hwndOwner,
613 WM_CONTROL,
614 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
615 TTN_POP),
616 0);
617 WinShowWindow(hwndTooltip, FALSE);
618 }
619
620 // stop autopop timer
621 if (pttd->idTimerAutopop)
622 {
623 WinStopTimer(pttd->hab,
624 hwndTooltip,
625 TOOLTIP_ID_TIMER_AUTOPOP);
626 pttd->idTimerAutopop = 0;
627 }
628 }
629
630 // store new visibility
631 pttd->fIsVisible = fShow;
632}
633
634/*
635 *@@ ctl_fnwpTooltip:
636 * window procedure for the "tooltip" control. This control is
637 * largely source-code compatible to the Win32 version and has
638 * been modelled according to the Win32 programmer's reference.
639 *
640 * A tooltip control is a small pop-up window that displays a
641 * single line of descriptive text giving the purpose of "tools"
642 * in an application.
643 * A "tool" is either a window, such as a child window or control,
644 * or an application-defined rectangular area within a window.
645 * See the TTM_ADDTOOL message for details.
646 *
647 * To clarify: There is usually one tooltip control, which is hidden
648 * most of the time, for many tools (parts of a visible window).
649 * When the user puts the cursor on a tool and leaves it there for
650 * approximately one-half second, the tooltip control is set up for
651 * that tool and made visible. The tooltip control appears near the
652 * pointer and disappears when the user clicks a mouse button or moves
653 * the pointer off of the tool.
654 *
655 * The Win32 concept has been extended with this implementation to
656 * display even longer texts, including line breaks. The tooltip
657 * window is formatted accordingly.
658 *
659 * All default window styles are ignored when you create the tooltip,
660 * but will rather be set by this window proc automatically. The
661 * only valid window styles are the TTS_* flags (see notes below).
662 *
663 * Presentation parameters are fully supported.
664 *
665 * To create a tooltip control using comctl.c, use
666 + ctlRegisterTooltip(hab);
667 + hwndTooltip = WinCreateWindow(HWND_DESKTOP, // parent
668 + COMCTL_TOOLTIP_CLASS, // wnd class (comctl.h)
669 + NULL, // window text
670 + TTS_ALWAYSTIP, // window style, ignored except for TTS_* flags
671 + 0, 0, 0, 0, // window pos and size, ignored
672 + hwndOwner, // owner window -- important!
673 + NULLHANDLE, // hwndInsertBehind, ignored
674 + ulID, // window ID, optional
675 + NULL, // control data
676 + NULL); // presparams
677 +
678 * ctl_fnwpTooltip automatically sets the size, position, and visibility
679 * of the tooltip control. The size of the tooltip window will vary
680 * depending on the text to be displayed and on the font presentation
681 * parameters, which are supported by this control (OS/2 only).
682 *
683 * Note: OS/2 normally does not destroy windows which are only owned by
684 * another window. As a result, when the tooltip's owner is destroyed,
685 * you must explicitly also destroy the tooltip window.
686 *
687 * Under both Win32 and OS/2, a tooltip control has two class-specific styles:
688 *
689 * -- TTS_ALWAYSTIP: the tooltip appears when the cursor is on a tool,
690 * regardless of whether the tooltip control's owner window is active
691 * or inactive. Without this style, the tooltip control appears when the
692 * tool's owner window is active, but not when it is inactive.
693 *
694 * -- TTS_NOPREFIX: this prevents the system from stripping the ampersand (&)
695 * character from a string. If a tooltip control does not have the TTS_NOPREFIX
696 * style, the system automatically strips ampersand characters, allowing an
697 * application to use the same string as both a menu item and tooltip text.
698 *
699 * The tooltip control can be (de)activated using the TTM_ACTIVATE message.
700 *
701 * To register tools with the tooltip control (to make it do anything
702 * meaningful), send the TTM_ADDTOOL message to the tooltip control.
703 *
704 * This control supports the following presentation parameters (if the
705 * PP_* value is not found, the SYSCLR_* system color is used):
706 * -- PP_MENUBACKGROUNDCOLOR / SYSCLR_ENTRYFIELD: tooltip background color.
707 * -- PP_MENUFOREGROUNDCOLOR / SYSCLR_WINDOWTEXT: tooltip text color.
708 * -- PP_MENUHILITEFGNDCOLOR / SYSCLR_WINDOWTEXT: 3D border light color.
709 * -- PP_MENUHILITEBGNDCOLOR / SYSCLR_WINDOWTEXT: 3D border dark color.
710 * -- PP_FONTNAMESIZE: font to use for the tooltip. The default is "8.Helv"
711 * on Warp 3 and "9.WarpSans" on Warp 4.
712 *
713 * So per default, if no presentation parameters are set, the control
714 * paints the background like an entry field and the text and the border
715 * in the same window text color (usually black).
716 * The tooltip does _not_ inherit presentation parameters from the parent,
717 * so unless you explicitly set presparams, the tooltip looks pretty much
718 * like the Win32 counterpart (with the default system colors, black border
719 * and text on yellow background).
720 *
721 *@@added V0.9.0 [umoeller]
722 */
723
724MRESULT EXPENTRY ctl_fnwpTooltip(HWND hwndTooltip, ULONG msg, MPARAM mp1, MPARAM mp2)
725{
726 MRESULT mrc = 0;
727
728 PTOOLTIPDATA pttd = (PTOOLTIPDATA)WinQueryWindowPtr(hwndTooltip, 1);
729
730 TRY_LOUD(excpt1)
731 {
732 switch (msg)
733 {
734 /*
735 * WM_CREATE:
736 * this message is sent to the window procedure of
737 * the window being created, thus offering it an
738 * opportunity to initialize that window.
739 *
740 * The window procedure receives this after the window
741 * is created but before the window becomes visible.
742 */
743
744 case WM_CREATE:
745 {
746 PCREATESTRUCT pcs = (PCREATESTRUCT)mp2;
747
748 // allocate and initialize tooltip data
749 pttd = (PTOOLTIPDATA)malloc(sizeof(TOOLTIPDATA));
750 if (pttd)
751 {
752 CHAR szFont[256];
753 memset(pttd, 0, sizeof(TOOLTIPDATA));
754 WinSetWindowPtr(hwndTooltip, 1, pttd);
755
756 pttd->hwndOwner = pcs->hwndOwner;
757 pttd->hab = WinQueryAnchorBlock(hwndTooltip);
758 pttd->ulTooltipID = pcs->id;
759
760 pttd->fIsActive = TRUE;
761
762 // default timeouts
763 pttd->ulTimeoutInitial = 1000;
764 pttd->ulTimeoutAutopop = 5000;
765 pttd->ulTimeoutReshow = 500;
766
767 // get colors from presparams/syscolors
768 UpdateTooltipPresColors(hwndTooltip, pttd);
769
770 // check if font presparam set
771 if (WinQueryPresParam(hwndTooltip,
772 PP_FONTNAMESIZE, 0,
773 NULL,
774 sizeof(szFont),
775 szFont,
776 QPF_NOINHERIT)
777 == 0)
778 {
779 // no: set default font presparam
780 // (we never want the System Proportional font)
781 winhSetWindowFont(hwndTooltip,
782 NULL); // default (WarpSans or 8.Helv)
783 }
784
785 pttd->pszPaintText = strdup("undefined");
786
787 lstInit(&pttd->llTools, TRUE); // auto-free items
788
789 // override CREATESTRUCT
790 WinSetWindowPos(hwndTooltip,
791 HWND_TOP,
792 50, 50,
793 100, 100,
794 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_HIDE);
795
796 mrc = (MPARAM)FALSE;
797 }
798 else
799 // malloc failed:
800 mrc = (MPARAM)TRUE;
801 break; }
802
803 /*
804 * WM_DESTROY:
805 * clean up upon destruction.
806 */
807
808 case WM_DESTROY:
809 // stop timers
810 if (pttd->ulTimeoutInitial)
811 WinStopTimer(pttd->hab,
812 hwndTooltip,
813 pttd->ulTimeoutInitial);
814 if (pttd->idTimerAutopop)
815 WinStopTimer(pttd->hab,
816 hwndTooltip,
817 pttd->idTimerAutopop);
818 if (pttd->pszPaintText)
819 free(pttd->pszPaintText);
820 lstClear(&pttd->llTools);
821 free(pttd);
822
823 mrc = (MPARAM)0;
824 break;
825
826 /*
827 * WM_HITTEST:
828 * since we have the CS_HITTEST class style set,
829 * we get this message. We return HT_TRANSPARENT
830 * always so the tooltip does not block mouse clicks
831 * for the windows which lie below.
832 */
833
834 case WM_HITTEST: // done
835 mrc = (MPARAM)HT_TRANSPARENT;
836 break;
837
838 /*
839 * WM_TIMER:
840 * posted when either the "initial" timer
841 * or the "autopop" timer times out.
842 * We'll show or hide the tooltip then.
843 */
844
845 case WM_TIMER: // done
846 {
847 USHORT usTimer = SHORT1FROMMP(mp1);
848
849 switch (usTimer)
850 {
851 case TOOLTIP_ID_TIMER_INITIAL:
852 // _Pmpf(("WM_TIMER: Stopping initial timer: %d", usTimer));
853 _Pmpf((__FUNCTION__ ": TOOLTIP_ID_TIMER_INITIAL"));
854 WinStopTimer(pttd->hab,
855 hwndTooltip,
856 usTimer);
857 pttd->idTimerInitial = 0;
858
859 if (pttd->fIsActive)
860 // show tooltip
861 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)TRUE, 0);
862 break;
863
864 case TOOLTIP_ID_TIMER_AUTOPOP:
865 // _Pmpf(("WM_TIMER: Stopping autopop timer: %d", usTimer));
866 WinStopTimer(pttd->hab,
867 hwndTooltip,
868 usTimer);
869 pttd->idTimerAutopop = 0;
870 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)FALSE, 0);
871 break;
872
873 default:
874 mrc = WinDefWindowProc(hwndTooltip, msg, mp1, mp2);
875 } // end switch
876
877 break; }
878
879 /*
880 * WM_PAINT:
881 *
882 */
883
884 case WM_PAINT: // done
885 PaintTooltip(hwndTooltip, pttd);
886 break;
887
888 /*
889 * WM_PRESPARAMCHANGED:
890 * presentation parameter has changed.
891 */
892
893 case WM_PRESPARAMCHANGED:
894 {
895 LONG lPPIndex = (LONG)mp1;
896 switch (lPPIndex)
897 {
898 case 0: // layout palette thing dropped
899 case PP_MENUBACKGROUNDCOLOR:
900 case PP_MENUFOREGROUNDCOLOR:
901 case PP_MENUHILITEFGNDCOLOR:
902 case PP_MENUHILITEBGNDCOLOR:
903 // re-query our presparams
904 UpdateTooltipPresColors(hwndTooltip, pttd);
905 }
906 break; }
907
908 /*
909 * WM_SYSCOLORCHANGE:
910 * system color has changed.
911 */
912
913 case WM_SYSCOLORCHANGE:
914 UpdateTooltipPresColors(hwndTooltip, pttd);
915 break;
916
917 /*
918 *@@ TTM_ACTIVATE:
919 * activates or deactives the tooltip control.
920 *
921 * Parameters:
922 * -- BOOL mp1: if TRUE, activate, if FALSE, deactivate.
923 * -- mp2: always 0.
924 *
925 * Return value: 0 always.
926 */
927
928 case TTM_ACTIVATE: // done
929 pttd->fIsActive = (BOOL)mp1;
930 if (!pttd->fIsActive)
931 // disable: hide tooltip
932 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)FALSE, 0);
933 break;
934
935 /*
936 *@@ TTM_ADDTOOL:
937 * registers a tool with a tooltip control.
938 *
939 * Parameters:
940 * -- mp1: always 0.
941 * -- PTOOLINFO mp2: information about the tool.
942 *
943 * Return value: TRUE if successful or FALSE otherwise.
944 *
945 * A tooltip control can support any number of tools. To
946 * support a particular tool, you must register the tool
947 * with the tooltip control by sending the TTM_ADDTOOL
948 * message to the tooltip control. The message includes
949 * the address of a TOOLINFO structure, which provides
950 * information the tooltip control needs to display text
951 * for the tool.
952 *
953 * A tooltip control supports tools implemented as windows
954 * (such as child windows or control windows) and as
955 * rectangular areas within a window's client area.
956 *
957 * -- When you add a tool implemented as a rectangular area, the
958 * "hwndToolOwner" member of TOOLINFO must specify the handle
959 * of the window that contains the area, and the "rect" member must
960 * specify the client coordinates of the area's bounding
961 * rectangle. ### not implemented yet
962 *
963 * -- When you add a tool implemented as a window, the "hwndTool"
964 * member of TOOLINFO must contain the window handle of the
965 * tool. hwndToolOwner should be the owner of the tool.
966 *
967 * When you add a tool to a tooltip control, the "pszText"
968 * member of the TOOLINFO structure must specify the string
969 * to display for the tool. You can change the text any time
970 * after adding the tool by using the TTM_UPDATETIPTEXT message.
971 *
972 * If you specify the PSZ_TEXTCALLBACK value in the pszText
973 * member, whenever the tooltip control needs the text for the
974 * tool, it sends a WM_CONTROL message to hwndToolOwner with
975 * the TTN_NEEDTEXT notification code.
976 *
977 * The message includes the address of a TOOLTIPTEXT structure,
978 * which contains the window handle of the tool. You can then
979 * fill the TOOLTIPTEXT structure with the tool text.
980 *
981 * To retrieve the text for a tool, use the TTM_GETTEXT message.
982 */
983
984 case TTM_ADDTOOL: // done
985 mrc = (MPARAM)FALSE;
986 if (mp2)
987 {
988 PTOOLINFO ptiPassed = (PTOOLINFO)mp2,
989 ptiNew = (PTOOLINFO)malloc(sizeof(TOOLINFO));
990 if (ptiNew)
991 {
992 memcpy(ptiNew, ptiPassed, sizeof(TOOLINFO));
993 lstAppendItem(&pttd->llTools,
994 ptiNew);
995
996 if (ptiPassed->ulFlags & TTF_SUBCLASS)
997 SubclassToolForToolinfo(hwndTooltip,
998 ptiPassed->hwndTool);
999
1000 mrc = (MPARAM)TRUE;
1001 }
1002 }
1003 break;
1004
1005 /*
1006 *@@ TTM_DELTOOL:
1007 * removes a tool from a tooltip control.
1008 *
1009 * Parameters:
1010 * -- mp1: always 0.
1011 * -- PTOOLINFO mp2: information about the tool;
1012 * all fields except cbSize, hwnd, uID are
1013 * ignored.
1014 *
1015 * Return value: 0 always.
1016 */
1017
1018 case TTM_DELTOOL: // done
1019 {
1020 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1021 if (ptiSearch)
1022 {
1023 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1024 while (pToolNode)
1025 {
1026 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1027 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1028 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1029 )
1030 {
1031 // found:
1032 lstRemoveNode(&pttd->llTools, pToolNode);
1033 break;
1034 }
1035 }
1036 pToolNode = pToolNode->pNext;
1037 }
1038 break; }
1039
1040 /*
1041 *@@ TTM_NEWTOOLRECT:
1042 * sets a new bounding rectangle for a tool
1043 * already registered with a tooltip control.
1044 *
1045 * Parameters:
1046 * -- mp1: always 0.
1047 * -- PTOOLINFO mp2: information about the tool;
1048 * all fields except hwnd, uID, and rect
1049 * are ignored.
1050 *
1051 * Return value: 0 always.
1052 *
1053 * If an application includes a tool implemented as a rectangular
1054 * area and the size or position of the control changes, it can
1055 * use the TTM_NEWTOOLRECT message to report the change to the
1056 * tooltip control. An application does not need to report size
1057 * and position changes for a tool implemented as a window.
1058 * Reporting that is not necessary because the tooltip control
1059 * uses the window handle of a tool to determine if the cursor
1060 * is on the tool, not the tool's bounding rectangle.
1061 */
1062
1063 case TTM_NEWTOOLRECT:
1064 break;
1065
1066 /*
1067 *@@ TTM_RELAYEVENT:
1068 * passes a mouse message to a tooltip control
1069 * for further processing.
1070 *
1071 * Parameters:
1072 * -- mp1: always 0.
1073 * -- PQMSG mp2: pointer to a QMSG struct (Win95: MSG struct)
1074 * containing a mouse message. Only the above messages
1075 * are processed.
1076 *
1077 * Return value: 0 always.
1078 *
1079 * A tooltip control needs to receive mouse messages to determine
1080 * when to display the tooltip window. Because mouse messages are
1081 * sent only to the window that contains the cursor, you must
1082 * use the TTM_RELAYEVENT message to relay mouse messages to the
1083 * tooltip control.
1084 *
1085 * If a tool is implemented as a rectangular area in an
1086 * application-defined window, the window procedure receives all
1087 * mouse messages and can relay the ones listed below to the
1088 * tooltip control, using this message.
1089 *
1090 * However, if a tool is implemented as a system-defined window,
1091 * the mouse messages are sent to that window and are not readily
1092 * available to the application. There are two ways you can have
1093 * the tooltip control notified of these mouse messages:
1094 *
1095 * -- You can specify the TTF_SUBCLASS flag when adding the tool
1096 * to the tooltip control. The tooltip control will then subclass
1097 * the tool window to get mouse-related messages, and you're off.
1098 *
1099 * -- You can implement a message hook for your process and check
1100 * for your tool windows there and send TTM_RELAYEVENT to the
1101 * tooltip control. In that case, you need to intercept the
1102 * messages specified below.
1103 *
1104 * When a tooltip control receives a relayed WM_MOUSEMOVE message,
1105 * it determines whether the cursor is in the bounding rectangle of
1106 * a tool. If the cursor is there, the tooltip control sets a timer.
1107 * At the end of the time-out duration, the tooltip control checks
1108 * the position of the cursor to see whether it has moved. If the
1109 * cursor has not, the tooltip control retrieves the text for the tool,
1110 * copies the text into the tooltip window, and shows the window.
1111 * The tooltip control continues to show the window until it receives
1112 * a relayed button-up or button-down message or until a relayed
1113 * WM_MOUSEMOVE message indicates that the cursor has moved outside
1114 * the bounding rectangle of the tool.
1115 *
1116 * For the timer descriptions, see TTM_SETDELAYTIME.
1117 *
1118 * When it is about to be displayed, a tootip control sends the
1119 * TTN_SHOW notification to the owner window. A tooltip control
1120 * sends the TTN_POP notification when it is about to be hidden.
1121 * Each notification is sent in the context of a WM_NOTIFY message
1122 * (OS/2: WM_CONTROL).
1123 *
1124 * Relevant messages:
1125 * -- WM_MOUSEMOVE
1126 * -- WM_BUTTON1DOWN (Win95: WM_LBUTTONDOWN)
1127 * -- WM_BUTTON1UP (Win95: WM_LBUTTONUP)
1128 * -- WM_BUTTON2DOWN (Win95: WM_RBUTTONDOWN)
1129 * -- WM_BUTTON2UP (Win95: WM_RBUTTONUP)
1130 * -- WM_BUTTON3DOWN (Win95: WM_MBUTTONDOWN)
1131 * -- WM_BUTTON3UP (Win95: WM_MBUTTONUP)
1132 */
1133
1134 case TTM_RELAYEVENT:
1135 {
1136 PQMSG pqmsg = (PQMSG)mp2;
1137 if (pqmsg)
1138 {
1139 POINTL ptlPointer;
1140 PLISTNODE pToolNode;
1141
1142 if (pttd->idTimerInitial)
1143 {
1144 // _Pmpf(("TTM_RELAYEVENT: Stopping timer: %d", pttd->idTimerInitial));
1145 WinStopTimer(pttd->hab,
1146 hwndTooltip,
1147 TOOLTIP_ID_TIMER_INITIAL);
1148 pttd->idTimerInitial = 0;
1149 }
1150
1151 WinQueryPointerPos(HWND_DESKTOP, &ptlPointer);
1152
1153 // find TOOLINFO from mouse position
1154 pttd->ptiMouseOver = NULL;
1155 pToolNode = lstQueryFirstNode(&pttd->llTools);
1156 while (pToolNode)
1157 {
1158 PTOOLINFO pti = (PTOOLINFO)pToolNode->pItemData;
1159 if (pti->hwndTool == pqmsg->hwnd)
1160 {
1161 _Pmpf((__FUNCTION__ ": found tool"));
1162 pttd->ptiMouseOver = pti;
1163 break;
1164 }
1165 pToolNode = pToolNode->pNext;
1166 }
1167
1168 if ( (ptlPointer.x != pttd->ptlPointerLast.x)
1169 || (ptlPointer.y != pttd->ptlPointerLast.y)
1170 || (pqmsg->msg == WM_BUTTON1DOWN)
1171 || (pqmsg->msg == WM_BUTTON2DOWN)
1172 || (pqmsg->msg == WM_BUTTON3DOWN)
1173 )
1174 {
1175 // mouse pos changed:
1176 // hide tooltip
1177 WinPostMsg(hwndTooltip,
1178 TTM_SHOWTOOLTIPNOW,
1179 (MPARAM)FALSE,
1180 0);
1181 memcpy(&pttd->ptlPointerLast, &ptlPointer, sizeof(POINTL));
1182
1183 _Pmpf((__FUNCTION__ ": pttd->ptiMouseOver: 0x%lX", pttd->ptiMouseOver));
1184 _Pmpf((__FUNCTION__ ": pttd->fIsActive: 0x%lX", pttd->fIsActive));
1185 if ( (pttd->ptiMouseOver)
1186 && (pttd->fIsActive)
1187 )
1188 {
1189 // tool found and tooltip is activated:
1190 pttd->idTimerInitial = WinStartTimer(pttd->hab,
1191 hwndTooltip,
1192 TOOLTIP_ID_TIMER_INITIAL,
1193 pttd->ulTimeoutInitial);
1194 // _Pmpf(("TTM_RELAYEVENT: Started timer: %d", pttd->idTimerInitial));
1195 }
1196 }
1197 } // end if (pqmsg)
1198 break; }
1199
1200 /*
1201 *@@ TTM_SETDELAYTIME:
1202 * overrides a few default timeout values for the
1203 * tooltip control.
1204 *
1205 * A tooltip control actually has three time-out durations
1206 * associated with it. The initial duration is the length
1207 * of time that the cursor must remain stationary within
1208 * the bounding rectangle of a tool before the tooltip window
1209 * is displayed. The reshow duration is the length of the delay
1210 * before subsequent tooltip windows are displayed when the
1211 * cursor moves from one tool to another. The autopopup duration
1212 * is the length of time that the tooltip window remains
1213 * displayed before it is hidden. That is, if the cursor remains
1214 * stationary within the bounding rectangle after the tooltip
1215 * window is displayed, the tooltip window is automatically
1216 * hidden at the end of the autopopup duration.
1217 *
1218 * You can adjust all of the time-out durations by using this
1219 * message.
1220 *
1221 * Parameters:
1222 * -- USHORT mp1: parameter selection. One of the following:
1223 * -- TTDT_AUTOMATIC: automatically calculates the initial,
1224 * reshow, and autopopup durations based on the value of iDelay.
1225 * -- TTDT_AUTOPOP: sets the length of time before the tooltip
1226 * window is hidden if the cursor remains stationary
1227 * in the tool's bounding rectangle after the tooltip window
1228 * has appeared.
1229 * -- TTDT_INITIAL: sets the length of time that the cursor must
1230 * remain stationary within the bounding rectangle of
1231 * a tool before the tooltip window is displayed.
1232 * -- TTDT_RESHOW: sets the length of the delay before subsequent
1233 * tooltip windows are displayed when the cursor is moved
1234 * from one tool to another.
1235 * -- ULONG mp2: new duration, in milliseconds.
1236 *
1237 * Return value: 0 always.
1238 */
1239
1240 case TTM_SETDELAYTIME: // done
1241 {
1242 ULONG iDelay = (ULONG)mp2;
1243 switch (SHORT1FROMMP(mp1))
1244 {
1245 case TTDT_AUTOMATIC:
1246 pttd->ulTimeoutInitial = iDelay;
1247 pttd->ulTimeoutAutopop = iDelay * 5;
1248 pttd->ulTimeoutReshow = iDelay / 2;
1249 break;
1250
1251 case TTDT_AUTOPOP:
1252 pttd->ulTimeoutAutopop = iDelay;
1253 break;
1254
1255 case TTDT_INITIAL:
1256 pttd->ulTimeoutInitial = iDelay;
1257 break;
1258
1259 case TTDT_RESHOW:
1260 pttd->ulTimeoutReshow = iDelay;
1261 break;
1262 }
1263 break; }
1264
1265 /*
1266 *@@ TTM_GETTEXT:
1267 * retrieves the text for a tool in the tooltip control.
1268 *
1269 * Parameters:
1270 * -- mp1: always 0
1271 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. When sending the
1272 * message, the hwnd and uId members identify a tool. If the tooltip
1273 * control includes the tool, the lpszText member receives the pointer
1274 * to the string.
1275 *
1276 * Return value: 0 always.
1277 *
1278 * Additional note: On input, if TOOLINFO.lpszText == LPSTR_TEXTCALLBACK,
1279 * this sends the TTN_NEEDTEXT notification to TOOLINFO.hwnd.
1280 */
1281
1282 case TTM_GETTEXT: // done, I think
1283 {
1284 PTOOLINFO pti = (PTOOLINFO)mp2;
1285
1286 if (pti->pszText == PSZ_TEXTCALLBACK)
1287 {
1288 // TTN_NEEDTEXT notification desired:
1289 // compose values for that msg
1290 TOOLTIPTEXT ttt = {0};
1291 _Pmpf(("TTM_GETTEXT: LPSTR_TEXTCALLBACK"));
1292 ttt.hwndTooltip = hwndTooltip;
1293 ttt.hwndTool = pti->hwndTool;
1294 WinSendMsg(pti->hwndTool,
1295 WM_CONTROL,
1296 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
1297 TTN_NEEDTEXT),
1298 &ttt);
1299
1300 // in case of error: set lpszText to NULL; this
1301 // is not specified in the docs however.
1302 pti->pszText = NULL;
1303
1304 switch (ttt.ulFormat)
1305 {
1306 case TTFMT_PSZ:
1307 if (ttt.pszText)
1308 pti->pszText = ttt.pszText;
1309 break;
1310
1311 case TTFMT_STRINGRES:
1312 // ### not supported yet
1313 break;
1314 }
1315 }
1316 break; }
1317
1318 /*
1319 *@@ TTM_UPDATETIPTEXT:
1320 * sets the tooltip text for a tool.
1321 *
1322 * Parameters:
1323 * -- mp1: always 0.
1324 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. The "hinst"
1325 * and "lpszText" members must specify the instance handle and
1326 * the pointer to the text.
1327 * The "hwnd" and "uId" members identify the tool to update.
1328 */
1329
1330 case TTM_UPDATETIPTEXT:
1331 break;
1332
1333 /*
1334 *@@ TTM_HITTEST:
1335 * tests a point to determine whether it is within the
1336 * bounding rectangle of the specified tool and, if the
1337 * point is within, retrieves information about the tool.
1338 *
1339 * Parameters:
1340 * -- mp1: always 0.
1341 * -- PHITTESTINFO mp2: pointer to a TTHITTESTINFO structure.
1342 * When sending the message, the "hwnd" member must specify
1343 * the handle of a tool and the "pt" member must specify the
1344 * coordinates of a point. If the return value is TRUE, the
1345 * "ti" member receives information about the tool that
1346 * occupies the point.
1347 *
1348 * Return value: returns TRUE if the tool occupies the specified
1349 * point or FALSE otherwise.
1350 */
1351
1352 case TTM_HITTEST:
1353 break;
1354
1355 /*
1356 *@@ TTM_WINDOWFROMPOINT:
1357 * this message allows a subclass procedure to cause a tooltip
1358 * to display text for a window other than the one beneath the
1359 * mouse cursor.
1360 *
1361 * Parameters:
1362 * -- mp1: always 0.
1363 * -- mp2: PPOINTL lppt (Win95: (POINT FAR *)lppt):
1364 * pointer to a POINTL structure that defines the point to be checked.
1365 *
1366 * Return value: the handle to the window that contains the point, or
1367 * NULL if no window exists at the specified point.
1368 *
1369 * This message is intended to be processed by an application that
1370 * subclasses a tooltip. It is not intended to be sent by an
1371 * application. A tooltip sends this message to itself before
1372 * displaying the text for a window. By changing the coordinates
1373 * of the point specified by lppt, the subclass procedure can cause
1374 * the tooltip to display text for a window other than the one
1375 * beneath the mouse cursor.
1376 */
1377
1378 case TTM_WINDOWFROMPOINT:
1379 break;
1380
1381 /*
1382 *@@ TTM_ENUMTOOLS:
1383 * this message retrieves the information that a tooltip control
1384 * maintains about a certain tool.
1385 *
1386 * Parameters:
1387 * -- USHORT mp1: zero-based index of the tool for which to
1388 * retrieve information.
1389 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1390 * receives information about the tool. Before sending
1391 * this message, the cbSize member must specify the size
1392 * of the structure.
1393 *
1394 * Return value: TRUE if any tools are enumerated or FALSE otherwise.
1395 */
1396
1397 case TTM_ENUMTOOLS: // done
1398 {
1399 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1400 mrc = (MPARAM)FALSE;
1401 if (ptiTarget)
1402 {
1403 PTOOLINFO ptiFound = (PTOOLINFO)lstItemFromIndex(&pttd->llTools,
1404 SHORT1FROMMP(mp1));
1405 if (ptiFound)
1406 {
1407 memcpy(ptiTarget, ptiFound, sizeof(TOOLINFO));
1408 mrc = (MRESULT)TRUE;
1409 }
1410 }
1411 break; }
1412
1413 /*
1414 *@@ TTM_GETCURRENTTOOL:
1415 * this message retrieves the information that the tooltip control
1416 * maintains for the _current_ tool; that is, the one for which
1417 * the tooltip control is currently displaying text.
1418 *
1419 * Parameters:
1420 * -- mp1: always 0.
1421 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that receives
1422 * information about the current tool.
1423 *
1424 * Return value: TRUE if successful or FALSE otherwise.
1425 */
1426
1427 case TTM_GETCURRENTTOOL: // done
1428 {
1429 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1430 mrc = (MPARAM)FALSE;
1431 if (ptiTarget)
1432 {
1433 if (pttd->ptiMouseOver)
1434 {
1435 memcpy(ptiTarget, pttd->ptiMouseOver, sizeof(TOOLINFO));
1436 mrc = (MPARAM)TRUE;
1437 }
1438 }
1439 break; }
1440
1441 /*
1442 *@@ TTM_GETTOOLCOUNT:
1443 * returns the number of tools in the tooltip control.
1444 *
1445 * No parameters.
1446 */
1447
1448 case TTM_GETTOOLCOUNT: // done
1449 mrc = (MPARAM)lstCountItems(&pttd->llTools);
1450 break;
1451
1452 /*
1453 *@@ TTM_GETTOOLINFO:
1454 * this message retrieves the information that a tooltip
1455 * control maintains about a tool.
1456 *
1457 * Parameters:
1458 * -- mp1: always 0.
1459 * -- PTOOLINFO mp2:
1460 * pointer to a TOOLINFO structure. When sending the message,
1461 * the hwnd and uId members identify a tool, and the cbSize
1462 * member must specify the size of the structure. If the
1463 * tooltip control includes the tool, the structure receives
1464 * information about the tool.
1465 *
1466 * Return value: TRUE if successful or FALSE otherwise.
1467 */
1468
1469 case TTM_GETTOOLINFO: // done
1470 {
1471 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1472 mrc = (MPARAM)FALSE;
1473 if (ptiSearch)
1474 {
1475 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1476 while (pToolNode)
1477 {
1478 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1479 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1480 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1481 )
1482 {
1483 // found:
1484 memcpy(ptiSearch, ptiThis, sizeof(TOOLINFO));
1485 mrc = (MPARAM)TRUE;
1486 break;
1487 }
1488 pToolNode = pToolNode->pNext;
1489 }
1490 }
1491 break; }
1492
1493 /*
1494 *@@ TTM_SETTOOLINFO:
1495 * this message sets the information that a tooltip control
1496 * maintains for a tool.
1497 *
1498 * Parameters:
1499 * -- mp1: always 0.
1500 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1501 * specifies the information to set.
1502 *
1503 * Return value: 0 always.
1504 */
1505
1506 case TTM_SETTOOLINFO:
1507 break;
1508
1509 /*
1510 *@@ TTM_SHOWTOOLTIPNOW:
1511 * depending on BOOL mp1, shows or hides the tooltip.
1512 * This is required because we cannot show or hide
1513 * the window during processing of WM_MOUSEMOVE etc,
1514 * which will lead to strange PM hangs.
1515 *
1516 * This is not part of the Win95 message set but used
1517 * in the OS/2 implementation only. This calls TtmShowTooltip
1518 * in turn.
1519 */
1520
1521 case TTM_SHOWTOOLTIPNOW:
1522 _Pmpf((__FUNCTION__ ": TTM_SHOWTOOLTIPNOW %d", mp1));
1523 TtmShowTooltip(hwndTooltip, pttd, (BOOL)mp1);
1524 break;
1525
1526 default:
1527 mrc = WinDefWindowProc(hwndTooltip, msg, mp1, mp2);
1528 }
1529 }
1530 CATCH(excpt1) {} END_CATCH();
1531
1532 return (mrc);
1533}
1534
1535
Note: See TracBrowser for help on using the repository browser.