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

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

Initial checkin of helpers code which used to be in WarpIN.

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