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

Last change on this file since 69 was 68, checked in by umoeller, 24 years ago

Lotsa fixes from the last two weeks.

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