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

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

Final changes for 0.9.7, i hope...

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 60.9 KB
Line 
1
2/*
3 *@@sourcefile cctl_tooltip.c:
4 * implementation for the "tooltip" common control.
5 * See comctl.c for an overview.
6 *
7 * This has been extracted from comctl.c with V0.9.3 (2000-05-21) [umoeller].
8 *
9 * Note: Version numbering in this file relates to XWorkplace version
10 * numbering.
11 *
12 *@@header "helpers\comctl.h"
13 *@@added V0.9.3 (2000-05-21) [umoeller].
14 */
15
16/*
17 * Copyright (C) 1997-2000 Ulrich M”ller.
18 * This file is part of the "XWorkplace helpers" source package.
19 * This is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published
21 * by the Free Software Foundation, in version 2 as it comes in the
22 * "COPYING" file of the XWorkplace main distribution.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 */
28
29#define OS2EMX_PLAIN_CHAR
30 // this is needed for "os2emx.h"; if this is defined,
31 // emx will define PSZ as _signed_ char, otherwise
32 // as unsigned char
33
34#define INCL_DOSEXCEPTIONS
35#define INCL_DOSPROCESS
36#define INCL_DOSSEMAPHORES
37#define INCL_DOSERRORS
38
39#define INCL_WINWINDOWMGR
40#define INCL_WINFRAMEMGR
41#define INCL_WINMESSAGEMGR
42#define INCL_WININPUT
43#define INCL_WINPOINTERS
44#define INCL_WINTRACKRECT
45#define INCL_WINTIMER
46#define INCL_WINSYS
47
48#define INCL_WINRECTANGLES /// xxx temporary
49
50#define INCL_WINMENUS
51#define INCL_WINSTATICS
52#define INCL_WINBUTTONS
53#define INCL_WINSTDCNR
54
55#define INCL_GPIPRIMITIVES
56#define INCL_GPILOGCOLORTABLE
57#define INCL_GPILCIDS
58#define INCL_GPIPATHS
59#define INCL_GPIREGIONS
60#define INCL_GPIBITMAPS // added V0.9.1 (2000-01-04) [umoeller]: needed for EMX headers
61#include <os2.h>
62
63#include <stdlib.h>
64#include <stdio.h>
65#include <string.h>
66#include <setjmp.h> // needed for except.h
67#include <assert.h> // needed for except.h
68
69#include "setup.h" // code generation and debugging options
70
71#include "helpers\cnrh.h"
72#include "helpers\except.h" // exception handling
73#include "helpers\gpih.h"
74#include "helpers\linklist.h"
75#include "helpers\winh.h"
76
77#include "helpers\comctl.h"
78
79#pragma hdrstop
80
81/*
82 *@@category: Helpers\PM helpers\Window classes\Tooltips
83 * 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 if ( (pttd->ptiMouseOver->ulFlags & TTF_CENTERBELOW)
506 || (pttd->ptiMouseOver->ulFlags & TTF_CENTERABOVE)
507 )
508 {
509 // center below control:
510 SWP swpTool;
511 WinQueryWindowPos(pttd->ptiMouseOver->hwndTool, &swpTool);
512 ptlTooltip.x = swpTool.x;
513 ptlTooltip.y = swpTool.y;
514 // convert x, y to desktop points
515 WinMapWindowPoints(WinQueryWindow(pttd->ptiMouseOver->hwndTool,
516 QW_PARENT), // hwndFrom
517 HWND_DESKTOP, // hwndTo
518 &ptlTooltip,
519 1);
520 ptlTooltip.x += ((swpTool.cx - cx) / 2L);
521 if (pttd->ptiMouseOver->ulFlags & TTF_CENTERBELOW)
522 ptlTooltip.y -= cy;
523 else
524 ptlTooltip.y += swpTool.cy;
525 }
526 else
527 {
528 // use pointer pos:
529 ptlTooltip.x = ptlPointer.x - cx/2;
530 ptlTooltip.y = ptlPointer.y - cy;
531 }
532
533 // if "shy mouse" is enabled, make
534 // sure the tool tip is not under the
535 // mouse pointer
536 if (ulStyle & TTF_SHYMOUSE)
537 {
538 // we need to subtract the current mouse
539 // pointer's hot spot from the current
540 // pointer position
541 HPOINTER hptr = WinQueryPointer(HWND_DESKTOP);
542 POINTERINFO pi;
543 if (WinQueryPointerInfo(hptr, &pi))
544 {
545 /* ULONG cyPointer = WinQuerySysValue(HWND_DESKTOP,
546 SV_CYPOINTER); */
547 // calc bottom edge of mouse pointer rect
548 ULONG yBottomPointer = (ptlPointer.y - pi.yHotspot);
549 // _Pmpf(("yHotspot: %d", pi.yHotspot));
550 if ( (ptlTooltip.y + cy) // top edge of tool tip
551 > yBottomPointer
552 )
553 {
554 ptlTooltip.y = ptlPointer.y - cy - pi.yHotspot;
555 }
556 }
557 }
558
559 // constrain to screen
560 if (ptlTooltip.x < 0)
561 ptlTooltip.x = 0;
562 if (ptlTooltip.y < 0)
563 ptlTooltip.y = 0;
564 if (ptlTooltip.x + cx > G_cxScreen)
565 ptlTooltip.x = G_cxScreen-cx;
566 if (ptlTooltip.y + cy > G_cyScreen)
567 ptlTooltip.y = G_cyScreen-cy;
568
569 // if shadow is enabled,
570 // enlarge; the shadow might by
571 // off-screen now, but that's OK
572 if (ulStyle & TTS_SHADOW)
573 {
574 cx += TT_SHADOWOFS;
575 cy += TT_SHADOWOFS;
576 ptlTooltip.y -= TT_SHADOWOFS;
577 }
578
579 // notify owner
580 WinSendMsg(pttd->hwndOwner,
581 WM_CONTROL,
582 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
583 TTN_SHOW),
584 0);
585
586 // set tooltip position at the pos we calculated
587 // and show tooltip
588 WinSetWindowPos(hwndTooltip,
589 HWND_TOP,
590 ptlTooltip.x,
591 ptlTooltip.y,
592 cx, cy,
593 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW);
594 pttd->fIsVisible = TRUE;
595
596 // start autopop timer
597 pttd->idTimerAutopop = WinStartTimer(pttd->hab,
598 hwndTooltip,
599 TOOLTIP_ID_TIMER_AUTOPOP,
600 pttd->ulTimeoutAutopop);
601 } // end if (pttd->pszPaintText)
602 } // end if ( (ptlPointer.x == pttd->ptlPointerLast.x)...
603 } // end if (mp1)
604 else
605 {
606 /*
607 * hide tooltip::
608 *
609 */
610
611 if (pttd->fIsVisible)
612 {
613 WinSendMsg(pttd->hwndOwner,
614 WM_CONTROL,
615 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
616 TTN_POP),
617 0);
618 WinShowWindow(hwndTooltip, FALSE);
619 }
620
621 // stop autopop timer
622 if (pttd->idTimerAutopop)
623 {
624 WinStopTimer(pttd->hab,
625 hwndTooltip,
626 TOOLTIP_ID_TIMER_AUTOPOP);
627 pttd->idTimerAutopop = 0;
628 }
629 }
630
631 // store new visibility
632 pttd->fIsVisible = fShow;
633}
634
635/*
636 *@@ ctl_fnwpTooltip:
637 * window procedure for the "tooltip" control. This control is
638 * largely source-code compatible to the Win32 version and has
639 * been modelled according to the Win32 programmer's reference.
640 *
641 * A tooltip control is a small pop-up window that displays a
642 * single line of descriptive text giving the purpose of "tools"
643 * in an application.
644 * A "tool" is either a window, such as a child window or control,
645 * or an application-defined rectangular area within a window.
646 * See the TTM_ADDTOOL message for details.
647 *
648 * To clarify: There is usually one tooltip control, which is hidden
649 * most of the time, for many tools (parts of a visible window).
650 * When the user puts the cursor on a tool and leaves it there for
651 * approximately one-half second, the tooltip control is set up for
652 * that tool and made visible. The tooltip control appears near the
653 * pointer and disappears when the user clicks a mouse button or moves
654 * the pointer off of the tool.
655 *
656 * The Win32 concept has been extended with this implementation to
657 * display even longer texts, including line breaks. The tooltip
658 * window is formatted accordingly.
659 *
660 * All default window styles are ignored when you create the tooltip,
661 * but will rather be set by this window proc automatically. The
662 * only valid window styles are the TTS_* flags (see notes below).
663 *
664 * Presentation parameters are fully supported.
665 *
666 * To create a tooltip control using comctl.c, use
667 + ctlRegisterTooltip(hab);
668 + hwndTooltip = WinCreateWindow(HWND_DESKTOP, // parent
669 + COMCTL_TOOLTIP_CLASS, // wnd class (comctl.h)
670 + NULL, // window text
671 + TTS_ALWAYSTIP, // window style, ignored except for TTS_* flags
672 + 0, 0, 0, 0, // window pos and size, ignored
673 + hwndOwner, // owner window -- important!
674 + NULLHANDLE, // hwndInsertBehind, ignored
675 + ulID, // window ID, optional
676 + NULL, // control data
677 + NULL); // presparams
678 +
679 * ctl_fnwpTooltip automatically sets the size, position, and visibility
680 * of the tooltip control. The size of the tooltip window will vary
681 * depending on the text to be displayed and on the font presentation
682 * parameters, which are supported by this control (OS/2 only).
683 *
684 * Note: OS/2 normally does not destroy windows which are only owned by
685 * another window. As a result, when the tooltip's owner is destroyed,
686 * you must explicitly also destroy the tooltip window.
687 *
688 * Under both Win32 and OS/2, a tooltip control has two class-specific styles:
689 *
690 * -- TTS_ALWAYSTIP: the tooltip appears when the cursor is on a tool,
691 * regardless of whether the tooltip control's owner window is active
692 * or inactive. Without this style, the tooltip control appears when the
693 * tool's owner window is active, but not when it is inactive.
694 *
695 * -- TTS_NOPREFIX: this prevents the system from stripping the ampersand (&)
696 * character from a string. If a tooltip control does not have the TTS_NOPREFIX
697 * style, the system automatically strips ampersand characters, allowing an
698 * application to use the same string as both a menu item and tooltip text.
699 *
700 * The tooltip control can be (de)activated using the TTM_ACTIVATE message.
701 *
702 * To register tools with the tooltip control (to make it do anything
703 * meaningful), send the TTM_ADDTOOL message to the tooltip control.
704 *
705 * This control supports the following presentation parameters (if the
706 * PP_* value is not found, the SYSCLR_* system color is used):
707 * -- PP_MENUBACKGROUNDCOLOR / SYSCLR_ENTRYFIELD: tooltip background color.
708 * -- PP_MENUFOREGROUNDCOLOR / SYSCLR_WINDOWTEXT: tooltip text color.
709 * -- PP_MENUHILITEFGNDCOLOR / SYSCLR_WINDOWTEXT: 3D border light color.
710 * -- PP_MENUHILITEBGNDCOLOR / SYSCLR_WINDOWTEXT: 3D border dark color.
711 * -- PP_FONTNAMESIZE: font to use for the tooltip. The default is "8.Helv"
712 * on Warp 3 and "9.WarpSans" on Warp 4.
713 *
714 * So per default, if no presentation parameters are set, the control
715 * paints the background like an entry field and the text and the border
716 * in the same window text color (usually black).
717 * The tooltip does _not_ inherit presentation parameters from the parent,
718 * so unless you explicitly set presparams, the tooltip looks pretty much
719 * like the Win32 counterpart (with the default system colors, black border
720 * and text on yellow background).
721 *
722 *@@added V0.9.0 [umoeller]
723 */
724
725MRESULT EXPENTRY ctl_fnwpTooltip(HWND hwndTooltip, ULONG msg, MPARAM mp1, MPARAM mp2)
726{
727 MRESULT mrc = 0;
728
729 PTOOLTIPDATA pttd = (PTOOLTIPDATA)WinQueryWindowPtr(hwndTooltip, 1);
730
731 TRY_LOUD(excpt1)
732 {
733 switch (msg)
734 {
735 /*
736 * WM_CREATE:
737 * this message is sent to the window procedure of
738 * the window being created, thus offering it an
739 * opportunity to initialize that window.
740 *
741 * The window procedure receives this after the window
742 * is created but before the window becomes visible.
743 */
744
745 case WM_CREATE:
746 {
747 PCREATESTRUCT pcs = (PCREATESTRUCT)mp2;
748
749 // allocate and initialize tooltip data
750 pttd = (PTOOLTIPDATA)malloc(sizeof(TOOLTIPDATA));
751 if (pttd)
752 {
753 CHAR szFont[256];
754 memset(pttd, 0, sizeof(TOOLTIPDATA));
755 WinSetWindowPtr(hwndTooltip, 1, pttd);
756
757 pttd->hwndOwner = pcs->hwndOwner;
758 pttd->hab = WinQueryAnchorBlock(hwndTooltip);
759 pttd->ulTooltipID = pcs->id;
760
761 pttd->fIsActive = TRUE;
762
763 // default timeouts
764 pttd->ulTimeoutInitial = 1000;
765 pttd->ulTimeoutAutopop = 5000;
766 pttd->ulTimeoutReshow = 500;
767
768 // get colors from presparams/syscolors
769 UpdateTooltipPresColors(hwndTooltip, pttd);
770
771 // check if font presparam set
772 if (WinQueryPresParam(hwndTooltip,
773 PP_FONTNAMESIZE, 0,
774 NULL,
775 sizeof(szFont),
776 szFont,
777 QPF_NOINHERIT)
778 == 0)
779 {
780 // no: set default font presparam
781 // (we never want the System Proportional font)
782 winhSetWindowFont(hwndTooltip,
783 NULL); // default (WarpSans or 8.Helv)
784 }
785
786 pttd->pszPaintText = strdup("undefined");
787
788 lstInit(&pttd->llTools, TRUE); // auto-free items
789
790 // override CREATESTRUCT
791 WinSetWindowPos(hwndTooltip,
792 HWND_TOP,
793 50, 50,
794 100, 100,
795 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_HIDE);
796
797 mrc = (MPARAM)FALSE;
798 }
799 else
800 // malloc failed:
801 mrc = (MPARAM)TRUE;
802 break; }
803
804 /*
805 * WM_DESTROY:
806 * clean up upon destruction.
807 */
808
809 case WM_DESTROY:
810 // stop timers
811 if (pttd->ulTimeoutInitial)
812 WinStopTimer(pttd->hab,
813 hwndTooltip,
814 pttd->ulTimeoutInitial);
815 if (pttd->idTimerAutopop)
816 WinStopTimer(pttd->hab,
817 hwndTooltip,
818 pttd->idTimerAutopop);
819 if (pttd->pszPaintText)
820 free(pttd->pszPaintText);
821 lstClear(&pttd->llTools);
822 free(pttd);
823
824 mrc = (MPARAM)0;
825 break;
826
827 /*
828 * WM_HITTEST:
829 * since we have the CS_HITTEST class style set,
830 * we get this message. We return HT_TRANSPARENT
831 * always so the tooltip does not block mouse clicks
832 * for the windows which lie below.
833 */
834
835 case WM_HITTEST: // done
836 mrc = (MPARAM)HT_TRANSPARENT;
837 break;
838
839 /*
840 * WM_TIMER:
841 * posted when either the "initial" timer
842 * or the "autopop" timer times out.
843 * We'll show or hide the tooltip then.
844 */
845
846 case WM_TIMER: // done
847 {
848 USHORT usTimer = SHORT1FROMMP(mp1);
849
850 switch (usTimer)
851 {
852 case TOOLTIP_ID_TIMER_INITIAL:
853 // _Pmpf(("WM_TIMER: Stopping initial timer: %d", usTimer));
854 _Pmpf((__FUNCTION__ ": TOOLTIP_ID_TIMER_INITIAL"));
855 WinStopTimer(pttd->hab,
856 hwndTooltip,
857 usTimer);
858 pttd->idTimerInitial = 0;
859
860 if (pttd->fIsActive)
861 // show tooltip
862 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)TRUE, 0);
863 break;
864
865 case TOOLTIP_ID_TIMER_AUTOPOP:
866 // _Pmpf(("WM_TIMER: Stopping autopop timer: %d", usTimer));
867 WinStopTimer(pttd->hab,
868 hwndTooltip,
869 usTimer);
870 pttd->idTimerAutopop = 0;
871 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)FALSE, 0);
872 break;
873
874 default:
875 mrc = WinDefWindowProc(hwndTooltip, msg, mp1, mp2);
876 } // end switch
877
878 break; }
879
880 /*
881 * WM_PAINT:
882 *
883 */
884
885 case WM_PAINT: // done
886 PaintTooltip(hwndTooltip, pttd);
887 break;
888
889 /*
890 * WM_PRESPARAMCHANGED:
891 * presentation parameter has changed.
892 */
893
894 case WM_PRESPARAMCHANGED:
895 {
896 LONG lPPIndex = (LONG)mp1;
897 switch (lPPIndex)
898 {
899 case 0: // layout palette thing dropped
900 case PP_MENUBACKGROUNDCOLOR:
901 case PP_MENUFOREGROUNDCOLOR:
902 case PP_MENUHILITEFGNDCOLOR:
903 case PP_MENUHILITEBGNDCOLOR:
904 // re-query our presparams
905 UpdateTooltipPresColors(hwndTooltip, pttd);
906 }
907 break; }
908
909 /*
910 * WM_SYSCOLORCHANGE:
911 * system color has changed.
912 */
913
914 case WM_SYSCOLORCHANGE:
915 UpdateTooltipPresColors(hwndTooltip, pttd);
916 break;
917
918 /*
919 *@@ TTM_ACTIVATE:
920 * activates or deactives the tooltip control.
921 *
922 * Parameters:
923 * -- BOOL mp1: if TRUE, activate, if FALSE, deactivate.
924 * -- mp2: always 0.
925 *
926 * Return value: 0 always.
927 */
928
929 case TTM_ACTIVATE: // done
930 pttd->fIsActive = (BOOL)mp1;
931 if (!pttd->fIsActive)
932 // disable: hide tooltip
933 WinPostMsg(hwndTooltip, TTM_SHOWTOOLTIPNOW, (MPARAM)FALSE, 0);
934 break;
935
936 /*
937 *@@ TTM_ADDTOOL:
938 * registers a tool with a tooltip control.
939 *
940 * Parameters:
941 * -- mp1: always 0.
942 * -- PTOOLINFO mp2: information about the tool.
943 *
944 * Return value: TRUE if successful or FALSE otherwise.
945 *
946 * A tooltip control can support any number of tools. To
947 * support a particular tool, you must register the tool
948 * with the tooltip control by sending the TTM_ADDTOOL
949 * message to the tooltip control. The message includes
950 * the address of a TOOLINFO structure, which provides
951 * information the tooltip control needs to display text
952 * for the tool.
953 *
954 * A tooltip control supports tools implemented as windows
955 * (such as child windows or control windows) and as
956 * rectangular areas within a window's client area.
957 *
958 * -- When you add a tool implemented as a rectangular area, the
959 * "hwndToolOwner" member of TOOLINFO must specify the handle
960 * of the window that contains the area, and the "rect" member must
961 * specify the client coordinates of the area's bounding
962 * rectangle. ### not implemented yet
963 *
964 * -- When you add a tool implemented as a window, the "hwndTool"
965 * member of TOOLINFO must contain the window handle of the
966 * tool. hwndToolOwner should be the owner of the tool.
967 *
968 * When you add a tool to a tooltip control, the "pszText"
969 * member of the TOOLINFO structure must specify the string
970 * to display for the tool. You can change the text any time
971 * after adding the tool by using the TTM_UPDATETIPTEXT message.
972 *
973 * If you specify the PSZ_TEXTCALLBACK value in the pszText
974 * member, whenever the tooltip control needs the text for the
975 * tool, it sends a WM_CONTROL message to hwndToolOwner with
976 * the TTN_NEEDTEXT notification code.
977 *
978 * The message includes the address of a TOOLTIPTEXT structure,
979 * which contains the window handle of the tool. You can then
980 * fill the TOOLTIPTEXT structure with the tool text.
981 *
982 * To retrieve the text for a tool, use the TTM_GETTEXT message.
983 */
984
985 case TTM_ADDTOOL: // done
986 mrc = (MPARAM)FALSE;
987 if (mp2)
988 {
989 PTOOLINFO ptiPassed = (PTOOLINFO)mp2,
990 ptiNew = (PTOOLINFO)malloc(sizeof(TOOLINFO));
991 if (ptiNew)
992 {
993 memcpy(ptiNew, ptiPassed, sizeof(TOOLINFO));
994 lstAppendItem(&pttd->llTools,
995 ptiNew);
996
997 if (ptiPassed->ulFlags & TTF_SUBCLASS)
998 SubclassToolForToolinfo(hwndTooltip,
999 ptiPassed->hwndTool);
1000
1001 mrc = (MPARAM)TRUE;
1002 }
1003 }
1004 break;
1005
1006 /*
1007 *@@ TTM_DELTOOL:
1008 * removes a tool from a tooltip control.
1009 *
1010 * Parameters:
1011 * -- mp1: always 0.
1012 * -- PTOOLINFO mp2: information about the tool;
1013 * all fields except cbSize, hwnd, uID are
1014 * ignored.
1015 *
1016 * Return value: 0 always.
1017 */
1018
1019 case TTM_DELTOOL: // done
1020 {
1021 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1022 if (ptiSearch)
1023 {
1024 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1025 while (pToolNode)
1026 {
1027 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1028 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1029 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1030 )
1031 {
1032 // found:
1033 lstRemoveNode(&pttd->llTools, pToolNode);
1034 break;
1035 }
1036 }
1037 pToolNode = pToolNode->pNext;
1038 }
1039 break; }
1040
1041 /*
1042 *@@ TTM_NEWTOOLRECT:
1043 * sets a new bounding rectangle for a tool
1044 * already registered with a tooltip control.
1045 *
1046 * Parameters:
1047 * -- mp1: always 0.
1048 * -- PTOOLINFO mp2: information about the tool;
1049 * all fields except hwnd, uID, and rect
1050 * are ignored.
1051 *
1052 * Return value: 0 always.
1053 *
1054 * If an application includes a tool implemented as a rectangular
1055 * area and the size or position of the control changes, it can
1056 * use the TTM_NEWTOOLRECT message to report the change to the
1057 * tooltip control. An application does not need to report size
1058 * and position changes for a tool implemented as a window.
1059 * Reporting that is not necessary because the tooltip control
1060 * uses the window handle of a tool to determine if the cursor
1061 * is on the tool, not the tool's bounding rectangle.
1062 */
1063
1064 case TTM_NEWTOOLRECT:
1065 break;
1066
1067 /*
1068 *@@ TTM_RELAYEVENT:
1069 * passes a mouse message to a tooltip control
1070 * for further processing.
1071 *
1072 * Parameters:
1073 * -- mp1: always 0.
1074 * -- PQMSG mp2: pointer to a QMSG struct (Win95: MSG struct)
1075 * containing a mouse message. Only the above messages
1076 * are processed.
1077 *
1078 * Return value: 0 always.
1079 *
1080 * A tooltip control needs to receive mouse messages to determine
1081 * when to display the tooltip window. Because mouse messages are
1082 * sent only to the window that contains the cursor, you must
1083 * use the TTM_RELAYEVENT message to relay mouse messages to the
1084 * tooltip control.
1085 *
1086 * If a tool is implemented as a rectangular area in an
1087 * application-defined window, the window procedure receives all
1088 * mouse messages and can relay the ones listed below to the
1089 * tooltip control, using this message.
1090 *
1091 * However, if a tool is implemented as a system-defined window,
1092 * the mouse messages are sent to that window and are not readily
1093 * available to the application. There are two ways you can have
1094 * the tooltip control notified of these mouse messages:
1095 *
1096 * -- You can specify the TTF_SUBCLASS flag when adding the tool
1097 * to the tooltip control. The tooltip control will then subclass
1098 * the tool window to get mouse-related messages, and you're off.
1099 *
1100 * -- You can implement a message hook for your process and check
1101 * for your tool windows there and send TTM_RELAYEVENT to the
1102 * tooltip control. In that case, you need to intercept the
1103 * messages specified below.
1104 *
1105 * When a tooltip control receives a relayed WM_MOUSEMOVE message,
1106 * it determines whether the cursor is in the bounding rectangle of
1107 * a tool. If the cursor is there, the tooltip control sets a timer.
1108 * At the end of the time-out duration, the tooltip control checks
1109 * the position of the cursor to see whether it has moved. If the
1110 * cursor has not, the tooltip control retrieves the text for the tool,
1111 * copies the text into the tooltip window, and shows the window.
1112 * The tooltip control continues to show the window until it receives
1113 * a relayed button-up or button-down message or until a relayed
1114 * WM_MOUSEMOVE message indicates that the cursor has moved outside
1115 * the bounding rectangle of the tool.
1116 *
1117 * For the timer descriptions, see TTM_SETDELAYTIME.
1118 *
1119 * When it is about to be displayed, a tootip control sends the
1120 * TTN_SHOW notification to the owner window. A tooltip control
1121 * sends the TTN_POP notification when it is about to be hidden.
1122 * Each notification is sent in the context of a WM_NOTIFY message
1123 * (OS/2: WM_CONTROL).
1124 *
1125 * Relevant messages:
1126 * -- WM_MOUSEMOVE
1127 * -- WM_BUTTON1DOWN (Win95: WM_LBUTTONDOWN)
1128 * -- WM_BUTTON1UP (Win95: WM_LBUTTONUP)
1129 * -- WM_BUTTON2DOWN (Win95: WM_RBUTTONDOWN)
1130 * -- WM_BUTTON2UP (Win95: WM_RBUTTONUP)
1131 * -- WM_BUTTON3DOWN (Win95: WM_MBUTTONDOWN)
1132 * -- WM_BUTTON3UP (Win95: WM_MBUTTONUP)
1133 */
1134
1135 case TTM_RELAYEVENT:
1136 {
1137 PQMSG pqmsg = (PQMSG)mp2;
1138 if (pqmsg)
1139 {
1140 POINTL ptlPointer;
1141 PLISTNODE pToolNode;
1142
1143 if (pttd->idTimerInitial)
1144 {
1145 // _Pmpf(("TTM_RELAYEVENT: Stopping timer: %d", pttd->idTimerInitial));
1146 WinStopTimer(pttd->hab,
1147 hwndTooltip,
1148 TOOLTIP_ID_TIMER_INITIAL);
1149 pttd->idTimerInitial = 0;
1150 }
1151
1152 WinQueryPointerPos(HWND_DESKTOP, &ptlPointer);
1153
1154 // find TOOLINFO from mouse position
1155 pttd->ptiMouseOver = NULL;
1156 pToolNode = lstQueryFirstNode(&pttd->llTools);
1157 while (pToolNode)
1158 {
1159 PTOOLINFO pti = (PTOOLINFO)pToolNode->pItemData;
1160 if (pti->hwndTool == pqmsg->hwnd)
1161 {
1162 _Pmpf((__FUNCTION__ ": found tool"));
1163 pttd->ptiMouseOver = pti;
1164 break;
1165 }
1166 pToolNode = pToolNode->pNext;
1167 }
1168
1169 if ( (ptlPointer.x != pttd->ptlPointerLast.x)
1170 || (ptlPointer.y != pttd->ptlPointerLast.y)
1171 || (pqmsg->msg == WM_BUTTON1DOWN)
1172 || (pqmsg->msg == WM_BUTTON2DOWN)
1173 || (pqmsg->msg == WM_BUTTON3DOWN)
1174 )
1175 {
1176 // mouse pos changed:
1177 // hide tooltip
1178 WinPostMsg(hwndTooltip,
1179 TTM_SHOWTOOLTIPNOW,
1180 (MPARAM)FALSE,
1181 0);
1182 memcpy(&pttd->ptlPointerLast, &ptlPointer, sizeof(POINTL));
1183
1184 _Pmpf((__FUNCTION__ ": pttd->ptiMouseOver: 0x%lX", pttd->ptiMouseOver));
1185 _Pmpf((__FUNCTION__ ": pttd->fIsActive: 0x%lX", pttd->fIsActive));
1186 if ( (pttd->ptiMouseOver)
1187 && (pttd->fIsActive)
1188 )
1189 {
1190 // tool found and tooltip is activated:
1191 pttd->idTimerInitial = WinStartTimer(pttd->hab,
1192 hwndTooltip,
1193 TOOLTIP_ID_TIMER_INITIAL,
1194 pttd->ulTimeoutInitial);
1195 // _Pmpf(("TTM_RELAYEVENT: Started timer: %d", pttd->idTimerInitial));
1196 }
1197 }
1198 } // end if (pqmsg)
1199 break; }
1200
1201 /*
1202 *@@ TTM_SETDELAYTIME:
1203 * overrides a few default timeout values for the
1204 * tooltip control.
1205 *
1206 * A tooltip control actually has three time-out durations
1207 * associated with it. The initial duration is the length
1208 * of time that the cursor must remain stationary within
1209 * the bounding rectangle of a tool before the tooltip window
1210 * is displayed. The reshow duration is the length of the delay
1211 * before subsequent tooltip windows are displayed when the
1212 * cursor moves from one tool to another. The autopopup duration
1213 * is the length of time that the tooltip window remains
1214 * displayed before it is hidden. That is, if the cursor remains
1215 * stationary within the bounding rectangle after the tooltip
1216 * window is displayed, the tooltip window is automatically
1217 * hidden at the end of the autopopup duration.
1218 *
1219 * You can adjust all of the time-out durations by using this
1220 * message.
1221 *
1222 * Parameters:
1223 * -- USHORT mp1: parameter selection. One of the following:
1224 * -- TTDT_AUTOMATIC: automatically calculates the initial,
1225 * reshow, and autopopup durations based on the value of iDelay.
1226 * -- TTDT_AUTOPOP: sets the length of time before the tooltip
1227 * window is hidden if the cursor remains stationary
1228 * in the tool's bounding rectangle after the tooltip window
1229 * has appeared.
1230 * -- TTDT_INITIAL: sets the length of time that the cursor must
1231 * remain stationary within the bounding rectangle of
1232 * a tool before the tooltip window is displayed.
1233 * -- TTDT_RESHOW: sets the length of the delay before subsequent
1234 * tooltip windows are displayed when the cursor is moved
1235 * from one tool to another.
1236 * -- ULONG mp2: new duration, in milliseconds.
1237 *
1238 * Return value: 0 always.
1239 */
1240
1241 case TTM_SETDELAYTIME: // done
1242 {
1243 ULONG iDelay = (ULONG)mp2;
1244 switch (SHORT1FROMMP(mp1))
1245 {
1246 case TTDT_AUTOMATIC:
1247 pttd->ulTimeoutInitial = iDelay;
1248 pttd->ulTimeoutAutopop = iDelay * 5;
1249 pttd->ulTimeoutReshow = iDelay / 2;
1250 break;
1251
1252 case TTDT_AUTOPOP:
1253 pttd->ulTimeoutAutopop = iDelay;
1254 break;
1255
1256 case TTDT_INITIAL:
1257 pttd->ulTimeoutInitial = iDelay;
1258 break;
1259
1260 case TTDT_RESHOW:
1261 pttd->ulTimeoutReshow = iDelay;
1262 break;
1263 }
1264 break; }
1265
1266 /*
1267 *@@ TTM_GETTEXT:
1268 * retrieves the text for a tool in the tooltip control.
1269 *
1270 * Parameters:
1271 * -- mp1: always 0
1272 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. When sending the
1273 * message, the hwnd and uId members identify a tool. If the tooltip
1274 * control includes the tool, the lpszText member receives the pointer
1275 * to the string.
1276 *
1277 * Return value: 0 always.
1278 *
1279 * Additional note: On input, if TOOLINFO.lpszText == PSZ_TEXTCALLBACK,
1280 * this sends the TTN_NEEDTEXT notification to TOOLINFO.hwnd.
1281 */
1282
1283 case TTM_GETTEXT: // done, I think
1284 {
1285 PTOOLINFO pti = (PTOOLINFO)mp2;
1286
1287 if (pti->pszText == PSZ_TEXTCALLBACK)
1288 {
1289 // TTN_NEEDTEXT notification desired:
1290 // compose values for that msg
1291 TOOLTIPTEXT ttt = {0};
1292 _Pmpf(("TTM_GETTEXT: PSZ_TEXTCALLBACK... sending TTN_NEEDTEXT"));
1293 ttt.hwndTooltip = hwndTooltip;
1294 ttt.hwndTool = pti->hwndTool;
1295 WinSendMsg(pti->hwndToolOwner,
1296 WM_CONTROL,
1297 MPFROM2SHORT(pttd->ulTooltipID, // tooltip control wnd ID
1298 TTN_NEEDTEXT),
1299 &ttt);
1300
1301 // in case of error: set lpszText to NULL; this
1302 // is not specified in the docs however.
1303 pti->pszText = NULL;
1304
1305 switch (ttt.ulFormat)
1306 {
1307 case TTFMT_PSZ:
1308 if (ttt.pszText)
1309 pti->pszText = ttt.pszText;
1310 break;
1311
1312 case TTFMT_STRINGRES:
1313 // ### not supported yet
1314 break;
1315 }
1316 }
1317 break; }
1318
1319 /*
1320 *@@ TTM_UPDATETIPTEXT:
1321 * sets the tooltip text for a tool.
1322 *
1323 * Parameters:
1324 * -- mp1: always 0.
1325 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure. The "hinst"
1326 * and "lpszText" members must specify the instance handle and
1327 * the pointer to the text.
1328 * The "hwnd" and "uId" members identify the tool to update.
1329 */
1330
1331 case TTM_UPDATETIPTEXT:
1332 break;
1333
1334 /*
1335 *@@ TTM_HITTEST:
1336 * tests a point to determine whether it is within the
1337 * bounding rectangle of the specified tool and, if the
1338 * point is within, retrieves information about the tool.
1339 *
1340 * Parameters:
1341 * -- mp1: always 0.
1342 * -- PHITTESTINFO mp2: pointer to a TTHITTESTINFO structure.
1343 * When sending the message, the "hwnd" member must specify
1344 * the handle of a tool and the "pt" member must specify the
1345 * coordinates of a point. If the return value is TRUE, the
1346 * "ti" member receives information about the tool that
1347 * occupies the point.
1348 *
1349 * Return value: returns TRUE if the tool occupies the specified
1350 * point or FALSE otherwise.
1351 */
1352
1353 case TTM_HITTEST:
1354 break;
1355
1356 /*
1357 *@@ TTM_WINDOWFROMPOINT:
1358 * this message allows a subclass procedure to cause a tooltip
1359 * to display text for a window other than the one beneath the
1360 * mouse cursor.
1361 *
1362 * Parameters:
1363 * -- mp1: always 0.
1364 * -- mp2: PPOINTL lppt (Win95: (POINT FAR *)lppt):
1365 * pointer to a POINTL structure that defines the point to be checked.
1366 *
1367 * Return value: the handle to the window that contains the point, or
1368 * NULL if no window exists at the specified point.
1369 *
1370 * This message is intended to be processed by an application that
1371 * subclasses a tooltip. It is not intended to be sent by an
1372 * application. A tooltip sends this message to itself before
1373 * displaying the text for a window. By changing the coordinates
1374 * of the point specified by lppt, the subclass procedure can cause
1375 * the tooltip to display text for a window other than the one
1376 * beneath the mouse cursor.
1377 */
1378
1379 case TTM_WINDOWFROMPOINT:
1380 break;
1381
1382 /*
1383 *@@ TTM_ENUMTOOLS:
1384 * this message retrieves the information that a tooltip control
1385 * maintains about a certain tool.
1386 *
1387 * Parameters:
1388 * -- USHORT mp1: zero-based index of the tool for which to
1389 * retrieve information.
1390 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1391 * receives information about the tool. Before sending
1392 * this message, the cbSize member must specify the size
1393 * of the structure.
1394 *
1395 * Return value: TRUE if any tools are enumerated or FALSE otherwise.
1396 */
1397
1398 case TTM_ENUMTOOLS: // done
1399 {
1400 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1401 mrc = (MPARAM)FALSE;
1402 if (ptiTarget)
1403 {
1404 PTOOLINFO ptiFound = (PTOOLINFO)lstItemFromIndex(&pttd->llTools,
1405 SHORT1FROMMP(mp1));
1406 if (ptiFound)
1407 {
1408 memcpy(ptiTarget, ptiFound, sizeof(TOOLINFO));
1409 mrc = (MRESULT)TRUE;
1410 }
1411 }
1412 break; }
1413
1414 /*
1415 *@@ TTM_GETCURRENTTOOL:
1416 * this message retrieves the information that the tooltip control
1417 * maintains for the _current_ tool; that is, the one for which
1418 * the tooltip control is currently displaying text.
1419 *
1420 * Parameters:
1421 * -- mp1: always 0.
1422 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that receives
1423 * information about the current tool.
1424 *
1425 * Return value: TRUE if successful or FALSE otherwise.
1426 */
1427
1428 case TTM_GETCURRENTTOOL: // done
1429 {
1430 PTOOLINFO ptiTarget = (PTOOLINFO)mp2;
1431 mrc = (MPARAM)FALSE;
1432 if (ptiTarget)
1433 {
1434 if (pttd->ptiMouseOver)
1435 {
1436 memcpy(ptiTarget, pttd->ptiMouseOver, sizeof(TOOLINFO));
1437 mrc = (MPARAM)TRUE;
1438 }
1439 }
1440 break; }
1441
1442 /*
1443 *@@ TTM_GETTOOLCOUNT:
1444 * returns the number of tools in the tooltip control.
1445 *
1446 * No parameters.
1447 */
1448
1449 case TTM_GETTOOLCOUNT: // done
1450 mrc = (MPARAM)lstCountItems(&pttd->llTools);
1451 break;
1452
1453 /*
1454 *@@ TTM_GETTOOLINFO:
1455 * this message retrieves the information that a tooltip
1456 * control maintains about a tool.
1457 *
1458 * Parameters:
1459 * -- mp1: always 0.
1460 * -- PTOOLINFO mp2:
1461 * pointer to a TOOLINFO structure. When sending the message,
1462 * the hwnd and uId members identify a tool, and the cbSize
1463 * member must specify the size of the structure. If the
1464 * tooltip control includes the tool, the structure receives
1465 * information about the tool.
1466 *
1467 * Return value: TRUE if successful or FALSE otherwise.
1468 */
1469
1470 case TTM_GETTOOLINFO: // done
1471 {
1472 PTOOLINFO ptiSearch = (PTOOLINFO)mp2;
1473 mrc = (MPARAM)FALSE;
1474 if (ptiSearch)
1475 {
1476 PLISTNODE pToolNode = lstQueryFirstNode(&pttd->llTools);
1477 while (pToolNode)
1478 {
1479 PTOOLINFO ptiThis = (PTOOLINFO)pToolNode->pItemData;
1480 if ( (ptiThis->hwndToolOwner == ptiSearch->hwndToolOwner)
1481 && (ptiThis->hwndTool == ptiSearch->hwndTool)
1482 )
1483 {
1484 // found:
1485 memcpy(ptiSearch, ptiThis, sizeof(TOOLINFO));
1486 mrc = (MPARAM)TRUE;
1487 break;
1488 }
1489 pToolNode = pToolNode->pNext;
1490 }
1491 }
1492 break; }
1493
1494 /*
1495 *@@ TTM_SETTOOLINFO:
1496 * this message sets the information that a tooltip control
1497 * maintains for a tool.
1498 *
1499 * Parameters:
1500 * -- mp1: always 0.
1501 * -- PTOOLINFO mp2: pointer to a TOOLINFO structure that
1502 * specifies the information to set.
1503 *
1504 * Return value: 0 always.
1505 */
1506
1507 case TTM_SETTOOLINFO:
1508 break;
1509
1510 /*
1511 *@@ TTM_SHOWTOOLTIPNOW:
1512 * depending on BOOL mp1, shows or hides the tooltip.
1513 * This is required because we cannot show or hide
1514 * the window during processing of WM_MOUSEMOVE etc,
1515 * which will lead to strange PM hangs.
1516 *
1517 * This is not part of the Win95 message set but used
1518 * in the OS/2 implementation only. This calls TtmShowTooltip
1519 * in turn.
1520 */
1521
1522 case TTM_SHOWTOOLTIPNOW:
1523 _Pmpf((__FUNCTION__ ": TTM_SHOWTOOLTIPNOW %d", mp1));
1524 TtmShowTooltip(hwndTooltip, pttd, (BOOL)mp1);
1525 break;
1526
1527 default:
1528 mrc = WinDefWindowProc(hwndTooltip, msg, mp1, mp2);
1529 }
1530 }
1531 CATCH(excpt1) {} END_CATCH();
1532
1533 return (mrc);
1534}
1535
1536
Note: See TracBrowser for help on using the repository browser.