home *** CD-ROM | disk | FTP | other *** search
/ Softwarová Záchrana 3 / Softwarova-zachrana-3.bin / ArsClip / source.zip / UnitfrmDummyUnicodePopup.pas < prev    next >
Pascal/Delphi Source File  |  2004-10-16  |  22KB  |  725 lines

  1. unit UnitFrmDummyUnicodePopup;
  2. {
  3.     Purpose:
  4.         Wrap all the logic needed to to create a low level API popup
  5.         menu that has Unicode text and gather the data needed
  6.         to show a Unicode Tooltip hint (see FrmDummyUnicodeTooltip
  7.  
  8.     Updates:
  9.  
  10.         Code completely re-written and simplified - FrmMainPopup's popup
  11.         menu it traversed and duplicated instead of creating is from scratch
  12.         
  13.         -------------
  14.  
  15.         Show tooltip for "All Items..." hover
  16.         ------------------------
  17.         "All Items..." support
  18.         ------------------------
  19.  
  20.         "Number of characters to show for each item" required a restart to
  21.         work with the unicode popup
  22.  
  23.         ----------------------
  24.         Let Permanent Items grow as large as they want
  25.         "Beep" on accelerator key
  26.  
  27. }
  28.  
  29. interface
  30.  
  31. uses
  32.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  33.   Dialogs, ExtCtrls, StrUtils, INIFIles, Math, Menus,
  34.  
  35.   UnitClipQueue, UnitFrmMainPopup, UnitTWideChar, UnitMisc,
  36.   UnitOtherQueue, UnitKeyboardQuery, UnitFrmDummyUnicodeTooltip, Contnrs,
  37.   StdCtrls;
  38.  
  39. type
  40.   TFrmDummyUnicodePopup = class(TForm)
  41.     tim: TTimer;
  42.     Label1: TLabel;
  43.     procedure timTimer(Sender: TObject);
  44.     procedure FormCreate(Sender: TObject);
  45.     procedure FormDestroy(Sender: TObject);
  46.   private
  47.     { Private declarations }
  48.     LastCursorPos : TPoint;
  49.     LastHint : string;
  50.     LastClipItem : TClipItem;
  51.     CurrentClipboard : TClipItem;
  52.     KeyToItemID : THashedStringList;
  53.     VisibleCharCount : integer;
  54.     Tooltip : TTooltipWindow;
  55.     TimeFiring : boolean;
  56.  
  57.     SubMenuItemList : THashedStringList;
  58.     SubObjectList : TObjectList;
  59.     mi : TMenuITem;
  60.     
  61.     function ItemIDToMenuItem(itemID : integer) : TMenuItem;
  62.   public
  63.     { Public declarations }
  64.  
  65.     procedure PopulatePopupUnicode(var M : TMenuItem; parent : HMENU);
  66.     procedure ShowPopup(x,y : integer; inpopup : TPopupMenu);
  67.  
  68.     procedure WMDrawItem(var Msg: TWMDrawItem); message WM_DRAWITEM;
  69.     procedure WMMeasureItem(var Msg: TWMMeasureItem); message WM_MEASUREITEM;
  70.     procedure WMCommand(var Msg : TWMCommand); message WM_COMMAND;
  71.     procedure WMMenuChar(var Msg : TWMMenuChar); message WM_MENUCHAR;
  72.     procedure WMMenuSelect(var Msg : TWMMenuSelect); message WM_MENUSELECT;
  73.     procedure WMEnterIdle(var Msg : TWMEnterIdle); message WM_ENTERIDLE;
  74.   end;
  75.  
  76. var
  77.   FrmDummyUnicodePopup: TFrmDummyUnicodePopup;
  78. {////////////////////}
  79. {//}implementation{//}
  80. {////////////////////}
  81. {$R *.dfm}
  82.  
  83.  
  84. uses UnitFrmPermanentNew, UnitFrmConfig, UnitFrmSysTrayMenu, UnitPaste;
  85. const PU_LAST_TEXT = 'Las&t: ';
  86.       PU_CURRENT_TEXT = 'Cu&rrent: ';
  87.  
  88.  
  89. procedure TFrmDummyUnicodePopup.FormCreate(Sender: TObject);
  90. begin
  91.     KeyToItemID := THashedStringList.Create;
  92.     CurrentClipboard := TClipItem.Create;
  93.     LastClipItem := TClipItem.Create;
  94.     //Popup := TPopupMenu.Create(self);
  95.     Tooltip := TTooltipWindow.Create;
  96.  
  97.  
  98.     self.SubMenuItemList := THashedStringList.Create;
  99.     SubObjectList := TObjectList.Create;
  100.     SubObjectList.OwnsObjects := false;
  101.  
  102.     mi := TMenuItem.Create(self);
  103. end;
  104.  
  105. procedure TFrmDummyUnicodePopup.FormDestroy(Sender: TObject);
  106. begin
  107.  
  108.     SubMenuItemList.Free;
  109.     SubObjectList.Free;
  110.     
  111.     mi.Free;
  112. end;
  113.  
  114.  
  115. procedure TFrmDummyUnicodePopup.ShowPopup(x, y: integer;  inpopup: TPopupMenu);
  116. var p : HMENU;
  117.     m : TMenuItem;
  118. begin
  119.     Windows.SetLastError(ERROR_SUCCESS);
  120.     self.VisibleCharCount := FrmConfig.udCharacters.Position;
  121.  
  122.  
  123.     // add new items
  124.     p := Windows.CreatePopupMenu;
  125.     m := inpopup.items;
  126.     self.PopulatePopupUnicode(m, p);
  127.     self.CurrentClipboard.GetClipboardItem(0);
  128.  
  129.     // show it
  130.     Windows.TrackPopupMenu(p,
  131.         TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_LEFTALIGN,
  132.         x, y, 0,
  133.         self.Handle, nil);
  134.  
  135.     Windows.DrawMenuBar(p);
  136.     // clean up
  137.     while Windows.GetMenuItemCount(p) > 0 do begin
  138.         Windows.DeleteMenu(p,0, MF_BYPOSITION);
  139.     end;
  140.  
  141. end;
  142.  
  143. // Call Order
  144. //--------------
  145. // Populate -> Measure Item -> Draw Item
  146. // Some user event trigers
  147. // (MenuSelect, EnterIdle, Command)
  148.  
  149. procedure TFrmDummyUnicodePopup.PopulatePopupUnicode(var M : TMenuItem; parent : HMENU);
  150.     procedure TraverseMenuItems(var m : TMenuItem; parent : HMENU; level : integer = 0) ;
  151.     var i : integer;
  152.         menu : HMENU;
  153.         m2 : TMenuItem;
  154.         s : string;
  155.     begin
  156.         if (m.count = 0) then begin
  157.             if (m.IsLine) then begin
  158.                 Windows.AppendMenu(parent, MF_SEPARATOR, 0, nil);
  159.             end else begin
  160.                 i := SubObjectList.Add(m);
  161.                 if (m.Checked) then begin
  162.                     case m.Tag of
  163.                     Integer(PASTE_CTRL_V):    s := '&1 CTRL+V';
  164.                     Integer(PASTE_SHIFT_INS): s := '&2 SHIFT+INS';
  165.                     Integer(PASTE_MIMIC):     s := '&3 Mimic Typing';
  166.                     Integer(PASTE_CLIPBOARD): s := '&4 Clipboard Only';
  167.                     Integer(PASTE_DEFAULT):   s := '&5 Default';
  168.                     end;
  169.  
  170.                     Windows.AppendMenu(parent,
  171.                         MF_ENABLED or MF_BYCOMMAND or MF_CHECKED,
  172.                         i, PChar(s));
  173.                 end else begin
  174.                     Windows.AppendMenu(parent, MF_OWNERDRAW, i, nil);
  175.                 end;
  176.             end;
  177.         end else begin
  178.             if (level <> 0) then begin
  179.                 menu := Windows.CreatePopupMenu;
  180.             end;
  181.             for i := 0 to (m.Count - 1) do begin
  182.                 m2 := m.Items[i];
  183.                 if (level <> 0) then begin
  184.                     TraverseMenuItems(m2, menu, level + 1);
  185.                 end else begin
  186.                     TraverseMenuItems(m2, parent, level + 1);
  187.                 end;
  188.             end;
  189.             if (level <> 0) then begin
  190.                 i := SubObjectList.Add(m);
  191.                 SubMenuItemList.Values[IntToStr(menu)] := IntToStr(i);
  192.                 Windows.AppendMenu(parent, MF_OWNERDRAW or MF_POPUP, menu, nil);
  193.             end;
  194.         end;
  195.     end;
  196. begin
  197.     SubObjectList.Clear;
  198.     SubMenuItemList.clear;
  199.     TraverseMenuItems(m, parent, 0);
  200. end;
  201.  
  202.  
  203. {
  204. //
  205. // These 2 messages are just do draw the damn popu
  206. //
  207. }
  208.  
  209. procedure TFrmDummyUnicodePopup.WMMeasureItem(var Msg: TWMMeasureItem);
  210. var id : Cardinal;
  211.     s : string;
  212.     sz : TSize;
  213.     procedure GetTextSizeOf( s : string );
  214.     begin
  215.         Windows.GetTextExtentPoint32(self.Canvas.Handle, PChar(s),
  216.         min(length(s), VisibleCharCount),
  217.         sz);
  218.         msg.MeasureItemStruct^.itemWidth := max(sz.cx + loword(GetMenuCheckMarkDimensions),20);
  219.         msg.MeasureItemStruct^.itemHeight := max(sz.cy+2, 6);
  220.     end;
  221.     procedure GetTextSizeOfNoLimit( s : string );
  222.     begin
  223.         Windows.GetTextExtentPoint32(self.Canvas.Handle, PChar(s),
  224.         length(s),
  225.         sz);
  226.         msg.MeasureItemStruct^.itemWidth := max(sz.cx + loword(GetMenuCheckMarkDimensions),20);
  227.         msg.MeasureItemStruct^.itemHeight := max(sz.cy+2, 6);
  228.     end;
  229.  
  230. var
  231.     mi2 : TMenuItem;
  232. begin
  233.     Windows.SetLastError(ERROR_SUCCESS);
  234.     id := msg.MeasureItemStruct^.itemID;
  235.  
  236.     //
  237.     // Basically, use the longest text item to gauge the width of the popup
  238.     // At a minimum the height is the 2 pixels above the size of an icon
  239.     //
  240.     mi2 := self.ItemIDToMenuItem(id);
  241.     if mi2 <> nil then begin
  242.         s := mi2.Caption;
  243.     end;
  244.  
  245.     if (s <> '') then begin
  246.         GetTextSizeOf(s);
  247.     end else begin
  248.         s := self.CurrentClipboard.GetAsText;
  249.         if length(s) < length(FrmMainPopup.GetLastStringSelected) then begin
  250.             GetTextSizeOf(PU_LAST_TEXT + FrmMainPopup.GetTrimmedItem(FrmMainPopup.GetLastStringSelected));
  251.         end else begin
  252.             GetTextSizeOf(PU_LAST_TEXT + FrmMainPopup.GetTrimmedItem(s));
  253.         end;
  254.     end;
  255.     
  256.     //TODO: Unsure how to handle this, swapping Perm Items back and
  257.     // forth will be way to costly
  258.  
  259.     msg.MeasureItemStruct^.itemWidth := max(msg.MeasureItemStruct^.itemWidth + 8, 100);
  260. end;
  261.  
  262. procedure TFrmDummyUnicodePopup.WMDrawItem(var Msg: TWMDrawItem);
  263. var
  264.     i  : cardinal;
  265.     ci : TClipItem;
  266.     tc, bc : cardinal;
  267.     dc : integer;
  268. CONST ICON_SPACER = 20;
  269.     //
  270.     // Since it's owner drawns, I have to know what &x character related
  271.     // to what ItemID
  272.     //
  273.     procedure UpdateAccessKeys(s : string);
  274.     var amp : integer;
  275.     begin
  276.         amp := pos('&', s);
  277.         if (amp <> 0) then begin
  278.             inc(amp);
  279.             KeyToItemID.Values[lowercase(s[amp])] := IntToStr(msg.DrawItemStruct^.itemID);
  280.         end;
  281.     end;
  282.     procedure DrawTextAndBitmap(bm : TBitmap; s : string);
  283.     var ico : TIcon;
  284.         il : TImageList;
  285.         r : TRect;
  286.     begin
  287.         with msg.DrawItemStruct^ do begin
  288.         UpdateAccessKeys(s);
  289.  
  290.         r.Top := rcItem.Top;
  291.         r.Bottom := rcItem.Bottom;
  292.         r.Left := rcItem.Left + ICON_SPACER;
  293.         r.Right := rcItem.Right;
  294.  
  295.         DrawText(hdc, PChar(s), length(s),
  296.             r, DT_VCENTER);
  297.  
  298.         if (bm <> nil) and ((bm.Width and bm.Height) <> 0) then begin
  299.             ico := TIcon.Create;
  300.             il := TImageList.CreateSize(bm.Width, bm.Height);
  301.             il.AddMasked(bm, bm.TransparentColor);
  302.             il.GetIcon(0, ico);
  303.             il.Free;
  304.             if (ico.Handle <> 0) then begin
  305.                 DrawIconEx(hdc,
  306.                         rcItem.left,
  307.                         rcItem.top,
  308.                         ico.Handle,
  309.                         16,16, 0, 0, DI_NORMAL);
  310.             end;
  311.             ico.Free;
  312.         end;
  313.         end;
  314.     end;
  315.     procedure DrawTextAndImage(ti : TImage; s : string);
  316.     begin
  317.         if ti = nil then begin
  318.             DrawTextAndBitmap(nil, s);
  319.         end else begin
  320.             DrawTextAndBitmap(ti.Picture.Bitmap, s);
  321.         end;
  322.     end;
  323.  
  324.     procedure DrawUnicodeAndIcon(h : HICON; ci : TClipItem; prefix : string);
  325.     var wc : TWideChar;
  326.         r : TRect;
  327.         sz : TSize;
  328.     begin
  329.         UpdateAccessKeys(prefix);
  330.  
  331.         wc := TWideChar.Create;
  332.         wc.Append(prefix);
  333.         wc.Append(ci.GetHandle, ci.GetDataSize);
  334.         wc.Replace(WideChar($9), WideChar($3)); // replace these whitespace
  335.         wc.Replace(WideChar(#13),WideChar($3)); // characters with "squares"
  336.         wc.Replace(WideChar(#10),WideChar($3)); //
  337.  
  338.         if (ci.GetDataSize / 2) > VisibleCharCount then begin
  339.             wc.LeftStr(self.VisibleCharCount);
  340.             wc.Append('...');
  341.         end;
  342.  
  343.         Windows.GetTextExtentPoint32W(self.Canvas.Handle, wc.Memory,
  344.             wc.StrLength,sz);
  345.  
  346.  
  347.         with msg.DrawItemStruct^ do begin
  348.         r.Top := rcItem.Top;
  349.         r.Bottom := r.top + sz.cy;
  350.         r.Left := rcItem.Left + ICON_SPACER;
  351.         r.Right := rcItem.Right;
  352.         // trim the rectangle so the next line of text won't be
  353.         // partially visible
  354.  
  355.         DrawTextW(hdc, PWideChar(wc.Memory), wc.strlength - 1,
  356.             r, DT_VCENTER );
  357.         MyFree(wc);
  358.  
  359.         if (h <> 0) then begin
  360.             DrawIconEx(hdc,
  361.                 rcItem.left, rcItem.top,
  362.                 h,
  363.                 16,16, 0, 0, DI_NORMAL);
  364.         end;
  365.         end;
  366.     end;
  367.  
  368.     procedure DrawTextAndIcon(h : HICON; s : string); overload;
  369.     var r : TRect;
  370.     begin
  371.         UpdateAccessKeys(s);
  372.  
  373.         with msg.DrawItemStruct^ do begin
  374.         r.Top := rcItem.Top;
  375.         r.Bottom := rcItem.Bottom;
  376.         r.Left := rcItem.Left + ICON_SPACER;
  377.         r.Right := rcItem.Right;
  378.  
  379.         DrawText(hdc, PChar(s), length(s),
  380.             r, DT_VCENTER);
  381.  
  382.         if (h <> 0) then begin
  383.             DrawIconEx(hdc,
  384.                     rcItem.left, rcItem.top,
  385.                     h, 16,16,
  386.                     0, 0, DI_NORMAL);
  387.         end;
  388.         end;
  389.     end;
  390.  
  391.     procedure DrawTextAndIcon(ci : TClipItem); overload;
  392.     begin
  393.         if (ci.GetFormat = CF_UNICODETEXT) then begin
  394.             DrawUnicodeAndIcon(ci.CData.GetHICON, ci, '');
  395.         end else begin
  396.             DrawTextAndIcon(ci.CData.GetHICON, FrmMainPopup.GetTrimmedItem(ci.getastext));
  397.         end;
  398.     end;
  399.  
  400.  
  401. var HB : HBRUSH;
  402.     prefix : string;
  403.     mi : TMenuItem;
  404.     ni, ni2 : TNotifyEvent;
  405.     h : HGDIOBJ;
  406.     oldf, f : HFONT;
  407.     name : string;
  408. begin
  409.     Windows.SetLastError(ERROR_SUCCESS);
  410.     with msg.DrawItemStruct^ do begin
  411.     dc := Windows.SaveDC(hDC);
  412.     if (dc = 0) then begin
  413.         UnitMisc.AppendLog('WMDrawItem: SaveDC failed - ', true);
  414.         EXIT;
  415.     end;
  416.     //
  417.     // Fill the entire background with a hilight or no higlight
  418.     //
  419.  
  420.  
  421.  
  422.     name := self.Font.Name;
  423.  
  424.  
  425.      f :=Createfont(
  426.         self.Font.Height,0,0,0,0,0,0,0,Ansi_Charset,Out_Default_Precis,
  427.         clip_Default_Precis,Draft_Quality,variable_Pitch OR ff_swiss,
  428.         pchar(name)
  429.      );
  430.  
  431.     oldf := Windows.SelectObject(hdc, f);
  432.  
  433.  
  434.     if (itemState and ODS_SELECTED) = 0 then begin
  435.         tc := Windows.SetTextColor(hDC, ColorToRGB(clMenuText));
  436.         bc := Windows.SetBkColor(hDC, ColorToRGB(clMenu));
  437.         hb := Windows.CreateSolidBrush(ColorToRGB(clMenu));
  438.     end else begin
  439.         tc := Windows.SetTextColor(hdc, ColorToRGB(clHighLightText));
  440.         bc := Windows.SetBkColor(hdc, ColorToRGB(clHighLight));
  441.         hb := Windows.CreateSolidBrush(ColorToRGB(clHighLight));
  442.     end;
  443.     if (hb <> 0) then begin
  444.         Windows.FillRect(hdc, rcItem, hb);
  445.         Windows.DeleteObject(hb);
  446.     end;
  447.  
  448.     try
  449.         mi := self.ItemIDToMenuItem(itemID);
  450.         if (mi <> nil) then begin
  451.             ni := mi.OnClick;
  452.             ni2 := FrmMainPopup.MenuItemClickEvent;;
  453.             if (@ni = @ni2) then begin
  454.                 i := ClipQueue.IndexOf(mi.hint);
  455.                 ci := ClipQueue.GetClipItem(i);
  456.  
  457.                 if (FrmConfig.cbUseKeyboard.Checked) then begin
  458.                     prefix := '&' + FrmMainPopup.GetAccelerator(i) + ': ';
  459.                 end;
  460.                 if (FrmConfig.cbShowTypes.Checked) then begin
  461.                     prefix := prefix + UnitMisc.GetCliptypeSymbol(ci.GetFormat) + ' ';
  462.                 end;
  463.                 if (ci.GetFormat = Windows.CF_UNICODETEXT) then begin
  464.                     DrawUnicodeAndIcon(ci.CData.GetHICON, ci, Prefix)
  465.                 end else begin
  466.                     DrawTextAndIcon(ci.CData.GetHICON,prefix +
  467.                         FrmMainPopup.GetTrimmedItem(ci.GetAsText));
  468.                 end;
  469.             end else begin
  470.                 ni2 := FrmMainPopup.CurrentMenuItemClickEvent;
  471.                 if (@ni = @ni2) then begin
  472.                     if (self.CurrentClipboard.GetFormat = CF_UNICODETEXT) then begin
  473.                         DrawUnicodeAndIcon(0, self.CurrentClipboard, PU_CURRENT_TEXT);
  474.                     end else begin
  475.                         DrawTextAndImage(nil, PU_CURRENT_TEXT + LeftStr(self.CurrentClipboard.GetAsText, VisibleCharCount));
  476.                     end;
  477.                 end else begin
  478.                     DrawTextAndBitmap(mi.Bitmap, mi.caption);
  479.                 end;
  480.  
  481.             end;
  482.  
  483.         end;
  484.     finally
  485.         h := SelectObject(hdc, oldf);
  486.         DeleteObject(h);
  487.  
  488.         Windows.SetTextColor(hdc, tc);
  489.         Windows.SetBkColor(hdc, bc);
  490.         Windows.RestoreDC(hdc, dc);
  491.  
  492.  
  493.     end;
  494.     end;
  495. end;
  496.  
  497.  
  498.  
  499. //
  500. // And Item was selected by keystroke, or by click
  501. //
  502. procedure TFrmDummyUnicodePopup.WMMenuChar(var Msg: TWMMenuChar);
  503. var m : TWMCommand;
  504.     s : string;
  505.  
  506. begin
  507.     if (msg.MenuFlag and MF_POPUP) <> 0 then begin
  508.         //
  509.         // Wait until user releases keystrok
  510.         // Translate key to ItemID
  511.         // pass information WMCommand - as if it was clicked by a mouse
  512.         //
  513.         while KeyboardQuery.IsPressed(VkKeyScan(msg.user)) do begin
  514.             Application.ProcessMessages;
  515.         end;
  516.         msg.Result := MakeLong(0, MNC_CLOSE);
  517.  
  518.         s := KeyToItemID.Values[lowercase(msg.User)];
  519.  
  520.         if (s <> '') then begin
  521.             //
  522.             // trigger the correct WMCommand event
  523.             //
  524.             Application.ProcessMessages;
  525.             m.NotifyCode := 0;
  526.             m.ItemID := StrToInt(s);
  527.             m.Ctl := 0;
  528.             self.WMCommand(m);
  529.         end;
  530.     end else begin
  531.         inherited;
  532.     end;
  533. end;
  534.  
  535. procedure TFrmDummyUnicodePopup.WMCommand(var Msg: TWMCommand);
  536. var
  537.     itemID : integer;
  538.     mi2 : TMenuItem;
  539.     ni, ni2, ni3, ni4, ni5, ni6, ni7 : TNotifyEvent;
  540. begin
  541.     // Given an ItemID - carry out the selected action
  542.  
  543.     if (msg.NotifyCode = 0) then begin
  544.         itemID := msg.ItemID;
  545.         mi2 := self.ItemIDToMenuItem(itemID);
  546.         if (mi2 <> nil) then begin
  547.         
  548.             // Some items expect the menu item passed back
  549.             // Other items need this form's handle to set focus correctly
  550.  
  551.             ni := mi2.OnClick;
  552.             ni2 := FrmMainPopup.MenuItemClickEvent;
  553.             ni3 := FrmMainPopup.OtherItemClickEvent;
  554.             ni4 := FrmMainPopup.PermanentMenuItemClickEvent;
  555.             ni5 := FrmMainPopup.PermanentGroupItemClickEvent;
  556.             ni6 := frmSysTrayMenu.SwitchPermFolder;
  557.             ni7 := frmSysTrayMenu.MethodMenuItemClickEvent;
  558.             if (@ni = @ni2) or (@ni = @ni3) or
  559.                (@ni = @ni4) or (@ni = @ni5) or
  560.                (@ni = @ni6) or (@ni = @ni7) then begin
  561.                 Mi2.OnClick(mi2);
  562.             end else begin
  563.                 Mi2.OnClick(self);
  564.             end;
  565.         end;
  566.     end else begin
  567.         {dunno if this is needed}
  568.         inherited;
  569.     end;
  570. end;
  571.  
  572.  
  573.  
  574.  
  575. {
  576. //
  577. // These 3 messages control the menu popup
  578. // Item is selected, Idle state occurs, then the time will fire the
  579. // showtooltip event
  580. }
  581.  
  582. procedure TFrmDummyUnicodePopup.WMEnterIdle(var Msg: TWMEnterIdle);
  583. begin
  584.     // use this position to show the tooltip
  585.     tim.Interval := Application.HintPause;
  586.     tim.Enabled := true;
  587.     Windows.GetCursorPos(LastCursorPos);
  588. end;
  589.  
  590. procedure TFrmDummyUnicodePopup.timTimer(Sender: TObject);
  591. var ci : TClipItem;
  592. begin
  593.     self.TimeFiring  := true;
  594.  
  595.     tim.Enabled := false;
  596.  
  597.     if (self.LastClipItem = nil) and (self.LastHint = '') then begin
  598.         EXIT;
  599.     end;
  600.  
  601.     inc(self.LastCursorPos.X, 20);
  602.     inc(self.LastCursorPos.Y, 10);
  603.  
  604.     UnitMisc.AppendLog('Showing Tooltip hint');
  605.     if (self.LastClipItem <> nil) then begin
  606.         Tooltip.ShowTooltip(self.LastClipITem, self.LastCursorPos);
  607.         //FrmDummyUnicodeTooltip.ShowTooltip(self.LastClipITem, self.LastCursorPos);
  608.     end else begin
  609.         if (FrmPermanent.IsComplexItem(self.LastHint)) then begin
  610.             ci := FrmPermanent.GetComplexItem(self.LastHint);
  611.             if (ci.GetFormat = Windows.CF_UNICODETEXT) then begin
  612.                 Tooltip.ShowTooltip(ci, self.LastCursorPos);
  613.             end else begin
  614.                 Tooltip.ShowTooltip('[Clip format: ' + ci.GetFormatName + ']',
  615.                     self.LastCursorPos);
  616.             end;
  617.             MyFree(ci);
  618.         end else begin
  619.             Tooltip.ShowTooltip(self.LastHint, self.LastCursorPos);
  620.         end;
  621.  
  622.     end;
  623.  
  624.     self.LastHint := '';
  625.     self.TimeFiring := false;
  626. end;
  627.  
  628.  
  629. procedure TFrmDummyUnicodePopup.WMMenuSelect(var Msg: TWMMenuSelect);
  630. var id : word;
  631.     i  : integer;
  632.     ni, ni2 : TNotifyEvent;
  633.     mi : TMenuItem;
  634. begin
  635.     tim.Enabled := false;
  636.     ToolTip.CloseTooltip;
  637.  
  638.  
  639.     //
  640.     // Here, we assign either set "Hint" to display as a tooltip as plain
  641.     // text, or we use the complex item (unicode) if available
  642.     //
  643.  
  644.     self.LastHint := '';
  645.     self.LastClipITem := nil;
  646.     id := TWMMENUSELECT(msg).IDItem;
  647.  
  648.  
  649.     //
  650.     // ignore Menu items with submenus - they don't have popups
  651.     //
  652.     if ((TWMMENUSELECT(msg).MenuFlag and MF_POPUP) <> 0) then begin
  653.         EXIT;
  654.     end;
  655.  
  656.     mi := self.ItemIDToMenuItem(id);
  657.     if (mi <> nil) then begin
  658.  
  659.         // use the click event address to determin the type of menu item
  660.         // that's hilighted
  661.  
  662.         ni := mi.OnClick;
  663.         ni2 := FrmMainPopup.MenuItemClickEvent;
  664.         if (@ni = @ni2) then begin
  665.             i := ClipQueue.IndexOf(mi.hint);
  666.             self.LastClipItem := ClipQueue.GetClipItem(i)
  667.         end;
  668.  
  669.         ni2 := FrmMainPopup.LastMenuItemClickEvent;
  670.         if (@ni = @ni2) then begin
  671.             self.LastHint := FrmMainPopup.GetLastStringSelected;
  672.         end;
  673.  
  674.         ni2 := FrmMainPopup.CurrentMenuItemClickEvent;
  675.         if (@ni = @ni2) then begin
  676.             self.LastHint := self.CurrentClipboard.GetAsText;
  677.         end;
  678.  
  679.         ni2 := FrmMainPopup.PermanentMenuItemClickEvent;
  680.         if (@ni = @ni2) then begin
  681.             // Caption contains name
  682.             // hint contains plain text value
  683.             // tag containg the group ID or -1 for current group
  684.  
  685.             self.LastHint := mi.Hint;
  686.             if (mi.Tag <> - 1) then begin
  687.                 FrmPermanent.PermFolderPush;
  688.                 FrmPermanent.SetPermanentPath(FrmPermanent.PermFoldersGetItem(mi.tag));
  689.                 self.LastHint := FrmPermanent.GetTextFrom(mi.caption);
  690.  
  691.                 FrmPermanent.PermFolderPop;
  692.             end;
  693.         end;
  694.     end;
  695. end;
  696.  
  697.  
  698. function TFrmDummyUnicodePopup.ItemIDToMenuItem(
  699.   itemID: integer): TMenuItem;
  700. var s : string;
  701.     i : integer;
  702. begin
  703.     result := nil;
  704.  
  705.     // either ItemID is a WM_COMMAND (an index to an object)
  706.     // or it's an address of a menu item
  707.     // - find the correct one and return it or NIL
  708.  
  709.     if itemID < SubObjectList.Count then begin
  710.         result := TMenuItem(SubObjectList.Items[itemID]);
  711.     end;
  712.  
  713.     if result = nil then begin
  714.         s := SubMenuItemList.values[IntToStr(itemID)];
  715.         if (s <> '') then begin
  716.             i := StrToInt(s);
  717.             if i < SubObjectList.Count then begin
  718.                 result := TMenuItem( SubObjectList.items[i] );
  719.             end;
  720.         end;
  721.     end;
  722. end;
  723.  
  724. end.
  725.