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

Delphi控件源码

开发平台:

Delphi

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