SkinMenus.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:72k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }     
  4. {       DynamicSkinForm                                             }
  5. {       Version 5.60                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2003 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. unit SkinMenus;
  15. {$P+,S-,W-,R-}
  16. {$WARNINGS OFF}
  17. {$HINTS OFF}
  18. interface
  19. uses
  20.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  21.   Menus, ExtCtrls, ImgList, SkinData, SPUtils, spEffBMp;
  22. type
  23.   TspSkinPopupWindow = class;
  24.   TspSkinMenuItem = class(TObject)
  25.   protected
  26.     Parent: TspSkinPopupWindow;
  27.     MI: TspDataSkinMenuItem;
  28.     ActivePicture: TBitMap;
  29.     FMorphKf: Double;
  30.     procedure SetMorphKf(Value: Double);
  31.     procedure Redraw;
  32.   public
  33.     MenuItem: TMenuItem;
  34.     ObjectRect: TRect;
  35.     Active: Boolean;
  36.     Down: Boolean;
  37.     FVisible: Boolean;
  38.     WaitCommand: Boolean;
  39.     constructor Create(AParent: TspSkinPopupWindow; AMenuItem: TMenuItem;
  40.                        AData: TspDataSkinMenuItem);
  41.     procedure Draw(Cnvs: TCanvas);
  42.     procedure DefaultDraw(Cnvs: TCanvas);
  43.     function CanMorphing: Boolean; virtual;
  44.     procedure DoMorphing;
  45.     property MorphKf: Double read FMorphKf write SetMorphKf;
  46.     procedure MouseDown(X, Y: Integer);
  47.     procedure MouseEnter(Kb: Boolean);
  48.     procedure MouseLeave;
  49.   end;
  50.   TspSkinMenu = class;
  51.   TspSkinPopupWindow = class(TCustomControl)
  52.   private
  53.     DSMI: TspDataSkinMenuItem;
  54.     VisibleCount: Integer;
  55.     VisibleStartIndex: Integer;
  56.     Scroll: Boolean;
  57.     ScrollCode: Integer;
  58.     NewLTPoint, NewRTPoint,
  59.     NewLBPoint, NewRBPoint: TPoint;
  60.     NewItemsRect: TRect;
  61.     FRgn: HRGN;
  62.     ShowX, ShowY: Integer;
  63.     WT: TTimer;
  64.     OMX, OMY: Integer;
  65.     procedure WTProc(Sender: TObject);
  66.     procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
  67.     procedure WMEraseBkGrnd(var Message: TMessage); message WM_ERASEBKGND;
  68.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  69.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  70.     procedure CreateMenu(Item: TMenuItem; StartIndex: Integer);
  71.     procedure CreateMenu2(Item, Item2: TMenuItem; StartIndex: Integer);
  72.     procedure CreateRealImage(B: TBitMap);
  73.     procedure SetMenuWindowRegion;
  74.     procedure DrawUpMarker(Cnvs: TCanvas);
  75.     procedure DrawDownMarker(Cnvs: TCanvas);
  76.     procedure StartScroll;
  77.     procedure StopScroll;
  78.   protected
  79.     ImgL: TCustomImageList;
  80.     GlyphWidth: Integer;
  81.     WindowPicture, MaskPicture: TBitMap;
  82.     OldActiveItem: Integer;
  83.     MouseTimer, MorphTimer: TTimer;
  84.     ParentMenu: TspSkinMenu;
  85.     SD: TspSkinData;
  86.     PW: TspDataSkinPopupWindow;
  87.     procedure WMTimer(var Message: TWMTimer); message WM_Timer;
  88.     function CanScroll(AScrollCode: Integer): Boolean;
  89.     procedure ScrollUp(Cycle: Boolean);
  90.     procedure ScrollDown(Cycle: Boolean);
  91.     function GetEndStartVisibleIndex: Integer;
  92.     procedure CalcItemRects;
  93.     procedure CreateParams(var Params: TCreateParams); override;
  94.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  95.       X, Y: Integer); override;
  96.     procedure TestMouse(Sender: TObject);
  97.     procedure TestActive(X, Y: Integer);
  98.     function InWindow(P: TPoint): Boolean;
  99.     procedure TestMorph(Sender: TObject);
  100.     procedure UpDatePW;
  101.     function GetActive(X, Y: Integer): Boolean;
  102.   public
  103.     Sc: TBitMap;
  104.     ESc: TspEffectBmp;
  105.     AlphaBlend: Boolean;
  106.     AlphaBlendValue: Byte;
  107.     AlphaBlendAnimation: Boolean;
  108.     ItemList: TList;
  109.     ActiveItem: Integer;
  110.     constructor CreateEx(AOwner: TComponent; AParentMenu: TspSkinMenu;
  111.                        AData: TspDataSkinPopupWindow);
  112.     destructor Destroy; override;
  113.      procedure Hide;
  114.     procedure Show(R: TRect; AItem: TMenuItem; StartIndex: Integer;
  115.                    PopupByItem: Boolean;  PopupUp: Boolean);
  116.     procedure Show2(R: TRect; AItem, AItem2: TMenuItem; StartIndex: Integer;
  117.                    PopupByItem: Boolean;  PopupUp: Boolean);
  118.     procedure PaintMenu(DC: HDC);
  119.     procedure PopupKeyDown(CharCode: Integer);
  120.   end;
  121.   TspSkinMenu = class(TComponent)
  122.   protected
  123.     FUseSkinFont: Boolean;
  124.     FFirst: Boolean;
  125.     FDefaultMenuItemHeight: Integer;
  126.     FDefaultMenuItemFont: TFont;
  127.     PopupCtrl, DCtrl: TControl;
  128.     FForm: TForm;
  129.     WaitTimer: TTimer;
  130.     WItem: TspSkinMenuItem;
  131.     WorkArea: TRect;
  132.     FVisible: Boolean;
  133.     SkinData: TspSkinData;
  134.     procedure SetDefaultMenuItemFont(Value: TFont);
  135.     function GetWorkArea: TRect;
  136.     function GetPWIndex(PW: TspSkinPopupWindow): Integer;
  137.     procedure CheckItem(PW: TspSkinPopupWindow; MI: TspSkinMenuItem; Down: Boolean; Kb: Boolean);
  138.     procedure CloseMenu(EndIndex: Integer);
  139.     procedure PopupSub(R: TRect; AItem: TMenuItem; StartIndex: Integer;
  140.                        PopupByItem, PopupUp: Boolean);
  141.     procedure PopupSub2(R: TRect; AItem, AItem2: TMenuItem; StartIndex: Integer;
  142.                        PopupByItem, PopupUp: Boolean);
  143.     procedure WaitItem(Sender: TObject);
  144.   public
  145.     { Public declarations }
  146.     FPopupList: TList;
  147.     AlphaBlend: Boolean;
  148.     AlphaBlendValue: Byte;
  149.     AlphaBlendAnimation: Boolean;
  150.     property Visible: Boolean read FVisible;
  151.     constructor CreateEx(AOwner: TComponent; AForm: TForm);
  152.     destructor Destroy; override;
  153.     procedure Popup(APopupCtrl: TControl; ASkinData: TspSkinData; StartIndex: Integer;
  154.                     R: TRect; AItem: TMenuItem; PopupUp: Boolean);
  155.     procedure Popup2(APopupCtrl: TControl; ASkinData: TspSkinData; StartIndex: Integer;
  156.                     R: TRect; AItem, AItem2: TMenuItem; PopupUp: Boolean);
  157.     procedure Hide;
  158.     property First: Boolean read FFirst;
  159.     property DefaultMenuItemFont: TFont
  160.       read FDefaultMenuItemFont write SetDefaultMenuItemFont;
  161.     property DefaultMenuItemHeight: Integer
  162.       read FDefaultMenuItemHeight write FDefaultMenuItemHeight;
  163.     property UseSkinFont: Boolean
  164.      read FUseSkinFont write FUseSkinFont;
  165.   end;
  166.   TspSkinPopupMenu = class(TPopupMenu)
  167.   protected
  168.     FSD: TspSkinData;
  169.     FComponentForm: TForm;
  170.     procedure Notification(AComponent: TComponent;
  171.       Operation: TOperation); override;
  172.   public
  173.     constructor Create(AOwner: TComponent); override;
  174.     procedure Popup(X, Y: Integer); override;
  175.     procedure PopupFromRect(R: TRect; APopupUp: Boolean);
  176.     procedure Popup2(ACtrl: TControl; X, Y: Integer);
  177.     procedure PopupFromRect2(ACtrl: TControl; R: TRect; APopupUp: Boolean);
  178.     property ComponentForm: TForm read FComponentForm write FComponentForm;
  179.   published
  180.     property SkinData: TspSkinData read FSD write FSD;
  181.   end;
  182.   function CanMenuClose(Msg: Cardinal): Boolean;
  183. const
  184.     WM_CLOSESKINMENU = WM_USER + 204;
  185.     WM_AFTERDISPATCH = WM_USER + 205;
  186. implementation
  187.    Uses DynamicSkinForm;
  188. const
  189.     MorphInc = 0.1;
  190.     MouseTimerInterval = 50;
  191.     MorphTimerInterval = 20;
  192.     WaitTimerInterval = 500;
  193.     MarkerItemHeight = 10;
  194.     ScrollTimerInterval = 100;
  195.     MI_MINNAME = 'DSF_MINITEM';
  196.     MI_MAXNAME = 'DSF_MAXITEM';
  197.     MI_CLOSENAME = 'DSF_CLOSE';
  198.     MI_RESTORENAME = 'DSF_RESTORE';
  199.     MI_MINTOTRAYNAME = 'DSF_MINTOTRAY';
  200.     MI_ROLLUPNAME = 'DSF_ROLLUP';
  201.     TMI_RESTORENAME = 'TRAY_DSF_RESTORE';
  202.     TMI_CLOSENAME = 'TRAY_DSF_CLOSE';
  203. procedure DrawCheckImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  204. var
  205.   i: Integer;
  206. begin
  207.   with Cnvs do
  208.   begin
  209.     Pen.Color := Color;
  210.     for i := 0 to 2 do
  211.     begin
  212.       MoveTo(X, Y + 5 - i);
  213.       LineTo(X + 2, Y + 7 - i);
  214.       LineTo(X + 7, Y + 2 - i);
  215.     end;
  216.   end;
  217. end;
  218. procedure DrawSubImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  219. var
  220.   i: Integer;
  221. begin
  222.   with Cnvs do
  223.   begin
  224.     Pen.Color := Color;
  225.     for i := 0 to 3 do
  226.     begin
  227.       MoveTo(X + i, Y + i);
  228.       LineTo(X + i, Y + 7 - i);
  229.     end;
  230.   end;
  231. end;
  232. procedure DrawRadioImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  233. begin
  234.   with Cnvs do
  235.   begin
  236.     Pen.Color := Color;
  237.     Brush.Color := Color;
  238.     Ellipse(X, Y, X + 6, Y + 6);
  239.   end;
  240. end;
  241. function RectWidth(R: TRect): Integer;
  242. begin
  243.   Result := R.Right - R.Left;
  244. end;
  245. function RectHeight(R: TRect): Integer;
  246. begin
  247.   Result := R.Bottom - R.Top;
  248. end;
  249. function CanMenuClose;
  250. begin
  251.   Result := False;
  252.   case Msg of
  253.     WM_MOUSEACTIVATE, WM_ACTIVATE,
  254.     WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN,
  255.     WM_NCLBUTTONDOWN, WM_NCMBUTTONDOWN, WM_NCRBUTTONDOWN,
  256.     WM_KILLFOCUS, WM_MOVE, WM_SIZE, WM_CANCELMODE, WM_PARENTNOTIFY:
  257.       Result := True;
  258.   end;
  259. end;
  260. //===============TspSkinMenuItem===================//
  261. constructor TspSkinMenuItem.Create;
  262. begin
  263.   WaitCommand := False;
  264.   Parent := AParent;
  265.   MenuItem := AMenuItem;
  266.   FVisible := True;
  267.   MI := AData;
  268.   if MI <> nil then 
  269.   with AData do
  270.   begin
  271.     if (ActivePictureIndex <> - 1) and
  272.        (ActivePictureIndex < Self.Parent.SD.FActivePictures.Count)
  273.     then
  274.       ActivePicture := Self.Parent.SD.FActivePictures.Items[ActivePictureIndex]
  275.     else
  276.       begin
  277.         ActivePicture := nil;
  278.         SkinRect := NullRect;
  279.         ActiveSkinRect := NullRect;
  280.       end;
  281.   end;
  282.   FMorphKf := 0;
  283. end;
  284. function TspSkinMenuItem.CanMorphing;
  285. var
  286.   AD: Boolean;
  287. begin
  288.   AD := Active or Down;
  289.   Result := FVisible and ((AD and (MorphKf < 1)) or
  290.                          (not AD and (MorphKf > 0)));
  291.   if not FVisible and (FMorphKf <> 0)
  292.   then
  293.     begin
  294.       Active := False;
  295.       Down := False;
  296.       FMorphKf := 0;
  297.     end;
  298. end;
  299. procedure TspSkinMenuItem.DoMorphing;
  300. begin
  301.   if Active or Down
  302.   then MorphKf := MorphKf + MorphInc
  303.   else MorphKf := MorphKf - MorphInc;
  304.   Draw(Parent.Canvas);
  305. end;
  306. procedure TspSkinMenuItem.SetMorphKf(Value: Double);
  307. begin
  308.   FMorphKf := Value;
  309.   if FMorphKf < 0 then FMorphKf := 0 else
  310.   if FMorphKf > 1 then FMorphKf := 1;
  311. end;
  312. procedure TspSkinMenuItem.ReDraw;
  313. begin
  314.   if (MI <> nil) and MI.Morphing
  315.   then Parent.MorphTimer.Enabled := True
  316.   else Draw(Parent.Canvas);
  317. end;
  318. procedure TspSkinMenuItem.MouseDown(X, Y: Integer);
  319. begin
  320.   WaitCommand := False;
  321.   if not Down and MenuItem.Enabled
  322.   then
  323.     Parent.ParentMenu.CheckItem(Parent, Self, True, False);
  324. end;
  325. procedure TspSkinMenuItem.MouseEnter;
  326. var
  327.   i: Integer;
  328. begin
  329.   Active := True;
  330.   for i := 0 to Parent.ItemList.Count - 1 do
  331.     if (TspSkinMenuItem(Parent.ItemList.Items[i]) <> Self)
  332.        and TspSkinMenuItem(Parent.ItemList.Items[i]).Down
  333.     then
  334.       with TspSkinMenuItem(Parent.ItemList.Items[i]) do
  335.       begin
  336.         Down := False;
  337.         ReDraw;
  338.       end;
  339.   if WaitCommand and not Kb
  340.   then
  341.     begin
  342.       ReDraw;
  343.     end
  344.   else
  345.   if not Down
  346.   then
  347.     begin
  348.       ReDraw;
  349.       Parent.ParentMenu.CheckItem(Parent, Self, False, Kb);
  350.     end
  351.   else
  352.     with Parent.ParentMenu do
  353.     begin
  354.       i := GetPWIndex(Parent);
  355.       if i + 2 < FPopupList.Count
  356.       then
  357.         TspSkinPopupWindow(FPopupList.Items[i + 1]).UpDatePW;
  358.     end;
  359.     
  360. end;
  361. procedure TspSkinMenuItem.MouseLeave;
  362. begin
  363.   WaitCommand := False;
  364.   Active := False;
  365.   if not Down then ReDraw;
  366.   with Parent.ParentMenu do
  367.   begin
  368.     if (WItem <> nil) and (WItem = Self)
  369.     then
  370.       begin
  371.         WaitTimer.Enabled := False;
  372.         WItem := nil;
  373.       end;
  374.   end;
  375. end;
  376. procedure TspSkinMenuItem.DefaultDraw(Cnvs: TCanvas);
  377. var
  378.   MIShortCut: String;
  379.   B: TBitMap;
  380.   TextOffset: Integer;
  381.   R, TR, SR: TRect;
  382.   DrawGlyph: Boolean;
  383.   GX, GY, IX, IY: Integer;
  384.   EB1: TspEffectBmp;
  385.   kf: Double;
  386. begin
  387.   if MenuItem.ShortCut <> 0
  388.   then
  389.     MIShortCut := ShortCutToText(MenuItem.ShortCut)
  390.   else
  391.     MIShortCut := '';
  392.   B := TBitMap.Create;
  393.   B.Width := RectWidth(ObjectRect);
  394.   B.Height := RectHeight(ObjectRect);
  395.   if Parent.ImgL = nil
  396.   then TextOffset := 19
  397.   else TextOffset := Parent.GlyphWidth;
  398.   
  399.   with B.Canvas do
  400.   begin
  401.     R := Rect(0, 0, B.Width, B.Height);
  402.     Font.Assign(Parent.ParentMenu.FDefaultMenuItemFont);
  403.     if (Active or Down) and (MenuItem.Caption <> '-')
  404.     then
  405.       begin
  406.         Frame3D(B.Canvas, R, SP_XP_BTNFRAMECOLOR, SP_XP_BTNFRAMECOLOR, 1);
  407.         Brush.Color := SP_XP_BTNACTIVECOLOR;
  408.         Font.Color := clWindowText;
  409.         FillRect(R);
  410.       end
  411.     else
  412.       begin
  413.         R := Rect(0, 0, TextOffset, B.Height);
  414.         Brush.Color := clBtnFace;
  415.         FillRect(R);
  416.         R := Rect(TextOffset, 0, B.Width, B.Height);
  417.         Brush.Color := clWindow;
  418.         if MenuItem.Enabled
  419.         then
  420.           Font.Color := clWindowText
  421.         else
  422.           Font.Color := clBtnShadow;
  423.         FillRect(R);
  424.       end;
  425.   end;
  426.   if MenuItem.Caption = '-'
  427.   then
  428.     begin
  429.       R.Left := TextOffset;
  430.       R.Top := B.Height div 2;
  431.       R.Right := B.Width;
  432.       R.Bottom := B.Height div 2 + 1;
  433.       Frame3D(B.Canvas, R, clBtnShadow, clBtnShadow, 1);
  434.       if Parent.AlphaBlend and not CheckW2KWXP
  435.       then
  436.         begin
  437.           EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  438.           kf := 1 - Parent.AlphaBlendValue / 255;
  439.           EB1.MorphRect(Parent.ESc, kf, Rect(0, 0, B.Width, B.Height),
  440.             ObjectRect.Left, ObjectRect.Top);
  441.           EB1.Draw(Cnvs.Handle, ObjectRect.Left, ObjectRect.Top);
  442.           EB1.Free;
  443.         end
  444.       else
  445.         Cnvs.Draw(ObjectRect.Left, ObjectRect.Top, B);
  446.       B.Free;
  447.       Exit;
  448.     end;
  449.   TR := Rect(2, 2, B.Width - 2, B.Height - 2);
  450.   // text
  451.   R := Rect(TR.Left + TextOffset, 0, TR.Right - 19, 0);
  452.   DrawText(B.Canvas.Handle, PChar(MenuItem.Caption), Length(MenuItem.Caption), R,
  453.              DT_CALCRECT);
  454.   OffsetRect(R, 0, TR.Top + RectHeight(TR) div 2 - R.Bottom div 2);
  455.   Inc(R.Right, 2);
  456.   DrawText(B.Canvas.Handle,
  457.            PChar(MenuItem.Caption), Length(MenuItem.Caption), R, DT_CENTER or DT_VCENTER);
  458.   // short cut
  459.   if MIShortCut <> ''
  460.   then
  461.     begin
  462.       SR := Rect(0, 0, 0, 0);
  463.       DrawText(B.Canvas.Handle, PChar(MIShortCut), Length(MIShortCut), SR,
  464.                DT_CALCRECT);
  465.       SR := Rect(TR.Right - SR.Right - 19, R.Top, TR.Right - 19, R.Bottom);
  466.       DrawText(B.Canvas.Handle,
  467.         PChar(MIShortCut), Length(MIShortCut), SR, DT_CENTER or DT_VCENTER);
  468.     end;
  469.   //
  470.   if MenuItem.Count <> 0
  471.   then
  472.     DrawSubImage(B.Canvas,
  473.                  TR.Right - 7, TR.Top + RectHeight(TR) div 2 - 4,
  474.                  B.Canvas.Font.Color);
  475.   //
  476.   DrawGlyph := (Parent.ImgL <> nil) and (MenuItem.ImageIndex > -1) and
  477.        (MenuItem.ImageIndex < Parent.ImgL.Count);
  478.   if DrawGlyph
  479.   then
  480.     begin
  481.       GX := TR.Left;
  482.       GY := TR.Top + RectHeight(TR) div 2 - Parent.ImgL.Height div 2;
  483.       if MenuItem.Checked
  484.       then
  485.         with B.Canvas do
  486.         begin
  487.           Brush.Style := bsClear;
  488.           Pen.Color := Font.Color;
  489.           Rectangle(GX - 1, GY - 1,
  490.                     GX + Parent.ImgL.Width + 1,
  491.                     GY + Parent.ImgL.Height + 1);
  492.         end;
  493.     end
  494.   else
  495.     begin
  496.       GX := 0; GY := 0;
  497.       IY := TR.Top + RectHeight(TR) div 2 - 4;
  498.       IX := TR.Left + 2;
  499.       if (MenuItem.Name = MI_CLOSENAME) or (MenuItem.Name = TMI_CLOSENAME)
  500.       then DrawCloseImage(B.Canvas, IX, IY, B.Canvas.Font.Color) else
  501.       if MenuItem.Name = MI_MINNAME
  502.       then DrawMinimizeImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  503.       else
  504.       if MenuItem.Name = MI_MAXNAME
  505.       then DrawMaximizeImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  506.       else
  507.       if (MenuItem.Name = MI_RESTORENAME) or (MenuItem.Name = TMI_RESTORENAME)
  508.       then DrawRestoreImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  509.       else
  510.       if MenuItem.Name = MI_ROLLUPNAME
  511.       then DrawRollUpImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  512.       else
  513.       if MenuItem.Name = MI_MINTOTRAYNAME
  514.       then DrawMTImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  515.       else
  516.       if MenuItem.Checked
  517.       then
  518.       if MenuItem.RadioItem
  519.       then
  520.         DrawRadioImage(B.Canvas,
  521.                        TR.Left + 3, TR.Top + RectHeight(TR) div 2 - 3,
  522.                        B.Canvas.Font.Color)
  523.       else
  524.         DrawCheckImage(B.Canvas,
  525.                        TR.Left + 3, TR.Top + RectHeight(TR) div 2 - 4,
  526.                        B.Canvas.Font.Color);
  527.     end;
  528.   //
  529.   if DrawGlyph
  530.   then
  531.     Parent.ImgL.Draw(B.Canvas, GX, GY, MenuItem.ImageIndex, MenuItem.Enabled);
  532.   if Parent.AlphaBlend and not CheckW2KWXP
  533.   then
  534.     begin
  535.       EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  536.       kf := 1 - Parent.AlphaBlendValue / 255;
  537.       EB1.MorphRect(Parent.ESc, kf, Rect(0, 0, B.Width, B.Height),
  538.        ObjectRect.Left, ObjectRect.Top);
  539.       EB1.Draw(Cnvs.Handle, ObjectRect.Left, ObjectRect.Top);
  540.       EB1.Free;
  541.     end
  542.   else
  543.     Cnvs.Draw(ObjectRect.Left, ObjectRect.Top, B);
  544.   B.Free;
  545. end;
  546. procedure TspSkinMenuItem.Draw;
  547. var
  548.   GX, GY: Integer;
  549.   DrawGlyph: Boolean;
  550.   EB1: TspEffectBmp;
  551.   kf: Double;
  552. procedure CreateItemImage(B: TBitMap; AActive: Boolean);
  553. var
  554.   R, TR, SR, Rct: TRect;
  555.   TextOffset: Integer;
  556.   MIShortCut: String;
  557.   IX, IY: Integer;
  558. begin
  559.   if MenuItem.ShortCut <> 0
  560.   then
  561.     MIShortCut := ShortCutToText(MenuItem.ShortCut)
  562.   else
  563.     MIShortCut := '';
  564.   if AActive
  565.   then Rct := MI.ActiveSkinRect
  566.   else Rct := MI.SkinRect;
  567.   CreateHSkinImage(MI.ItemLO, MI.ItemRO,
  568.    B, ActivePicture, Rct,
  569.    RectWidth(ObjectRect), RectHeight(ObjectRect));
  570.   if Parent.ImgL = nil
  571.   then TextOffset := 16
  572.   else TextOffset := Parent.GlyphWidth;
  573.   TR := MI.TextRct;
  574.   TR.Right := B.Width - (RectWidth(MI.SkinRect) - MI.TextRct.Right);
  575.   with B.Canvas do
  576.   begin
  577.     Brush.Style := bsClear;
  578.     if Self.Parent.ParentMenu.UseSkinFont
  579.     then
  580.       begin
  581.         Font.Name := MI.FontName;
  582.         Font.Style := MI.FontStyle;
  583.         Font.Height := MI.FontHeight;
  584.         Font.CharSet := Self.Parent.ParentMenu.FDefaultMenuItemFont.Charset;
  585.       end
  586.     else
  587.       Font.Assign(Self.Parent.ParentMenu.DefaultMenuItemFont);
  588.     if AActive
  589.     then
  590.       Font.Color := MI.ActiveFontColor
  591.     else
  592.       if MenuItem.Enabled
  593.       then
  594.         Font.Color := MI.FontColor
  595.       else
  596.         Font.Color := MI.UnEnabledFontColor;
  597.     //
  598.     R := Rect(TR.Left + TextOffset, 0, TR.Right - 16, 0);
  599.     DrawText(B.Canvas.Handle, PChar(MenuItem.Caption), Length(MenuItem.Caption), R,
  600.              DT_CALCRECT);
  601.     OffsetRect(R, 0, TR.Top + RectHeight(TR) div 2 - R.Bottom div 2);
  602.     Inc(R.Right, 2);
  603.     DrawText(B.Canvas.Handle,
  604.              PChar(MenuItem.Caption), Length(MenuItem.Caption), R, DT_CENTER or DT_VCENTER);
  605.     // shortcut
  606.     if MIShortCut <> ''
  607.     then
  608.       begin
  609.         SR := Rect(0, 0, 0, 0);
  610.         DrawText(B.Canvas.Handle, PChar(MIShortCut), Length(MIShortCut), SR,
  611.                  DT_CALCRECT);
  612.         SR := Rect(TR.Right - SR.Right - 16, R.Top, TR.Right - 16, R.Bottom);
  613.         DrawText(B.Canvas.Handle,
  614.            PChar(MIShortCut), Length(MIShortCut), SR, DT_CENTER or DT_VCENTER);
  615.       end;
  616.     //
  617.     if MenuItem.Count <> 0
  618.     then
  619.       DrawSubImage(B.Canvas,
  620.                    TR.Right - 7, TR.Top + RectHeight(TR) div 2 - 4,
  621.                    B.Canvas.Font.Color);
  622.     //
  623.     DrawGlyph := (Parent.ImgL <> nil) and (MenuItem.ImageIndex > -1) and
  624.        (MenuItem.ImageIndex < Parent.ImgL.Count);
  625.     if DrawGlyph
  626.     then
  627.       begin
  628.         GX := TR.Left + 2;
  629.         GY := TR.Top + RectHeight(TR) div 2 - Parent.ImgL.Height div 2;
  630.         if MenuItem.Checked
  631.         then
  632.           begin
  633.             Brush.Style := bsClear;
  634.             Pen.Color := Font.Color;
  635.             Rectangle(GX - 1, GY - 1,
  636.                       GX + Parent.ImgL.Width + 1,
  637.                       GY + Parent.ImgL.Height + 1);
  638.           end;
  639.       end
  640.     else
  641.       begin
  642.         IY := TR.Top + RectHeight(TR) div 2 - 4;
  643.         IX := TR.Left + 2;
  644.         if (MenuItem.Name = MI_CLOSENAME) or (MenuItem.Name = TMI_CLOSENAME) 
  645.         then DrawCloseImage(B.Canvas, IX, IY, B.Canvas.Font.Color) else
  646.         if MenuItem.Name = MI_MINNAME
  647.         then DrawMinimizeImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  648.         else
  649.         if MenuItem.Name = MI_MAXNAME
  650.         then DrawMaximizeImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  651.         else
  652.         if (MenuItem.Name = MI_RESTORENAME) or (MenuItem.Name = TMI_RESTORENAME)
  653.         then DrawRestoreImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  654.         else
  655.         if MenuItem.Name = MI_ROLLUPNAME
  656.         then DrawRollUpImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  657.         else
  658.         if MenuItem.Name = MI_MINTOTRAYNAME
  659.         then DrawMTImage(B.Canvas, IX, IY, B.Canvas.Font.Color)
  660.         else
  661.         if MenuItem.Checked
  662.         then
  663.           if MenuItem.RadioItem
  664.           then
  665.             DrawRadioImage(B.Canvas,
  666.                            TR.Left + 2, TR.Top + RectHeight(TR) div 2 - 3,
  667.                            B.Canvas.Font.Color)
  668.           else
  669.             DrawCheckImage(B.Canvas,
  670.                            TR.Left + 2, TR.Top + RectHeight(TR) div 2 - 4,
  671.                            B.Canvas.Font.Color);
  672.       end;
  673.   end;
  674.   //
  675.   if DrawGlyph
  676.   then
  677.     Parent.ImgL.Draw(B.Canvas, GX, GY, MenuItem.ImageIndex, MenuItem.Enabled);
  678. end;
  679. var
  680.   B, AB: TBitMap;
  681.   EffB, EffAB: TspEffectBmp;
  682.   AD: Boolean;
  683. begin
  684.   if not FVisible then Exit;
  685.   if MI = nil
  686.   then
  687.     begin
  688.       DefaultDraw(Cnvs);
  689.       Exit;
  690.     end;
  691.   B := TBitMap.Create;
  692.   if MenuItem.Caption = '-'
  693.   then
  694.     begin
  695.       CreateHSkinImage(MI.DividerLO, MI.DividerRO,
  696.         B, ActivePicture, MI.DividerRect,
  697.         RectWidth(ObjectRect), RectHeight(ObjectRect));
  698.       if Parent.AlphaBlend and not CheckW2KWXP
  699.       then
  700.         begin
  701.           EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  702.           kf := 1 - Parent.AlphaBlendValue / 255;
  703.           EB1.MorphRect(Parent.ESc, kf, Rect(0, 0, B.Width, B.Height),
  704.             ObjectRect.Left, ObjectRect.Top);
  705.           EB1.Draw(Cnvs.Handle, ObjectRect.Left, ObjectRect.Top);
  706.           EB1.Free;
  707.         end
  708.       else
  709.         Cnvs.Draw(ObjectRect.Left, ObjectRect.Top, B);
  710.      end
  711.   else
  712.     begin
  713.       AD := Active or Down;
  714.       if not MI.Morphing or
  715.       ((AD and (MorphKf = 1)) or (not AD and (MorphKf  = 0)))
  716.       then
  717.         begin
  718.           CreateItemImage(B, AD);
  719.           if Parent.AlphaBlend and not CheckW2KWXP
  720.           then
  721.             begin
  722.               EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  723.               kf := 1 - Parent.AlphaBlendValue / 255;
  724.               EB1.MorphRect(Parent.ESc, kf, Rect(0, 0, B.Width, B.Height),
  725.                 ObjectRect.Left, ObjectRect.Top);
  726.               EB1.Draw(Cnvs.Handle, ObjectRect.Left, ObjectRect.Top);
  727.               EB1.Free;
  728.             end
  729.           else
  730.             Cnvs.Draw(ObjectRect.Left, ObjectRect.Top, B);
  731.         end
  732.       else
  733.         begin
  734.           CreateItemImage(B, False);
  735.           AB := TBitMap.Create;
  736.           CreateItemImage(AB, True);
  737.           EffB := TspEffectBmp.CreateFromhWnd(B.Handle);
  738.           EffAB := TspEffectBmp.CreateFromhWnd(AB.Handle);
  739.           case MI.MorphKind of
  740.             mkDefault: EffB.Morph(EffAB, MorphKf);
  741.             mkGradient: EffB.MorphGrad(EffAB, MorphKf);
  742.             mkLeftGradient: EffB.MorphLeftGrad(EffAB, MorphKf);
  743.             mkRightGradient: EffB.MorphRightGrad(EffAB, MorphKf);
  744.             mkLeftSlide: EffB.MorphLeftSlide(EffAB, MorphKf);
  745.             mkRightSlide: EffB.MorphRightSlide(EffAB, MorphKf);
  746.             mkPush: EffB.MorphPush(EffAB, MorphKf);
  747.           end;
  748.           if Parent.AlphaBlend and not CheckW2KWXP
  749.           then
  750.             begin
  751.               kf := 1 - Parent.AlphaBlendValue / 255;
  752.               EffB.MorphRect(Parent.ESc, kf, Rect(0, 0, B.Width, B.Height),
  753.                 ObjectRect.Left, ObjectRect.Top);
  754.             end;
  755.           EffB.Draw(Cnvs.Handle, ObjectRect.Left, ObjectRect.Top);
  756.           AB.Free;
  757.           EffB.Free;
  758.           EffAB.Free;
  759.         end;
  760.     end;
  761.   B.Free;
  762. end;
  763. //================TspSkinPopupWindow======================//
  764. constructor TspSkinPopupWindow.CreateEx;
  765. begin
  766.   inherited Create(AOwner);
  767.   ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable,
  768.                   csAcceptsControls];
  769.   ParentMenu := AParentMenu;
  770.   AlphaBlend := ParentMenu.AlphaBlend;
  771.   AlphaBlendValue := ParentMenu.AlphaBlendValue;
  772.   AlphaBlendAnimation := ParentMenu.AlphaBlendAnimation;
  773.   Ctl3D := False;
  774.   ParentCtl3D := False;
  775.   Visible := False;
  776.   ItemList := TList.Create;
  777.   MouseTimer := TTimer.Create(Self);
  778.   MouseTimer.Enabled := False;
  779.   MouseTimer.OnTimer := TestMouse;
  780.   MouseTimer.Interval := MouseTimerInterval;
  781.   MorphTimer := TTimer.Create(Self);
  782.   MorphTimer.Enabled := False;
  783.   MorphTimer.OnTimer := TestMorph;
  784.   MorphTimer.Interval := MorphTimerInterval;
  785.   FRgn := 0;
  786.   WindowPicture := nil;
  787.   MaskPicture := nil;
  788.   if (AData = nil) or (AData.WindowPictureIndex = -1)
  789.   then
  790.     begin
  791.       PW := nil;
  792.       SD := nil;
  793.     end
  794.   else
  795.     begin
  796.       PW := AData;
  797.       SD := ParentMenu.SkinData;
  798.       with PW do
  799.       begin
  800.         if (WindowPictureIndex <> - 1) and
  801.            (WindowPictureIndex < SD.FActivePictures.Count)
  802.         then
  803.           WindowPicture := SD.FActivePictures.Items[WindowPictureIndex];
  804.         if (MaskPictureIndex <> - 1) and
  805.            (MaskPictureIndex < SD.FActivePictures.Count)
  806.         then
  807.           MaskPicture := SD.FActivePictures.Items[MaskPictureIndex];
  808.       end;
  809.     end;
  810.   ActiveItem := -1;
  811.   OldActiveItem := -1;
  812.   OMX := -1;
  813.   OMY := -1;
  814.   Sc := TBitMap.Create;
  815.   Esc := nil;
  816.   WT := TTimer.Create(Self);
  817.   WT.Enabled := False;
  818.   WT.OnTimer := WTProc;
  819.   WT.Interval := 100;
  820.   DSMI := nil;
  821.   ScrollCode := 0;
  822. end;
  823. destructor TspSkinPopupWindow.Destroy;
  824. var
  825.   i: Integer;
  826. begin
  827.   for i := 0 to ItemList.Count - 1 do
  828.     TspSkinMenuItem(ItemList.Items[i]).Free;
  829.   ItemList.Clear;
  830.   ItemList.Free;
  831.   MouseTimer.Free;
  832.   MorphTimer.Free;
  833.   Sc.Free;
  834.   if Esc <> nil then Esc.Free;
  835.   inherited Destroy;
  836.   if FRgn <> 0 then DeleteObject(FRgn);
  837. end;
  838. function TspSkinPopupWindow.CanScroll;
  839. begin
  840.   Result := False;
  841.   case AScrollCode of
  842.     1: Result := VisibleStartIndex > 0;
  843.     2: Result := VisibleStartIndex + VisibleCount - 1 < ItemList.Count - 1;
  844.   end;
  845. end;
  846. procedure TspSkinPopupWindow.WMTimer;
  847. begin
  848.   inherited;
  849.   case ScrollCode of
  850.     1: if CanScroll(1) then ScrollUp(False) else StopScroll;
  851.     2: if CanScroll(2) then ScrollDown(False) else StopScroll;
  852.   end;
  853. end;
  854. procedure TspSkinPopupWindow.DrawUpMarker;
  855. var
  856.   R: TRect;
  857.   C: TColor;
  858. begin
  859.   if PW <> nil
  860.   then
  861.     begin
  862.       R := Rect(NewItemsRect.Left, NewItemsRect.Top,
  863.                 NewItemsRect.Right, NewItemsRect.Top + MarkerItemHeight);
  864.       if ScrollCode = 1
  865.       then C := PW.ScrollMarkerActiveColor
  866.       else C := PW.ScrollMarkerColor;
  867.     end
  868.   else
  869.     begin
  870.       R := Rect(3, 3, Width - 3, 3 + MarkerItemHeight);
  871.       if ScrollCode = 1
  872.       then C := clBtnText
  873.       else C := clBtnShadow;
  874.     end;  
  875.   DrawArrowImage(Cnvs, R, C, 3);
  876. end;
  877. procedure TspSkinPopupWindow.DrawDownMarker;
  878. var
  879.   R: TRect;
  880.   C: TColor;
  881. begin
  882.   if PW <> nil
  883.   then
  884.     begin
  885.       R := Rect(NewItemsRect.Left, NewItemsRect.Bottom - MarkerItemHeight,
  886.             NewItemsRect.Right, NewItemsRect.Bottom);
  887.       if ScrollCode = 2
  888.       then C := PW.ScrollMarkerActiveColor
  889.       else C := PW.ScrollMarkerColor;
  890.     end
  891.   else
  892.     begin
  893.       R := Rect(3, Height - MarkerItemHeight, Width - 3, Height - 3);
  894.       if ScrollCode = 2
  895.       then C := clBtnText
  896.       else C := clBtnShadow;
  897.     end;
  898.   DrawArrowImage(Cnvs, R, C, 4);
  899. end;
  900. procedure TspSkinPopupWindow.StartScroll;
  901. var
  902.   i: Integer;
  903. begin
  904.   i := ParentMenu.GetPWIndex(Self);
  905.   WT.Enabled := False;
  906.   ParentMenu.CloseMenu(i + 1);
  907.   KillTimer(Handle, 1);
  908.   SetTimer(Handle, 1, ScrollTimerInterval, nil);
  909. end;
  910. procedure TspSkinPopupWindow.StopScroll;
  911. begin
  912.   ScrollCode := 0;
  913.   DrawUpMarker(Canvas);
  914.   DrawDownMarker(Canvas);
  915.   KillTimer(Handle, 1);
  916. end;
  917. procedure TspSkinPopupWindow.ScrollUp;
  918. begin
  919.   if VisibleStartIndex > 0
  920.   then
  921.     begin
  922.       VisibleStartIndex := VisibleStartIndex - 1;
  923.       CalcItemRects;
  924.       RePaint;
  925.     end
  926.   else
  927.     if Cycle
  928.     then
  929.       begin
  930.         VisibleStartIndex := GetEndStartVisibleIndex;
  931.         CalcItemRects;
  932.         RePaint;
  933.       end;
  934. end;
  935. procedure TspSkinPopupWindow.ScrollDown(Cycle: Boolean);
  936. begin
  937.   if VisibleStartIndex + VisibleCount - 1 < ItemList.Count - 1
  938.   then
  939.     begin
  940.       VisibleStartIndex := VisibleStartIndex + 1;
  941.       CalcItemRects;
  942.       RePaint;
  943.     end
  944.   else
  945.     if Cycle
  946.     then
  947.       begin
  948.         VisibleStartIndex := 0;
  949.         CalcItemRects;
  950.         RePaint;
  951.       end;
  952. end;
  953. procedure TspSkinPopupWindow.PopupKeyDown(CharCode: Integer);
  954. var
  955.   PW: TspSkinPopupWindow;
  956.  procedure NextItem;
  957.  var
  958.    i, j: Integer;
  959.  begin
  960.    if Scroll and (ScrollCode = 0) and (ActiveItem = VisibleStartIndex + VisibleCount - 1)
  961.    then ScrollDown(True);
  962.    OldActiveItem := ActiveItem;
  963.    if ActiveItem < 0 then j := 0 else j := ActiveItem + 1;
  964.    if j = ItemList.Count then j := 0;
  965.    for i := j to ItemList.Count - 1 do
  966.      with TspSkinMenuItem(ItemList.Items[i]) do
  967.      begin
  968.        if MenuItem.Enabled and (MenuItem.Caption <> '-')
  969.        then
  970.          begin
  971.            ActiveItem := i;
  972.            Break;
  973.          end
  974.        else
  975.          begin
  976.            if Scroll and (ScrollCode = 0) and (i = VisibleStartIndex + VisibleCount - 1)
  977.            then ScrollDown(True);
  978.          end;
  979.      end;
  980.    if OldActiveItem <> ActiveItem
  981.    then
  982.      begin
  983.        if ActiveItem > -1 then
  984.        with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  985.        begin
  986.          MouseEnter(True);
  987.        end;
  988.        if OldActiveItem > -1 then
  989.        with TspSkinMenuItem(ItemList.Items[OldActiveItem]) do
  990.         begin
  991.           MouseLeave;
  992.         end;
  993.      end;
  994.  end;
  995.  procedure PriorItem;
  996.  var
  997.    i, j: Integer;
  998.  begin
  999.    if Scroll and (ScrollCode = 0) and (ActiveItem = VisibleStartIndex)
  1000.    then ScrollUp(True);
  1001.    OldActiveItem := ActiveItem;
  1002.    if ActiveItem < 0 then j := ItemList.Count - 1 else j := ActiveItem - 1;
  1003.    if (j = -1) then j := ItemList.Count - 1;
  1004.    for i := j downto 0 do
  1005.      with TspSkinMenuItem(ItemList.Items[i]) do
  1006.      begin
  1007.        if MenuItem.Enabled and (MenuItem.Caption <> '-')
  1008.        then
  1009.          begin
  1010.            ActiveItem := i;
  1011.            Break;
  1012.          end
  1013.        else
  1014.          begin
  1015.            if Scroll and (ScrollCode = 0) and  (i = VisibleStartIndex)
  1016.            then ScrollUp(True);
  1017.          end;
  1018.      end;
  1019.    if OldActiveItem <> ActiveItem
  1020.    then
  1021.      begin
  1022.        if ActiveItem > -1 then
  1023.        with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  1024.        begin
  1025.          MouseEnter(True);
  1026.        end;
  1027.        if OldActiveItem > -1 then
  1028.        with TspSkinMenuItem(ItemList.Items[OldActiveItem]) do
  1029.         begin
  1030.           MouseLeave;
  1031.         end;
  1032.      end;
  1033.  end;
  1034. function FindHotKeyItem: Boolean;
  1035. var
  1036.   i: Integer;
  1037. begin
  1038.   Result := False;
  1039.   for i := 0 to ItemList.Count - 1 do
  1040.       with TspSkinMenuItem(ItemList.Items[i]) do
  1041.       begin
  1042.         if Enabled and IsAccel(CharCode, MenuItem.Caption)
  1043.         then
  1044.           begin
  1045.             MouseEnter(False);
  1046.             OldActiveItem := ActiveItem;
  1047.             ActiveItem := i;
  1048.             if OldActiveItem <> -1
  1049.             then
  1050.               TspSkinMenuItem(ItemList.Items[OldActiveItem]).MouseLeave;
  1051.             MouseDown(0, 0);
  1052.             Result := True;
  1053.             Break;
  1054.           end;
  1055.       end
  1056. end;
  1057. begin
  1058.   if not Visible then Exit;
  1059.   if not FindHotKeyItem
  1060.   then 
  1061.   case CharCode of
  1062.     VK_DOWN:
  1063.       NextItem;
  1064.     VK_UP:
  1065.       PriorItem;
  1066.     VK_RIGHT:
  1067.       begin
  1068.         if ActiveItem <> -1
  1069.         then
  1070.           with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  1071.           begin
  1072.             if MenuItem.Count <> 0 then MouseDown(0, 0);
  1073.           end;
  1074.       end;
  1075.     VK_RETURN:
  1076.       begin
  1077.         if ActiveItem <> -1
  1078.         then
  1079.           with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  1080.           begin
  1081.             MouseDown(0, 0);
  1082.           end;
  1083.       end;
  1084.     VK_LEFT:
  1085.       begin
  1086.         if ParentMenu.FPopupList.Count > 1
  1087.         then
  1088.           begin
  1089.             ParentMenu.CloseMenu(ParentMenu.FPopupList.Count - 1);
  1090.             PW := TspSkinPopupWindow(ParentMenu.FPopupList.Items[ParentMenu.FPopupList.Count - 1]);
  1091.             if PW.ActiveItem <> -1
  1092.             then
  1093.               TspSkinMenuItem(PW.ItemList.Items[PW.ActiveItem]).Down := False;
  1094.           end
  1095.       end;
  1096.     VK_ESCAPE:
  1097.       begin
  1098.         ParentMenu.CloseMenu(ParentMenu.FPopupList.Count - 1);
  1099.         if ParentMenu.FPopupList.Count > 0
  1100.         then
  1101.           begin
  1102.             PW := TspSkinPopupWindow(ParentMenu.FPopupList.Items[ParentMenu.FPopupList.Count - 1]);
  1103.             if PW.ActiveItem <> -1
  1104.             then
  1105.               TspSkinMenuItem(PW.ItemList.Items[PW.ActiveItem]).Down := False;
  1106.           end;   
  1107.       end;
  1108.   end;
  1109. end;
  1110. procedure TspSkinPopupWindow.WTProc;
  1111. begin
  1112.   Sc.Width := Width + 1;
  1113.   Sc.Height := Height + 1;
  1114.   GetScreenImage(ShowX, ShowY, Sc);
  1115.   ESc := TspEffectBMP.CreateFromhWnd(Sc.Handle);
  1116.   //
  1117.   if (PW <> nil) and (PW.CursorIndex <> -1)
  1118.   then
  1119.     Cursor := SD.StartCursorIndex + PW.CursorIndex;
  1120.   //
  1121.   SetWindowPos(Handle, HWND_TOPMOST, ShowX, ShowY, 0, 0,
  1122.       SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
  1123.   Visible := True;
  1124.   MouseTimer.Enabled := True;
  1125.   if ItemList.Count > 0
  1126.   then
  1127.     begin
  1128.       ActiveItem := 0;
  1129.       TspSkinMenuItem(ItemList.Items[0]).MouseEnter(True);
  1130.     end;
  1131.   WT.Enabled := False;
  1132. end;
  1133. procedure TspSkinPopupWindow.UpDatePW;
  1134. var
  1135.   i: Integer;
  1136.   j: Integer;
  1137. begin
  1138.   j := ParentMenu.GetPWIndex(Self);
  1139.   if j + 1 < ParentMenu.FPopupList.Count
  1140.   then ParentMenu.CloseMenu(j + 1);
  1141.   for i := 0 to ItemList.Count - 1 do
  1142.     if TspSkinMenuItem(ItemList.Items[i]).Down
  1143.     then
  1144.       with TspSkinMenuItem(ItemList.Items[i]) do
  1145.       begin
  1146.         Down := False;
  1147.         ReDraw;
  1148.       end;
  1149. end;
  1150. procedure TspSkinPopupWindow.TestMorph;
  1151. var
  1152.   i: Integer;
  1153.   StopMorph: Boolean;
  1154. begin
  1155.   if PW = nil then Exit;
  1156.   StopMorph := True;
  1157.   for i := 0 to ItemList.Count  - 1 do
  1158.     with TspSkinMenuItem(ItemList.Items[i]) do
  1159.     begin
  1160.       if MI.Morphing and CanMorphing
  1161.       then
  1162.         begin
  1163.           DoMorphing;
  1164.           StopMorph := False;
  1165.         end;
  1166.     end;
  1167.   if StopMorph then MorphTimer.Enabled := False;
  1168. end;
  1169. procedure TspSkinPopupWindow.SetMenuWindowRegion;
  1170. var
  1171.   TempRgn: HRgn;
  1172. begin
  1173.   if PW = nil then Exit;
  1174.   TempRgn := FRgn;
  1175.   CreateSkinRegion
  1176.     (FRgn, PW.LTPoint, PW.RTPoint, PW.LBPoint, PW.RBPoint, PW.ItemsRect,
  1177.      NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewItemsRect,
  1178.      MaskPicture, Width, Height);
  1179.   SetWindowRgn(Handle, FRgn, True);
  1180.   if TempRgn <> 0 then DeleteObject(TempRgn);
  1181. end;
  1182. procedure TspSkinPopupWindow.CreateRealImage;
  1183. var
  1184.   EB1: TspEffectBmp;
  1185.   Kf: Double;
  1186.   R: TRect;
  1187.   TextOffset: Integer;
  1188. begin
  1189.   if PW <> nil
  1190.   then
  1191.     CreateSkinImageBS(PW.LTPoint, PW.RTPoint, PW.LBPoint, PW.RBPoint,
  1192.       PW.ItemsRect, NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint,
  1193.       NewItemsRect, B, WindowPicture,
  1194.       Rect(0, 0, WindowPicture.Width, WindowPicture.Height),
  1195.       Width, Height, Scroll,
  1196.       PW.LeftStretch, PW.TopStretch,
  1197.       PW.RightStretch, PW.BottomStretch)
  1198.   else
  1199.     begin
  1200.       B.Width := Width;
  1201.       B.Height := Height;
  1202.       with B.Canvas do
  1203.       begin
  1204.         if ImgL = nil
  1205.         then TextOffset := 22
  1206.         else TextOffset := GlyphWidth + 3;
  1207.         R := Rect(0, 0, TextOffset, Height);
  1208.         Brush.Color := clBtnFace;
  1209.         FillRect(R);
  1210.         R := Rect(TextOffset, 0, Width, Height);
  1211.         Brush.Color := clWindow;
  1212.         FillRect(R);
  1213.       end;
  1214.       R := Rect(0, 0, Width, Height);
  1215.       Frame3D(B.Canvas, R, clBtnShadow, clBtnShadow, 1);
  1216.       Frame3D(B.Canvas, R, clWindow, clWindow, 1);
  1217.     end;
  1218.   if AlphaBlend and not CheckW2KWXP
  1219.   then
  1220.     begin
  1221.       EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  1222.       kf := 1 - AlphaBlendValue / 255;
  1223.       EB1.MorphRect(ESc, kf, Rect(0, 0, B.Width, B.Height), 0, 0);
  1224.       EB1.Draw(B.Canvas.Handle, 0, 0);
  1225.       EB1.Free;
  1226.     end;
  1227. end;
  1228. procedure TspSkinPopupWindow.CreateMenu;
  1229. var
  1230.   sw, sh: Integer;
  1231.   i, j: Integer;
  1232.   Menu: TMenu;
  1233.   function CalcItemTextWidth(Item: TMenuItem): Integer;
  1234.   var
  1235.     R: TRect;
  1236.     MICaption: String;
  1237.   begin
  1238.    if Item.ShortCut <> 0
  1239.    then
  1240.      MICaption := Item.Caption + '  ' + ShortCutToText(Item.ShortCut)
  1241.    else
  1242.      MICaption := Item.Caption;
  1243.     R := Rect(0, 0, 0, 0);
  1244.     DrawText(Canvas.Handle, PChar(MICaption), Length(MICaption), R,
  1245.              DT_CALCRECT);
  1246.     Result := R.Right + 2;
  1247.   end;
  1248.   function GetMenuWindowHeight: Integer;
  1249.   var
  1250.     i, j, ih: integer;
  1251.   begin
  1252.     j := 0;
  1253.     for i := VisibleStartIndex to VisibleCount - 1 do
  1254.     with TspSkinMenuItem(ItemList.Items[i]) do
  1255.      begin
  1256.       if PW <> nil
  1257.       then
  1258.         begin
  1259.           if MenuItem.Caption = '-'
  1260.           then ih := RectHeight(DSMI.DividerRect)
  1261.           else ih := RectHeight(DSMI.SkinRect);
  1262.         end
  1263.       else
  1264.         begin
  1265.           if MenuItem.Caption = '-'
  1266.           then ih := 4
  1267.           else ih := ParentMenu.DefaultMenuItemHeight;
  1268.         end;
  1269.       inc(j, ih);
  1270.     end;
  1271.     if PW <> nil
  1272.     then
  1273.       Result := j + PW.ItemsRect.Top + (WindowPicture.Height - PW.ItemsRect.Bottom)
  1274.     else
  1275.       Result := j + 6;
  1276.   end;
  1277.   function GetMenuWindowWidth: Integer;
  1278.   var
  1279.     i, iw: Integer;
  1280.   begin
  1281.     iw := 0;
  1282.     for i := 0 to ItemList.Count - 1 do
  1283.     begin
  1284.       j := CalcItemTextWidth(TspSkinMenuItem(ItemList.Items[i]).MenuItem);
  1285.       if j > iw then iw := j;
  1286.     end;
  1287.     inc(iw, 16);
  1288.     if ImgL <> nil
  1289.     then
  1290.       GlyphWidth := ImgL.Width + 5
  1291.     else
  1292.       GlyphWidth := 16;
  1293.     Inc(iw, GlyphWidth);
  1294.     if (PW <> nil)
  1295.     then
  1296.       begin
  1297.         Inc(iw, DSMI.TextRct.Left);
  1298.         Inc(iw, RectWidth(DSMI.SkinRect) - DSMI.TextRct.Right);
  1299.         Result := iw + PW.ItemsRect.Left + (WindowPicture.Width - PW.ItemsRect.Right);
  1300.       end
  1301.     else
  1302.       Result := iw + 10;
  1303.   end;
  1304. procedure CalcSizes;
  1305. var
  1306.   W, H: Integer;
  1307. begin
  1308.   //
  1309.   VisibleStartIndex := 0;
  1310.   VisibleCount := ItemList.Count;
  1311.   W := GetMenuWindowWidth;
  1312.   H := GetMenuWindowHeight;
  1313.   Scroll := False;
  1314.   //
  1315.   if H > RectHeight(ParentMenu.WorkArea)
  1316.   then
  1317.     begin
  1318.       H := RectHeight(ParentMenu.WorkArea);
  1319.       Scroll := True;
  1320.     end;  
  1321.   //
  1322.   Width := W;
  1323.   Height := H;
  1324. end;
  1325. begin
  1326.   if SD <> nil
  1327.   then
  1328.     begin
  1329.       i := SD.GetIndex('MENUITEM');
  1330.       if i = -1 then i := SD.GetIndex('menuitem');
  1331.     end
  1332.   else
  1333.     i := -1;
  1334.   if (PW <> nil) and (i <> - 1) and ParentMenu.UseSkinFont
  1335.   then
  1336.     begin
  1337.       // init menu
  1338.       DSMI := TspDataSkinMenuItem(SD.ObjectList.Items[i]);
  1339.       with Canvas.Font do
  1340.       begin
  1341.         Height := DSMI.FontHeight;
  1342.         Style := DSMI.FontStyle;
  1343.         Name := DSMI.FontName;
  1344.         CharSet := ParentMenu.FDefaultMenuItemFont.Charset;
  1345.       end;
  1346.     end
  1347.   else
  1348.     begin
  1349.       if (i <> -1)
  1350.       then
  1351.         DSMI := TspDataSkinMenuItem(SD.ObjectList.Items[i])
  1352.       else
  1353.         DSMI := nil;
  1354.       Canvas.Font.Assign(Self.ParentMenu.FDefaultMenuItemFont);
  1355.     end;
  1356.   Menu := Item.GetParentMenu;
  1357.   ImgL := Menu.Images;
  1358.   j := Item.Count;
  1359.   for i := StartIndex to  j - 1 do
  1360.    if TMenuItem(Item.Items[i]).Visible
  1361.    then
  1362.      begin
  1363.        if TMenuItem(Item.Items[i]).Action <> nil
  1364.        then
  1365.          TMenuItem(Item.Items[i]).Action.Update;
  1366.        ItemList.Add(TspSkinMenuItem.Create(Self, TMenuItem(Item.Items[i]), DSMI));
  1367.      end;
  1368.   //
  1369.   CalcSizes;
  1370.   if PW <> nil
  1371.   then
  1372.     begin
  1373.       sw := WindowPicture.Width;
  1374.       sh := WindowPicture.Height;
  1375.       NewLTPoint := PW.LTPoint;
  1376.       NewRTPoint := Point(Width - (sw - PW.RTPoint.X), PW.RTPoint.Y);
  1377.       NewLBPoint := Point(PW.LBPoint.X, Height - (sh - PW.LBPoint.Y));
  1378.       NewRBPoint := Point(Width - (sw - PW.RBPoint.X),
  1379.                           Height - (sh - PW.RBPoint.Y));
  1380.       NewItemsRect := Rect(PW.ItemsRect.Left, PW.ItemsRect.Top,
  1381.                            Width - (sw - PW.ItemsRect.Right),
  1382.                            Height - (sh - PW.ItemsRect.Bottom));
  1383.     end
  1384.   else
  1385.     NewItemsRect := Rect(3, 3, Width - 3, Height - 3);
  1386.   CalcItemRects;
  1387.   if MaskPicture <> nil then SetMenuWindowRegion;
  1388. end;
  1389. procedure TspSkinPopupWindow.CreateMenu2;
  1390. var
  1391.   sw, sh: Integer;
  1392.   i, j: Integer;
  1393.   Menu: TMenu;
  1394.   function CalcItemTextWidth(Item: TMenuItem): Integer;
  1395.   var
  1396.     R: TRect;
  1397.     MICaption: String;
  1398.   begin
  1399.    if Item.ShortCut <> 0
  1400.    then
  1401.      MICaption := Item.Caption + '  ' + ShortCutToText(Item.ShortCut)
  1402.    else
  1403.      MICaption := Item.Caption;
  1404.     R := Rect(0, 0, 0, 0);
  1405.     DrawText(Canvas.Handle, PChar(MICaption), Length(MICaption), R,
  1406.              DT_CALCRECT);
  1407.     Result := R.Right + 2;
  1408.   end;
  1409.   function GetMenuWindowHeight: Integer;
  1410.   var
  1411.     i, j, ih: integer;
  1412.   begin
  1413.     j := 0;
  1414.     for i := VisibleStartIndex to VisibleCount - 1 do
  1415.     with TspSkinMenuItem(ItemList.Items[i]) do
  1416.      begin
  1417.       if PW <> nil
  1418.       then
  1419.         begin
  1420.           if MenuItem.Caption = '-'
  1421.           then ih := RectHeight(DSMI.DividerRect)
  1422.           else ih := RectHeight(DSMI.SkinRect);
  1423.         end
  1424.       else
  1425.         begin
  1426.           if MenuItem.Caption = '-'
  1427.           then ih := 4
  1428.           else ih := ParentMenu.DefaultMenuItemHeight;
  1429.         end;
  1430.       inc(j, ih);
  1431.     end;
  1432.     if PW <> nil
  1433.     then
  1434.       Result := j + PW.ItemsRect.Top + (WindowPicture.Height - PW.ItemsRect.Bottom)
  1435.     else
  1436.       Result := j + 6;
  1437.   end;
  1438.   function GetMenuWindowWidth: Integer;
  1439.   var
  1440.     i, iw: Integer;
  1441.   begin
  1442.     iw := 0;
  1443.     for i := 0 to ItemList.Count - 1 do
  1444.     begin
  1445.       j := CalcItemTextWidth(TspSkinMenuItem(ItemList.Items[i]).MenuItem);
  1446.       if j > iw then iw := j;
  1447.     end;
  1448.     inc(iw, 16);
  1449.     if ImgL <> nil
  1450.     then
  1451.       GlyphWidth := ImgL.Width + 5
  1452.     else
  1453.       GlyphWidth := 16;
  1454.     Inc(iw, GlyphWidth);
  1455.     if (PW <> nil)
  1456.     then
  1457.       begin
  1458.         Inc(iw, DSMI.TextRct.Left);
  1459.         Inc(iw, RectWidth(DSMI.SkinRect) - DSMI.TextRct.Right);
  1460.         Result := iw + PW.ItemsRect.Left + (WindowPicture.Width - PW.ItemsRect.Right);
  1461.       end
  1462.     else
  1463.       Result := iw + 10;
  1464.   end;
  1465. procedure CalcSizes;
  1466. var
  1467.   W, H: Integer;
  1468. begin
  1469.   //
  1470.   VisibleStartIndex := 0;
  1471.   VisibleCount := ItemList.Count;
  1472.   W := GetMenuWindowWidth;
  1473.   H := GetMenuWindowHeight;
  1474.   Scroll := False;
  1475.   //
  1476.   if H > RectHeight(ParentMenu.WorkArea)
  1477.   then
  1478.     begin
  1479.       H := RectHeight(ParentMenu.WorkArea);
  1480.       Scroll := True;
  1481.     end;  
  1482.   //
  1483.   Width := W;
  1484.   Height := H;
  1485. end;
  1486. var
  1487.   TmpStartIndex: Integer;
  1488. begin
  1489.   if SD <> nil
  1490.   then
  1491.     begin
  1492.       i := SD.GetIndex('MENUITEM');
  1493.       if i = -1 then i := SD.GetIndex('menuitem');
  1494.     end
  1495.   else
  1496.     i := -1;
  1497.   if (PW <> nil) and (i <> - 1) and ParentMenu.UseSkinFont
  1498.   then
  1499.     begin
  1500.       // init menu
  1501.       DSMI := TspDataSkinMenuItem(SD.ObjectList.Items[i]);
  1502.       with Canvas.Font do
  1503.       begin
  1504.         Height := DSMI.FontHeight;
  1505.         Style := DSMI.FontStyle;
  1506.         Name := DSMI.FontName;
  1507.         CharSet := ParentMenu.FDefaultMenuItemFont.Charset;
  1508.       end;
  1509.     end
  1510.   else
  1511.     begin
  1512.       if (i <> -1)
  1513.       then
  1514.         DSMI := TspDataSkinMenuItem(SD.ObjectList.Items[i])
  1515.       else
  1516.         DSMI := nil;
  1517.       Canvas.Font.Assign(Self.ParentMenu.FDefaultMenuItemFont);
  1518.     end;
  1519.   Menu := Item.GetParentMenu;
  1520.   ImgL := Menu.Images;
  1521.   j := Item.Count;
  1522.   if StartIndex < j then
  1523.   for i := StartIndex to  j - 1 do
  1524.    if TMenuItem(Item.Items[i]).Visible
  1525.    then
  1526.      begin
  1527.        if TMenuItem(Item.Items[i]).Action <> nil
  1528.        then
  1529.          TMenuItem(Item.Items[i]).Action.Update;
  1530.        ItemList.Add(TspSkinMenuItem.Create(Self, TMenuItem(Item.Items[i]), DSMI));
  1531.      end;
  1532.   TmpStartIndex := StartIndex - Item.Count;
  1533.   if TmpStartIndex < 0 then TmpStartIndex := 0;
  1534.   j := Item2.Count;
  1535.   if TmpStartIndex < j then
  1536.   for i := TmpStartIndex to  j - 1 do
  1537.    if TMenuItem(Item2.Items[i]).Visible
  1538.    then
  1539.      begin
  1540.        if TMenuItem(Item2.Items[i]).Action <> nil
  1541.        then
  1542.          TMenuItem(Item2.Items[i]).Action.Update;
  1543.        ItemList.Add(TspSkinMenuItem.Create(Self, TMenuItem(Item2.Items[i]), DSMI));
  1544.      end;
  1545.   //
  1546.   CalcSizes;
  1547.   if PW <> nil
  1548.   then
  1549.     begin
  1550.       sw := WindowPicture.Width;
  1551.       sh := WindowPicture.Height;
  1552.       NewLTPoint := PW.LTPoint;
  1553.       NewRTPoint := Point(Width - (sw - PW.RTPoint.X), PW.RTPoint.Y);
  1554.       NewLBPoint := Point(PW.LBPoint.X, Height - (sh - PW.LBPoint.Y));
  1555.       NewRBPoint := Point(Width - (sw - PW.RBPoint.X),
  1556.                           Height - (sh - PW.RBPoint.Y));
  1557.       NewItemsRect := Rect(PW.ItemsRect.Left, PW.ItemsRect.Top,
  1558.                            Width - (sw - PW.ItemsRect.Right),
  1559.                            Height - (sh - PW.ItemsRect.Bottom));
  1560.     end
  1561.   else
  1562.     NewItemsRect := Rect(3, 3, Width - 3, Height - 3);
  1563.   CalcItemRects;
  1564.   if MaskPicture <> nil then SetMenuWindowRegion;
  1565. end;
  1566. function TspSkinPopupWindow.GetEndStartVisibleIndex: Integer;
  1567. var
  1568.   i, j, k, ih, H: Integer;
  1569. begin
  1570.   j := NewItemsRect.Bottom - MarkerItemHeight;
  1571.   H := MarkerItemHeight;
  1572.   k := 0;
  1573.   for i := ItemList.Count - 1 downto 0 do
  1574.   begin
  1575.     with TspSkinMenuItem(ItemList.Items[i]) do
  1576.      begin
  1577.        if DSMI <> nil
  1578.        then
  1579.          begin
  1580.            if MenuItem.Caption = '-'
  1581.            then ih := RectHeight(DSMI.DividerRect)
  1582.            else ih := RectHeight(DSMI.SkinRect);
  1583.          end
  1584.        else
  1585.          begin
  1586.            if MenuItem.Caption = '-'
  1587.            then ih := 4
  1588.            else ih := ParentMenu.DefaultMenuItemHeight;
  1589.          end;
  1590.        j := j - ih;
  1591.        if j >= H
  1592.        then
  1593.          inc(k)
  1594.        else
  1595.          Break;
  1596.      end;
  1597.   end;
  1598.   Result := ItemList.Count - k;
  1599. end;
  1600. procedure TspSkinPopupWindow.CalcItemRects;
  1601. var
  1602.   i, j, ih, H: Integer;
  1603. begin
  1604.   j := NewItemsRect.Top;
  1605.   H := NewItemsRect.Bottom;
  1606.   if Scroll
  1607.   then
  1608.     begin
  1609.       H := H - MarkerItemHeight;
  1610.       j := j + MarkerItemHeight;
  1611.     end;
  1612.   VisibleCount := 0;
  1613.   for i := VisibleStartIndex to ItemList.Count - 1 do
  1614.     with TspSkinMenuItem(ItemList.Items[i]) do
  1615.      begin
  1616.       if DSMI <> nil
  1617.       then
  1618.         begin
  1619.           if MenuItem.Caption = '-'
  1620.           then ih := RectHeight(DSMI.DividerRect)
  1621.           else ih := RectHeight(DSMI.SkinRect)
  1622.         end
  1623.       else
  1624.         begin
  1625.           if MenuItem.Caption = '-'
  1626.           then ih := 4
  1627.           else ih := ParentMenu.DefaultMenuItemHeight;
  1628.         end;
  1629.       ObjectRect.Left := NewItemsRect.Left;
  1630.       ObjectRect.Right := NewItemsRect.Right;
  1631.       ObjectRect.Top := j;
  1632.       ObjectRect.Bottom :=  j + ih;
  1633.       if ObjectRect.Bottom <= H
  1634.       then
  1635.         begin
  1636.           FVisible := True;
  1637.           Inc(VisibleCount)
  1638.         end
  1639.       else
  1640.         Break;
  1641.       inc(j, ih);
  1642.     end;
  1643.   if Scroll
  1644.   then
  1645.     begin
  1646.       if VisibleStartIndex > 0
  1647.       then
  1648.         for i := 0 to VisibleStartIndex - 1 do
  1649.           TspSkinMenuItem(ItemList.Items[i]).FVisible := False;
  1650.       if VisibleCount + VisibleStartIndex <= ItemList.Count - 1
  1651.       then
  1652.         for i := VisibleCount + VisibleStartIndex to ItemList.Count - 1 do
  1653.           TspSkinMenuItem(ItemList.Items[i]).FVisible := False;
  1654.     end;
  1655. end;
  1656. procedure TspSkinPopupWindow.CMMouseEnter;
  1657. begin
  1658.   inherited;
  1659. end;
  1660. procedure TspSkinPopupWindow.CMMouseLeave;
  1661. begin
  1662.   inherited;
  1663. end;
  1664. procedure TspSkinPopupWindow.CreateParams(var Params: TCreateParams);
  1665. begin
  1666.   inherited CreateParams(Params);
  1667.   with Params do
  1668.   begin
  1669.     Style := WS_POPUP;
  1670.     ExStyle := WS_EX_TOOLWINDOW;
  1671.     WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
  1672.   end;
  1673. end;
  1674. procedure TspSkinPopupWindow.WMMouseActivate(var Message: TMessage);
  1675. begin
  1676.   Message.Result := MA_NOACTIVATE;
  1677. end;
  1678. procedure TspSkinPopupWindow.Hide;
  1679. begin
  1680.   SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
  1681.     SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
  1682.   MouseTimer.Enabled := False;
  1683.   Visible := False;
  1684. end;
  1685. procedure TspSkinPopupWindow.Show;
  1686. procedure CalcMenuPos(var X, Y: Integer; R: TRect);
  1687. var
  1688.   WA: TRect;
  1689.   ChangeY: Boolean;
  1690.   function GetY: Integer;
  1691.   var
  1692.     Offset: Integer;
  1693.   begin
  1694.     if Scroll
  1695.     then
  1696.       Result := WA.Top
  1697.     else
  1698.       begin
  1699.         if PopupByItem
  1700.         then
  1701.           begin
  1702.             Offset := R.Top + Height - NewItemsRect.Top - WA.Bottom;
  1703.             if Offset > 0
  1704.             then
  1705.               begin
  1706.                 if R.Top < WA.Top + RectHeight(WA) div 2
  1707.                 then
  1708.                   Result := WA.Bottom - Height
  1709.                 else
  1710.                   begin
  1711.                     Result := R.Bottom - Height + NewItemsRect.Top;
  1712.                     if Result  < WA.Top then Result := WA.Top;
  1713.                   end
  1714.               end
  1715.             else
  1716.               Result := R.Top - NewItemsRect.Top;
  1717.           end
  1718.         else
  1719.           begin
  1720.             if PopupUp
  1721.             then
  1722.               begin
  1723.                 if R.Top - Height < WA.Top
  1724.                 then
  1725.                   begin
  1726.                     if R.Top < WA.Top + RectHeight(WA) div 2
  1727.                     then
  1728.                       begin
  1729.                         Result := R.Bottom;
  1730.                         Offset := Result + Height - WA.Bottom;
  1731.                         if Offset > 0
  1732.                         then
  1733.                           begin
  1734.                             Result  := Result - Offset;
  1735.                             ChangeY := True;
  1736.                           end;
  1737.                        end
  1738.                      else
  1739.                        begin
  1740.                          Result := WA.Top;
  1741.                          ChangeY := True;
  1742.                        end;
  1743.                   end
  1744.                 else
  1745.                   Result  := R.Top - Height;
  1746.               end
  1747.             else
  1748.               begin
  1749.                 Offset := R.Bottom + Height - WA.Bottom;
  1750.                 if Offset > 0
  1751.                 then
  1752.                   begin
  1753.                     if R.Top < WA.Top + RectHeight(WA) div 2
  1754.                     then
  1755.                       begin
  1756.                         Result := R.Bottom - Offset;
  1757.                         ChangeY := True
  1758.                       end
  1759.                     else
  1760.                       begin
  1761.                         if R.Top - Height < WA.Top
  1762.                         then
  1763.                           begin
  1764.                             Result := WA.Top;
  1765.                             ChangeY := True;
  1766.                           end
  1767.                         else
  1768.                           Result := R.Top - Height;
  1769.                       end
  1770.                   end
  1771.                 else
  1772.                   Result := R.Bottom;
  1773.               end;
  1774.           end;
  1775.       end;
  1776.   end;
  1777.   function GetX: Integer;
  1778.   begin
  1779.     if PopupByItem or Scroll or ChangeY
  1780.     then
  1781.       begin
  1782.         if R.Right + Width + 1 > WA.Right
  1783.         then Result := R.Left - Width - 1 else Result := R.Right + 1;
  1784.       end
  1785.     else
  1786.       begin
  1787.         if R.Left + Width > WA.Right
  1788.         then Result := WA.Right - Width else
  1789.         if R.Left < WA.Left then Result := WA.Left else Result := R.Left;
  1790.       end;
  1791.   end;
  1792. begin
  1793.   WA := ParentMenu.WorkArea;
  1794.   ChangeY := False;
  1795.   Y := GetY;
  1796.   X := GetX;
  1797. end;
  1798. const
  1799.   WS_EX_LAYERED = $80000;
  1800. var
  1801.   i: Integer;
  1802.   ABV: Byte;
  1803. begin
  1804.   if CheckW2KWXP and ParentMenu.AlphaBlend and ParentMenu.AlphaBlendAnimation and
  1805.      ParentMenu.First
  1806.   then
  1807.     Application.ProcessMessages;
  1808.   CreateMenu(AItem, StartIndex);
  1809.   CalcMenuPos(ShowX, ShowY, R);
  1810.   if AlphaBlend and not CheckW2KWXP
  1811.   then
  1812.     WT.Enabled := True
  1813.   else
  1814.     begin
  1815.       //
  1816.       if (PW <> nil) and (PW.CursorIndex <> -1)
  1817.       then
  1818.         Cursor := SD.StartCursorIndex + PW.CursorIndex;
  1819.       //
  1820.       if CheckW2KWXP and ParentMenu.AlphaBlend
  1821.       then
  1822.         begin
  1823.           SetWindowLong(Handle, GWL_EXSTYLE,
  1824.                         GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  1825.           if ParentMenu.First and ParentMenu.AlphaBlendAnimation
  1826.           then SetAlphaBlendTransparent(Handle, 0)
  1827.           else SetAlphaBlendTransparent(Handle, ParentMenu.AlphaBlendValue);
  1828.         end;
  1829.       //
  1830.       SetWindowPos(Handle, HWND_TOPMOST, ShowX, ShowY, 0, 0,
  1831.       SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
  1832.       Visible := True;
  1833.       //
  1834.       if CheckW2KWXP and ParentMenu.AlphaBlend and ParentMenu.AlphaBlendAnimation and
  1835.          ParentMenu.First
  1836.       then
  1837.         begin
  1838.           i := 0;
  1839.           ABV := ParentMenu.AlphaBlendValue;
  1840.           repeat
  1841.             Inc(i, 2);
  1842.             if i > ABV then i := ABV;
  1843.             SetAlphaBlendTransparent(Handle, i);
  1844.           until i >= ABV;
  1845.         end;
  1846.       //
  1847.       MouseTimer.Enabled := True;
  1848.       ActiveItem := -1;
  1849.       if ItemList.Count > 0
  1850.       then
  1851.         for i := 0 to ItemList.Count - 1 do
  1852.         with TspSkinMenuItem(ItemList.Items[i]) do
  1853.         begin
  1854.           if (MenuItem.Enabled) and (MenuItem.Caption <> '-')
  1855.           then
  1856.             begin
  1857.               WaitCommand := True;
  1858.               ActiveItem := i;
  1859.               MouseEnter(True);
  1860.               Break;
  1861.             end;
  1862.         end;
  1863.       //
  1864.     end;
  1865. end;
  1866. procedure TspSkinPopupWindow.Show2;
  1867. procedure CalcMenuPos(var X, Y: Integer; R: TRect);
  1868. var
  1869.   WA: TRect;
  1870.   ChangeY: Boolean;
  1871.   function GetY: Integer;
  1872.   var
  1873.     Offset: Integer;
  1874.   begin
  1875.     if Scroll
  1876.     then
  1877.       Result := WA.Top
  1878.     else
  1879.       begin
  1880.         if PopupByItem
  1881.         then
  1882.           begin
  1883.             Offset := R.Top + Height - NewItemsRect.Top - WA.Bottom;
  1884.             if Offset > 0
  1885.             then
  1886.               begin
  1887.                 if R.Top < WA.Top + RectHeight(WA) div 2
  1888.                 then
  1889.                   Result := WA.Bottom - Height
  1890.                 else
  1891.                   begin
  1892.                     Result := R.Bottom - Height + NewItemsRect.Top;
  1893.                     if Result  < WA.Top then Result := WA.Top;
  1894.                   end
  1895.               end
  1896.             else
  1897.               Result := R.Top - NewItemsRect.Top;
  1898.           end
  1899.         else
  1900.           begin
  1901.             if PopupUp
  1902.             then
  1903.               begin
  1904.                 if R.Top - Height < WA.Top
  1905.                 then
  1906.                   begin
  1907.                     if R.Top < WA.Top + RectHeight(WA) div 2
  1908.                     then
  1909.                       begin
  1910.                         Result := R.Bottom;
  1911.                         Offset := Result + Height - WA.Bottom;
  1912.                         if Offset > 0
  1913.                         then
  1914.                           begin
  1915.                             Result  := Result - Offset;
  1916.                             ChangeY := True;
  1917.                           end;
  1918.                        end
  1919.                      else
  1920.                        begin
  1921.                          Result := WA.Top;
  1922.                          ChangeY := True;
  1923.                        end;
  1924.                   end
  1925.                 else
  1926.                   Result  := R.Top - Height;
  1927.               end
  1928.             else
  1929.               begin
  1930.                 Offset := R.Bottom + Height - WA.Bottom;
  1931.                 if Offset > 0
  1932.                 then
  1933.                   begin
  1934.                     if R.Top < WA.Top + RectHeight(WA) div 2
  1935.                     then
  1936.                       begin
  1937.                         Result := R.Bottom - Offset;
  1938.                         ChangeY := True
  1939.                       end
  1940.                     else
  1941.                       begin
  1942.                         if R.Top - Height < WA.Top
  1943.                         then
  1944.                           begin
  1945.                             Result := WA.Top;
  1946.                             ChangeY := True;
  1947.                           end
  1948.                         else
  1949.                           Result := R.Top - Height;
  1950.                       end
  1951.                   end
  1952.                 else
  1953.                   Result := R.Bottom;
  1954.               end;
  1955.           end;
  1956.       end;
  1957.   end;
  1958.   function GetX: Integer;
  1959.   begin
  1960.     if PopupByItem or Scroll or ChangeY
  1961.     then
  1962.       begin
  1963.         if R.Right + Width + 1 > WA.Right
  1964.         then Result := R.Left - Width - 1 else Result := R.Right + 1;
  1965.       end
  1966.     else
  1967.       begin
  1968.         if R.Left + Width > WA.Right
  1969.         then Result := WA.Right - Width else
  1970.         if R.Left < WA.Left then Result := WA.Left else Result := R.Left;
  1971.       end;
  1972.   end;
  1973. begin
  1974.   WA := ParentMenu.WorkArea;
  1975.   ChangeY := False;
  1976.   Y := GetY;
  1977.   X := GetX;
  1978. end;
  1979. const
  1980.   WS_EX_LAYERED = $80000;
  1981. var
  1982.   i: Integer;
  1983.   ABV: Byte;
  1984. begin
  1985.   if CheckW2KWXP and ParentMenu.AlphaBlend and ParentMenu.AlphaBlendAnimation and
  1986.      ParentMenu.First
  1987.   then
  1988.     Application.ProcessMessages;
  1989.   CreateMenu2(AItem, AItem2, StartIndex);
  1990.   CalcMenuPos(ShowX, ShowY, R);
  1991.   if AlphaBlend and not CheckW2KWXP
  1992.   then
  1993.     WT.Enabled := True
  1994.   else
  1995.     begin
  1996.       //
  1997.       if (PW <> nil) and (PW.CursorIndex <> -1)
  1998.       then
  1999.         Cursor := SD.StartCursorIndex + PW.CursorIndex;
  2000.       //
  2001.       if CheckW2KWXP and ParentMenu.AlphaBlend
  2002.       then
  2003.         begin
  2004.           SetWindowLong(Handle, GWL_EXSTYLE,
  2005.                         GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  2006.           if ParentMenu.First and ParentMenu.AlphaBlendAnimation
  2007.           then SetAlphaBlendTransparent(Handle, 0)
  2008.           else SetAlphaBlendTransparent(Handle, ParentMenu.AlphaBlendValue);
  2009.         end;
  2010.       //
  2011.       SetWindowPos(Handle, HWND_TOPMOST, ShowX, ShowY, 0, 0,
  2012.       SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
  2013.       Visible := True;
  2014.       //
  2015.       if CheckW2KWXP and ParentMenu.AlphaBlend and ParentMenu.AlphaBlendAnimation and
  2016.          ParentMenu.First
  2017.       then
  2018.         begin
  2019.           i := 0;
  2020.           ABV := ParentMenu.AlphaBlendValue;
  2021.           repeat
  2022.             Inc(i, 2);
  2023.             if i > ABV then i := ABV;
  2024.             SetAlphaBlendTransparent(Handle, i);
  2025.           until i >= ABV;
  2026.         end;
  2027.       //
  2028.       MouseTimer.Enabled := True;
  2029.       ActiveItem := -1;
  2030.       if ItemList.Count > 0
  2031.       then
  2032.         for i := 0 to ItemList.Count - 1 do
  2033.         with TspSkinMenuItem(ItemList.Items[i]) do
  2034.         begin
  2035.           if MenuItem.Enabled and (MenuItem.Caption <> '-')
  2036.           then
  2037.             begin
  2038.               WaitCommand := True;
  2039.               ActiveItem := i;
  2040.               MouseEnter(True);
  2041.               Break;
  2042.             end;
  2043.         end;
  2044.       //
  2045.     end;
  2046. end;
  2047. procedure TspSkinPopupWindow.PaintMenu;
  2048. var
  2049.   C: TCanvas;
  2050.   i: Integer;
  2051.   B: TBitMap;
  2052. begin
  2053.   C := TCanvas.Create;
  2054.   C.Handle := DC;
  2055.   B := TBitMap.Create;
  2056.   CreateRealImage(B);
  2057.   // Draw items
  2058.   for i := VisibleStartIndex to VisibleStartIndex + VisibleCount - 1 do
  2059.     TspSkinMenuItem(ItemList.Items[i]).Draw(B.Canvas);
  2060.   // markers
  2061.   if Scroll
  2062.   then
  2063.     begin
  2064.       DrawUpMarker(B.Canvas);
  2065.       DrawDownMarker(B.Canvas);
  2066.     end;
  2067.   C.Draw(0, 0, B);
  2068.   B.Free;
  2069.   C.Free;
  2070. end;
  2071. procedure TspSkinPopupWindow.WMEraseBkgrnd;
  2072. begin
  2073.   PaintMenu(Message.WParam);
  2074. end;
  2075. procedure TspSkinPopupWindow.MouseUp;
  2076. begin
  2077.   TestActive(X, Y);
  2078.   if (ActiveItem <> -1) and (Button = mbleft) and GetActive(X, Y)
  2079.   then
  2080.     with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  2081.      if MenuItem.Caption <> '-' then MouseDown(X, Y);
  2082. end;
  2083. procedure TspSkinPopupWindow.TestMouse;
  2084. var
  2085.   P, P1: TPoint;
  2086. begin
  2087.   GetCursorPos(P1);
  2088.   P := ScreenToClient(P1);
  2089.   if (OMX <> P.X) or (OMY <> P.Y)
  2090.   then 
  2091.     if InWindow(P1)
  2092.     then
  2093.       TestActive(P.X, P.Y)
  2094.     else
  2095.       if Scroll
  2096.       then
  2097.         begin
  2098.           ScrollCode := 0;
  2099.           DrawUpMarker(Canvas);
  2100.           DrawDownMarker(Canvas);
  2101.         end;
  2102.   OMX := P.X;
  2103.   OMY := P.Y;
  2104. end;
  2105. function TspSkinPopupWindow.GetActive;
  2106. var
  2107.   i: Integer;
  2108. begin
  2109.   i := -1;
  2110.   if ItemList.Count = 0
  2111.   then
  2112.     Result := False
  2113.   else
  2114.   repeat
  2115.     Inc(i);
  2116.     with TspSkinMenuItem(ItemList.Items[i]) do
  2117.       Result := FVisible and PtInRect(ObjectRect, Point(X, Y));
  2118.   until Result or (i = ItemList.Count - 1);
  2119. end;
  2120. procedure TspSkinPopupWindow.TestActive;
  2121. var
  2122.   i: Integer;
  2123.   B: Boolean;
  2124.   R1, R2: TRect;
  2125. begin
  2126.   if Scroll
  2127.   then
  2128.     begin
  2129.       R1 := Rect(NewItemsRect.Left, NewItemsRect.Top,
  2130.             NewItemsRect.Right, NewItemsRect.Top + MarkerItemHeight);
  2131.       R2 := Rect(NewItemsRect.Left, NewItemsRect.Bottom - MarkerItemHeight,
  2132.             NewItemsRect.Right, NewItemsRect.Bottom);
  2133.       if PtInRect(R1, Point(X, Y)) and (ScrollCode = 0) and CanScroll(1)
  2134.       then
  2135.         begin
  2136.           ScrollCode := 1;
  2137.           DrawUpMarker(Canvas);
  2138.           StartScroll;
  2139.         end
  2140.       else
  2141.       if PtInRect(R2, Point(X, Y)) and (ScrollCode = 0)  and CanScroll(2)
  2142.       then
  2143.         begin
  2144.           ScrollCode := 2;
  2145.           DrawDownMarker(Canvas);
  2146.           StartScroll;
  2147.         end
  2148.       else
  2149.         if (ScrollCode <> 0) and not PtInRect(R1, Point(X, Y)) and
  2150.                                  not PtInRect(R2, Point(X, Y))
  2151.         then
  2152.           StopScroll;
  2153.      end;
  2154.   if (ItemList.Count = 0) then Exit;
  2155.   OldActiveItem := ActiveItem;
  2156.   i := -1;
  2157.   repeat
  2158.     Inc(i);
  2159.     with TspSkinMenuItem(ItemList.Items[i]) do
  2160.     begin
  2161.       B := FVisible and PtInRect(ObjectRect, Point(X, Y));
  2162.     end;
  2163.   until B or (i = ItemList.Count - 1);
  2164.   if B then ActiveItem := i;
  2165.   if OldActiveItem >= ItemList.Count then OldActiveItem := -1;
  2166.   if ActiveItem >= ItemList.Count then ActiveItem := -1;
  2167.   if (OldActiveItem = ActiveItem) and (ActiveItem <> -1)
  2168.   then
  2169.     begin
  2170.       with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  2171.        if WaitCommand
  2172.        then
  2173.          begin
  2174.            WaitCommand := False;
  2175.            if MenuItem.Count <> 0
  2176.            then
  2177.              MouseEnter(False);
  2178.          end;
  2179.     end
  2180.   else
  2181.   if (OldActiveItem <> ActiveItem)
  2182.   then
  2183.     begin
  2184.       if OldActiveItem <> - 1
  2185.       then
  2186.         with TspSkinMenuItem(ItemList.Items[OldActiveItem]) do
  2187.         begin
  2188.           if MenuItem.Enabled and (MenuItem.Caption <> '-')
  2189.           then
  2190.             MouseLeave;
  2191.         end;
  2192.       if ActiveItem <> - 1
  2193.       then
  2194.         with TspSkinMenuItem(ItemList.Items[ActiveItem]) do
  2195.         begin
  2196.           if MenuItem.Enabled and (MenuItem.Caption <> '-')
  2197.           then
  2198.             MouseEnter(False);
  2199.         end;
  2200.     end;
  2201. end;
  2202. function TspSkinPopupWindow.InWindow;
  2203. var
  2204.   H: HWND;
  2205. begin
  2206.   H := WindowFromPoint(P);
  2207.   Result := H = Handle;
  2208. end;
  2209. //====================TspSkinMenu===================//
  2210. constructor TspSkinMenu.CreateEx;
  2211. begin
  2212.   inherited Create(AOwner);
  2213.   FUseSkinFont := True;
  2214.   FPopupList := TList.Create;
  2215.   WaitTimer := TTimer.Create(Self);
  2216.   WaitTimer.Enabled := False;
  2217.   WaitTimer.OnTimer := WaitItem;
  2218.   WaitTimer.Interval := WaitTimerInterval;
  2219.   WItem := nil;
  2220.   FVisible := False;
  2221.   FForm := AForm;
  2222.   AlphaBlend := False;
  2223.   AlphaBlendValue := 200;
  2224.   PopupCtrl := nil;
  2225.   DCtrl := nil;
  2226.   FDefaultMenuItemHeight := 20;
  2227.   FDefaultMenuItemFont := TFont.Create;
  2228.   with FDefaultMenuItemFont do
  2229.   begin
  2230.     Name := 'Arial';
  2231.     Style := [];
  2232.     Height := 14;
  2233.   end;
  2234. end;
  2235. destructor TspSkinMenu.Destroy;
  2236. begin
  2237.   CloseMenu(0);
  2238.   FPopupList.Free;
  2239.   WaitTimer.Free;
  2240.   FDefaultMenuItemFont.Free;
  2241.   inherited Destroy;
  2242. end;
  2243. procedure TspSkinMenu.SetDefaultMenuItemFont(Value: TFont);
  2244. begin
  2245.   FDefaultMenuItemFont.Assign(Value);
  2246. end;
  2247. function TspSkinMenu.GetWorkArea;
  2248. begin
  2249.   Result := GetMonitorWorkArea(FForm.Handle, True);
  2250. end;
  2251. procedure TspSkinMenu.WaitItem(Sender: TObject);
  2252. begin
  2253.   if WItem <> nil then CheckItem(WItem.Parent, WItem, True, False);
  2254.   WaitTimer.Enabled := False;
  2255. end;
  2256. function TspSkinMenu.GetPWIndex;
  2257. var
  2258.   i: Integer;
  2259. begin
  2260.   for i := 0 to FPopupList.Count - 1 do
  2261.     if PW = TspSkinPopupWindow(FPopupList.Items[i]) then Break;
  2262.   Result := i;
  2263. end;
  2264. procedure TspSkinMenu.CheckItem;
  2265. var
  2266.   Menu: TMenu;
  2267.   MenuI: TMenuItem;
  2268.   i: Integer;
  2269.   R: TRect;
  2270. begin
  2271.   if (MI.MenuItem.Count = 0) and not Down
  2272.   then
  2273.     begin
  2274.       WaitTimer.Enabled := False;
  2275.       WItem := nil;
  2276.       i := GetPWIndex(PW);
  2277.       if i < FPopupList.Count - 1 then CloseMenu(i + 1);
  2278.     end
  2279.   else
  2280.   if (MI.MenuItem.Count = 0) and Down
  2281.   then
  2282.     begin
  2283.       WaitTimer.Enabled := False;
  2284.       WItem := nil;
  2285.       MenuI := MI.MenuItem;
  2286.       Hide;
  2287.       Menu := MenuI.GetParentMenu;
  2288.       Menu.DispatchCommand(MenuI.Command);
  2289.       //
  2290.       if DCtrl <> nil
  2291.       then
  2292.         if DCtrl is TWinControl
  2293.         then
  2294.           SendMessage(TWinControl(DCtrl).Handle, WM_AFTERDISPATCH, 0, 0)
  2295.         else
  2296.           DCtrl.Perform(WM_AFTERDISPATCH, 0, 0);
  2297.       //
  2298.     end
  2299.   else
  2300.   if (MI.MenuItem.Count <> 0) and not Down and not Kb
  2301.   then
  2302.     begin
  2303.       WaitTimer.Enabled := False;
  2304.       WItem := nil;
  2305.       i := GetPWIndex(PW);
  2306.       if i < FPopupList.Count - 1 then CloseMenu(i + 1);
  2307.       WItem := MI;
  2308.       WaitTimer.Enabled := True;
  2309.     end
  2310.   else
  2311.   if (MI.MenuItem.Count <> 0) and Down
  2312.   then
  2313.     begin
  2314.       //
  2315.       MenuI := MI.MenuItem;
  2316.       Menu := MenuI.GetParentMenu;
  2317.       Menu.DispatchCommand(MenuI.Command);
  2318.       //
  2319.       WaitTimer.Enabled := False;
  2320.       WItem := nil;
  2321.       MI.Down := True;
  2322.       R.Left := PW.Left + MI.ObjectRect.Left;
  2323.       R.Top := PW.Top + MI.ObjectRect.Top;
  2324.       R.Right := PW.Left + MI.ObjectRect.Right;
  2325.       R.Bottom := PW.Top + MI.ObjectRect.Bottom;
  2326.       PopupSub(R, MI.MenuItem, 0, True, False);
  2327.     end
  2328. end;
  2329. procedure TspSkinMenu.Popup;
  2330. begin
  2331.   FFirst := not FVisible;
  2332.   PopupCtrl := APopupCtrl;
  2333.   if FPopupList.Count <> 0 then CloseMenu(0);
  2334.   WorkArea := GetWorkArea;
  2335.   SkinData := ASkinData;
  2336.   if (AItem.Count = 0) or (StartIndex >= AItem.Count) then Exit;
  2337.   FVisible := True;
  2338.   PopupSub(R, AItem, StartIndex, False, PopupUp);
  2339.   FFirst := False;
  2340. end;
  2341. procedure TspSkinMenu.Popup2;
  2342. begin
  2343.   FFirst := not FVisible;
  2344.   PopupCtrl := APopupCtrl;
  2345.   if FPopupList.Count <> 0 then CloseMenu(0);
  2346.   WorkArea := GetWorkArea;
  2347.   SkinData := ASkinData;
  2348.    if (AItem.Count = 0) or (StartIndex >= AItem.Count + AItem2.Count) then Exit;
  2349.   FVisible := True;
  2350.   PopupSub2(R, AItem, AItem2, StartIndex, False, PopupUp);
  2351.   FFirst := False;
  2352. end;
  2353. procedure TspSkinMenu.PopupSub;
  2354. begin
  2355.   if (SkinData = nil) or (SkinData.Empty)
  2356.   then
  2357.     FPopupList.Add(TspSkinPopupWindow.CreateEx(Self, Self, nil))
  2358.   else
  2359.     FPopupList.Add(TspSkinPopupWindow.CreateEx(Self, Self, SkinData.PopupWindow));
  2360.   with TspSkinPopupWindow(FPopupList.Items[FPopupList.Count - 1]) do
  2361.     Show(R, AItem, StartIndex, PopupByItem, PopupUp);
  2362. end;
  2363. procedure TspSkinMenu.PopupSub2;
  2364. begin
  2365.   if (SkinData = nil) or (SkinData.Empty)
  2366.   then
  2367.     FPopupList.Add(TspSkinPopupWindow.CreateEx(Self, Self, nil))
  2368.   else
  2369.     FPopupList.Add(TspSkinPopupWindow.CreateEx(Self, Self, SkinData.PopupWindow));
  2370.   with TspSkinPopupWindow(FPopupList.Items[FPopupList.Count - 1]) do
  2371.     Show2(R, AItem, AItem2, StartIndex, PopupByItem, PopupUp);
  2372. end;
  2373. procedure TspSkinMenu.CloseMenu;
  2374. var
  2375.   i: Integer;
  2376. begin
  2377.   for i := FPopupList.Count - 1 downto EndIndex do
  2378.   begin
  2379.     TspSkinPopupWindow(FPopupList.Items[i]).Free;
  2380.     FPopupList.Delete(i);
  2381.   end;
  2382.   if EndIndex = 0
  2383.   then
  2384.     begin
  2385.       WaitTimer.Enabled := False;
  2386.       FVisible := False;
  2387.       DCtrl := PopupCtrl;
  2388.       if PopupCtrl <> nil
  2389.       then
  2390.         begin
  2391.           if PopupCtrl is TWinControl
  2392.           then
  2393.             SendMessage(TWinControl(PopupCtrl).Handle, WM_CLOSESKINMENU, 0, 0)
  2394.           else
  2395.             PopupCtrl.Perform(WM_CLOSESKINMENU, 0, 0);
  2396.           PopupCtrl := nil;
  2397.         end;
  2398.     end;
  2399. end;
  2400. procedure TspSkinMenu.Hide;
  2401. begin
  2402.   CloseMenu(0);
  2403.   WaitTimer.Enabled := False;
  2404.   WItem := nil;
  2405.   if FForm <> nil then
  2406.   SendMessage(FForm.Handle, WM_CLOSESKINMENU, 0, 0);
  2407.   if PopupCtrl <> nil
  2408.   then
  2409.     begin
  2410.       if PopupCtrl is TWinControl
  2411.       then
  2412.         SendMessage(TWinControl(PopupCtrl).Handle, WM_CLOSESKINMENU, 0, 0)
  2413.        else
  2414.          PopupCtrl.Perform(WM_CLOSESKINMENU, 0, 0);
  2415.       PopupCtrl := nil;
  2416.     end;
  2417. end;
  2418. //============= TspSkinPopupMenu =============//
  2419. function FindDSFComponent(AForm: TForm): TSpDynamicSkinForm;
  2420. var
  2421.   i: Integer;
  2422. begin
  2423.   Result := nil;
  2424.   for i := 0 to AForm.ComponentCount - 1 do
  2425.    if AForm.Components[i] is TspDynamicSkinForm
  2426.    then
  2427.      begin
  2428.        Result := TspDynamicSkinForm(AForm.Components[i]);
  2429.        Break;
  2430.      end;
  2431. end;
  2432. constructor TspSkinPopupMenu.Create;
  2433. begin
  2434.   inherited Create(AOwner);
  2435.   FComponentForm := nil;
  2436.   FSD := nil;
  2437. end;
  2438. procedure TspSkinPopupMenu.Notification;
  2439. begin
  2440.   inherited Notification(AComponent, Operation);
  2441.   if (Operation = opRemove) and (AComponent = FSD) then FSD := nil;
  2442. end;
  2443. procedure TspSkinPopupMenu.PopupFromRect;
  2444. var
  2445.   DSF: TspDynamicSkinForm;
  2446. begin
  2447.   if Assigned(OnPopup) then OnPopup(Self);
  2448.   if FComponentForm = nil
  2449.   then
  2450.     begin
  2451.       //DSF := FindDSFComponent(TForm(Owner))
  2452.       if Owner.InheritsFrom(TForm) then
  2453.         DSF := FindDSFComponent(TForm(Owner)) else
  2454.          if Owner.Owner.InheritsFrom(TForm) then
  2455.          DSF := FindDSFComponent(TForm(Owner.Owner)) else
  2456.            DSF := nil;
  2457.     end
  2458.   else
  2459.     DSF := FindDSFComponent(FComponentForm);
  2460.   if (DSF <> nil) and (FSD = nil)
  2461.   then
  2462.     if DSF.MenusSkinData = nil
  2463.     then
  2464.       FSD := DSF.SkinData
  2465.     else
  2466.       FSD := DSF.MenusSkinData;
  2467.   if DSF <> nil
  2468.   then
  2469.     begin
  2470.       DSF.SkinMenuOpen;
  2471.       DSF.SkinMenu.Popup(nil, FSD, 0, R, Items, APopupUp);
  2472.     end;
  2473. end;
  2474. procedure TspSkinPopupMenu.Popup;
  2475. var
  2476.   DSF: TspDynamicSkinForm;
  2477. var
  2478.   R: TRect;
  2479. begin
  2480.   if Assigned(OnPopup) then OnPopup(Self);
  2481.   if FComponentForm = nil
  2482.   then
  2483.     begin
  2484.       //DSF := FindDSFComponent(TForm(Owner))
  2485.       if Owner.InheritsFrom(TForm) then
  2486.         DSF := FindDSFComponent(TForm(Owner)) else
  2487.          if Owner.Owner.InheritsFrom(TForm) then
  2488.          DSF := FindDSFComponent(TForm(Owner.Owner)) else
  2489.            DSF := nil;
  2490.     end
  2491.   else
  2492.     DSF := FindDSFComponent(FComponentForm);
  2493.   if (DSF <> nil) and (FSD = nil)
  2494.   then
  2495.     if DSF.MenusSkinData = nil
  2496.     then
  2497.       FSD := DSF.SkinData
  2498.     else
  2499.       FSD := DSF.MenusSkinData;
  2500.   if DSF <> nil
  2501.   then
  2502.     begin
  2503.       DSF.SkinMenuOpen;
  2504.       R := Rect(X, Y, X, Y);
  2505.       DSF.SkinMenu.Popup(nil, FSD, 0, R, Items, False);
  2506.     end;
  2507. end;
  2508. procedure TspSkinPopupMenu.PopupFromRect2;
  2509. var
  2510.   DSF: TspDynamicSkinForm;
  2511. begin
  2512.   if Assigned(OnPopup) then OnPopup(Self);
  2513.   if FComponentForm = nil
  2514.   then
  2515.     begin
  2516.       //DSF := FindDSFComponent(TForm(Owner))
  2517.       if Owner.InheritsFrom(TForm) then
  2518.         DSF := FindDSFComponent(TForm(Owner)) else
  2519.          if Owner.Owner.InheritsFrom(TForm) then
  2520.          DSF := FindDSFComponent(TForm(Owner.Owner)) else
  2521.            DSF := nil;
  2522.     end
  2523.   else
  2524.     DSF := FindDSFComponent(FComponentForm);
  2525.   if (DSF <> nil) and (FSD = nil)
  2526.   then
  2527.     if DSF.MenusSkinData = nil
  2528.     then
  2529.       FSD := DSF.SkinData
  2530.     else
  2531.       FSD := DSF.MenusSkinData;
  2532.   if DSF <> nil
  2533.   then
  2534.     begin
  2535.       DSF.SkinMenuOpen;
  2536.       DSF.SkinMenu.Popup(ACtrl, FSD, 0, R, Items, APopupUp);
  2537.     end;
  2538. end;
  2539. procedure TspSkinPopupMenu.Popup2;
  2540. var
  2541.   R: TRect;
  2542.   DSF: TspDynamicSkinForm;
  2543. begin
  2544.   if Assigned(OnPopup) then OnPopup(Self);
  2545.   if FComponentForm = nil
  2546.   then
  2547.     begin
  2548.       //DSF := FindDSFComponent(TForm(Owner))
  2549.       if Owner.InheritsFrom(TForm) then
  2550.         DSF := FindDSFComponent(TForm(Owner)) else
  2551.          if Owner.Owner.InheritsFrom(TForm) then
  2552.          DSF := FindDSFComponent(TForm(Owner.Owner)) else
  2553.            DSF := nil;
  2554.     end
  2555.   else
  2556.     DSF := FindDSFComponent(FComponentForm);
  2557.   if (DSF <> nil) and (FSD = nil)
  2558.   then
  2559.     if DSF.MenusSkinData = nil
  2560.     then
  2561.       FSD := DSF.SkinData
  2562.     else
  2563.       FSD := DSF.MenusSkinData;
  2564.   if (DSF <> nil) and (FSD <> nil)
  2565.   then
  2566.     begin
  2567.       DSF.SkinMenuOpen;
  2568.       R := Rect(X, Y, X, Y);
  2569.       DSF.SkinMenu.Popup(ACtrl, FSD, 0, R, Items, False);
  2570.     end;
  2571. end;
  2572. end.