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

Last change on this file since 55 was 54, checked in by umoeller, 24 years ago

Misc changes.

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