am2000menubar.pas
上传用户:powellwoo
上传日期:2007-01-07
资源大小:109k
文件大小:55k
源码类别:

Delphi控件源码

开发平台:

C++ Builder

  1. {*******************************************************}
  2. {                                                       }
  3. {       AnimatedMenus/2000                              }
  4. {       TMenuBar2000                                    }
  5. {                                                       }
  6. {       Copyright (c) 1997-99 AnimatedMenus.com         }
  7. {       All rights reserved.                            }
  8. {                                                       }
  9. {       Redesigned and improved by Victor Santos        }
  10. {                                                       }
  11. {*******************************************************}
  12. unit am2000menubar;
  13. {$I am2000.inc}
  14. interface
  15. uses
  16.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus,
  17.   ComCtrls, ExtCtrls,
  18.   am2000utils, am2000options, am2000hintwindow, am2000popupmenu;
  19. type
  20.   T_AM2000_aiState = (aiFlat, aiRaised, aiSunken);
  21.   T_AM2000_SystemButtonPressed = (sbNone, sbMinimize, sbRestore, sbClose);
  22.   T_AM2000_NextMenuItemParam = (niBackward, niIgnoreInvisible, niStopOnLimit);
  23.   T_AM2000_NextMenuItemParams = set of T_AM2000_NextMenuItemParam;
  24.   T_AM2000_mbType =(mbHorizontal, mbVertical, mbFloating);
  25.   PMenuItemRect = ^TMenuItemRect;
  26.   TMenuItemRect = record
  27.     mi: TMenuItem;
  28.     iR: TRect;
  29.   end;
  30.   TCustomMenuBar2000 = class(TCustomControl)
  31.   private
  32.     OwnerForm, LastChild: TForm;
  33.     FMenu: TMenu;
  34.     Buffer, Back: TBitmap;
  35.     BufferState, DisableMouseUp, DisableAltKeyUp, WindowActive, KeepSelected: Boolean;
  36.     FOptions, FLocalOptions: T_AM2000_Options;
  37.     FPopupMenu: TCustomPopupMenu2000;
  38.     SaveMenuTextColor: TColor;
  39.     ToolTipWindow: T_AM2000_ToolTipWindow;
  40.     FSBPanelNo: Integer;
  41.     FStatusBar: TStatusBar;
  42.     Lastai: TMenuItem;
  43.     ai: TMenuItem;
  44.     aiIndex: Integer;
  45.     SystemButtonPressed: T_AM2000_SystemButtonPressed;
  46.     SystemMenu: TMenuItem;
  47.     ASTimer: TTimer;
  48.     IgnorePaint: Boolean;
  49.     FAlignParent  : Boolean;
  50.     FSystemFont   : Boolean;
  51.     FSystemFontHandle, FOldFontHandle: HFont;
  52.     FOnMenuCommand   : TNotifyEvent;
  53.     FOnMenuClose     : TNotifyEvent;
  54.     FOnCloseQuery    : TCloseQueryEvent;
  55.     FHotTrack: Boolean;
  56.     FTransparent: Boolean;
  57.     procedure SetAlignParent(Value: Boolean);
  58.     procedure SetMenu(Value: TMenu);
  59.     procedure SetOptions(Value: T_AM2000_Options);
  60.     procedure SetSystemFont(Value: Boolean);
  61.     procedure SetTransparent(Value: Boolean);
  62.     procedure RebuildToolTipWindow;
  63.     procedure wmWindowPosChanged(var Msg: TMessage); message wm_WindowPosChanged;
  64.     procedure wmSetKeepSelected(var Msg: TMessage);  message wm_SetKeepSelected;
  65.     procedure wmUpdateMenuBar(var Msg: TMessage);    message wm_UpdateMenuBar;
  66.     procedure wmActivateMenuBar(var Msg: TMessage);  message wm_ActivateMenuBar;
  67.     procedure cmMouseLeave(var Msg: TMessage);       message cm_MouseLeave;
  68.     procedure cmIsToolControl(var Msg: TMessage);    message cm_IsToolControl;
  69.     procedure wmSysKeyDown(var Msg: TWMKeyDown);     message wm_SysKeyDown;
  70.     procedure wmSysKeyUp(var Msg: TWMKeyUp);         message wm_SysKeyUp;
  71.     procedure wmKeyDown(var Msg: TWMKeyDown);        message wm_KeyDown;
  72.     procedure wmMouseMove(var Msg: TWMMouse);        message wm_MouseMove;
  73. {$IFDEF Delphi3OrHigher}
  74.     procedure cmSysFontChanged(var Msg: TMessage);   message cm_SysFontChanged;
  75. {$ENDIF}
  76.     procedure wmSettingChange(var Msg: TMessage);    message wm_SettingChange;
  77.     procedure cmFontChanged(var Msg: TMessage);      message cm_FontChanged;
  78.     function GetMenuItemCount: Integer;
  79.     function GetMenuItem(Index: Integer): TMenuItem;
  80.     function GetNextMenuItem(var CurIndex: Integer; Params: T_AM2000_NextMenuItemParams): TMenuItem;
  81.     procedure MoveActiveTo(NewItem: TMenuItem);
  82.     procedure MoveActiveToIndex(NewIndex: Integer; NewItem: TMenuItem);
  83.     function GetBitmapWidth(Item: TMenuItem): Integer;
  84.     procedure PopupMenuXY(X, Y: Integer; SetHidden, SelectFirst: Boolean);
  85.     procedure PopupMenuRect(R: TRect; SetHidden, SelectFirst: Boolean);
  86.     function GetSysBtnRect(SysBtn : T_AM2000_SystemButtonPressed): TRect;
  87.     function GetMenuIconRect: TRect;
  88.     procedure TimerShow(Sender: TObject);
  89.     procedure SetHotTrack(const Value: Boolean);
  90.   protected
  91.     procedure Paint; override;
  92.     procedure Loaded; override;
  93.     function GetBufOffsetX: Integer;
  94.     function PtInRect2(const R: TRect; P: TPoint): Boolean;
  95.     function GetItemSize(Item: TMenuItem): TSize;
  96.     procedure PaintItem(Canvas: TCanvas; Item: TMenuItem;
  97.                         R: TRect; BitBlt2SelfCanvas: Boolean);
  98.     procedure PaintActiveItem;
  99.     procedure PaintSystemButton(R: TRect; Letter: Char; Down, Enabled: Boolean);
  100.     procedure PaintSystemButtons;
  101.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  102.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  103.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  104.     procedure DblClick; override;
  105.     procedure CreateParams(var Params: TCreateParams); override;
  106.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  107.     property PopupMenu       : TCustomPopupMenu2000
  108.       read FPopupMenu write FPopupMenu;
  109.     property AlignParent     : Boolean
  110.       read FAlignParent write SetAlignParent default False;
  111.     property HotTrack        : Boolean
  112.       read FHotTrack write SetHotTrack default False;
  113.     property Transparent     : Boolean
  114.       read FTransparent write SetTransparent default False;
  115.     property OnMenuCommand   : TNotifyEvent
  116.       read FOnMenuCommand write FOnMenuCommand;
  117.     property OnMenuClose     : TNotifyEvent
  118.       read FOnMenuClose write FOnMenuClose;
  119.     property OnCloseQuery    : TCloseQueryEvent
  120.       read FOnCloseQuery write FOnCloseQuery;
  121.   public
  122.     aiState: T_AM2000_aiState;
  123.     aiRect: TRect;
  124.     mbType: T_AM2000_mbType;
  125.     miRects: TList;
  126.     miSysBtnRect: TRect;
  127.     ParentClientWidth: Integer;
  128.     property StatusBar       : TStatusBar
  129.       read FStatusBar write FStatusBar;
  130.     property StatusBarIndex  : Integer
  131.       read FSBPanelNo write FSBPanelNo;
  132.     property Options         : T_AM2000_Options
  133.       read FOptions write SetOptions;
  134.     property Menu            : TMenu
  135.       read FMenu write SetMenu;
  136.     property SystemFont      : Boolean
  137.       read FSystemFont write SetSystemFont default True;
  138.     property Font;
  139.     constructor Create(AOwner: TComponent); override;
  140.     destructor Destroy; override;
  141.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  142.     procedure ResetBuffer;
  143.     procedure PopupActiveItem(SelectFirst: Boolean);
  144.     procedure SetActiveItemIndex(Index: Integer);
  145.     procedure KillActiveItem;
  146.     procedure HideActiveItem;
  147.     procedure UpdateMenuBar(RebuildMenu: Boolean);
  148.     procedure SetDisableAltKeyUp(Value: Boolean);
  149.     function GetOffsetX: Integer;
  150.     function GetLastOffsetX: Integer;
  151. {$IFDEF Delphi4OrHigher}
  152.     procedure InitiateAction; override;
  153. {$ENDIF}
  154.     procedure DoLoaded;
  155.   end;
  156. const
  157.   iSystemIconWidth: Integer = 16;
  158.   ActiveMenuBar   : TCustomMenuBar2000 = nil;
  159. procedure AddMiRects(List : TList; MenuItem : TMenuItem; R : TRect);
  160. procedure RemoveMiRects(List : TList; MenuItem : TMenuItem);
  161. procedure ClearMiRects(List : TList);
  162. function GetMiRect(List : TList; mI : Integer; MenuItem : TMenuItem) : TRect;
  163. implementation
  164. uses
  165.   am2000menuitem, am2000mainmenu;
  166. procedure AddMiRects(List : TList; MenuItem : TMenuItem; R : TRect);
  167. var
  168.   miRect: PMenuItemRect;
  169. begin
  170.      if (List <> nil) then begin
  171.         New(miRect);
  172.         if miRect <> nil then
  173.         with miRect^ do begin
  174.            mi:= MenuItem;
  175.            iR:= R;
  176.            List.Add(miRect);
  177.         end;
  178.      end;
  179. end;
  180. procedure RemoveMiRects(List : TList; MenuItem : TMenuItem);
  181. var miRect: PMenuItemRect;
  182.     i: Integer;
  183. begin
  184.      if (List <> nil) then
  185.         for i:= 0 to List.Count-1 do begin
  186.             miRect := PMenuItemRect(List.Items[i]);
  187.             if miRect.mi = MenuItem then begin
  188.                Dispose(miRect);
  189.                List.Delete(i);
  190.                Exit;
  191.             end;
  192.         end;
  193. end;
  194. procedure ClearMiRects(List : TList);
  195. var miRect: PMenuItemRect;
  196.     i: Integer;
  197. begin
  198.      if (List <> nil) then begin
  199.         for i:= 0 to List.Count-1 do begin
  200.             miRect := PMenuItemRect(List.Items[i]);
  201.             Dispose(miRect);
  202.         end;
  203.         List.Clear;
  204.      end;
  205. end;
  206. function GetMiRect(List : TList; mI : Integer; MenuItem : TMenuItem) : TRect;
  207. var i: Integer;
  208. begin
  209.      Result := Rect(0,0,0,0);
  210.      if (List <> nil) then
  211.      with List do
  212.        if (mI >= 0) and (mI < Count) and
  213.           (PMenuItemRect(Items[mI])^.mi = MenuItem) then
  214.           Result := PMenuItemRect(Items[mI])^.iR
  215.        else
  216.        { find the menuitem: }
  217.        for i:= 0 to Count -1 do
  218.           if PMenuItemRect(Items[i])^.mi = MenuItem then begin
  219.              Result := PMenuItemRect(Items[i])^.iR;
  220.              Exit;
  221.           end;
  222. end;
  223. function CheckForHidden(Item: TMenuItem): Boolean;
  224. var
  225.   I: Integer;
  226. begin
  227.   Result:= False;
  228.   if (Item = nil) then Exit;
  229.   for I:= 0 to Item.Count -1 do
  230.     if (Item is TMenuItem2000) then
  231.       with TMenuItem2000(Item[I]) do
  232.         if Hidden
  233.         or ((Count > 0) and CheckForHidden(Item[I]))
  234.         then begin
  235.           Result:= True;
  236.           Exit;
  237.         end;
  238. end;
  239. { TCustomMenuBar2000 }
  240. constructor TCustomMenuBar2000.Create;
  241. var
  242.   O1: TComponent;
  243. begin
  244.   inherited;
  245.   // control style
  246.   ControlStyle := [csClickEvents, csDoubleClicks, csSetCaption, csOpaque,
  247.     csReplicatable {$IFDEF Delphi4OrHigher}, csActionClient{$ENDIF}];
  248.   // create the buffer
  249.   Buffer:= TBitmap.Create;
  250.   WindowActive:= True;
  251.   FSystemFont:= True;
  252.   ParentFont:= False;
  253.   SystemMenu:= TMenuItem2000.Create(Self);
  254.   ASTimer:= TTimer.Create(Self);
  255.   ASTimer.Enabled:= False;
  256.   ASTimer.Interval:= 3000;
  257.   ASTimer.OnTimer:= TimerShow;
  258.   // init menu item options
  259.   FOptions:= T_AM2000_Options.Create;
  260.   FLocalOptions:= T_AM2000_Options.Create;
  261.   with FLocalOptions, Margins do begin
  262.     Alignment:= taCenter;
  263.     Left:= 0;
  264.     Right:= 0;
  265.     Top:= 0;
  266.     Bottom:= 0;
  267.   end;
  268.   Width:= 50;
  269.   Height:= 21;
  270.   Align:= alTop;
  271.   if ActiveMenuBar = nil
  272.   then ActiveMenuBar:= Self;
  273.   mbType:= mbHorizontal;
  274.   miRects:= TList.Create;
  275.   OwnerForm:= nil;
  276.   O1:= AOwner;
  277.   while (O1 <> nil) and (not (O1 is TForm)) do O1:= O1.Owner;
  278.   if O1 is TForm then OwnerForm:= TForm(O1);
  279. end;
  280. destructor TCustomMenuBar2000.Destroy;
  281. begin
  282.   if ActiveMenuBar = Self
  283.   then ActiveMenuBar:= nil;
  284.   RemoveCWHooks;
  285.   Buffer.Free;
  286.   Back.Free;
  287.   FOptions.Free;
  288.   FLocalOptions.Free;
  289.   PopupMenu.Free;
  290.   ToolTipWindow.Free;
  291.   ClearMiRects(miRects);
  292.   miRects.Free;
  293.   inherited;
  294. end;
  295. procedure TCustomMenuBar2000.CreateParams(var Params: TCreateParams);
  296. begin
  297.   inherited CreateParams(Params);
  298.   with Params do
  299.     WindowClass.Style:= WindowClass.Style and not (CS_HREDRAW or CS_VREDRAW);
  300. end;
  301. procedure TCustomMenuBar2000.Loaded;
  302. begin
  303.   inherited;
  304.   // grab OwnerForm's menu
  305.   if (OwnerForm is TForm) then begin
  306.     if FMenu = nil
  307.     then FMenu:= TForm(OwnerForm).Menu;
  308.     if (FMenu = TForm(OwnerForm).Menu)
  309.     then TForm(OwnerForm).Menu:= nil;
  310.   end;
  311.   // initialize other properties
  312.   if not (csDesigning in ComponentState) then begin
  313.     SaveMenuTextColor:= Options.Colors.MenuText;
  314.     PopupMenu:= TCustomPopupMenu2000.Create(OwnerForm);
  315.     InstallCWHooks;
  316.     RebuildToolTipWindow;
  317.     FLocalOptions.Assign(FOptions);
  318.     with FLocalOptions, Margins do begin
  319.       Alignment:= taCenter;
  320.       Left:= 0;
  321.       Right:= 0;
  322.       Top:= 0;
  323.       Bottom:= 0;
  324.     end;
  325.   end;
  326.   if (Buffer.Empty)
  327.   then SetBounds(Left, Top, 0, 0);
  328. end;
  329. { Windows Messages Handlers }
  330. procedure TCustomMenuBar2000.wmWindowPosChanged(var Msg: TMessage);
  331. begin
  332.   Invalidate;
  333.   inherited;
  334. end;
  335. procedure TCustomMenuBar2000.wmUpdateMenuBar(var Msg: TMessage);
  336.   // updates menu bar
  337. const
  338.   RebuildFlag: Boolean = False;
  339. var
  340.   M: TMsg;
  341. begin
  342.   // force menu merge rebuild
  343.   if (Menu is TCustomMainMenu2000)
  344.   and ((Msg.wParam = upForceRebuild)
  345.   or ((Msg.wParam = upChildChanged)
  346.   and (TForm(OwnerForm).ActiveMdiChild <> LastChild)))
  347.   then begin
  348.     TCustomMainMenu2000(Menu).RebuildMergedMenuItems;
  349.     RebuildFlag:= True;
  350.   end;
  351.   // child changed
  352.   if not AssignedActivePopupMenu2000Form
  353.   then begin
  354.     if (Msg.wParam = upChildChanged) // is child changed?
  355.     then
  356.       if (TForm(OwnerForm).ActiveMdiChild = LastChild)
  357.       then begin
  358.         if LastChild = nil
  359.         then
  360.            Msg.wParam:= 0
  361.         else
  362.            Msg.wParam:= WPARAM(LastChild.WindowState =
  363.                                TForm(OwnerForm).ActiveMdiChild.WindowState);
  364.       end
  365.       else
  366.         LastChild:= TForm(OwnerForm).ActiveMdiChild;
  367.     // skip update on other messages
  368.     if PeekMessage(M, Handle, wm_UpdateMenuBar, wm_UpdateMenuBar, pm_NoRemove)
  369.     then begin
  370.       RebuildFlag:= RebuildFlag or (M.wParam <> 0);
  371.       Msg.Result:= 1;
  372.       Exit;
  373.     end;
  374.     RebuildFlag:= RebuildFlag or (Msg.wParam <> 0);
  375.     if RebuildFlag
  376.     then begin
  377.       UpdateMenuBar(True);
  378.       RebuildFlag:= False;
  379.     end
  380.     else begin
  381.       ResetBuffer;
  382.       Paint;
  383.     end;
  384.   end;
  385. end;
  386. procedure TCustomMenuBar2000.PopupMenuXY(X, Y: Integer; SetHidden, SelectFirst: Boolean);
  387.   // pops up menu
  388. var
  389.   P: TPoint;
  390. begin
  391.   // if active item is not active
  392.   if not ((ai <> nil) and ai.Enabled)
  393.   then Exit;
  394.   // popup menu 98
  395.   PopupMenu.MenuItems:= nil;
  396.   P:= ClientToScreen(Point(X, Y));
  397.   // switch between different cases of activeitem
  398.   if (ai <> nil)
  399.   then begin
  400.     // OnClick event
  401.     if Assigned(ai.OnClick)
  402.     then ai.OnClick(ai); 
  403.     // main system menu
  404.     if (ai = SystemMenu)
  405.     then begin
  406.       PopupMenu.MenuItems:= nil;
  407.       PopupMenu.MenuHandle:= GetSystemMenu(TForm(OwnerForm).ActiveMdiChild.Handle, False);
  408.     end
  409.     else
  410.     // attached menu
  411.     if (ai is TMenuItem2000)
  412.     and (TMenuItem2000(ai).AttachMenu <> nil)
  413.     then
  414.       with TMenuItem2000(ai).AttachMenu as TCustomPopupMenu2000 do begin
  415.         if Items.Count = 0 then InitItems(True);
  416.         PopupMenu.MenuItems:= Items2000; // ordinal item
  417.         PopupMenu.MenuHandle:= Items2000.Handle;
  418.       end
  419.     else
  420.     // normal submenu
  421.     if ai.Count > 0
  422.     then begin
  423.       PopupMenu.MenuItems:= ai; // ordinal item
  424.       PopupMenu.MenuHandle:= ai.Handle;
  425.     end
  426.     // ordinary item
  427.     else begin
  428.       DisableMouseUp:= False;
  429.       if KeepSelected then HideActiveItem;
  430.       Exit;
  431.     end;
  432.       
  433.   end
  434.   else
  435.     // child's system menu
  436.     if (TForm(OwnerForm).FormStyle = fsMdiForm)
  437.     and (TForm(OwnerForm).ActiveMdiChild <> nil)
  438.     then PopupMenu.MenuHandle:= GetSystemMenu(TForm(OwnerForm).ActiveMdiChild.Handle, False);
  439.   PopupMenu.Options.Assign(Options);
  440.   PopupMenu.StatusBar:= StatusBar;
  441.   PopupMenu.StatusBarIndex:= StatusBarIndex;
  442.   PopupMenu.ShowHint:= ShowHint;
  443.   PopupMenu.PopupComponent:= Self;
  444.   PopupMenu.OnMenuCommand:= OnMenuCommand;
  445.   PopupMenu.OnMenuClose:= OnMenuClose;
  446.   PopupMenu.OnCloseQuery:= OnCloseQuery;
  447.   PopupMenu.SystemFont:= SystemFont;
  448.   PopupMenu.Font:= Font;
  449.   PopupMenu.Ctl3D:= Ctl3D;
  450.   // set selected first
  451.   if KeepSelected or SelectFirst
  452.   then PopupMenu.SetSelectedIndex(True);
  453.   KeepSelected:= False;
  454.   // set hidden flag
  455.   ASTimer.Enabled:= False;
  456.   if SetHidden
  457.   then
  458.     PopupMenu.Options.Flags:= PopupMenu.Options.Flags + [mfHiddenIsVisible]
  459.   else
  460.     // is hidden properties present then enable time
  461.     if (not (mfNoAutoShowHidden in Options.Flags))
  462.     and CheckForHidden(ai)
  463.     then ASTimer.Enabled:= True;
  464.   with PopupMenu do
  465. {$IFDEF Delphi4OrHigher}
  466.     Images:= Menu.Images;
  467. {$ELSE}
  468.     if (Menu is TCustomMainMenu2000)
  469.     then Images:= TCustomMainMenu2000(Menu).Images
  470.     else Images:= nil;
  471. {$ENDIF}
  472.   PopupMenu.Popup(P.X, P.Y);
  473.   Lastai:= ai;
  474. end;
  475. procedure TCustomMenuBar2000.PopupMenuRect(R: TRect; SetHidden, SelectFirst: Boolean);
  476. var X, Y: Integer;
  477. begin
  478.      if mbType = mbVertical then begin
  479.         X:= R.Right +1;
  480.         Y:= R.Top -1;
  481.      end
  482.      else begin
  483.         if Options.Alignment = taRightToLeft
  484.         then X:= R.Right + GetBufOffsetX
  485.         else X:= R.Left;
  486.         Y:= R.Bottom;
  487.      end;
  488.      PopupMenuXY(X, Y, SetHidden, SelectFirst);
  489. end;
  490. function TCustomMenuBar2000.GetSysBtnRect(SysBtn : T_AM2000_SystemButtonPressed): TRect;
  491.   // get rect for system button
  492. begin
  493.   if SysBtn = sbNone then
  494.     Result := Rect(0, 0, 0, 0)
  495.   else begin
  496.     // get close button rect
  497.     if mbType = mbHorizontal
  498.     then
  499.       Result:= Rect(Width - iSystemIconWidth -1,
  500.          Height - iSystemIconWidth -2,
  501.          Width -1,
  502.          Height -2)
  503.     else
  504.       Result:= Rect(miSysBtnRect.Right - iSystemIconWidth,
  505.         miSysBtnRect.Bottom - iSystemIconWidth,
  506.         miSysBtnRect.Right,
  507.         miSysBtnRect.Bottom);
  508.     case SysBtn of
  509.       sbRestore:
  510.         if mbType = mbVertical
  511.         then
  512.           OffsetRect(Result, 0, -iSystemIconWidth)
  513.         else
  514.           OffsetRect(Result, -iSystemIconWidth -2, 0);
  515.       sbMinimize:
  516.         if mbType = mbVertical then
  517.           OffsetRect(Result, 0, -iSystemIconWidth*2 +2)
  518.         else
  519.           OffsetRect(Result, -iSystemIconWidth*2 -2, 0);
  520.     end;
  521.   end;
  522. end;
  523. function TCustomMenuBar2000.GetMenuIconRect: TRect;
  524. var X, Y: Integer;
  525. begin
  526.      if GetOffsetX = 0 then
  527.         Result := Rect(0, 0, 0, 0)
  528.      else begin
  529.         if mbType = mbVertical then begin
  530.            X:= Width - iSystemIconWidth -1;
  531.            Y:= 2;
  532.         end
  533.         else begin
  534.            if Options.Alignment = taRightToLeft
  535.            then X:= Buffer.Width - iSystemIconWidth -3
  536.            else X:= 3;
  537.            Y:= 2;
  538.         end;
  539.         Result := Rect(X, Y, X + iSystemIconWidth, Y + iSystemIconWidth);
  540.      end;
  541. end;
  542. function TCustomMenuBar2000.PtInRect2(const R: TRect; P: TPoint): Boolean;
  543. begin
  544.   Dec(P.X, GetBufOffsetX);
  545.   Result:= PtInRect(R, P);
  546. end;
  547. procedure TCustomMenuBar2000.wmSetKeepSelected(var Msg: TMessage);
  548. begin
  549.   KeepSelected:= Msg.wParam <> 0;
  550. end;
  551. procedure TCustomMenuBar2000.wmActivateMenuBar(var Msg: TMessage);
  552. begin
  553.   WindowActive:= Msg.wParam <> 0;
  554.   if not WindowActive
  555.   then HideActiveItem
  556.   else ActiveMenuBar:= Self;
  557.   PostMessage(Handle, wm_UpdateMenuBar, upNothing, 0);
  558. end;
  559. procedure TCustomMenuBar2000.wmSysKeyDown(var Msg: TWMKeyDown);
  560. var
  561.   I: Integer;
  562.   Item: TMenuItem;
  563.   UseFirstLetter: Boolean;
  564. begin
  565.   // if menu state is active
  566.   if aiState <> aiFlat then begin
  567.     SetDisableAltKeyUp(True);
  568.     KillActiveItem;
  569.     Msg.Result:= 1;
  570.   end
  571.   else
  572.   // show child system menu
  573.   if (Msg.CharCode = VK_SUBTRACT)
  574.   and (TForm(OwnerForm).FormStyle = fsMdiForm)
  575.   and (TForm(OwnerForm).ActiveMdiChild <> nil)
  576.   and (TForm(OwnerForm).ActiveMdiChild.WindowState = wsMaximized)
  577.   then begin
  578.     aiRect.Left:= 0;
  579.     ai:= SystemMenu;
  580.     PopupActiveItem(True);
  581.     Msg.Result:= 1;
  582.   end
  583.   // shortcut
  584.   else
  585.   if (Msg.CharCode <> VK_MENU)
  586.   and (Msg.CharCode <> VK_F10)
  587.   and (FMenu <> nil)
  588.   then begin
  589.     UseFirstLetter:= True;
  590.     repeat
  591.       UseFirstLetter:= not UseFirstLetter;
  592.       for I:= 0 to GetMenuItemCount -1 do begin
  593.         Item:= GetMenuItem(I);
  594.         // if item is visible
  595.         if (Item <> nil)
  596.         and Item.Visible
  597.         // and accelerator pressed
  598.         and IsAccelEx(Msg.CharCode, Item.Caption, UseFirstLetter)
  599.         then begin
  600.           MoveActiveToIndex(I, Item);
  601.           SetDisableAltKeyUp(True);
  602.           PopupActiveItem(True);
  603.           Msg.Result:= 1;
  604.           Exit;
  605.         end;
  606.       end;
  607.     until UseFirstLetter;
  608.   end;
  609. end;
  610. procedure TCustomMenuBar2000.wmSysKeyUp(var Msg: TWMKeyUp);
  611. begin
  612.   if (Menu <> nil)
  613.   and (aiState = aiFlat)
  614.   and ((Msg.CharCode = vk_Menu) or (Msg.CharCode = vk_F10))
  615.   and not DisableAltKeyUp
  616.   then begin
  617.     FullHideCaret;
  618.     KeepSelected:= True;
  619.     aiState:= aiSunken;
  620.     SetCursor(LoadCursor(0, MakeIntResource(idc_Arrow)));
  621.     if ai = nil
  622.     then begin
  623.       if (TForm(OwnerForm).FormStyle = fsMdiForm)
  624.       and (TForm(OwnerForm).ActiveMdiChild <> nil)
  625.       then ai:= SystemMenu
  626.       else ai:= GetMenuItem(0);
  627.       MoveActiveToIndex(0, ai);
  628.     end
  629.     else begin
  630.       PaintActiveItem;
  631.     end;
  632.   end;
  633.   Msg.Result:= 1;
  634.   SetDisableAltKeyUp(False);
  635. end;
  636. procedure TCustomMenuBar2000.wmKeyDown(var Msg: TWMKeyDown);
  637.   // handles basic cursor movements and menu shortcuts
  638. var
  639.   M: TMsg;
  640.   procedure SearchForMergedMenus;
  641.   var
  642.     I: Integer;
  643.   begin
  644.     if IsShortCutEx(Msg, Menu.Items, csDesigning in ComponentState)
  645.     then Exit;
  646.     I:= 1;
  647.     if (Menu is TCustomMainMenu2000) then
  648.       with TCustomMainMenu2000(Menu) do
  649.         while (Msg.Result = 0) and (I < MergedMenus.Count) do begin
  650.           if IsShortCutEx(Msg, TMainMenu(MergedMenus[I]).Items, csDesigning in ComponentState)
  651.           then Exit;
  652.           Inc(I);
  653.         end;
  654.   end;
  655.   function IsShortCut: Boolean;
  656.     // checks is this is a shortcut
  657.   begin
  658.     Result:= (Msg.CharCode <> vk_Control)
  659.       and (Msg.CharCode <> vk_Shift)
  660.       and ((GetKeyState(vk_Control) < 0)
  661.       or (Msg.KeyData and AltMask <> 0)
  662.       or ((Msg.CharCode >= vk_F1) and (Msg.CharCode <= vk_F12))
  663.       or (Msg.CharCode = vk_Escape)
  664.       or (Msg.CharCode = vk_Delete)
  665.       or (Msg.CharCode = vk_Insert)
  666.       or (Msg.CharCode = vk_Back));
  667.   end;
  668. begin
  669.   if (aiState = aiSunken) then
  670.     case Msg.CharCode of
  671.       // open menu
  672.       vk_Return, vk_Space, vk_Down, vk_Up:
  673.         if not TCustomPopupMenu2000(PopupMenu).FormOnScreen then begin
  674.           PopupMenuRect(aiRect, False, True);
  675.           Msg.Result:= 1;
  676.         end;
  677.       // move selection left or right
  678.       vk_Tab:
  679.         begin
  680.           KeepSelected:= True;
  681.           if GetKeyState(vk_Shift) < 0
  682.           then
  683.              MoveActiveTo(GetNextMenuItem(aiIndex, [niBackward, niIgnoreInvisible]))
  684.           else
  685.              MoveActiveTo(GetNextMenuItem(aiIndex, [niIgnoreInvisible]));
  686.           KeepSelected:= False;
  687.           Msg.Result:= 1;
  688.         end;
  689.       // move selection left
  690.       vk_Right:
  691.         begin
  692.           KeepSelected:= True;
  693.           MoveActiveTo(GetNextMenuItem(aiIndex, [niIgnoreInvisible]));
  694.           KeepSelected:= False;
  695.           Msg.Result:= 1;
  696.         end;
  697.       // move selection right
  698.       vk_Left:
  699.         begin
  700.           KeepSelected:= True;
  701.           MoveActiveTo(GetNextMenuItem(aiIndex, [niBackward, niIgnoreInvisible]));
  702.           KeepSelected:= False;
  703.           Msg.Result:= 1;
  704.         end;
  705.       // escape
  706.       vk_Escape:
  707.         begin
  708.           KillActiveItem;
  709.           Msg.Result:= 1;
  710.         end;
  711.       vk_F1:
  712.         if (Application.HelpFile <> '')
  713.         and (ai <> nil)
  714.         and (ai.HelpContext <> 0)
  715.         then begin
  716.           KillActivePopupMenu2000(True, False);
  717.           if (OwnerForm is TForm)
  718.           and (biHelp in TForm(OwnerForm).BorderIcons)
  719.           then Application.HelpCommand(HELP_CONTEXTPOPUP, ai.HelpContext)
  720.           else Application.HelpCommand(HELP_CONTEXT, ai.HelpContext);
  721.           // We have to remove the next message that is in the queue.
  722.           PeekMessage(M, 0, 0, 0, pm_Remove);
  723.           Msg.Result:= 1;
  724.         end;
  725.     end
  726.   else
  727.     if IsShortCut
  728.     then SearchForMergedMenus;
  729. end;
  730. procedure TCustomMenuBar2000.wmMouseMove(var Msg: TWMMouse);
  731. begin
  732.   inherited;
  733.   if (ToolTipWindow <> nil)
  734.   then ToolTipWindow.RelayMouseMove(Msg.Pos);
  735. end;
  736. { Set Bounds Routines }
  737. function TCustomMenuBar2000.GetOffsetX: Integer;
  738. begin
  739.   Result:= 0;
  740.   if OwnerForm = nil then Exit;
  741.   // is system icon present?
  742.   with OwnerForm as TForm do
  743.     if (ActiveMdiChild <> nil)
  744.     and (ActiveMdiChild.WindowState = wsMaximized)
  745.     then Inc(Result, iSystemIconWidth +4);
  746. end;
  747. function TCustomMenuBar2000.GetLastOffsetX: Integer;
  748. begin
  749.   Result:= 0;
  750.   if OwnerForm = nil then Exit;
  751.   // increase by mdi caption buttons
  752.   with OwnerForm as TForm do
  753.     if (ActiveMdiChild <> nil)
  754.     and (ActiveMdiChild.WindowState = wsMaximized)
  755.     then begin
  756.       if mbType <> mbVertical
  757.       then Inc(Result, 4);
  758.       // if Form is an MDI form, and it's ActiveMdiForm property
  759.       // is not nil and the child form is maximized
  760.       // then add caption buttons' width and space width
  761.       if (biMaximize in ActiveMdiChild.BorderIcons)
  762.       or (biMinimize in ActiveMdiChild.BorderIcons)
  763.       then begin
  764.         Inc(Result, iSystemIconWidth *2);
  765.         if mbType <> mbVertical then Inc(Result, 2);
  766.       end;
  767.       if (biSystemMenu in ActiveMdiChild.BorderIcons)
  768.       then Inc(Result, iSystemIconWidth);
  769.     end;
  770. end;
  771. function TCustomMenuBar2000.GetBufOffsetX: Integer;
  772. begin
  773.   if (Options.Alignment = taRightToLeft)
  774.   then Result:= Width - Buffer.Width - GetLastOffsetX
  775.   else Result:= 0;
  776. end;
  777. function TCustomMenuBar2000.GetItemSize(Item: TMenuItem): TSize;
  778. var
  779.   W: Integer;
  780.   S: String;
  781. begin
  782.   Result.Cx:= 0;
  783.   Result.Cy:= 0;
  784.   if (Item = nil) then Exit;
  785.   S:= StripAmpersands(Item.Caption);
  786.   // select font
  787.   if FSystemFont then begin
  788.     if FSystemFontHandle = 0 then FSystemFontHandle:= GetMenuFontHandle;
  789.     FOldFontHandle:= SelectObject(Buffer.Canvas.Handle, FSystemFontHandle);
  790.   end
  791.   else
  792.     Buffer.Canvas.Font.Assign(Font);
  793.   GetTextExtentPoint32(Buffer.Canvas.Handle, PChar(S), Length(S), Result);
  794.   // if bitmap present...
  795.   W:= GetBitmapWidth(Item);
  796.   if W > 0 then Inc(Result.CX, W);
  797. end;
  798. function TCustomMenuBar2000.GetMenuItemCount: Integer;
  799. begin
  800.   if FMenu = nil
  801.   then Result:= 0
  802.   else
  803.   if FMenu is TCustomMainMenu2000
  804.   then Result:= TCustomMainMenu2000(FMenu).MergedMenuItemsCount
  805.   else Result:= FMenu.Items.Count;
  806. end;
  807. function TCustomMenuBar2000.GetMenuItem(Index: Integer): TMenuItem;
  808. begin
  809.   if FMenu = nil
  810.   then Result:= nil
  811.   else
  812.   if FMenu is TCustomMainMenu2000
  813.   then Result:= TCustomMainMenu2000(FMenu).MergedMenuItems[Index]
  814.   else Result:= FMenu.Items[Index];
  815. end;
  816. function TCustomMenuBar2000.GetNextMenuItem(var CurIndex: Integer; Params: T_AM2000_NextMenuItemParams): TMenuItem;
  817.   // returns nearest menu item
  818. var
  819.   SaveIndex: Integer; // prevents looping
  820.   CurItem: TMenuItem;
  821.   Maximized: Boolean;
  822. begin
  823.   SaveIndex:= CurIndex;
  824.   Result:= nil;
  825.   Maximized:= (TForm(OwnerForm).ActiveMdiChild <> nil)
  826.     and (TForm(OwnerForm).ActiveMdiChild.WindowState = wsMaximized);
  827.   repeat
  828.     if niBackward in Params
  829.     then Dec(CurIndex)
  830.     else Inc(CurIndex);
  831.     // check right limit
  832.     if (CurIndex >= GetMenuItemCount) then begin
  833.       if (niStopOnLimit in Params) then Exit;
  834.       if Maximized then begin
  835.         CurIndex:= -1;
  836.         Result:= SystemMenu;
  837.         Exit;
  838.       end;
  839.       CurIndex:= 0;
  840.     end;
  841.     // check left limit
  842.     if (CurIndex < 0) then begin
  843.       if (niStopOnLimit in Params) then Exit;
  844.       if Maximized and (CurIndex = -1) then begin
  845.         Result:= SystemMenu;
  846.         Exit;
  847.       end;
  848.       CurIndex:= GetMenuItemCount -1;
  849.     end;
  850.     // check for looping
  851.     if (CurIndex = SaveIndex)
  852.     then Exit;
  853.     CurItem:= GetMenuItem(CurIndex);
  854.   until (CurItem <> nil) and (CurItem.Visible or (not (niIgnoreInvisible in Params)));
  855.   Result:= CurItem;
  856. end;
  857. { Drawing Rountines }
  858. procedure TCustomMenuBar2000.PaintItem(Canvas: TCanvas; Item: TMenuItem;
  859.                                        R: TRect; BitBlt2SelfCanvas: Boolean);
  860.   procedure PaintHorizontal(Canvas: TCanvas; R: TRect; DrawBackground: Boolean);
  861.   var
  862.     DX, DY: Integer;
  863.   begin
  864.     if FSystemFont
  865.     then begin
  866.       SelectObject(Canvas.Handle, FOldFontHandle);
  867.       Canvas.Font.Handle:= FSystemFontHandle;
  868.       FOldFontHandle:= SelectObject(Canvas.Handle, FSystemFontHandle);
  869.     end;
  870.     if (ai = Item)
  871.     and (aiState = aiSunken)
  872.     and Ctl3D
  873.     then DX:= 1
  874.     else DX:= 0;
  875.     if mbType = mbVertical
  876.     then DY:= -DX
  877.     else DY:= DX;
  878.     if (Item <> nil) then begin
  879.       DrawRect.Item:= Item;
  880.       // is it necessary to re-init DrawRect?
  881.       if DrawRect.Canvas <> Canvas then begin
  882.         DrawRect.mir.Clear;
  883.         DrawRect.State:= [];
  884.         DrawRect.Canvas:= Canvas;
  885.         DrawRect.Options:= FLocalOptions;
  886. {$IFDEF Delphi4OrHigher}
  887.         DrawRect.Images:= TImageList(Menu.Images);
  888. {$ELSE}
  889.         if (Menu is TCustomMainMenu2000)
  890.         then DrawRect.Images:= TCustomMainMenu2000(Menu).Images;
  891. {$ENDIF}
  892.       end;
  893.       with DrawRect do begin
  894.         mir.BitmapLeft:= R.Left + DX +4;
  895.         mir.BitmapWidth:= GetBitmapWidth(Item);
  896.         mir.LineLeft:= R.Left + DX;
  897.         mir.LineRight:= R.Right + DX;
  898.         mir.ItemLeft:= R.Left + DX;
  899.         if mir.BitmapWidth > 0
  900.         then Inc(mir.ItemLeft, mir.BitmapWidth);
  901.         mir.ItemWidth:= mir.LineRight - mir.ItemLeft;
  902.         mir.Top:= R.Top + DY;
  903.         mir.Height:= R.Bottom - R.Top;
  904.         // is Ctl3d is false then highlight menu item
  905.         if (ai = Item)
  906.         and (aiState <> aiFlat)
  907.         and not Ctl3D
  908.         then Include(State, isSelected)
  909.         else Exclude(State, isSelected);
  910.         // Transparent background
  911.         if DrawBackground
  912.         then Include(State, isGraphBack)
  913.         else Exclude(State, isGraphBack);
  914.         // draw item
  915.         DrawMenuItem(@DrawRect);
  916.       end;
  917.     end;
  918.   end;
  919.   procedure PaintVertical(Canvas: TCanvas; R: TRect);
  920.   var
  921.     bmp: TBitmap;
  922.     procedure PaintRotated;
  923.     var
  924.       W, X, Y: Integer;
  925.       P, T: TColor;
  926.     begin
  927.       W:= bmp.Height;
  928.       T:= bmp.Canvas.Pixels[bmp.Width -1, W -1];
  929.       for X:= 0 to bmp.Width -1 do
  930.         for Y:= 0 to bmp.Height -1 do begin
  931.           P:= bmp.Canvas.Pixels[X, Y];
  932.           if P <> T
  933.           then Canvas.Pixels[R.Left + W-Y -1, R.Top + X]:= P;
  934.         end;
  935.     end;
  936.   begin
  937.     if (Item <> nil) then begin
  938.       bmp:= TBitmap.Create;
  939.       try
  940.          bmp.Width:= R.Bottom - R.Top;
  941.          bmp.Height:= R.Right - R.Left;
  942.          PaintHorizontal(bmp.Canvas, Rect(0,0,bmp.Width,bmp.Height), True);
  943.          PaintRotated;
  944.       finally
  945.          bmp.Free;
  946.       end;
  947.     end;
  948.   end;
  949. begin
  950.   // Transparent background
  951.   if FTransparent
  952.   then
  953.     BitBlt(Canvas.Handle, R.Left, R.Top, R.Right - R.Left +1, R.Bottom - R.Top +1,
  954.       Back.Canvas.Handle, R.Left, R.Top, SrcCopy);
  955.   if mbType = mbVertical then
  956.     PaintVertical(Canvas, R)
  957.   else
  958.     PaintHorizontal(Canvas, R, FTransparent);
  959.   if (ai = Item) then
  960.     if Ctl3D then
  961.       case aiState of
  962.         aiRaised: DrawEdge(Canvas.Handle, R, bdr_RaisedInner, bf_Rect);
  963.         aiSunken: DrawEdge(Canvas.Handle, R, bdr_SunkenOuter, bf_Rect);
  964.         aiFlat:   Canvas.FrameRect(R);
  965.       end
  966.     else
  967.       Canvas.FrameRect(R);
  968.   if BitBlt2SelfCanvas
  969.   then
  970.     with R do begin
  971.       // paint background
  972.       // bitblt with a mask
  973.       BitBlt(Self.Canvas.Handle, Left + GetBufOffsetX, Top, Right - Left, Bottom - Top,
  974.         Canvas.Handle, Left, Top, SrcCopy);
  975.     end;
  976. end;
  977. procedure TCustomMenuBar2000.PaintActiveItem;
  978. begin
  979.   if (ai <> SystemMenu)
  980.   then PaintItem({$IFNDEF DrawOnCanvas}Buffer.{$ENDIF}Canvas, ai, aiRect, True);
  981. end;
  982. procedure TCustomMenuBar2000.ResetBuffer;
  983. begin
  984.   Canvas.Brush.Style:= bsClear;
  985.   Canvas.Brush.Bitmap:= nil;
  986.   BufferState:= False;
  987.   Buffer.FreeImage;
  988. end;
  989. procedure TCustomMenuBar2000.PaintSystemButton(R: TRect; Letter: Char; Down, Enabled: Boolean);
  990.   // draw system button
  991. const
  992.   dt_Flags = dt_Center + dt_VCenter + dt_SingleLine;
  993.   Edge: array [Boolean] of UINT = (Edge_Raised, Edge_Sunken);
  994.   ButtonColors: array [Boolean] of TColor = (clBtnText, clGrayText);
  995. begin
  996.   Canvas.Brush.Style:= bsSolid;
  997.   Canvas.Brush.Color:= Options.Colors.Menu;
  998.   Canvas.FillRect(R);
  999.   DrawEdge(Canvas.Handle, R, Edge[Down], bf_Soft + bf_Rect);
  1000.   if Down then OffsetRect(R, 1, 1);
  1001.   InflateRect(R, -1, -1);
  1002.   if Canvas.Brush.Style <> bsClear
  1003.   then Canvas.Brush.Style:= bsClear;
  1004.   Canvas.Font.Name:= 'Marlett';
  1005.   Canvas.Font.Height:= iSystemIconWidth -6;
  1006.   if not Enabled then begin
  1007.     Canvas.Font.Color:= clBtnHighlight;
  1008.     OffsetRect(R, 1, 1);
  1009.     DrawText(Canvas.Handle, @Letter, 1, R, dt_Flags);
  1010.     OffsetRect(R, -1, -1);
  1011.     Canvas.Font.Color:= clGrayText;
  1012.   end
  1013.   else
  1014.     if Canvas.Font.Color <> clBtnText
  1015.     then Canvas.Font.Color:= clBtnText;
  1016.   DrawText(Canvas.Handle, @Letter, 1, R, dt_Flags);
  1017. end;
  1018. procedure TCustomMenuBar2000.PaintSystemButtons;
  1019. var
  1020.   F: TForm;
  1021.   R: TRect;
  1022. begin
  1023.   // fill the background
  1024.   R:= miSysBtnRect;
  1025.   InflateRect(R, 1, 1);
  1026.   
  1027. {  if FTransparent then begin
  1028.     BitBlt(Canvas.Handle, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
  1029.       Back.Canvas.Handle, R.Left, R.Top, SrcCopy);
  1030.   end
  1031.   else begin
  1032.     Canvas.FillRect(R);
  1033.   end;
  1034. }
  1035.   // draw
  1036.   F:= TForm(OwnerForm);
  1037.   if (F <> nil)
  1038.   and (F.ActiveMdiChild <> nil)
  1039.   and (F.ActiveMdiChild.WindowState = wsMaximized)
  1040.   then
  1041.     with F.ActiveMdiChild do begin
  1042.       { close }
  1043.       R:= GetSysBtnRect(sbClose);
  1044.       PaintSystemButton(R, 'r', SystemButtonPressed = sbClose, True);
  1045.       if (biMaximize in BorderIcons) or (biMinimize in BorderIcons) then begin
  1046.         { restore }
  1047.         R:= GetSysBtnRect(sbRestore);
  1048.         PaintSystemButton(R, '2', SystemButtonPressed = sbRestore,
  1049.                                         biMaximize in BorderIcons);
  1050.         { minimize }
  1051.         R:= GetSysBtnRect(sbMinimize);
  1052.         PaintSystemButton(R, '0', SystemButtonPressed = sbMinimize,
  1053.                                          biMinimize in BorderIcons);
  1054.       end;
  1055.     end;
  1056. end;
  1057. procedure TCustomMenuBar2000.Paint;
  1058. var
  1059.   F: TForm;
  1060.   R: TRect;
  1061.   I, DX: Integer;
  1062.   CurItem: TMenuItem;
  1063. begin
  1064.   if (csLoading in ComponentState)
  1065.   or (csDestroying in ComponentState)
  1066.   or IgnorePaint
  1067.   then Exit;
  1068.   R:= Rect(0, 0, 0, 0);
  1069.   if not WindowActive
  1070.   then FLocalOptions.Colors.MenuText:= Options.Colors.DisabledText
  1071.   else FLocalOptions.Colors.MenuText:= SaveMenuTextColor;
  1072.   // if the buffer is empty...
  1073.   if (not BufferState)
  1074.   and (GetMenuItemCount > 0)
  1075.   then
  1076.     with {$IFNDEF DrawOnCanvas} Buffer, {$ENDIF}Canvas do begin
  1077.       if FTransparent then begin
  1078.         BitBlt(Handle, 0, 0, Self.Width +2, Self.Height +2, Back.Canvas.Handle, Self.Left, Self.Top, SrcCopy);
  1079.       end
  1080.       else begin
  1081.         Brush.Style:= bsSolid;
  1082.         Brush.Color:= FLocalOptions.Colors.Menu;
  1083.         FillRect(ClipRect);
  1084.       end;
  1085.       // if Form is MDI and ChildForm is assigned man maximized
  1086.       F:= TForm(OwnerForm);
  1087.       if (F <> nil)
  1088.       and (F.ActiveMdiChild <> nil)
  1089.       and (F.ActiveMdiChild.WindowState = wsMaximized)
  1090.       then begin
  1091.         R:= GetMenuIconRect;
  1092.         PaintMenuIcon(F, F.ActiveMdiChild, Handle, R.Left, R.Top, iSystemIconWidth);
  1093.       end;
  1094.       // draw menu items
  1095.       if ai = SystemMenu
  1096.       then aiRect:= R;
  1097.       if (FMenu <> nil) then
  1098.         for I:= 0 to GetMenuItemCount -1 do begin
  1099.           CurItem:= GetMenuItem(I);
  1100.           if (CurItem = nil)
  1101.           or (not CurItem.Visible)
  1102.           then Continue;
  1103.           R := GetMiRect(miRects, I, CurItem);
  1104.           PaintItem(Canvas, CurItem, R, {$IFDEF DrawOnCanvas}True{$ELSE}False{$ENDIF});
  1105.           if CurItem = ai
  1106.           then aiRect:= R;
  1107.         end;
  1108.       aiRect.Bottom:= R.Bottom;
  1109.     end;
  1110.   BufferState:= True;
  1111.   if (Options.Alignment = taRightToLeft)
  1112.   then DX:= Width - Buffer.Width - GetLastOffsetX
  1113.   else DX:= 0;
  1114. {$IFNDEF DrawOnCanvas}
  1115.   BitBlt(Canvas.Handle, DX, 0, Buffer.Width, Buffer.Height, Buffer.Canvas.Handle, 0, 0, SrcCopy);
  1116. {$ENDIF}
  1117.   // fill the rest
  1118.   if FTransparent then begin
  1119.     if mbType = mbVertical
  1120.     then begin
  1121.       if Buffer.Height < Height
  1122.       then BitBlt(Canvas.Handle, 0, Buffer.Height, Width +1, Height +1, Back.Canvas.Handle, 0, Buffer.Height, SrcCopy);
  1123.     end
  1124.     else
  1125.     if Buffer.Width < Width
  1126.     then
  1127.       if Options.Alignment = taRightToLeft
  1128.       then BitBlt(Canvas.Handle, 0, 0, DX, Height +1, Back.Canvas.Handle, 0, 0, SrcCopy)
  1129.       else BitBlt(Canvas.Handle, Buffer.Width, 0, Width +1, Height +1, Back.Canvas.Handle, Buffer.Width, 0, SrcCopy);
  1130.   end
  1131.   else begin
  1132.     Canvas.Brush.Style:= bsSolid;
  1133.     Canvas.Brush.Color:= Options.Colors.Menu;
  1134.     if mbType = mbVertical
  1135.     then begin
  1136.       if Buffer.Height < Height
  1137.       then Canvas.FillRect(Rect(0, Buffer.Height, Width +1, Height +1))
  1138.     end
  1139.     else
  1140.     if Buffer.Width < Width
  1141.     then
  1142.       if Options.Alignment = taRightToLeft
  1143.       then Canvas.FillRect(Rect(0, 0, DX, Height +1))
  1144.       else Canvas.FillRect(Rect(Buffer.Width, 0, Width +1, Height +1));
  1145.   end;
  1146.   // draw caption buttons
  1147.   PaintSystemButtons;
  1148. end;
  1149. procedure TCustomMenuBar2000.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  1150.   procedure OrderMenuItems(var bWidth, bHeight: Integer);
  1151.   var
  1152.     iW,iH, i: Integer;
  1153.     rSize, bX,bY: Integer;
  1154.   begin
  1155.     rSize:= 0;
  1156.     if (Parent <> nil)
  1157.     then
  1158.       case mbType of
  1159.         mbVertical:   rSize:= Parent.ClientHeight;
  1160.         mbHorizontal: rSize:= Parent.ClientWidth;
  1161.         mbFloating:   rSize:= ParentClientWidth;
  1162.       end
  1163.     else
  1164.       rSize:= High(rSize);
  1165.     if rSize < 0 then Exit;
  1166.     for i:=0 to miRects.Count -1 do begin
  1167.       with PMenuItemRect(miRects.Items[i])^ do
  1168.         iW:= iR.Right-iR.Left;
  1169.       if rSize < iW then rSize:= iW;
  1170.     end;
  1171.     // offsets
  1172.     if rSize < GetOffsetX     then rSize:= GetOffsetX;
  1173.     // start
  1174.     bX:= GetOffsetX;
  1175.     bY:= 0;
  1176.     iH:= 0;
  1177.     bWidth:= 0;
  1178.     bHeight:= 0;
  1179.     for I:= 0 to miRects.Count -1 do
  1180.        with PMenuItemRect(miRects.Items[i])^ do begin
  1181.          iW:= iR.Right-iR.Left;
  1182.          iH:= iR.Bottom-iR.Top;
  1183.          if i=0 then bHeight:= iH +1;
  1184.          if (bX + iW) > rSize then begin
  1185.            Inc(bY, iH +1);
  1186.            Inc(bHeight, iH +1);
  1187.            bX:= 0;
  1188.          end;
  1189.          iR:= Rect(bX, bY, bX + iW, bY + iH);
  1190.          Inc(bX, iW);
  1191.          if bX > bWidth then bWidth:= bX;
  1192.        end;
  1193.     // sys buttons
  1194.     iW:= GetLastOffsetX;
  1195.     if (bX + iW) > rSize then begin
  1196.       Inc(bY, iH +2);
  1197.       Inc(bHeight, iH +1);
  1198.       bX:= 0;
  1199.     end;
  1200.     Inc(bX, iW);
  1201.     if bX > bWidth then bWidth:= bX;
  1202.     if mbType = mbVertical
  1203.     then
  1204.       miSysBtnRect:= Rect(bY, bX - iW, bY + iH, bX)
  1205.     else
  1206.       miSysBtnRect:= Rect(bWidth - iW, bY, bWidth, bY + iH);
  1207.     // right-to-left reading
  1208.     if Options.Alignment = taRightToLeft
  1209.     then
  1210.       for I:= 0 to miRects.Count -1 do
  1211.         with PMenuItemRect(miRects.Items[i])^ do
  1212.           iR:= Rect(bWidth - iR.Right, iR.Top, bWidth - iR.Left, iR.Bottom);
  1213.   end;
  1214. var
  1215.   I, W, H: Integer;
  1216.   CurItem: TMenuItem;
  1217.   miX1, miY1, SaveIndex: Integer;
  1218.   DC: HDC;
  1219. begin
  1220.   W:= 0;
  1221.   H:= 0;
  1222.   iSystemIconWidth:= GetSystemMetrics(SM_CYMENUSIZE) -2;
  1223.   // calculating interior's width and height
  1224.   if (FMenu <> nil)
  1225.   and not (csLoading in ComponentState)
  1226.   then begin
  1227.     ClearMiRects(miRects);
  1228.     if mbType = mbVertical then begin
  1229.        miX1:= 0;
  1230.        miY1:= GetOffsetX;
  1231.     end
  1232.     else begin
  1233.        miX1:= GetOffsetX;
  1234.        miY1:= 0;
  1235.     end;
  1236.     // calculate menu items' width
  1237.     for I:= 0 to GetMenuItemCount -1 do begin
  1238.       CurItem:= GetMenuItem(I);
  1239.       if (CurItem <> nil)
  1240.       and CurItem.Visible
  1241.       then
  1242.         with GetItemSize(CurItem) do begin
  1243.           AddMiRects(miRects, CurItem, Rect(miX1, miY1, miX1 +(Cx +12), miY1 +(Cy +5)));
  1244.           Inc(miX1, Cx +12);
  1245.         end;
  1246.     end;
  1247.     OrderMenuItems(W, H);
  1248.     if mbType = mbVertical then
  1249.        for i:= 0 to miRects.Count -1 do
  1250.            with PMenuItemRect(miRects.Items[i])^ do
  1251.            iR:= Rect(H - iR.Bottom, iR.Left, H - iR.Top, iR.Right);
  1252.     // set minimal bounds
  1253.     if W = 0 then W:= 50;
  1254.     if H = 0 then H:= 10;
  1255.     if mbType = mbVertical then begin
  1256.       I:= W;
  1257.       W:= H;
  1258.       H:= I;
  1259.     end;
  1260.     // arranging buffer
  1261.     if Buffer.Width <> W then begin
  1262.       Buffer.Width:= W;
  1263.       ResetBuffer;
  1264.     end;
  1265.     if Buffer.Height <> H then begin
  1266.       Buffer.Height:= H;
  1267.       ResetBuffer;
  1268.     end;
  1269.     case mbType of
  1270.       mbFloating: begin
  1271.                     AWidth:= W;
  1272.                     AHeight:= H;
  1273.                   end;
  1274.       mbHorizontal: if (Parent <> nil) then begin
  1275.                        if Parent.ClientWidth < W then
  1276.                           AWidth:= W
  1277.                        else AWidth:= Parent.ClientWidth;
  1278.                        AHeight:= H;
  1279.                     end;
  1280.       mbVertical:   if (Parent <> nil) then begin
  1281.                        if Parent.ClientHeight < H then
  1282.                           AHeight:= H
  1283.                        else AHeight:= Parent.ClientHeight;
  1284.                        AWidth:= W;
  1285.                     end;
  1286.     end;
  1287.     // draw back
  1288.     if FTransparent
  1289.     and (Parent <> nil)
  1290.     then begin
  1291.       Back.Width:= AWidth;
  1292.       Back.Height:= AHeight;
  1293.       IgnorePaint:= True;
  1294.       DC:= Back.Canvas.Handle;
  1295.       with Parent do begin
  1296.         ControlState:= ControlState + [csPaintCopy];
  1297.         SaveIndex:= SaveDC(DC);
  1298.         MoveWindowOrg(DC, -Self.Left, -Self.Top);
  1299.         IntersectClipRect(DC, 0, 0, Width +1, Height +1);
  1300.         Perform(WM_ERASEBKGND, DC, 0);
  1301.         
  1302.         if not (csDesigning in ComponentState)
  1303.         then Perform(WM_PAINT, DC, 0);
  1304.         RestoreDC(DC, SaveIndex);
  1305.         ControlState:= ControlState - [csPaintCopy];
  1306.       end;
  1307.       IgnorePaint:= False;
  1308.     end;
  1309.     if (not (csDesigning in ComponentState))
  1310.     and FAlignParent
  1311.     and (Parent <> nil)
  1312.     then begin
  1313.       Parent.ClientHeight:= AHeight +3;
  1314.       Parent.ClientWidth:= AWidth +3;
  1315.       ALeft:= 1;
  1316.       ATop:= 1;
  1317.     end;
  1318.   end;
  1319.   // inherited
  1320.   inherited;
  1321. end;
  1322. procedure TCustomMenuBar2000.cmMouseLeave(var Msg: TMessage);
  1323. begin
  1324.   if (aiState = aiRaised)
  1325.   and not KeepSelected
  1326.   then HideActiveItem;
  1327.   ASTimer.Enabled:= False;
  1328. end;
  1329. procedure TCustomMenuBar2000.CMIsToolControl(var Msg: TMessage);
  1330. begin
  1331.   Msg.Result:= 1;
  1332. end;
  1333. {$IFDEF Delphi3OrHigher}
  1334. procedure TCustomMenuBar2000.cmSysFontChanged(var Msg: TMessage);
  1335. begin
  1336.   inherited;
  1337.   if FOldFontHandle <> 0 then begin
  1338.     SelectObject(Canvas.Handle, FOldFontHandle);
  1339.     DeleteObject(FSystemFontHandle);
  1340.     FSystemFontHandle:= 0;
  1341.     FOldFontHandle:= 0;
  1342.   end;
  1343.   UpdateMenuBar(True);
  1344. end;
  1345. {$ENDIF}
  1346. procedure TCustomMenuBar2000.wmSettingChange(var Msg: TMessage);
  1347. begin
  1348.   inherited;
  1349.   if FOldFontHandle <> 0 then begin
  1350.     SelectObject(Canvas.Handle, FOldFontHandle);
  1351.     DeleteObject(FSystemFontHandle);
  1352.     FSystemFontHandle:= 0;
  1353.     FOldFontHandle:= 0;
  1354.   end;
  1355.   UpdateMenuBar(True);
  1356. end;
  1357. procedure TCustomMenuBar2000.cmFontChanged(var Msg: TMessage);
  1358. begin
  1359.   inherited;
  1360.   UpdateMenuBar(True);
  1361. end;
  1362. { Mouse movements } 
  1363. procedure TCustomMenuBar2000.MouseMove(Shift: TShiftState; X, Y: Integer);
  1364. const
  1365.   LastX: Integer = 0;
  1366.   LastY: Integer = 0;
  1367. var
  1368.   I: Integer;
  1369.   R: TRect;
  1370.   CurItem: TMenuItem;
  1371. begin
  1372.   inherited;
  1373.   // now active menu bar
  1374.   ActiveMenuBar:= Self;
  1375.   // ignore little movements
  1376.   if (FMenu = nil)
  1377.   or (not WindowActive)
  1378.   or ((Abs(X - LastX) <= 2)
  1379.   and (Abs(Y - LastY) <= 2))
  1380.   then Exit;
  1381.   LastX:= X;
  1382.   LastY:= Y;
  1383.   // activate tooltip window
  1384.   if (aiState = aiRaised)
  1385.   and (ToolTipWindow <> nil)
  1386.   then ToolTipWindow.Activate;
  1387.   if GetOffsetX > 0 then begin
  1388.      I:= -1;
  1389.      CurItem:= SystemMenu;
  1390.      R:= GetMenuIconRect;
  1391.      if PtInRect2(R, Point(X,Y)) then begin
  1392.        // don't redraw on duplicating
  1393.        if (ai = CurItem)
  1394.        and (aiState <> aiFlat)
  1395.        then Exit;
  1396.        MoveActiveToIndex(I, CurItem);
  1397.        Exit;
  1398.      end;
  1399.   end;
  1400.   // loop for each of menu items
  1401.   for I:= 0 to GetMenuItemCount -1 do begin
  1402.       CurItem:= GetMenuItem(I);
  1403.       if CurItem = nil then Continue;
  1404.       R:= GetMiRect(miRects, I, CurItem);
  1405.       if PtInRect2(R, Point(X,Y)) then begin
  1406.         // don't redraw on duplicating
  1407.         if (ai = CurItem)
  1408.         and (aiState <> aiFlat)
  1409.         then Exit;
  1410.         MoveActiveToIndex(I, CurItem);
  1411.         Exit;
  1412.       end;
  1413.   end;
  1414.   { paint System Buttons: }
  1415.   if SystemButtonPressed <> sbNone then begin
  1416.      R:= GetSysBtnRect(SystemButtonPressed);
  1417.      if not PtInRect(R, Point(X,Y)) then begin
  1418.        SystemButtonPressed:= sbNone;
  1419.        PaintSystemButtons;
  1420.        Exit;
  1421.      end;
  1422.   end;
  1423.   if aiState = aiRaised
  1424.   then KillActiveItem;
  1425. end;
  1426. procedure TCustomMenuBar2000.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1427. var
  1428.   P: TPoint;
  1429.   R: TRect;
  1430.   F: TForm;
  1431. begin
  1432.   inherited;
  1433.   // exit when other key
  1434.   if Button <> mbLeft then begin
  1435.     KillActivePopupMenu2000(True, False);
  1436.     Exit;
  1437.   end;
  1438.   // disable tooltip window
  1439.   if (ToolTipWindow <> nil)
  1440.   then ToolTipWindow.Deactivate;
  1441.   // disable menu item
  1442.   DisableMouseUp:= DisableMouseUp or
  1443.     ((aiState <> aiSunken) and (ai <> nil) and ai.Enabled);
  1444.   if (aiState = aiRaised)  then begin
  1445.     PopupActiveItem(False);
  1446.     Exit;
  1447.   end;
  1448.   // check for menu items
  1449.   F:= TForm(OwnerForm);
  1450.   if (F.ActiveMdiChild <> nil)
  1451.   and (F.ActiveMdiChild.WindowState = wsMaximized)
  1452.   then
  1453.     with F.ActiveMdiChild do begin
  1454.       P:= Point(X, Y);
  1455.       R:= GetSysBtnRect(sbClose);
  1456.       SystemButtonPressed:= sbNone;
  1457.       if PtInRect(R, P)
  1458.       then SystemButtonPressed:= sbClose;
  1459.       R:= GetSysBtnRect(sbRestore);
  1460.       if PtInRect(R, P)
  1461.       and (biMaximize in BorderIcons)
  1462.       then SystemButtonPressed:= sbRestore;
  1463.       R:= GetSysBtnRect(sbMinimize);
  1464.       if PtInRect(R, P)
  1465.       and (biMinimize in BorderIcons)
  1466.       then SystemButtonPressed:= sbMinimize;
  1467.       // if system button is pressed then kill opened
  1468.       // menu and repaint menu bar
  1469.       if SystemButtonPressed <> sbNone then begin
  1470.         KillActiveItem;
  1471.         Paint;
  1472.       end;
  1473.     end;
  1474. end;
  1475. procedure TCustomMenuBar2000.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1476. const
  1477.   SysCmd: array [T_AM2000_SystemButtonPressed] of UINT =
  1478.     (0, sc_Minimize, sc_Restore, sc_Close);
  1479. var
  1480.   F: TForm;
  1481. begin
  1482.   inherited;
  1483.   if Button <> mbLeft then Exit;
  1484.   // check for system buttons
  1485.   if (SystemButtonPressed <> sbNone) then begin
  1486.     F:= TForm(OwnerForm).ActiveMdiChild;
  1487.     if (F <> nil)
  1488.     then F.Perform(wm_SysCommand, SysCmd[SystemButtonPressed], 0);
  1489.     SystemButtonPressed:= sbNone;
  1490.     UpdateMenuBar(False);
  1491.     Exit;
  1492.   end;
  1493.   // ignore this mouse up event
  1494.   if DisableMouseUp then begin
  1495.     DisableMouseUp:= False;
  1496.     Exit;
  1497.   end;
  1498.   // menu item pressed
  1499.   if (aiState = aiSunken)
  1500.   then
  1501.     if (ai <> nil)
  1502.     then begin
  1503.       KillActiveItem;
  1504.       aiState:= aiRaised;
  1505.       PaintActiveItem;
  1506.     end
  1507.     else
  1508.       TForm(OwnerForm).ActiveMdiChild.Close;
  1509. end;
  1510. procedure TCustomMenuBar2000.HideActiveItem;
  1511. begin
  1512.   // remove hidden flag
  1513.   If (PopupMenu <> nil)
  1514.   then PopupMenu.RemoveShowHiddenFlag;
  1515.   // draw
  1516.   if aiState <> aiFlat then begin
  1517.      aiState:= aiFlat;
  1518.      PaintActiveItem;
  1519.   end;
  1520.   aiState:= aiFlat;
  1521.   DisableMouseUp:= False;
  1522.   KeepSelected:= False;
  1523. end;
  1524. procedure TCustomMenuBar2000.MoveActiveTo(NewItem: TMenuItem);
  1525.   // set new ActiveItem
  1526. var
  1527.   IsMenuOpened: Boolean;
  1528.   aaiState: T_AM2000_aiState;
  1529. begin
  1530.   if (NewItem = nil)
  1531.   or (csDestroying in ComponentState)
  1532.   then Exit;
  1533.   if ai <> NewItem
  1534.   then
  1535.     IsMenuOpened:= TCustomPopupMenu2000(PopupMenu).FormOnScreen
  1536.       or ((aiState = aiSunken) and (not KeepSelected))
  1537.       or FHotTrack
  1538.   else
  1539.     IsMenuOpened:= FHotTrack;
  1540.   if IsMenuOpened
  1541.   then KillActivePopupMenu2000(False, False);
  1542.   // draw new activeitem
  1543.   if (ai <> nil)
  1544.   and (ai <> SystemMenu)
  1545.   and (aiState <> aiFlat)
  1546.   then begin
  1547.      aaiState:= aiState;
  1548.      aiState:= aiFlat;
  1549.      PaintItem(Buffer.Canvas, ai, aiRect, True);
  1550.      aiState:= aaiState;
  1551.   end;
  1552.   ai:= NewItem;
  1553.   if (aiState = aiFlat)
  1554.   and (ai <> nil)
  1555.   and (ai.Enabled)
  1556.   then
  1557.     if FHotTrack
  1558.     then aiState:= aiSunken
  1559.     else aiState:= aiRaised;
  1560.   if ai = SystemMenu then
  1561.      aiRect:= GetMenuIconRect
  1562.   else
  1563.   if ai <> nil then begin
  1564.      aiRect := GetMiRect(miRects, aiIndex, ai);
  1565.      PaintItem(Buffer.Canvas, ai, aiRect, True);
  1566.   end;
  1567.   // if no item or no submenu
  1568.   if (ai.Count = 0)
  1569.   and (ai <> SystemMenu)
  1570.   and not ((ai is TMenuItem2000) and (TMenuItem2000(ai).AttachMenu <> nil))
  1571.   then Exit;
  1572.   // open submenu
  1573.   if (aiState = aiSunken)
  1574.   and IsMenuOpened
  1575.   then PopupMenuRect(aiRect, False, KeepSelected);
  1576. end;
  1577. procedure TCustomMenuBar2000.MoveActiveToIndex(NewIndex: Integer; NewItem: TMenuItem);
  1578.   // set new ActiveItem(ai) and ActiveItemIndex(aiIndex)
  1579. begin
  1580.   if NewItem = SystemMenu then
  1581.      NewIndex:= -1;
  1582.   aiIndex:= NewIndex;
  1583.   MoveActiveTo(NewItem);
  1584.   // set aiIndex
  1585.   if (ai = nil)
  1586.   then aiIndex:= -1
  1587.   else aiIndex:= NewIndex;
  1588. end;
  1589. procedure TCustomMenuBar2000.SetActiveItemIndex(Index: Integer);
  1590. begin
  1591.   if Index < GetMenuItemCount then
  1592.     MoveActiveToIndex(Index, GetMenuItem(Index));
  1593. end;
  1594. procedure TCustomMenuBar2000.PopupActiveItem(SelectFirst: Boolean);
  1595. begin
  1596.   if (ai <> nil)
  1597.   and ai.Enabled
  1598.   then aiState:= aiSunken;
  1599.   // repaint
  1600.   PaintActiveItem;
  1601.   // popup submenu
  1602.   PopupMenuRect(aiRect, False, SelectFirst);
  1603. end;
  1604. procedure TCustomMenuBar2000.KillActiveItem;
  1605. begin
  1606.   KillActivePopupMenu2000(True, False);
  1607.   FullShowCaret;
  1608. end;
  1609. { Properties }
  1610. procedure TCustomMenuBar2000.SetAlignParent(Value: Boolean);
  1611. begin
  1612.   FAlignParent:= Value;
  1613.   UpdateMenuBar(False);
  1614. end;
  1615. procedure TCustomMenuBar2000.SetMenu(Value: TMenu);
  1616. begin
  1617.   FMenu:= Value;
  1618.   UpdateMenuBar(True);
  1619. end; 
  1620. procedure TCustomMenuBar2000.SetOptions(Value: T_AM2000_Options);
  1621. begin
  1622.   FOptions.Assign(Value);
  1623. end;
  1624. procedure TCustomMenuBar2000.SetSystemFont(Value: Boolean);
  1625. begin
  1626.   FSystemFont:= Value;
  1627.   if Value then ParentFont:= False;
  1628.   UpdateMenuBar(True);
  1629. end;
  1630. procedure TCustomMenuBar2000.UpdateMenuBar(RebuildMenu: Boolean);
  1631. var
  1632.   SaveIdx, Count: Integer;
  1633. begin
  1634.   if (csLoading in ComponentState)
  1635.   or (csDestroying in ComponentState)
  1636.   then Exit;
  1637.   if PopupMenu = nil
  1638.   then DoLoaded;
  1639.   // reset bounds
  1640.   if RebuildMenu then begin
  1641.     if ai <> nil
  1642.     then SaveIdx:= aiIndex
  1643.     else SaveIdx:= 0;
  1644.     // rebuild main menu
  1645.     if (FMenu is TCustomMainMenu2000)
  1646.     then TCustomMainMenu2000(FMenu).RebuildMergedMenuItems;
  1647.     // clear bounds
  1648.     SetBounds(Left, Top, 0, 0);
  1649.     Count:= GetMenuItemCount;
  1650.     if (Count > 0)
  1651.     and (SaveIdx >=0)
  1652.     and (SaveIdx < Count)
  1653.     then begin
  1654.       ai:= GetMenuItem(SaveIdx);
  1655.       aiIndex:= 0;
  1656.     end
  1657.     else begin
  1658.       ai:= nil;
  1659.       aiIndex:= -1;
  1660.     end;
  1661.     RebuildToolTipWindow;
  1662.   end;
  1663.   ResetBuffer;
  1664.   Paint;
  1665. end;
  1666. procedure TCustomMenuBar2000.RebuildToolTipWindow;
  1667. var
  1668.   I: Integer;
  1669.   R: TRect;
  1670.   CurItem: TMenuItem;
  1671. begin
  1672.   ToolTipWindow.Free;
  1673.   ToolTipWindow:= nil;
  1674.   if (not ShowHint)
  1675.   or (StatusBar <> nil)
  1676.   then Exit;
  1677.   // add tooltips
  1678.   ToolTipWindow:= T_AM2000_ToolTipWindow.Create(Self);
  1679.   R:= Rect(0, 0, 0, 0);
  1680.   for I:= 0 to GetMenuItemCount -1 do begin
  1681.     R.Left:= R.Right;
  1682.     CurItem:= GetMenuItem(I);
  1683.     if (CurItem = nil)
  1684.     or (not CurItem.Visible)
  1685.     then Continue;
  1686.     with GetItemSize(CurItem) do begin
  1687.       Inc(R.Right, Cx +12);
  1688.       R.Bottom:= R.Top + Cy +5;
  1689.     end;
  1690.     if (CurItem.Hint <> '')
  1691.     and (CurItem.Hint <> #1)
  1692.     and (ToolTipWindow <> nil)
  1693.     then ToolTipWindow.AddTool(R, CurItem.Hint);
  1694.   end;
  1695. end;
  1696. procedure TCustomMenuBar2000.Notification(AComponent: TComponent;
  1697.   Operation: TOperation);
  1698. begin
  1699.   inherited;
  1700.   // remove reference
  1701.   if (Operation = opRemove) then begin
  1702.     if (AComponent = FMenu) then SetMenu(nil);
  1703.     if (AComponent = FStatusBar) then FStatusBar:= nil;
  1704.   end;
  1705.   if (Operation = opInsert)
  1706.   and (AComponent is TMainMenu)
  1707.   and (FMenu = nil)
  1708.   then begin
  1709.     FMenu:= TMenu(AComponent);
  1710.     PostMessage(Handle, wm_UpdateMenuBar, 1, 0);
  1711.   end;
  1712. end;
  1713. procedure TCustomMenuBar2000.SetDisableAltKeyUp(Value: Boolean);
  1714. begin
  1715.   DisableAltKeyUp:= Value;
  1716. end;
  1717. function TCustomMenuBar2000.GetBitmapWidth(Item: TMenuItem): Integer;
  1718. begin
  1719.   Result:= 0;
  1720.   if (Item = nil) then Exit;
  1721.   if (Item is TMenuItem2000)
  1722.   and TMenuItem2000(Item).IsBitmapAssigned
  1723.   then
  1724.     Result:= TMenuItem2000(Item).Bitmap.Width +4
  1725.   // item index <> -1
  1726.   else
  1727.   if
  1728. {$IFNDEF Delphi4OrHigher}
  1729.   (Item is TMenuItem2000) and (TMenuItem2000(Item).ImageIndex <> -1)
  1730. {$ELSE}
  1731.   (Item.ImageIndex <> -1)
  1732. {$ENDIF}
  1733.   then begin
  1734. {$IFDEF Delphi4OrHigher}
  1735.     Result:= Menu.Images.Width;
  1736. {$ELSE}
  1737.     if (Menu is TCustomMainMenu2000)
  1738.     then Result:= TCustomMainMenu2000(Menu).Images.Width;
  1739. {$ENDIF}
  1740.   end
  1741.   // ordinal item
  1742. {$IFDEF Delphi4OrHigher}
  1743.   else
  1744.     if not Item.Bitmap.Empty
  1745.     then Result:= Item.Bitmap.Width +4;
  1746. {$ENDIF}
  1747. end;
  1748. procedure TCustomMenuBar2000.DblClick;
  1749. begin
  1750.   inherited;
  1751.   if (ai = SystemMenu)
  1752.   and (TForm(OwnerForm).ActiveMdiChild <> nil)
  1753.   then begin // close current child
  1754.     DisableMouseUp:= True;
  1755.     KillActiveItem;
  1756.     TForm(OwnerForm).ActiveMdiChild.Perform(wm_SysCommand, sc_Close, 0);
  1757.     Exit;
  1758.   end;
  1759.   if CheckForHidden(ai)
  1760.   and (not (mfNoAutoShowHidden in Options.Flags))
  1761.   then begin
  1762.     PopupMenuRect(aiRect, True, False);
  1763.     DisableMouseUp:= True;
  1764.   end;
  1765. end;
  1766. procedure TCustomMenuBar2000.TimerShow(Sender: TObject);
  1767. var
  1768.   P: TPoint;
  1769. begin
  1770.   ASTimer.Enabled:= False;
  1771.   if mfHiddenIsVisible in PopupMenu.Options.Flags
  1772.   then Exit;
  1773.   // check is mouse cursor still over menu bar
  1774.   GetCursorPos(P);
  1775.   if (aiState = aiSunken)
  1776.   and PtInRect(ClientRect, ScreenToClient(P))
  1777.   then PopupMenuRect(aiRect, True, False);
  1778. end;
  1779. {$IFDEF Delphi4OrHigher}
  1780. procedure TCustomMenuBar2000.InitiateAction;
  1781. var
  1782.   I: Integer;
  1783.   mi: TMenuItem;
  1784. begin
  1785.   if Menu <> nil then
  1786.     for I := 0 to GetMenuItemCount - 1 do begin
  1787.       mi:= GetMenuItem(I);
  1788.       if (mi <> nil)
  1789.       and (mi.Visible)
  1790.       then mi.InitiateAction;
  1791.     end;
  1792. end;
  1793. {$ENDIF}
  1794. procedure TCustomMenuBar2000.SetHotTrack(const Value: Boolean);
  1795. begin
  1796.   FHotTrack:= Value;
  1797.   KillActiveItem;
  1798. end;
  1799. procedure TCustomMenuBar2000.SetTransparent(Value: Boolean);
  1800. begin
  1801.   if FTransparent = Value then Exit;
  1802.   
  1803.   FTransparent:= Value;
  1804.   // create a bitmap
  1805.   if FTransparent
  1806.   then
  1807.     Back:= TBitmap.Create
  1808.   else begin
  1809.     Back.Free;
  1810.     Back:= nil;
  1811.   end;
  1812.   KillActiveItem;
  1813.   // update
  1814.   if csDesigning in ComponentState
  1815.   then UpdateMenuBar(False);
  1816. end;
  1817. procedure TCustomMenuBar2000.DoLoaded;
  1818. begin
  1819.   Loaded;
  1820. end;
  1821. initialization
  1822. finalization
  1823. //  ActiveMenuBar.Free;
  1824. end.