home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / toolti.zip / TOOLTIP.CPP < prev    next >
C/C++ Source or Header  |  1994-11-21  |  9KB  |  451 lines

  1. // =========================================================
  2. // TOOLTIP.CPP
  3. //
  4. // Tooltip classes for OWL 2
  5. //
  6. // Author:  Steve Saxon (Compuserve: 100321,2355)
  7. // Written: 26th June 1994
  8. // =========================================================
  9.  
  10. #include <owl\owlpch.h>
  11. #pragma hdrstop
  12.  
  13. #include "tooltip.h"
  14.  
  15. #define TIP_DELAY_FIRST    600
  16. #define TIP_DELAY_AFTER    150
  17.  
  18. #define ID_TIMER    1000
  19.  
  20. static BOOL     bEnableHints = FALSE;    // prevents menus displaying hints!!
  21.  
  22. static TToolTip *ptTooltip;                // pointer used by KbdProc
  23. static HHOOK    hookKbd;                // hookchain used by KbdProc
  24.  
  25. LRESULT CALLBACK KbdProc (int code, WPARAM wParam, LPARAM lParam);
  26.  
  27. DEFINE_RESPONSE_TABLE1 (TToolTip, TWindow)
  28.   EV_WM_TIMER,
  29. END_RESPONSE_TABLE;
  30.  
  31. // ================================================================ //
  32.  
  33. TToolTipFont::TToolTipFont () : TFont ("MS Sans Serif", -9)
  34. {
  35. }
  36.  
  37. // ================================================================ //
  38.  
  39. TToolTip::TToolTip (Tip::Style _style, TFont* _font) : TWindow (NULL, "")
  40. {
  41.     style            = _style;
  42.     font            = _font;
  43.  
  44.     Attr.Style         = WS_POPUP;
  45.     Attr.ExStyle     = WS_EX_TOPMOST;
  46.  
  47.     uiTimer            = NULL;
  48.     bEnabled        = TRUE;
  49.  
  50. #ifdef __WIN32__
  51.     ::hookKbd        = SetWindowsHookEx (WH_KEYBOARD, KbdProc, NULL, GetCurrentThreadId ());
  52. #else
  53.     ::hookKbd        = SetWindowsHookEx (WH_KEYBOARD, KbdProc, GetApplication ()->GetInstance (), GetCurrentTask ());
  54. #endif
  55.  
  56.     ::ptTooltip        = this;
  57.  
  58.     Create ();
  59. }
  60.  
  61. TToolTip::~TToolTip ()
  62. {
  63.     KillTipTimer ();
  64.  
  65.     UnhookWindowsHookEx (hookKbd);
  66.  
  67.     delete font;
  68. }
  69.  
  70. void TToolTip::GetWindowClass (WNDCLASS &wc)
  71. {
  72.     TWindow::GetWindowClass (wc);
  73.  
  74.     // no background brush
  75.     wc.hbrBackground = NULL;
  76.  
  77.     wc.style |= CS_SAVEBITS;
  78. }
  79.  
  80. LPSTR TToolTip::GetClassName ()
  81. {
  82.     return "Steve:Tooltip";
  83. }
  84.  
  85. void TToolTip::Paint (TDC &dc, BOOL, TRect &)
  86. {
  87.     char    szText[50];
  88.     TRect    client;
  89.  
  90.     // get the tooltip text
  91.     GetWindowText (szText, sizeof (szText));
  92.     GetClientRect (client);
  93.  
  94.     if (style & Tip::Shadow)
  95.     {
  96.         TMemoryDC    dcMem (dc);
  97.         TBitmap    bmp (client.right, client.bottom);
  98.  
  99.         client.right    -= 2;
  100.         client.bottom    -= 2;
  101.         
  102.         {
  103.             BYTE        byData[] = { 0x55, 0, 0xAA, 0, 0x55, 0, 0xAA, 0, 0x55, 0, 0xAA, 0, 0x55, 0, 0xAA, 0 };
  104.             TBitmap        bm (8, 8, 1, 1, byData);
  105.             TBrush        brush (bm);
  106.  
  107.             dcMem.SelectObject (bmp);
  108.  
  109.             dcMem.FillRect (client, (HBRUSH) GetStockObject (WHITE_BRUSH));
  110.  
  111.             dcMem.SelectObject (brush);
  112.             dcMem.SelectStockObject (NULL_PEN);
  113.             dcMem.SetTextColor (TColor::Black);
  114.             dcMem.SetBkColor (TColor::White);
  115.  
  116.             if (style & Tip::RoundedBorder)
  117.             {
  118.                 int rad = client.Height () / 2;
  119.  
  120.                 dcMem.RoundRect (client, TPoint (rad, rad));
  121.             }
  122.             else
  123.             {
  124.                 dcMem.Rectangle (client);
  125.             }
  126.         }
  127.  
  128.         TRect    rcTemp = client.OffsetBy (2, 2);
  129.  
  130.         dc.SetTextColor (RGB (128, 128, 128));
  131.         dc.BitBlt (rcTemp, dcMem, TPoint (0, 0), SRCAND);
  132.  
  133.         client.right    -= 2;
  134.         client.bottom    -= 2;
  135.     }
  136.  
  137.     TPen    pen (GetSysColor (COLOR_WINDOWFRAME));
  138.     TBrush    brush (RGB (255, 255, 128));
  139.  
  140.     dc.SelectObject (pen);
  141.     dc.SelectObject (brush);
  142.  
  143.     if (style & Tip::RoundedBorder)
  144.     {
  145.         int rad = client.Height () / 2;
  146.  
  147.         dc.RoundRect (client, TPoint (rad, rad));
  148.     }
  149.     else
  150.     {
  151.         dc.Rectangle (client);
  152.     }
  153.  
  154.     // set up the device context
  155.     dc.SetBkMode (TRANSPARENT);
  156.     dc.SelectObject (*font);
  157.  
  158.     // draw the text
  159.     dc.SetTextColor (TColor::Black);
  160.     dc.DrawText (szText, -1, client, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
  161. }
  162.  
  163. void TToolTip::SetCaption (const char far* title)
  164. {
  165.     static DWORD dwTickCount = 0;
  166.  
  167.     TWindow::SetCaption (title);
  168.  
  169.     // if the caption is missing, hide the tip window
  170.     if (title == NULL || !*title || !bEnabled)
  171.     {
  172.         KillTipTimer ();
  173.  
  174.         Show (SW_HIDE);
  175.  
  176.         dwTickCount = GetTickCount ();
  177.     }
  178.     else
  179.     {
  180.         DWORD dwTickNew = GetTickCount ();
  181.  
  182.         // work out the extent of the text
  183.         {
  184.             TClientDC    dc (HWindow);
  185.  
  186.             dc.SelectObject (*font);
  187.             sizeText = dc.GetTextExtent (title, lstrlen (title));
  188.  
  189.             sizeText.cx    += 5;
  190.             sizeText.cy    += 4;
  191.  
  192.             Show (SW_HIDE);
  193.         }
  194.  
  195.         // create the timer - this will send a WM_TIMER message
  196.         // after 'TIP_DELAY_xxxx' milliseconds
  197.  
  198.         if (dwTickNew - dwTickCount > 0)
  199.         {
  200.             uiTimer = SetTimer (ID_TIMER, TIP_DELAY_FIRST);
  201.         }
  202.         else
  203.         {
  204.             uiTimer = SetTimer (ID_TIMER, TIP_DELAY_AFTER);
  205.         }
  206.  
  207.         dwTickCount = 0;
  208.     }
  209. }
  210.  
  211. void TToolTip::PositionTip ()
  212. {
  213.     // position the tip relative to the mouse
  214.     TPoint    ptMouse;
  215.     TSize    scr (GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN));
  216.  
  217.     GetCursorPos (ptMouse);
  218.  
  219.     ptMouse.x    -= 2;
  220.     ptMouse.y    += 22;
  221.  
  222.     TRect    rc (ptMouse, sizeText);
  223.  
  224.     if (style & Tip::RoundedBorder)
  225.     {
  226.         rc = rc.InflatedBy (1, 1);
  227.     }
  228.  
  229.     // check x screen position
  230.     if (rc.left < 0)
  231.     {
  232.         rc.Offset (-rc.left + 2, 0);
  233.     }
  234.     else
  235.     {
  236.         if (rc.right > scr.cx)
  237.         {
  238.             rc.Offset (scr.cx - rc.right - 2, 0);
  239.         }
  240.     }
  241.  
  242.     // check y screen position
  243.     if (rc.bottom > scr.cy)
  244.     {
  245.         rc.Offset (0, -42);
  246.     }
  247.  
  248.     if (style & Tip::Shadow)
  249.     {
  250.         rc.right    += 4;
  251.         rc.bottom    += 4;
  252.     }
  253.  
  254.     SetWindowPos (NULL, rc, SWP_NOZORDER | SWP_NOACTIVATE);
  255. }
  256.  
  257. void TToolTip::KillTipTimer ()
  258. {
  259.     // destroy the timer
  260.     if (uiTimer)
  261.     {
  262.         KillTimer (ID_TIMER);
  263.         uiTimer = NULL;
  264.     }
  265. }
  266.  
  267. void TToolTip::ShowNow ()
  268. {
  269.     // position the tip window
  270.     PositionTip ();
  271.  
  272.     // show the tip window
  273.     Show (SW_SHOWNA);
  274.     UpdateWindow ();
  275. }
  276.  
  277. void TToolTip::EvTimer (UINT)
  278. {
  279.     // timer message received - show the tip window!
  280.     if (uiTimer)
  281.     {
  282.         KillTipTimer ();    // prevent further timer messages
  283.  
  284.         ShowNow ();
  285.     }
  286. }
  287.  
  288. // ================================================================ //
  289. // override class for control bar
  290. // ================================================================ //
  291.  
  292. DEFINE_RESPONSE_TABLE1 (TTipControlBar, TControlBar)
  293.   EV_WM_MOUSEMOVE,
  294.   EV_WM_LBUTTONDOWN,
  295. END_RESPONSE_TABLE;
  296.  
  297. TTipControlBar::TTipControlBar (TToolTip& tip, TWindow* parent, TTileDirection direction, TFont* font, TModule* module)
  298.      :     TControlBar (parent, direction, font, module),
  299.         tooltip (tip)
  300. {
  301.     SetHintMode(TGadgetWindow::EnterHints);
  302. }
  303.  
  304. void TTipControlBar::EvMouseMove (UINT modKeys, TPoint& point)
  305. {
  306.     if (!Capture && !GadgetFromPoint (point))
  307.     {
  308.         // hide the tip window if not over a gadget
  309.         tooltip.HideTip ();
  310.     }
  311.  
  312.     bEnableHints = TRUE;
  313.  
  314.     TControlBar::EvMouseMove (modKeys, point);
  315.  
  316.     bEnableHints = FALSE;
  317. }
  318.  
  319. void TTipControlBar::EvLButtonDown (UINT modKeys, TPoint& point)
  320. {
  321.     // hide the tip window if mouse-button pressed
  322.     tooltip.HideTip ();
  323.  
  324.     TControlBar::EvLButtonDown (modKeys, point);
  325. }
  326.  
  327. // ================================================================ //
  328. // override class for status bar
  329. // ================================================================ //
  330.  
  331. DEFINE_RESPONSE_TABLE1 (TTipStatusBar, TStatusBar)
  332.   EV_WM_MOUSEMOVE,
  333.   EV_WM_LBUTTONDOWN,
  334. END_RESPONSE_TABLE;
  335.  
  336. TTipStatusBar::TTipStatusBar (TToolTip& tip, TWindow* parent, TGadget::TBorderStyle borderStyle, UINT modeIndicators, TFont *font, TModule* module)
  337.     :     TStatusBar (parent, borderStyle, modeIndicators, font, module),
  338.         tooltip (tip)
  339. {
  340.       bShowTips = FALSE;
  341. }
  342.  
  343. void TTipStatusBar::SetHintText (const char *lpszText)
  344. {
  345.     // when hint message displayed on the status bar,
  346.     // pick out the tooltip text and display it (with delay)
  347.  
  348.     if (lpszText != NULL)
  349.     {
  350.         static char    buf[128];
  351.  
  352.         lstrcpy (buf, lpszText);
  353.  
  354.         // locate the tooltip text
  355.         for (int n = 0; buf[n] && buf[n] != '\n'; n++) ;
  356.  
  357.         if (buf[n])
  358.         {
  359.             buf[n++] = '\0';
  360.         }
  361.  
  362.         // only display hints from gadgets (not menus!)
  363.         if (bEnableHints)
  364.         {
  365.             tooltip.SetCaption (buf + n);
  366.         }
  367.  
  368.         if (bShowTips)
  369.         {
  370.             SetTextEx (buf);
  371.         }
  372.         else
  373.         {
  374.             TStatusBar::SetHintText (buf);
  375.         }
  376.     }
  377.     else
  378.     {
  379.         tooltip.SetCaption (NULL);
  380.  
  381.         if (bShowTips)
  382.         {
  383.             SetTextEx (NULL);
  384.         }
  385.         else
  386.         {
  387.             TStatusBar::SetHintText (NULL);
  388.         }
  389.     }
  390. }
  391.  
  392. void TTipStatusBar::EvMouseMove (UINT modKeys, TPoint& point)
  393. {
  394.     if (bShowTips)
  395.     {
  396.         if (!Capture && !GadgetFromPoint (point))
  397.         {
  398.             // hide the tip window if not over a gadget
  399.             tooltip.HideTip ();
  400.         }
  401.  
  402.         bEnableHints = TRUE;
  403.  
  404.         TStatusBar::EvMouseMove (modKeys, point);
  405.  
  406.         bEnableHints = FALSE;
  407.     }
  408.     else
  409.     {
  410.         TStatusBar::EvMouseMove (modKeys, point);
  411.     }
  412. }
  413.  
  414. void TTipStatusBar::EvLButtonDown (UINT modKeys, TPoint& point)
  415. {
  416.     if (bShowTips)
  417.     {
  418.         // hide the tip window if mouse-button pressed
  419.         tooltip.HideTip ();
  420.     }
  421.  
  422.     TStatusBar::EvLButtonDown (modKeys, point);
  423. }
  424.  
  425. void TTipStatusBar::UseTips ()
  426. {
  427.     bShowTips = TRUE;
  428.  
  429.     Margins.Units = TMargins::BorderUnits;
  430.  
  431.     if (Direction == Horizontal)
  432.     {
  433.         Margins.Left = Margins.Right = 6;
  434.         Margins.Top = Margins.Bottom = 2;
  435.     }
  436. }
  437.  
  438. // =========================================================
  439.  
  440. LRESULT CALLBACK KbdProc (int code, WPARAM wParam, LPARAM lParam)
  441. {
  442.     if (code >= 0)
  443.     {
  444.         ptTooltip->HideTip ();
  445.     }
  446.  
  447.     return CallNextHookEx (hookKbd, code, wParam, lParam);
  448. }
  449.  
  450.  
  451.