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

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

Misc. updates.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 61.2 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->ulTimeoutInitial)
819 WinStopTimer(pttd->hab,
820 hwndTooltip,
821 pttd->ulTimeoutInitial);
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. ### not implemented yet
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
992 case TTM_ADDTOOL: // done
993 mrc = (MPARAM)FALSE;
994 if (mp2)
995 {
996 PTOOLINFO ptiPassed = (PTOOLINFO)mp2,
997 ptiNew = (PTOOLINFO)malloc(sizeof(TOOLINFO));
998 if (ptiNew)
999 {
1000 memcpy(ptiNew, ptiPassed, sizeof(TOOLINFO));
1001 lstAppendItem(&pttd->llTools,
1002 ptiNew);
1003
1004 if (ptiPassed->ulFlags & TTF_SUBCLASS)
1005 SubclassToolForToolinfo(hwndTooltip,
1006 ptiPassed->hwndTool);
1007
1008 mrc = (MPARAM)TRUE;
1009 }
1010 }
1011 break;
1012
1013 /*
1014 *@@ TTM_DELTOOL:
1015 * removes a tool from a tooltip control.
1016 *
1017 * Parameters:
1018 * -- mp1: always 0.
1019 * -- PTOOLINFO mp2: information about the tool;
1020 * all fields except cbSize, hwnd, uID are
1021 * ignored.
1022 *
1023 * Return value: 0 always.
1024 */
1025
1026 case TTM_DELTOOL: // done
1027 {
1028 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1029 if (ptiSearch)
1030 {
1031 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1032 while (pToolNode)
1033 {
1034 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1035 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1036 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1037 )
1038 {
1039 // found:
1040 lstRemoveNode(&pttd->llTools, pToolNode);
1041 break;
1042 }
1043 }
1044 pToolNode = pToolNode->pNext;
1045 }
1046 break; }
1047
1048 /*
1049 *@@ TTM_NEWTOOLRECT:
1050 * sets a new bounding rectangle for a tool
1051 * already registered with a tooltip control.
1052 *
1053 * Parameters:
1054 * -- mp1: always 0.
1055 * -- PTOOLINFO mp2: information about the tool;
1056 * all fields except hwnd, uID, and rect
1057 * are ignored.
1058 *
1059 * Return value: 0 always.
1060 *
1061 * If an application includes a tool implemented as a rectangular
1062 * area and the size or position of the control changes, it can
1063 * use the TTM_NEWTOOLRECT message to report the change to the
1064 * tooltip control. An application does not need to report size
1065 * and position changes for a tool implemented as a window.
1066 * Reporting that is not necessary because the tooltip control
1067 * uses the window handle of a tool to determine if the cursor
1068 * is on the tool, not the tool's bounding rectangle.
1069 */
1070
1071 case TTM_NEWTOOLRECT:
1072 break;
1073
1074 /*
1075 *@@ TTM_RELAYEVENT:
1076 * passes a mouse message to a tooltip control
1077 * for further processing.
1078 *
1079 * Parameters:
1080 * -- mp1: always 0.
1081 * -- PQMSG mp2: pointer to a QMSG struct (Win95: MSG struct)
1082 * containing a mouse message. Only the above messages
1083 * are processed.
1084 *
1085 * Return value: 0 always.
1086 *
1087 * A tooltip control needs to receive mouse messages to determine
1088 * when to display the tooltip window. Because mouse messages are
1089 * sent only to the window that contains the cursor, you must
1090 * use the TTM_RELAYEVENT message to relay mouse messages to the
1091 * tooltip control.
1092 *
1093 * If a tool is implemented as a rectangular area in an
1094 * application-defined window, the window procedure receives all
1095 * mouse messages and can relay the ones listed below to the
1096 * tooltip control, using this message.
1097 *
1098 * However, if a tool is implemented as a system-defined window,
1099 * the mouse messages are sent to that window and are not readily
1100 * available to the application. There are two ways you can have
1101 * the tooltip control notified of these mouse messages:
1102 *
1103 * -- You can specify the TTF_SUBCLASS flag when adding the tool
1104 * to the tooltip control. The tooltip control will then subclass
1105 * the tool window to get mouse-related messages, and you're off.
1106 *
1107 * -- You can implement a message hook for your process and check
1108 * for your tool windows there and send TTM_RELAYEVENT to the
1109 * tooltip control. In that case, you need to intercept the
1110 * messages specified below.
1111 *
1112 * When a tooltip control receives a relayed WM_MOUSEMOVE message,
1113 * it determines whether the cursor is in the bounding rectangle of
1114 * a tool. If the cursor is there, the tooltip control sets a timer.
1115 * At the end of the time-out duration, the tooltip control checks
1116 * the position of the cursor to see whether it has moved. If the
1117 * cursor has not, the tooltip control retrieves the text for the tool,
1118 * copies the text into the tooltip window, and shows the window.
1119 * The tooltip control continues to show the window until it receives
1120 * a relayed button-up or button-down message or until a relayed
1121 * WM_MOUSEMOVE message indicates that the cursor has moved outside
1122 * the bounding rectangle of the tool.
1123 *
1124 * For the timer descriptions, see TTM_SETDELAYTIME.
1125 *
1126 * When it is about to be displayed, a tootip control sends the
1127 * TTN_SHOW notification to the owner window. A tooltip control
1128 * sends the TTN_POP notification when it is about to be hidden.
1129 * Each notification is sent in the context of a WM_NOTIFY message
1130 * (OS/2: WM_CONTROL).
1131 *
1132 * Relevant messages:
1133 * -- WM_MOUSEMOVE
1134 * -- WM_BUTTON1DOWN (Win95: WM_LBUTTONDOWN)
1135 * -- WM_BUTTON1UP (Win95: WM_LBUTTONUP)
1136 * -- WM_BUTTON2DOWN (Win95: WM_RBUTTONDOWN)
1137 * -- WM_BUTTON2UP (Win95: WM_RBUTTONUP)
1138 * -- WM_BUTTON3DOWN (Win95: WM_MBUTTONDOWN)
1139 * -- WM_BUTTON3UP (Win95: WM_MBUTTONUP)
1140 */
1141
1142 case TTM_RELAYEVENT:
1143 {
1144 PQMSG pqmsg = (PQMSG)mp2;
1145 if (pqmsg)
1146 {
1147 POINTL ptlPointer;
1148 PLISTNODE pToolNode;
1149
1150 if (pttd->idTimerInitial)
1151 {
1152 // _Pmpf(("TTM_RELAYEVENT: Stopping timer: %d", pttd->idTimerInitial));
1153 WinStopTimer(pttd->hab,
1154 hwndTooltip,
1155 TOOLTIP_ID_TIMER_INITIAL);
1156 pttd->idTimerInitial = 0;
1157 }
1158
1159 WinQueryPointerPos(HWND_DESKTOP, &ptlPointer);
1160
1161 // find TOOLINFO from mouse position
1162 pttd->ptiMouseOver = NULL;
1163 pToolNode = lstQueryFirstNode(&pttd->llTools);
1164 while (pToolNode)
1165 {
1166 PTOOLINFO pti = (PTOOLINFO)pToolNode->pItemData;
1167 if (pti->hwndTool == pqmsg->hwnd)
1168 {
1169 // _Pmpf((__FUNCTION__ ": found tool"));
1170 pttd->ptiMouseOver = pti;
1171 break;
1172 }
1173 pToolNode = pToolNode->pNext;
1174 }
1175
1176 if ( (ptlPointer.x != pttd->ptlPointerLast.x)
1177 || (ptlPointer.y != pttd->ptlPointerLast.y)
1178 || (pqmsg->msg == WM_BUTTON1DOWN)
1179 || (pqmsg->msg == WM_BUTTON2DOWN)
1180 || (pqmsg->msg == WM_BUTTON3DOWN)
1181 )
1182 {
1183 // mouse pos changed:
1184 // hide tooltip
1185 WinPostMsg(hwndTooltip,
1186 TTM_SHOWTOOLTIPNOW,
1187 (MPARAM)FALSE,
1188 0);
1189 memcpy(&pttd->ptlPointerLast, &ptlPointer, sizeof(POINTL));
1190
1191 // _Pmpf((__FUNCTION__ ": pttd->ptiMouseOver: 0x%lX", pttd->ptiMouseOver));
1192 // _Pmpf((__FUNCTION__ ": pttd->fIsActive: 0x%lX", pttd->fIsActive));
1193 if ( (pttd->ptiMouseOver)
1194 && (pttd->fIsActive)
1195 )
1196 {
1197 // tool found and tooltip is activated:
1198 pttd->idTimerInitial = WinStartTimer(pttd->hab,
1199 hwndTooltip,
1200 TOOLTIP_ID_TIMER_INITIAL,
1201 pttd->ulTimeoutInitial);
1202 // _Pmpf(("TTM_RELAYEVENT: Started timer: %d", pttd->idTimerInitial));
1203 }
1204 }
1205 } // end if (pqmsg)
1206 break; }
1207
1208 /*
1209 *@@ TTM_SETDELAYTIME:
1210 * overrides a few default timeout values for the
1211 * tooltip control.
1212 *
1213 * A tooltip control actually has three time-out durations
1214 * associated with it. The initial duration is the length
1215 * of time that the cursor must remain stationary within
1216 * the bounding rectangle of a tool before the tooltip window
1217 * is displayed. The reshow duration is the length of the delay
1218 * before subsequent tooltip windows are displayed when the
1219 * cursor moves from one tool to another. The autopopup duration
1220 * is the length of time that the tooltip window remains
1221 * displayed before it is hidden. That is, if the cursor remains
1222 * stationary within the bounding rectangle after the tooltip
1223 * window is displayed, the tooltip window is automatically
1224 * hidden at the end of the autopopup duration.
1225 *
1226 * You can adjust all of the time-out durations by using this
1227 * message.
1228 *
1229 * Parameters:
1230 * -- USHORT mp1: parameter selection. One of the following:
1231 * -- TTDT_AUTOMATIC: automatically calculates the initial,
1232 * reshow, and autopopup durations based on the value of iDelay.
1233 * -- TTDT_AUTOPOP: sets the length of time before the tooltip
1234 * window is hidden if the cursor remains stationary
1235 * in the tool's bounding rectangle after the tooltip window
1236 * has appeared.
1237 * -- TTDT_INITIAL: sets the length of time that the cursor must
1238 * remain stationary within the bounding rectangle of
1239 * a tool before the tooltip window is displayed.
1240 * -- TTDT_RESHOW: sets the length of the delay before subsequent
1241 * tooltip windows are displayed when the cursor is moved
1242 * from one tool to another.
1243 * -- ULONG mp2: new duration, in milliseconds.
1244 *
1245 * Return value: 0 always.
1246 */
1247
1248 case TTM_SETDELAYTIME: // done
1249 {
1250 ULONG iDelay = (ULONG)mp2;
1251 switch (SHORT1FROMMP(mp1))
1252 {
1253 case TTDT_AUTOMATIC:
1254 pttd->ulTimeoutInitial = iDelay;
1255 pttd->ulTimeoutAutopop = iDelay * 5;
1256 pttd->ulTimeoutReshow = iDelay / 2;
1257 break;
1258
1259 case TTDT_AUTOPOP:
1260 pttd->ulTimeoutAutopop = iDelay;
1261 break;
1262
1263 case TTDT_INITIAL:
1264 pttd->ulTimeoutInitial = iDelay;
1265 break;
1266
1267 case TTDT_RESHOW:
1268 pttd->ulTimeoutReshow = iDelay;
1269 break;
1270 }
1271 break; }
1272
1273 /*
1274 *@@ TTM_GETTEXT:
1275 * retrieves the text for a tool in the tooltip control.
1276 *
1277 * Parameters:
1278 * -- mp1: always 0
1279 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. When sending the
1280 * message, the hwnd and uId members identify a tool. If the tooltip
1281 * control includes the tool, the lpszText member receives the pointer
1282 * to the string.
1283 *
1284 * Return value: 0 always.
1285 *
1286 * Additional note: On input, if TOOLINFO.lpszText == PSZ_TEXTCALLBACK,
1287 * this sends the TTN_NEEDTEXT notification to TOOLINFO.hwnd.
1288 */
1289
1290 case TTM_GETTEXT: // done, I think
1291 {
1292 PTOOLINFO pti = (PTOOLINFO)mp2;
1293
1294 if (pti->pszText == PSZ_TEXTCALLBACK)
1295 {
1296 // TTN_NEEDTEXT notification desired:
1297 // compose values for that msg
1298 TOOLTIPTEXT ttt = {0};
1299 // _Pmpf(("TTM_GETTEXT: PSZ_TEXTCALLBACK... sending TTN_NEEDTEXT"));
1300 ttt.hwndTooltip = hwndTooltip;
1301 ttt.hwndTool = pti->hwndTool;
1302 WinSendMsg(pti->hwndToolOwner,
1303 WM_CONTROL,
1304 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
1305 TTN_NEEDTEXT),
1306 &ttt);
1307
1308 // in case of error: set lpszText to NULL; this
1309 // is not specified in the docs however.
1310 pti->pszText = NULL;
1311
1312 switch (ttt.ulFormat)
1313 {
1314 case TTFMT_PSZ:
1315 if (ttt.pszText)
1316 pti->pszText = ttt.pszText;
1317 break;
1318
1319 case TTFMT_STRINGRES:
1320 // ### not supported yet
1321 break;
1322 }
1323 }
1324 break; }
1325
1326 /*
1327 *@@ TTM_UPDATETIPTEXT:
1328 * sets the tooltip text for a tool.
1329 *
1330 * Parameters:
1331 * -- mp1: always 0.
1332 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. The "hinst"
1333 * and "lpszText" members must specify the instance handle and
1334 * the pointer to the text.
1335 * The "hwnd" and "uId" members identify the tool to update.
1336 */
1337
1338 case TTM_UPDATETIPTEXT:
1339 break;
1340
1341 /*
1342 *@@ TTM_HITTEST:
1343 * tests a point to determine whether it is within the
1344 * bounding rectangle of the specified tool and, if the
1345 * point is within, retrieves information about the tool.
1346 *
1347 * Parameters:
1348 * -- mp1: always 0.
1349 * -- PHITTESTINFO mp2: pointer to a TTHITTESTINFO structure.
1350 * When sending the message, the "hwnd" member must specify
1351 * the handle of a tool and the "pt" member must specify the
1352 * coordinates of a point. If the return value is TRUE, the
1353 * "ti" member receives information about the tool that
1354 * occupies the point.
1355 *
1356 * Return value: returns TRUE if the tool occupies the specified
1357 * point or FALSE otherwise.
1358 */
1359
1360 case TTM_HITTEST:
1361 break;
1362
1363 /*
1364 *@@ TTM_WINDOWFROMPOINT:
1365 * this message allows a subclass procedure to cause a tooltip
1366 * to display text for a window other than the one beneath the
1367 * mouse cursor.
1368 *
1369 * Parameters:
1370 * -- mp1: always 0.
1371 * -- mp2: PPOINTL lppt (Win95: (POINT FAR *)lppt):
1372 * pointer to a POINTL structure that defines the point to be checked.
1373 *
1374 * Return value: the handle to the window that contains the point, or
1375 * NULL if no window exists at the specified point.
1376 *
1377 * This message is intended to be processed by an application that
1378 * subclasses a tooltip. It is not intended to be sent by an
1379 * application. A tooltip sends this message to itself before
1380 * displaying the text for a window. By changing the coordinates
1381 * of the point specified by lppt, the subclass procedure can cause
1382 * the tooltip to display text for a window other than the one
1383 * beneath the mouse cursor.
1384 */
1385
1386 case TTM_WINDOWFROMPOINT:
1387 break;
1388
1389 /*
1390 *@@ TTM_ENUMTOOLS:
1391 * this message retrieves the information that a tooltip control
1392 * maintains about a certain tool.
1393 *
1394 * Parameters:
1395 * -- USHORT mp1: zero-based index of the tool for which to
1396 * retrieve information.
1397 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1398 * receives information about the tool. Before sending
1399 * this message, the cbSize member must specify the size
1400 * of the structure.
1401 *
1402 * Return value: TRUE if any tools are enumerated or FALSE otherwise.
1403 */
1404
1405 case TTM_ENUMTOOLS: // done
1406 {
1407 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1408 mrc = (MPARAM)FALSE;
1409 if (ptiTarget)
1410 {
1411 PTOOLINFO ptiFound = (PTOOLINFO)lstItemFromIndex(&pttd->llTools,
1412 SHORT1FROMMP(mp1));
1413 if (ptiFound)
1414 {
1415 memcpy(ptiTarget, ptiFound, sizeof(TOOLINFO));
1416 mrc = (MRESULT)TRUE;
1417 }
1418 }
1419 break; }
1420
1421 /*
1422 *@@ TTM_GETCURRENTTOOL:
1423 * this message retrieves the information that the tooltip control
1424 * maintains for the _current_ tool; that is, the one for which
1425 * the tooltip control is currently displaying text.
1426 *
1427 * Parameters:
1428 * -- mp1: always 0.
1429 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that receives
1430 * information about the current tool.
1431 *
1432 * Return value: TRUE if successful or FALSE otherwise.
1433 */
1434
1435 case TTM_GETCURRENTTOOL: // done
1436 {
1437 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1438 mrc = (MPARAM)FALSE;
1439 if (ptiTarget)
1440 {
1441 if (pttd->ptiMouseOver)
1442 {
1443 memcpy(ptiTarget, pttd->ptiMouseOver, sizeof(TOOLINFO));
1444 mrc = (MPARAM)TRUE;
1445 }
1446 }
1447 break; }
1448
1449 /*
1450 *@@ TTM_GETTOOLCOUNT:
1451 * returns the number of tools in the tooltip control.
1452 *
1453 * No parameters.
1454 */
1455
1456 case TTM_GETTOOLCOUNT: // done
1457 mrc = (MPARAM)lstCountItems(&pttd->llTools);
1458 break;
1459
1460 /*
1461 *@@ TTM_GETTOOLINFO:
1462 * this message retrieves the information that a tooltip
1463 * control maintains about a tool.
1464 *
1465 * Parameters:
1466 * -- mp1: always 0.
1467 * -- PTOOLINFO mp2:
1468 * pointer to a TOOLINFO structure. When sending the message,
1469 * the hwnd and uId members identify a tool, and the cbSize
1470 * member must specify the size of the structure. If the
1471 * tooltip control includes the tool, the structure receives
1472 * information about the tool.
1473 *
1474 * Return value: TRUE if successful or FALSE otherwise.
1475 */
1476
1477 case TTM_GETTOOLINFO: // done
1478 {
1479 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1480 mrc = (MPARAM)FALSE;
1481 if (ptiSearch)
1482 {
1483 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1484 while (pToolNode)
1485 {
1486 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1487 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1488 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1489 )
1490 {
1491 // found:
1492 memcpy(ptiSearch, ptiThis, sizeof(TOOLINFO));
1493 mrc = (MPARAM)TRUE;
1494 break;
1495 }
1496 pToolNode = pToolNode->pNext;
1497 }
1498 }
1499 break; }
1500
1501 /*
1502 *@@ TTM_SETTOOLINFO:
1503 * this message sets the information that a tooltip control
1504 * maintains for a tool.
1505 *
1506 * Parameters:
1507 * -- mp1: always 0.
1508 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1509 * specifies the information to set.
1510 *
1511 * Return value: 0 always.
1512 */
1513
1514 case TTM_SETTOOLINFO:
1515 break;
1516
1517 /*
1518 *@@ TTM_SHOWTOOLTIPNOW:
1519 * depending on BOOL mp1, shows or hides the tooltip.
1520 * This is required because we cannot show or hide
1521 * the window during processing of WM_MOUSEMOVE etc,
1522 * which will lead to strange PM hangs.
1523 *
1524 * This is not part of the Win95 message set but used
1525 * in the OS/2 implementation only. This calls TtmShowTooltip
1526 * in turn.
1527 */
1528
1529 case TTM_SHOWTOOLTIPNOW:
1530 // _Pmpf((__FUNCTION__ ": TTM_SHOWTOOLTIPNOW %d", mp1));
1531 TtmShowTooltip(hwndTooltip, pttd, (BOOL)mp1);
1532 break;
1533
1534 default:
1535 mrc = WinDefWindowProc(hwndTooltip, msg, mp1, mp2);
1536 }
1537 }
1538 CATCH(excpt1) {} END_CATCH();
1539
1540 return (mrc);
1541}
1542
1543
Note: See TracBrowser for help on using the repository browser.