home *** CD-ROM | disk | FTP | other *** search
/ Softwarová Záchrana 3 / Softwarova-zachrana-3.bin / ArsClip / source.zip / UnitMyPopup.pas < prev    next >
Pascal/Delphi Source File  |  2004-02-02  |  6KB  |  233 lines

  1. unit UnitMyPopup;
  2.  
  3. {
  4.     Purpose:
  5.         Show a tooltip when the mouse hovers a menu item
  6.  
  7.     NOTES:
  8.         Horrible, nasty, complicated, and no frikin fun to make
  9.  
  10.  
  11.     Updates:
  12.         Detect complex items
  13.         -----------
  14.  
  15.         Separated Tooltip into a generic class for use elsewhere
  16.         Updated TTooltipWindow for displaying Unicode
  17. }
  18.  
  19.  
  20. interface
  21.  
  22. uses Windows, CommCtrl, Messages, Controls, Classes, Menus, Forms,
  23.     UnitClipQueue,  ExtCtrls {TTimer}, UnitTWideChar, UnitFrmDummyUnicodeTooltip;
  24.  
  25. type TSubClasser = class(TObject)
  26.     private
  27.         FNewProc, FDefProc: Pointer;
  28.         h : HWND;
  29.     public
  30.         procedure SubclassHook(WinHandle : THandle; WndProc : TWndMethod);
  31.         procedure SubclassUnhook;
  32.         function GetOldWndProc : Pointer;
  33. end;
  34.  
  35.  
  36.  
  37. type TMyPopupMenu = class(TPopupMenu)
  38.     private
  39.         LastHint : string;
  40.  
  41.         tim : TTimer;
  42.         LastCursorPos : TPoint;
  43.         PopupX, PopupY : integer;
  44.         r : TRect;
  45.  
  46.         TooltipWindow : TTooltipWindow;
  47.         Sub : TSubClasser;
  48.         function GetPopupHint(h: HMENU; Menuflag : integer): string;
  49.         procedure MyOnTimer(Sender: TObject);
  50.     public
  51.         constructor Create(AOwner : TComponent); override;
  52.         destructor Destroy; override;
  53.         procedure Popup(X, Y: Integer); override;
  54.         procedure WndProc(var Msg: TMessage);
  55.  
  56. end;
  57.  
  58.  
  59. {////////////////////}
  60. {//}implementation{//}
  61. {////////////////////}
  62. uses Dialogs, SysUtils, StrUtils, UnitFrmMainPopup, Graphics{for color}, UnitMisc,
  63.   Types, UnitFrmPermanentNew, UnitFrmClipboardManager;
  64.  
  65.  
  66. { TSubClasser }
  67.  
  68. function TSubClasser.GetOldWndProc: Pointer;
  69. begin
  70.     result := FDefProc;
  71. end;
  72.  
  73. procedure TSubClasser.SubclassHook(WinHandle : THandle; WndProc : TWndMethod);
  74. begin
  75.     Windows.SetLastError(ERROR_SUCCESS);
  76.  
  77.     self.h := WinHandle;
  78.  
  79.     FNewProc := Classes.MakeObjectInstance(WndProc);
  80.     FDefProc := Pointer(Windows.SetWindowLong(h, GWL_WNDPROC, LongInt(FNewProc)));
  81. end;
  82.  
  83. procedure TSubClasser.SubclassUnhook;
  84. begin
  85.     Windows.SetLastError(ERROR_SUCCESS);
  86.  
  87.     if (h <> 0) then begin
  88.         Windows.SetWindowLong(h, GWL_WNDPROC, LongInt(FDefProc));
  89.         Classes.FreeObjectInstance(FNewProc);
  90.         FNewProc := nil
  91.     end;
  92. end;
  93.  
  94.  
  95. { TMyPopupMenu }
  96.  
  97. constructor TMyPopupMenu.Create(AOwner: TComponent);
  98. begin
  99.     inherited Create(AOwner);
  100.     sub := TSubClasser.Create;
  101.     sub.SubclassHook(Menus.PopupList.Window, WndProc);
  102.  
  103.  
  104.     TooltipWindow := TTooltipWindow.Create;
  105.     tim := TTimer.Create(self);
  106.     tim.OnTimer := MyOnTimer;
  107.     tim.Enabled := false;
  108.     tim.Interval := Application.HintPause;
  109. end;
  110.  
  111. destructor TMyPopupMenu.Destroy;
  112. begin
  113.     sub.SubclassUnhook;
  114.     MyFree(sub);
  115.     MyFree(TooltipWindow);
  116.     MyFree(tim);
  117.  
  118.     inherited Destroy;
  119. end;
  120.  
  121.  
  122.  
  123.  
  124. procedure TMyPopupMenu.MyOnTimer(Sender: TObject);
  125. var CursorPos : TPoint;
  126.     ci : TClipItem;
  127. begin
  128.  
  129.     Windows.GetCursorPos(CursorPos);
  130.     if (Abs(CursorPos.X - self.LastCursorPos.X) > 10) or
  131.         (Abs(CursorPos.Y - self.LastCursorPos.Y) > 10) then begin
  132.         LastHint := '';
  133.         EXIT;
  134.     end;
  135.     inc(CursorPos.x, 10);
  136.     inc(cursorPos.y, 20);
  137.  
  138.     if (FrmPermanent.IsComplexItem(LastHint)) then begin
  139.         ci := FrmPermanent.GetComplexItem(LastHint);
  140.         if (ci.GetFormat = Windows.CF_UNICODETEXT) then begin
  141.             TooltipWindow.ShowTooltip(ci, CursorPos);
  142.         end else begin
  143.             TooltipWindow.ShowTooltip('[Clip format: ' + ci.GetFormatName + ']',
  144.                 CursorPos);
  145.         end;
  146.  
  147.         MyFree(ci);
  148.     end else begin
  149.         TooltipWindow.ShowTooltip(LastHint, CursorPos);
  150.     end;
  151.     LastHint := '';
  152. end;
  153.  
  154. procedure TMyPopupMenu.Popup(X, Y: Integer);
  155. begin
  156.     PopupX := x;
  157.     PopupY := y;
  158.  
  159.     inherited Popup(x,y);
  160.  
  161.     LastHint := '';
  162. end;
  163.  
  164.  
  165.  
  166.  
  167. procedure TMyPopupMenu.WndProc(var Msg: TMessage);
  168. var s : string;
  169.     h : word;
  170. begin
  171.     Windows.SetLastError(ERROR_SUCCESS);
  172.  
  173.     //
  174.     // Save info about the newly selected item,
  175.     // Start the timer when the mouse idles on an item
  176.     // Don't break the message chain.
  177.     //
  178.     try
  179.         case Msg.msg of
  180.         WM_MENUSELECT: begin
  181.             TooltipWindow.CloseTooltip;
  182.             tim.Enabled := false;
  183.             LastHint := '';
  184.  
  185.  
  186.             h := TWMMENUSELECT(msg).IDItem;
  187.             // this stops the "all items" sub from displaying a tooltip
  188.             if (TWMMENUSELECT(msg).MenuFlag and MF_POPUP) = 0 then begin
  189.                 s := self.GetPopupHint(h, TWMMENUSELECT(msg).MenuFlag);
  190.             end;
  191.  
  192.             if s <> '' then LastHint := s;
  193.         end;
  194.         WM_ENTERIDLE: begin
  195.             tim.Enabled := true;
  196.             Windows.GetCursorPos(LastCursorPos);
  197.         end;
  198.         WM_NCPAINT: begin
  199.             Windows.GetRgnBox(TWMNCPAINT(msg).RGN, self.r);
  200.         end;
  201.         end;
  202.         msg.Result := Windows.CallWindowProc(sub.GetOldWndProc, self.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
  203.     except
  204.         Application.HandleException(Self);
  205.     end;
  206. end;
  207.  
  208. function TMyPopupMenu.GetPopupHint(h: HMENU; Menuflag : integer): string;
  209. var m : TMenuItem;
  210. begin
  211.     result := '';
  212.  
  213.     // A menu with a subitem would find the wrong item if this
  214.     // wasn't done
  215.  
  216.     if ((MenuFlag and MF_POPUP) <> 0) then begin
  217.         m := self.FindItem(h, fkHandle);
  218.     end else begin
  219.         m := self.FindItem(h, fkCommand);
  220.     end;
  221.  
  222.     if (m <> nil) then begin
  223.         result := m.Hint;
  224.     end;
  225. end;
  226.  
  227.  
  228.  
  229.  
  230.  
  231. end.
  232.  
  233.