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

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

Misc fixes.

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