home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwphescr.zip / XWPH0208.ZIP / src / helpers / cctl_tooltip.c < prev    next >
C/C++ Source or Header  |  2002-08-08  |  70KB  |  1,967 lines

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