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

Delphi控件源码

开发平台:

C++ Builder

  1. {*******************************************************}
  2. {                                                       }
  3. {       AnimatedMenus/2000                              }
  4. {       TMenuItem2000                                   }
  5. {                                                       }
  6. {       Copyright (c) 1997-99 AnimatedMenus.com         }
  7. {       All rights reserved.                            }
  8. {                                                       }
  9. {*******************************************************}
  10. unit am2000menuitem;
  11. {$I am2000.inc}
  12. interface
  13. uses
  14.   Windows, SysUtils, Classes, Controls, Graphics, Menus,
  15.   am2000options, am2000bitmap, am2000button, am2000buttonarray,
  16.   am2000editbox;
  17. type
  18.   // shortcut type
  19.   T_AM2000_ShortCut = Type String;
  20.   // options for menu item
  21.   T_AM2000_ControlType = (ctlNone, ctlButton, ctlButtonArray, ctlEditbox,
  22.     ctlBitmap, ctlFont);
  23.   // descendant of TPopupMenu
  24.   T_AM2000_PopupMenu = class(TPopupMenu)
  25.   end;
  26.   // menu item
  27.   TMenuItem2000 = class;
  28.   // edit menu item events
  29. //  T_AM2000_EditingEvent = procedure(Sender: TObject; Item: TMenuItem2000;
  30. //    var AllowEdit: Boolean) of object;
  31. //  T_AM2000_EditedEvent = procedure(Sender: TObject; Item: TMenuItem2000;
  32. //    var S: string) of object;
  33.   // TMenuItem2000
  34.   TMenuItem2000 = class(TMenuItem)
  35.   private
  36.     // improvements
  37.     FPopupMenu      : T_AM2000_PopupMenu;
  38.     FControl        : T_AM2000_ControlType;
  39.     FControlOptions : T_AM2000_ControlOptions;
  40.     FHidden         : Boolean;
  41.     FAttachMenu     : T_AM2000_PopupMenu;
  42.     FOptions        : T_AM2000_MenuOptions;
  43.     FShortCut       : T_AM2000_ShortCut;
  44.     FDefaultBitmapIndex : Integer;
  45. {$IFNDEF Delphi4OrHigher}
  46.     FBitmap         : TBitmap;
  47.     FImageIndex     : Integer;
  48. {$ENDIF}
  49.     FNumGlyphs      : Integer;
  50.     FFalseBreak     : Integer;
  51.     function GetItem(Index: Integer): TMenuItem2000;
  52.     function GetCaption: String;
  53.     function GetEnabled: Boolean;
  54.     function GetVisible: Boolean;
  55.     function GetParent: TMenuItem2000;
  56.     function GetBitmap: TBitmap;
  57.     function GetChecked: Boolean;
  58. {$IFDEF Delphi4OrHigher}
  59.     function GetAction: TBasicAction;
  60. {$ENDIF}
  61.     procedure SetCaption(const Value: String);
  62.     procedure SetEnabled(Value: Boolean);
  63.     procedure SetVisible(Value: Boolean);
  64.     procedure SetControl(Value: T_AM2000_ControlType);
  65.     procedure SetBitmap(Value: TBitmap);
  66. {$IFDEF Delphi4OrHigher}
  67.     procedure SetAction(Value: TBasicAction);
  68. {$ENDIF}    
  69.     function IsBitmapStored:   Boolean;
  70.     function IsOptionsStored:  Boolean;
  71.     function GetOptions: T_AM2000_MenuOptions;
  72.     procedure SetOptions(Value: T_AM2000_MenuOptions);
  73.     function IsHintStored:     Boolean;
  74.     function IsShortCutStored: Boolean;
  75.     function GetShortCut: T_AM2000_ShortCut;
  76.     function GetHint:     String;
  77.     procedure SetShortCut(Value: T_AM2000_ShortCut);
  78.     procedure SetHint(Value: String);
  79.     procedure SetDefaultIndex(Value: Integer);
  80.     procedure SetChecked(Value: Boolean);
  81.     procedure Update(UpdateDesigner, UpdateMenuBar: Integer);  
  82.   protected
  83.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  84.   public
  85.     property Parent        : TMenuItem2000  read GetParent;
  86.     property Items[Index: Integer]: TMenuItem2000 read GetItem; default;
  87.     constructor Create(AOwner: TComponent); override;
  88.     destructor Destroy; override;
  89.     procedure Insert(Index: Integer; Item: TMenuItem2000);
  90.     function IndexOf(Item: TMenuItem2000): Integer;
  91.     procedure Add(Item: TMenuItem2000);
  92.     procedure Remove(Item: TMenuItem2000);
  93.     procedure Delete(Index: Integer);
  94.     procedure TurnSiblingsOff;
  95.     function GetBitmapEx: TBitmap;
  96.     function IsTopLevelItem   : Boolean;
  97.     function IsBitmapAssigned : Boolean;
  98.     function IsOptionsAssigned: Boolean;
  99.     // control support
  100.     function AsButtonArray    : T_AM2000_ButtonArrayOptions;
  101.     function AsButton         : T_AM2000_ButtonOptions;
  102.     function AsBitmap         : T_AM2000_BitmapOptions;
  103.     function AsEdit           : T_AM2000_EditboxOptions;
  104.     // bounds measuring functions
  105.     function GetWidth(Canvas: TCanvas): Integer; 
  106.     function GetHeight(ItemHeight: Integer): Integer;
  107.     procedure Assign(Source: TPersistent); override;
  108. {$IFDEF Delphi4OrHigher}
  109.     procedure InitiateAction; override;
  110. {$ENDIF}    
  111.   published
  112.     property Bitmap        : TBitmap
  113.       read GetBitmap write SetBitmap stored IsBitmapStored;
  114.     property Caption       : String
  115.       read GetCaption write SetCaption;
  116.     property Checked       : Boolean
  117.       read GetChecked write SetChecked default False;
  118.     property Control       : T_AM2000_ControlType
  119.       read FControl write SetControl default ctlNone;
  120.     property ControlOptions: T_AM2000_ControlOptions
  121.       read FControlOptions write FControlOptions stored True;
  122.     property Enabled       : Boolean
  123.       read GetEnabled write SetEnabled default True;
  124.     property Hidden        : Boolean
  125.       read FHidden write FHidden default False;
  126.     property PopupMenu     : T_AM2000_PopupMenu
  127.       read FPopupMenu write FPopupMenu;
  128.     property Visible       : Boolean
  129.       read GetVisible write SetVisible default True;
  130.     property DefaultIndex  : Integer
  131.       read FDefaultBitmapIndex write SetDefaultIndex default -1;
  132.     property AttachMenu    : T_AM2000_PopupMenu
  133.       read FAttachMenu write FAttachMenu;
  134.     property Options       : T_AM2000_MenuOptions
  135.       read GetOptions write SetOptions stored IsOptionsStored;
  136.     property Hint          : String
  137.       read GetHint write SetHint stored IsHintStored;
  138.     property ShortCut      : T_AM2000_ShortCut
  139.       read GetShortCut write SetShortCut stored IsShortCutStored;
  140.     property NumGlyphs     : Integer
  141.       read FNumGlyphs write FNumGlyphs default 1;
  142. {$IFNDEF Delphi4OrHigher}
  143.     property ImageIndex    : Integer
  144.       read FImageIndex write FImageIndex default -1;
  145. {$ENDIF}
  146. {$IFDEF Delphi4OrHigher}
  147.     property Action        : TBasicAction
  148.       read GetAction write SetAction;
  149. {$ENDIF}
  150.     property Break         : Integer
  151.       read FFalseBreak default 0;
  152.   end;
  153.   // TEditableMenuItem98
  154.   // This class was designed because of error in Delphi:
  155.   // you cannot register another menu designer when you already have default designer
  156.   // This class are incompatible with TMenuItem nor TMenuItem2000 but acts like layer
  157.   // between your application and the TMenuItem2000 components stored in FItems property
  158.   // It has only minimal set of properties and methods so please verify your applications
  159.   // for bugs
  160.   // Also you can use Items2000 property of TMainMenu2000 and TPopupMenu2000 components
  161.   // to direct access real TMenuItem2000 components.
  162.   TEditableMenuItem2000 = class(TComponent)
  163.   private
  164.     function GetHandle: HMenu;
  165.     function GetCount: Integer;
  166.     function GetItem(Index: Integer): TMenuItem2000;
  167.   public                                  
  168.     property Handle        : HMenu        read GetHandle;
  169.     property Count         : Integer      read GetCount;
  170.     property Items[Index: Integer]: TMenuItem2000 read GetItem; default;
  171.     procedure Insert(Index: Integer; Item: TMenuItem2000);
  172.     procedure Delete(Index: Integer);
  173.     function IndexOf(Item: TMenuItem2000): Integer;
  174.     procedure Add(Item: TMenuItem2000);
  175.     procedure Remove(Item: TMenuItem2000);
  176.   end;
  177. // compatibility
  178. function NewMenu(Owner: TComponent; const AName: string; Items: array of TMenuItem): TMainMenu;
  179. function NewPopupMenu(Owner: TComponent; const AName: string;
  180.   Alignment: TPopupAlignment; AutoPopup: Boolean; Items: array of TMenuItem): TPopupMenu;
  181. function NewSubMenu(const ACaption: string; hCtx: Word; const AName: string;
  182.   Items: array of TMenuItem2000): TMenuItem2000;
  183. function NewItem(const ACaption: string; AShortCut: TShortCut;
  184.   AChecked, AEnabled: Boolean; AOnClick: TNotifyEvent; hCtx: Word;
  185.   const AName: string): TMenuItem2000;
  186. function NewLine: TMenuItem2000;
  187. function NewItem2000(const ACaption, AShortCut: string;
  188.   AChecked, AEnabled: Boolean; AOnClick: TNotifyEvent; hCtx: Word;
  189.   const AName: string): TMenuItem2000;
  190. function NewLine2000: TMenuItem2000;
  191. function GetMainShortCut(const S: String): String;
  192. procedure SetState(var its: T_AM2000_ItemState; Value: T_AM2000_its; Condition: Boolean);
  193. // drawing routines - both for TMenuItem and TMenuItem2000
  194. // draws menu item when TMenuItem or TMenuItem2000 component doesn't present
  195. // (like Window menu's menu items in Delphi 2 & 3)
  196. procedure DrawMenuItemWin32(DrawRect: P_AM2000_DrawMenuItemRect);
  197. // draws TMenuItem2000 with ControlStyle = ctlNone and TMenuItem
  198. procedure DrawMenuItem(DrawRect: P_AM2000_DrawMenuItemRect);
  199. { Drawing routines }
  200. procedure DrawCaption(Canvas: TCanvas;
  201.             Caption: String;
  202.             Alignment: T_AM2000_Alignment;
  203.             Rect: TRect);
  204. procedure DrawSubmenuTriangle(Canvas: TCanvas;
  205.             Draw: Boolean;
  206.             Alignment: T_AM2000_Alignment;
  207.             Rect: TRect);
  208. procedure DrawSeparator(Canvas: TCanvas;
  209.             State: T_AM2000_ItemState;
  210.             Options: T_AM2000_BaseOptions;
  211.             Rect: TRect);
  212. procedure DrawBackground(Canvas: TCanvas;
  213.             State: T_AM2000_ItemState;
  214.             Options: T_AM2000_BaseOptions;
  215.             Rect: TRect);
  216. procedure DrawBitmap(Canvas: TCanvas;
  217.             Bitmap: HBitmap;
  218.             BitmapIndex: Integer;
  219.             NumGlyphs: Integer;
  220.             Bitmap2: HBitmap;
  221.             State: T_AM2000_ItemState;
  222.             Options: T_AM2000_BaseOptions;
  223.             Rect: TRect;
  224.             Images: TImageList);
  225. procedure DrawPatternBackground(Canvas: TCanvas;
  226.             Rect: TRect);
  227. function CreatePattern(Color1, Color2: TColor): TBitmap;
  228. implementation
  229. uses
  230.   CommCtrl,
  231.   {$IFDEF Delphi4OrHigher} ActnList, {$ENDIF}
  232.   am2000utils, am2000menubar, am2000mainmenu, am2000popupmenu, am2000const, am2000cache;
  233. { Routines }
  234. function NewMenu(Owner: TComponent; const AName: string; Items: array of TMenuItem): TMainMenu;
  235. begin
  236.   raise EMenuError.Create(SNoNewMenu);
  237. end;
  238. function NewPopupMenu(Owner: TComponent; const AName: string;
  239.   Alignment: TPopupAlignment; AutoPopup: Boolean; Items: array of TMenuItem): TPopupMenu;
  240. begin
  241.   raise EMenuError.Create(SNoNewPopupMenu);
  242. end;
  243. function NewSubMenu(const ACaption: string; hCtx: Word; const AName: string;
  244.   Items: array of TMenuItem2000): TMenuItem2000;
  245. var
  246.   I: Integer;
  247. begin
  248.   Result := TMenuItem2000.Create(nil);
  249.   for I := Low(Items) to High(Items) do
  250.     Result.Add(Items[I]);
  251.   Result.Caption := ACaption;
  252.   Result.HelpContext := hCtx;
  253.   Result.Name := AName;
  254. end;
  255. function NewItem(const ACaption: string; AShortCut: TShortCut;
  256.   AChecked, AEnabled: Boolean; AOnClick: TNotifyEvent; hCtx: Word;
  257.   const AName: string): TMenuItem2000;
  258. begin
  259.   Result:= TMenuItem2000.Create(nil);
  260.   with Result do begin
  261.     Caption:= ACaption;
  262.     ShortCut:= ShortCutToText(AShortCut);
  263.     OnClick:= AOnClick;
  264.     HelpContext:= hCtx;
  265.     Checked:= AChecked;
  266.     Enabled:= AEnabled;
  267.     Name:= AName;
  268.   end;
  269. end;
  270. function NewLine: TMenuItem2000;
  271. begin
  272.   Result:= TMenuItem2000.Create(nil);
  273.   Result.Caption:= '-';
  274. end;
  275. function NewItem2000(const ACaption, AShortCut: string;
  276.   AChecked, AEnabled: Boolean; AOnClick: TNotifyEvent; hCtx: Word;
  277.   const AName: string): TMenuItem2000;
  278. begin
  279.   Result:= TMenuItem2000.Create(nil);
  280.   with Result do begin
  281.     Caption:= ACaption;
  282.     ShortCut:= AShortCut;
  283.     OnClick:= AOnClick;
  284.     HelpContext:= hCtx;
  285.     Checked:= AChecked;
  286.     Enabled:= AEnabled;
  287.     Name:= AName;
  288.   end;
  289. end;
  290. function NewLine2000: TMenuItem2000;
  291. begin
  292.   Result:= NewLine;
  293. end;
  294. function GetMainShortCut(const S: String): String;
  295. var
  296.   I: Integer;
  297. begin
  298.   I:= Pos(';', S);
  299.   if I < 1 then I:= Length(S) +1;
  300.   Result:= Trim(Copy(S, 1, I -1));
  301. end;
  302. { SetState }
  303. procedure SetState(var its: T_AM2000_ItemState; Value: T_AM2000_its; Condition: Boolean);
  304. begin
  305.   if Condition
  306.   then Include(its, Value)
  307.   else Exclude(its, Value);
  308. end;
  309. { Drawing routines }
  310. { Drawing routines }
  311. procedure DrawCaption(
  312.   Canvas: TCanvas;
  313.   Caption: String;
  314.   Alignment: T_AM2000_Alignment;
  315.   Rect: TRect);
  316. var
  317.   Flags, Lines, DY, P: Integer;
  318.   S: String;
  319.   R: TRect;
  320. begin
  321.   Flags:= dt_DrawTextFlags or dt_WordBreak;
  322.   // caption alignment
  323.   if (Alignment = taCenter)
  324.   then Flags:= Flags or dt_Center;
  325.   if (Alignment = taRightJustify) or (Alignment = taRightToLeft)
  326.   then Flags:= Flags or dt_Right;
  327.   Lines:= GetNumLines(Caption);
  328.   // draw caption
  329.   DY:= (Rect.Bottom - Rect.Top) div Lines;
  330.   R:= Rect;
  331.   R.Bottom:= R.Top + DY;
  332.   S:= Caption;
  333.   repeat
  334.     P:= Pos('n', S);
  335.     if P = 0 then P:= Pos(#13, S);
  336.     if P = 0 then P:= Length(S) +1;
  337.     DrawText(Canvas.Handle, PChar(Copy(S, 1, P -1)), -1, R, Flags);
  338.     OffsetRect(R, 0, DY);
  339.     if (P < Length(S))
  340.     and (S[P] = #13)
  341.     then Delete(S, 1, P)
  342.     else Delete(S, 1, P +1);
  343.   until S = '';
  344. end;
  345. procedure DrawSubmenuTriangle(
  346.   Canvas: TCanvas;
  347.   Draw: Boolean;
  348.   Alignment: T_AM2000_Alignment;
  349.   Rect: TRect);
  350. var
  351.   DX: Integer;
  352. begin
  353.   if (not Draw)
  354.   or (Rect.Left = Rect.Right)
  355.   then Exit;
  356.   Canvas.Pen.Color:= Canvas.Font.Color;
  357.   Canvas.Brush.Color:= Canvas.Font.Color;
  358.   Canvas.Brush.Style:= bsSolid;
  359.   DX:= (Rect.Top + Rect.Bottom - 5) div 2;
  360.   if Alignment <> taRightToLeft then
  361.     Canvas.PolyGon([
  362.       Point(Rect.Right -8, DX),
  363.       Point(Rect.Right -8, DX +6),
  364.       Point(Rect.Right -5, DX +3)])
  365.   else
  366.     Canvas.PolyGon([
  367.       Point(Rect.Left  +8, DX),
  368.       Point(Rect.Left  +8, DX +6),
  369.       Point(Rect.Left  +5, DX +3)])
  370. end;
  371. procedure DrawSeparator(
  372.   Canvas: TCanvas;
  373.   State: T_AM2000_ItemState;
  374.   Options: T_AM2000_BaseOptions;
  375.   Rect: TRect);
  376. var
  377.   Y, DX: Integer;
  378. begin
  379.   Exclude(State, isSelected);
  380.   // hide separator
  381.   if (isHiddenPrev in State) and (isHiddenSucc in State)
  382.   then Include(State, isHidden);
  383.   DrawBackground(Canvas, State, Options, Rect);
  384.   Y:= (Rect.Top + Rect.Bottom) div 2;
  385.   if mfNoShortDividers in Options.Flags
  386.   then DX:= 2
  387.   else DX:= 14;
  388.   if Options.Colors.Line <> clNone then begin
  389.     Canvas.Pen.Color:= Options.Colors.Line;
  390.     Canvas.PolyLine([Point(Rect.Left + DX, Y), Point(Rect.Right - DX, Y)]);
  391.   end;
  392.   if Options.Colors.LineShadow <> clNone then begin
  393.     Canvas.Pen.Color:= Options.Colors.LineShadow;
  394.     Canvas.PolyLine([Point(Rect.Left + DX, Y +1), Point(Rect.Right - DX, Y +1)]);
  395.   end;
  396. end;
  397. procedure DrawPatternBackground(
  398.   Canvas: TCanvas;
  399.   Rect: TRect);
  400. var
  401.   DC: HDC;
  402.   C2, bpx: Integer;
  403. begin
  404.   if not Assigned(Pattern) then begin
  405.     // test display's device capabilities
  406.     DC:= CreateDC('DISPLAY', nil, nil, nil);
  407.     bpx:= GetDeviceCaps(DC, BitsPixel);
  408.     DeleteDC(DC);
  409.     if bpx > 8
  410.     then C2:= clBtnFace
  411.     else C2:= clBtnHighlight;
  412.     // show pattern background if bits per pixel > 8 
  413.     Pattern:= CreatePattern(clBtnHighlight, C2);
  414.   end;
  415.   
  416.   Canvas.Brush.Bitmap:= Pattern;
  417.   Canvas.FillRect(Rect);
  418. end;
  419. procedure DrawSolidBackground(
  420.   Canvas: TCanvas;
  421.   Rect: TRect;
  422.   Color: TColor);
  423. begin
  424.   // set brush style
  425.   if Canvas.Brush.Style <> bsSolid
  426.   then Canvas.Brush.Style:= bsSolid;
  427.   // erase bitmap
  428.   if Canvas.Brush.Bitmap <> nil
  429.   then Canvas.Brush.Bitmap:= nil;
  430.   // set canvas color
  431.   if Canvas.Brush.Color <> Color
  432.   then Canvas.Brush.Color:= Color;
  433.   // fill
  434.   Canvas.FillRect(Rect);
  435. end;
  436. procedure DrawBackground(
  437.   Canvas: TCanvas;
  438.   State: T_AM2000_ItemState;
  439.   Options: T_AM2000_BaseOptions;
  440.   Rect: TRect);
  441. begin
  442.   // no background on graphic backround
  443.   if (isGraphBack in State)
  444.   and not (isSelected in State)
  445.   then Exit;
  446.   if (isSelected in State)
  447.   and ((not (isDisabled in State))
  448.   or (not (mfNoHighDisabled in Options.Flags)))
  449.   then begin
  450.     // for hidden menu items
  451.     if isHidden in State then InflateRect(Rect, 1, -1);
  452.     DrawSolidBackground(Canvas, Rect, Options.Colors.Highlight);
  453.   end
  454.   else
  455.     if isHidden in State then begin
  456.       // draw pattern background
  457.       if isNoLeftSunken in State
  458.       then Dec(Rect.Left)
  459.       else Dec(Rect.Left, 2);
  460.       if isNoRightSunken in State
  461.       then Inc(Rect.Right)
  462.       else Inc(Rect.Right, 2);
  463.       DrawPatternBackground(Canvas, Rect);
  464.       InflateRect(Rect, 0, -1);
  465.       // draw borders
  466.       if not (isHiddenPrev in State) then begin
  467.         Canvas.Pen.Color:= Options.Colors.Line;
  468.         Canvas.Polygon([Point(Rect.Left, Rect.Top -1), Point(Rect.Right -1, Rect.Top -1)]);
  469.       end;
  470.       if not (isHiddenSucc in State) then begin
  471.         Canvas.Pen.Color:= Options.Colors.LineShadow;
  472.         Canvas.Polygon([Point(Rect.Left, Rect.Bottom), Point(Rect.Right -1, Rect.Bottom)]);
  473.       end;
  474.     end
  475.     else
  476.       DrawSolidBackground(Canvas, Rect, Options.Colors.Menu);
  477. end;
  478. procedure DrawBitmap(
  479.   Canvas: TCanvas;
  480.   Bitmap: HBitmap;
  481.   BitmapIndex: Integer;
  482.   NumGlyphs: Integer;
  483.   Bitmap2: HBitmap;
  484.   State: T_AM2000_ItemState;
  485.   Options: T_AM2000_BaseOptions;
  486.   Rect: TRect;
  487.   Images: TImageList);
  488. var
  489.   bmprect, markrect: TRect;
  490.   nobmp: Boolean;
  491.   Glyph: Integer;
  492.   procedure DrawBmp(Canvas: TCanvas; Bitmap: HBitmap;
  493.     BitmapIndex: Integer);
  494.     // draws bitmap
  495.   begin
  496.     // is it a bitmap?
  497.     if BitmapIndex = -1
  498.     // yes
  499.     then TransBlt(Canvas, bmprect.Left +1, bmprect.Top +1, Glyph, NumGlyphs, Bitmap)
  500.     // no -- it's ImageIndex in the Images
  501.     else ImageList_Draw(Images.Handle, BitmapIndex, Canvas.Handle, bmprect.Left +1, bmprect.Top +1,
  502.       ild_Transparent);
  503.   end;
  504.   procedure DisdBmp(Canvas: TCanvas; Color1, Color2: TColor; Bitmap: HBitmap;
  505.     BitmapIndex: Integer);
  506.     // draws bitmap
  507.   begin
  508.     // is it a bitmap?
  509.     if BitmapIndex = -1
  510.     // yes
  511.     then
  512.       NewDisabledBlt(Canvas, bmprect.Left +1, bmprect.Top +1, Color1, Color2, Bitmap)
  513.     // no -- look for ImageIndex bimap in the Images image list
  514.     else
  515.       ImgDisabledBlt(Canvas, bmprect.Left +1, bmprect.Top +1, Images, BitmapIndex,
  516.         Color1, Color2);
  517.   end;
  518. begin
  519.   if (Rect.Left = Rect.Right)
  520.   then Exit;
  521.   nobmp:= (Bitmap = 0) and (BitmapIndex = -1);
  522.   // draw bitmap background
  523.   if Canvas.Brush.Style <> bsSolid
  524.   then Canvas.Brush.Style:= bsSolid;
  525.   if (Options <> nil)
  526.   and (Canvas.Brush.Color <> Options.Colors.Menu)
  527.   then Canvas.Brush.Color:= Options.Colors.Menu;
  528.   Dec(Rect.Right);
  529.   // calculate bmprect and markrect
  530.   bmprect:= Rect;
  531.   markrect:= Rect;
  532.   if (Options <> nil) and (mfShowCheckMark in Options.Flags)
  533.   then begin
  534.     markrect.Right:= (markrect.Right - markrect.Left) div 2 + markrect.Left;
  535.     bmprect.Left:= markrect.Right +1;
  536.   end;
  537.   // draw solid background
  538.   if (not (isHidden in State)) or (isSelected in State) then begin
  539.     if (Options <> nil) and (not (nobmp or (mfNoBitmapRect in Options.Flags)))
  540.     then begin
  541.       Inc(bmprect.Right);
  542.       Canvas.FillRect(bmprect);
  543.       Dec(bmprect.Right);
  544.     end;
  545.     if isChecked in State then begin
  546.       Inc(markrect.Right);
  547.       Canvas.FillRect(markrect);
  548.       Dec(markrect.Right);
  549.     end;
  550.   end;
  551.   // draw background and rect
  552.   if isSelected in State then begin
  553.     if not (nobmp or (mfNoBitmapRect in Options.Flags)) 
  554.     then DrawEdge(Canvas.Handle, bmprect, bdr_RaisedInner, bf_Rect);
  555.     if isChecked in State
  556.     then DrawEdge(Canvas.Handle, markrect, bdr_SunkenOuter, bf_Rect);
  557.   end
  558.   else
  559.     if isChecked in State then begin
  560.       DrawPatternBackground(Canvas, markrect);
  561.       DrawEdge(Canvas.Handle, markrect, bdr_SunkenOuter, bf_Rect);
  562.     end;
  563.   Inc(Rect.Right);
  564.   if isChecked in State then Inc(Rect.Left);
  565.   // select bitmap icon
  566.   if (NumGlyphs > 1) and (isDisabled in State)
  567.   then
  568.     Glyph:= 1
  569.   else
  570.   if (NumGlyphs > 2) and ((isChecked in State)
  571.   or ((isActivated in State) and (isSelected in State)))
  572.   then
  573.     Glyph:= 2
  574.   else
  575.   if (NumGlyphs > 3) and (isSelected in State)
  576.   then
  577.     Glyph:= 3
  578.   else
  579.     Glyph:= 0;
  580.   // draw bitmaps
  581.   if ((not nobmp) or (Options = nil))
  582.   and ((not (isDisabled in State))
  583.   or (NumGlyphs > 1))
  584.   then
  585.     DrawBmp(Canvas, Bitmap, BitmapIndex)
  586.   else
  587.     DisdBmp(Canvas, Options.Colors.DisabledText, Options.Colors.DisabledShadow, Bitmap,
  588.       BitmapIndex);
  589.   // draw mark
  590.   if (isChecked in State)
  591.   and (nobmp
  592.   or ((Options <> nil) and (mfShowCheckMark in Options.Flags)))
  593.   then
  594.     if (isDisabled in State)
  595.     then
  596.       NewDisabledBlt(Canvas, markrect.Left +1, markrect.Top +1, Options.Colors.DisabledText,
  597.         Options.Colors.DisabledShadow, Bitmap2)
  598.     else
  599.       TransBlt(Canvas, markrect.Left +1, markrect.Top +1, 0, 0, Bitmap2);
  600. end;
  601. function CreatePattern(Color1, Color2: TColor): TBitmap;
  602. var
  603.   X, Y: Integer;
  604. begin
  605.   Result:= TBitmap.Create;
  606.   Result.Width:= 8;
  607.   Result.Height:= 8;
  608.   for Y:= 0 to 7 do
  609.     for X:= 0 to 7 do
  610.       if (Y mod 2) = (X mod 2)
  611.       then Result.Canvas.Pixels[X, Y]:= Color1
  612.       else Result.Canvas.Pixels[X, Y]:= Color2;
  613. end;
  614. procedure DrawTextItem(
  615.   Canvas: TCanvas;
  616.   Options: T_AM2000_BaseOptions;
  617.   Caption: String;
  618.   Shortcut: String;
  619.   Bitmap: HBitmap;
  620.   BitmapIndex: Integer;
  621.   NumGlyphs: Integer;
  622.   State: T_AM2000_ItemState;
  623.   MouseState: T_AM2000_MouseState;
  624.   mir: T_AM2000_MenuItemRect;
  625.   Images: TImageList);
  626. var
  627.   OldFontStyle: TFontStyles;
  628.   ScAlign: T_AM2000_Alignment;
  629.   P: Integer;
  630.   Bitmap2: HBitmap;
  631. begin
  632.   DrawBackground(Canvas, State, Options, mir.LineRect);
  633.   if isHidden in State then begin
  634.     Inc(mir.Top);
  635.     Dec(mir.Height, 2);
  636.   end;
  637.   // draw bitmap
  638.   if isRadio in State
  639.   then Bitmap2:= bmpRadioItem
  640.   else Bitmap2:= bmpCheckMark;
  641.   DrawBitmap(Canvas, Bitmap, BitmapIndex, NumGlyphs, Bitmap2, State, Options, mir.BitmapRect, Images);
  642.   // draw caption
  643.   OldFontStyle:= Canvas.Font.Style;
  644.   if (isDefault in State) and (not (fsBold in OldFontStyle)) then
  645.     Canvas.Font.Style:= Canvas.Font.Style + [fsBold];
  646.   // shortcut's alignment
  647.   if (Options.Alignment = taRightToLeft)
  648.   or (mfStandardAlign in Options.Flags)
  649.   then ScAlign:= taLeftJustify
  650.   else ScAlign:= taRightJustify;
  651.   Canvas.Brush.Style:= bsClear;
  652.   // little interesting thing!
  653.   P:= Pos(#9, Caption);
  654.   if (P <> 0)
  655.   and (ShortCut = '')
  656.   then begin
  657.     Shortcut:= Copy(Caption, P +1, MaxInt);
  658.     Caption:= Copy(Caption, 1, P -1);
  659.   end;
  660.   // draw the caption
  661.   if not (isDisabled in State)
  662.   then               // enabled
  663.     if isSelected in State
  664.     then Canvas.Font.Color:= Options.Colors.HighlightText
  665.     else Canvas.Font.Color:= Options.Colors.MenuText
  666.   else begin         // disabled
  667.     // draw the shadow if not selected
  668.     if (not (isSelected in State))
  669.     or (mfNoHighDisabled in Options.Flags)
  670.     then begin
  671.       Canvas.Font.Color:= Options.Colors.DisabledShadow;
  672.       mir.IncreaseOffset;
  673.       DrawCaption(Canvas, Caption, Options.Alignment, mir.ItemRect);
  674.       DrawCaption(Canvas, Shortcut, ScAlign, mir.ShortcutRect);
  675.       DrawSubmenuTriangle(Canvas, isSubmenu in State, Options.Alignment, mir.TriangleRect);
  676.       mir.DecreaseOffset;
  677.       Canvas.Brush.Style:= bsClear;
  678.     end;
  679.     Canvas.Font.Color:= Options.Colors.DisabledText;
  680.   end;
  681.   // caption, shortcut & triangle
  682.   DrawCaption(Canvas, Caption, Options.Alignment, mir.ItemRect);
  683.   DrawCaption(Canvas, Shortcut, ScAlign, mir.ShortcutRect);
  684.   DrawSubmenuTriangle(Canvas, isSubmenu in State, Options.Alignment, mir.TriangleRect);
  685.   // disabled menu items
  686.   if Canvas.Font.Style <> OldFontStyle then
  687.     Canvas.Font.Style:= OldFontStyle;
  688. end;
  689. { Main drawing functions }
  690. procedure DrawMenuItemWin32;
  691. var
  692.   Caption: String;
  693.   Bitmap: HBitmap;
  694. begin
  695.   with DrawRect^ do begin
  696.     mii.fMask:= $3F;
  697.     mii.dwTypeData:= PChar(@Z);
  698.     mii.cch:= SizeOf(Z) -1;
  699.     if not GetMenuItemInfo(Handle, Index, True, mii) then Exit;
  700.     // separator
  701.     if mii.fType and mft_Separator <> 0 then begin
  702.       DrawSeparator(Canvas, State, Options, mir.LineRect);
  703.       Exit;
  704.     end;
  705.     // set caption
  706.     if mii.fState and mfs_Checked <> 0
  707.     then Bitmap:= mii.hbmpChecked
  708.     else Bitmap:= mii.hbmpUnchecked;
  709.     Caption:= StrPas(Z);
  710.     // load bitmap
  711.     case mii.wID of
  712.       sc_Restore:  Bitmap:= MenuItemCache['SYSTEMRESTORE' ].Bitmap;
  713.       sc_Move:     Bitmap:= MenuItemCache['SYSTEMMOVE'    ].Bitmap;
  714.       sc_Size:     Bitmap:= MenuItemCache['SYSTEMSIZE'    ].Bitmap;
  715.       sc_Minimize: Bitmap:= MenuItemCache['SYSTEMMINIMIZE'].Bitmap;
  716.       sc_Maximize: Bitmap:= MenuItemCache['SYSTEMMAXIMIZE'].Bitmap;
  717.       sc_Close:    Bitmap:= MenuItemCache['SYSTEMCLOSE'   ].Bitmap;
  718.     end;
  719.     // draw item
  720.     SetState(State, isChecked, mii.fState and mfs_Checked <> 0);
  721.     SetState(State, isDisabled, mii.fState and (mfs_Disabled + mfs_Grayed) <> 0);
  722.     SetState(State, isDefault, mii.fState and mfs_Default <> 0);
  723.     SetState(State, isRadio, mii.fType and mft_RadioCheck <> 0);
  724.     SetState(State, isSubmenu, mii.hSubmenu <> 0);
  725.     DrawTextItem(Canvas, Options, Caption, '', Bitmap, -1, 0, State, MouseState, mir, nil);
  726.   end;
  727. end;
  728. procedure DrawMenuItem;
  729. var
  730.   Caption, Shortcut: String;
  731.   Bitmap: HBitmap;
  732.   Item2000: TMenuItem2000;
  733.   BitmapIndex: Integer;
  734.   NumGlyphs: Integer;
  735. begin
  736.   Bitmap:= 0;
  737.   BitmapIndex:= -1;
  738.   with DrawRect^ do begin
  739.     Item2000:= TMenuItem2000(Item);
  740.     // separator
  741.     if Item.Caption = '-' then begin
  742.       DrawSeparator(Canvas, State, Options, mir.LineRect);
  743.       Exit;
  744.     end;
  745.     // get caption
  746.     Caption:= Item.Caption;
  747.     // get shortcut
  748.     if Item is TMenuItem2000
  749.     then ShortCut:= GetMainShortCut(Item2000.ShortCut)
  750.     else Shortcut:= ShortcutToText(Item.ShortCut);
  751.     // get user bitmap
  752.     if Item is TMenuItem2000
  753.     then NumGlyphs:= Item2000.NumGlyphs
  754.     else NumGlyphs:= 0;
  755.     // advanced bitmap
  756.     if (Item is TMenuItem2000)
  757.     and (Item2000.IsBitmapAssigned)
  758.     then Bitmap:= Item2000.Bitmap.Handle
  759.     // ordinal bitmap's ImageIndex
  760.     else
  761.     if
  762.     (Images <> nil) and
  763. {$IFDEF Delphi4OrHigher}
  764.     (Item.ImageIndex <> -1)
  765. {$ELSE}
  766.     (Item is TMenuItem2000) and (Item2000.ImageIndex <> -1)
  767. {$ENDIF}
  768.     then BitmapIndex:= Item2000.ImageIndex
  769.     // no advanced bitmap
  770.     else
  771. {$IFDEF Delphi4OrHigher}
  772.       Bitmap:= Item.Bitmap.Handle;
  773. {$ELSE}
  774.       Bitmap:= 0;
  775. {$ENDIF}
  776.     // initiate action
  777. {$IFDEF Delphi4OrHigher}
  778.     if not (csDesigning in Item.ComponentState)
  779.     then Item.InitiateAction;
  780. {$ENDIF}
  781.     // draw item
  782.     SetState(State, isChecked, Item.Checked);
  783.     SetState(State, isDisabled, not Item.Enabled);
  784.     SetState(State, isDefault, Item.Default);
  785.     SetState(State, isRadio, Item.RadioItem);
  786.     SetState(State, isSubmenu, (Item.Count > 0) or ((Item is TMenuItem2000) and (Item2000.AttachMenu <> nil)));
  787.     DrawTextItem(Canvas, Options, Caption, Shortcut, Bitmap, BitmapIndex, NumGlyphs, State, MouseState,
  788.       mir, Images);
  789.   end;
  790. end;
  791. { TMenuItem2000 }
  792. constructor TMenuItem2000.Create(AOwner: TComponent);
  793. begin
  794.   inherited;
  795. {$IFNDEF Delphi4OrHigher}
  796.   FImageIndex:= -1;
  797. {$ENDIF}
  798.   FControlOptions:= T_AM2000_ControlOptions.Create(Self);
  799.   FDefaultBitmapIndex:= -1;
  800.   FNumGlyphs:= 1;
  801. end;
  802. destructor TMenuItem2000.Destroy;
  803. var
  804.   OldParent: TMenuItem2000;
  805. begin
  806.   if (not (csLoading in ComponentState))
  807.   and (not (csDestroying in ComponentState))
  808.   then OldParent:= Parent
  809.   else OldParent:= nil;
  810.   // if this menu item uses AutoBitmap, it should
  811.   // release it before destroying the bitmap
  812.   if (MenuItemCache <> nil)
  813. {$IFDEF Delphi4OrHigher}
  814.   and (not Bitmap.Empty)
  815.   and (((Caption <> '')
  816.   and (MenuItemCache[Caption].Bitmap = Bitmap.Handle))
  817.   or (DefaultIndex <> -1))
  818.   then Bitmap.ReleaseHandle;
  819. {$ELSE}
  820.   and (FBitmap <> nil)
  821.   and (not FBitmap.Empty)
  822.   and (((Caption <> '')
  823.   and (MenuItemCache[Caption].Bitmap = FBitmap.Handle))
  824.   or (DefaultIndex <> -1))
  825.   then FBitmap.ReleaseHandle;
  826.   FBitmap.Free;
  827. {$ENDIF}
  828.   FOptions.Free;
  829.   FControlOptions.Free;
  830.   inherited;
  831.   // update parent
  832.   if (OldParent <> nil)
  833.   and (OldParent is TMenuItem2000)
  834.   then OldParent.Update(0, upForceRebuild);
  835. end;
  836. procedure TMenuItem2000.Insert(Index: Integer; Item: TMenuItem2000);
  837. begin
  838.   inherited Insert(Index, Item);
  839.   Update(0, upForceRebuild);
  840. end;
  841. function TMenuItem2000.IndexOf(Item: TMenuItem2000): Integer;
  842. begin
  843.   Result:= inherited IndexOf(Item);
  844. end;
  845. procedure TMenuItem2000.Add(Item: TMenuItem2000);
  846. begin
  847.   inherited Add(Item);
  848.   Update(0, upForceRebuild);
  849. end;
  850. procedure TMenuItem2000.Remove(Item: TMenuItem2000);
  851. begin
  852.   inherited Remove(Item);
  853.   Update(0, upForceRebuild);
  854. end;
  855. procedure TMenuItem2000.Delete(Index: Integer);
  856. begin
  857.   inherited Delete(Index);
  858.   Update(0, upForceRebuild);
  859. end;
  860. procedure TMenuItem2000.Assign(Source: TPersistent);
  861. begin
  862.   inherited;
  863. end;
  864. function TMenuItem2000.IsTopLevelItem: Boolean;
  865.   // is top level menu item from ActiveMenuBar?
  866. var
  867.   mi: TMenuItem;
  868. begin
  869.   mi:= Parent;
  870.   if (mi = nil) then mi:= Self;
  871.   Result:= (mi <> nil)
  872.     and (ActiveMenuBar <> nil)
  873.     and (ActiveMenuBar.Menu <> nil)
  874.     and (((ActiveMenuBar.Menu is TCustomMainMenu2000)
  875.     and (TCustomMainMenu2000(ActiveMenuBar.Menu).Items2000 = mi))
  876.     or ((ActiveMenuBar.Menu is TCustomPopupMenu2000)
  877.     and (TCustomPopupMenu2000(ActiveMenuBar.Menu).Items2000 = mi))
  878.     or (ActiveMenuBar.Menu.Items = mi));
  879. end;
  880. function TMenuItem2000.IsBitmapAssigned : Boolean;
  881.   // checks if menu item has any bitmap anywhere
  882. begin
  883.   Result:=
  884. {$IFDEF Delphi4OrHigher}
  885.     (not Bitmap.Empty)
  886. {$ELSE}
  887.     (Assigned(FBitmap) and (not FBitmap.Empty))
  888. {$ENDIF}
  889.     or (DefaultIndex <> -1)
  890.     or ((Caption <> '')
  891.     and (MenuItemCache[Caption].Bitmap <> 0));
  892. end;
  893. function TMenuItem2000.IsOptionsAssigned: Boolean;
  894. begin
  895.   Result:= Assigned(FOptions);
  896. end;
  897. function TMenuItem2000.GetParent: TMenuItem2000;
  898. begin
  899.   Result:= TMenuItem2000(inherited Parent);
  900. end;
  901. function TMenuItem2000.IsHintStored: Boolean;
  902. begin
  903.   Result:= Hint <> MenuItemCache[Caption].Hint;
  904. end;
  905. function TMenuItem2000.IsShortCutStored: Boolean;
  906. begin
  907.   Result:= FShortCut <> MenuItemCache[Caption].ShortCuts;
  908. end;
  909. function TMenuItem2000.IsBitmapStored: Boolean;
  910. var
  911.   B: Boolean;
  912. begin
  913.   B:=
  914. {$IFNDEF Delphi4OrHigher}
  915.     (FBitmap = nil) or
  916. {$ENDIF}
  917.     (Bitmap.Handle = 0)
  918.     or (DefaultIndex <> -1)
  919.     or (Bitmap.Handle = MenuItemCache[Caption].Bitmap);
  920.   // necessary for optimization purposes
  921.   Result:= not B;
  922. end;
  923. function TMenuItem2000.GetBitmap: TBitmap;
  924. begin
  925.   if (csDesigning in ComponentState)
  926.   then begin
  927. {$IFDEF Delphi4OrHigher}
  928.     Result:= inherited Bitmap;
  929. {$ELSE}
  930.     if FBitmap = nil then FBitmap:= TBitmap.Create;
  931.     Result:= FBitmap;
  932. {$ENDIF}
  933.   end
  934.   else
  935.     Result:= GetBitmapEx;
  936. end;
  937. function TMenuItem2000.GetBitmapEx: TBitmap;
  938. begin
  939. {$IFDEF Delphi4OrHigher}
  940.   Result:= inherited Bitmap;
  941. {$ELSE}
  942.   if FBitmap = nil then FBitmap:= TBitmap.Create;
  943.   Result:= FBitmap;
  944. {$ENDIF}
  945.   if MenuItemCache = nil
  946.   then Exit;
  947.   if DefaultIndex <> -1
  948.   then
  949.     Result.Handle:= MenuItemCache.GetDefaultBitmap(DefaultIndex)
  950.   else
  951.   if (Caption <> '')
  952.   and (Result.Handle = 0)
  953.   then
  954.     Result.Handle:= MenuItemCache[Caption].Bitmap;
  955. end;
  956. function TMenuItem2000.GetShortCut: T_AM2000_ShortCut;
  957. begin
  958.   Result:= '';
  959.   // inherited shortcut
  960.   if inherited ShortCut <> 0
  961.   then
  962.     Result:= ShortCutToText(inherited ShortCut)
  963.     
  964.   else begin
  965.     Result:= FShortCut;
  966.     if not (csWriting in ComponentState) then begin
  967.       if (Result = '') then Result:= MenuItemCache[Caption].ShortCuts;
  968.       if (Result = #1) then Result:= '';
  969.     end;
  970.   end;
  971. end;
  972. function TMenuItem2000.GetHint: String;
  973. begin
  974.   Result:= inherited Hint;
  975.   if not (csWriting in ComponentState) then begin
  976.     if (Result = '') then Result:= MenuItemCache[Caption].Hint;
  977.     if (Result = #1) then Result:= '';
  978.   end;
  979. end;
  980. procedure TMenuItem2000.SetBitmap(Value: TBitmap);
  981. begin
  982. {$IFDEF Delphi4OrHigher}
  983.   inherited Bitmap:= Value;
  984. {$ELSE}
  985.   if FBitmap = nil then FBitmap := TBitmap.Create;
  986.   FBitmap.Assign(Value);
  987. {$ENDIF}
  988.   // update
  989.   Update(wm_UpdateBitmap, upForceRebuild);
  990. end;
  991. procedure TMenuItem2000.TurnSiblingsOff;
  992. var
  993.   I: Integer;
  994.   SaveIRF: Boolean;
  995. begin
  996.   SaveIRF:= IgnoreRepaintFloating;
  997.   IgnoreRepaintFloating:= True;
  998.   for I:= 0 to Parent.Count -1 do
  999.     if (Parent.Items[I] <> Self)
  1000.     and (Parent.Items[I].GroupIndex = GroupIndex)
  1001.     then
  1002.       with Parent.Items[I] do begin
  1003.         case Control of
  1004.           ctlNone:        Checked:= False;
  1005.           ctlButton:      AsButton.Down:= False;
  1006.           ctlButtonArray: AsButtonArray.ItemIndex:= -1;
  1007.         end;
  1008.         
  1009.         Update(wm_UpdateBitmap, upNothing);
  1010.       end;
  1011.   IgnoreRepaintFloating:= SaveIRF;
  1012. end;
  1013. procedure TMenuItem2000.SetHint(Value: String);
  1014. begin
  1015.   if (Value = '')
  1016.   and (MenuItemCache[Caption].Hint <> '')
  1017.   then inherited Hint:= #1
  1018.   else inherited Hint:= Value;
  1019. end;
  1020. procedure TMenuItem2000.SetShortCut(Value: T_AM2000_ShortCut);
  1021. var
  1022.   I: Integer;
  1023.   S, S1: String;
  1024.   SC: TShortCut;
  1025. begin
  1026.   inherited ShortCut:= 0;
  1027.   // if shortcut is empty
  1028.   if (Value = '') or (Value = #1)
  1029.   then FShortCut:= #1
  1030.   else
  1031.   // supress checking when loading
  1032.   if csLoading in ComponentState
  1033.   then begin
  1034.     FShortCut:= Value;
  1035.   end
  1036.   // shortcut checking
  1037.   else begin
  1038.     S:= '';
  1039.     while Value <> '' do begin
  1040.       I:= Pos(';', Value);
  1041.       if I < 1 then I:= Length(Value) +1;
  1042.       S1:= Trim(Copy(Value, 1, I -1));
  1043.       System.Delete(Value, 1, I);
  1044.       if S1 = '' then System.Break;
  1045.       SC:= TextToShortCut(S1);
  1046.       if SC = 0
  1047.       then raise Exception.Create(SInvalidShortCut + S1 +'''');
  1048.       if S <> '' then AppendStr(S, ';');
  1049.       AppendStr(S, ShortCutToText(SC));
  1050.     end;
  1051.     FShortCut:= S;
  1052.   end;
  1053. end;
  1054. function TMenuItem2000.AsButtonArray: T_AM2000_ButtonArrayOptions;
  1055. begin
  1056.   if FControl = ctlButtonArray
  1057.   then Result:= FControlOptions as T_AM2000_ButtonArrayOptions
  1058.   else raise EMenuError.Create(Name + SThisIsNotAButtonArray);
  1059. end;
  1060. function TMenuItem2000.AsButton: T_AM2000_ButtonOptions;
  1061. begin
  1062.   if FControl = ctlButton
  1063.   then Result:= FControlOptions as T_AM2000_ButtonOptions
  1064.   else raise EMenuError.Create(Name + SThisIsNotAButton);
  1065. end;
  1066. function TMenuItem2000.AsBitmap: T_AM2000_BitmapOptions;
  1067. begin
  1068.   if FControl = ctlBitmap
  1069.   then Result:= FControlOptions as T_AM2000_BitmapOptions
  1070.   else raise EMenuError.Create(Name + SThisIsNotABitmap);
  1071. end;
  1072. function TMenuItem2000.AsEdit: T_AM2000_EditboxOptions;
  1073. begin
  1074.   if FControl = ctlEditbox
  1075.   then Result:= FControlOptions as T_AM2000_EditboxOptions
  1076.   else raise EMenuError.Create(Name + SThisIsNotAEdit);
  1077. end;
  1078. function TMenuItem2000.GetItem(Index: Integer): TMenuItem2000;
  1079. var
  1080.   R: TMenuItem;
  1081. begin
  1082.   R:= inherited GetItem(Index);
  1083.   if Assigned(R)
  1084.   then Result:= TMenuItem2000(R)
  1085.   else raise EMenuError.Create(SMenuNotFound);
  1086. end;
  1087. procedure TMenuItem2000.SetCaption(const Value: String);
  1088. begin
  1089.   inherited Caption:= Value;
  1090.   Update(wm_UpdateCaption, upForceRebuild);
  1091. end;
  1092. procedure TMenuItem2000.SetEnabled(Value: Boolean);
  1093. begin
  1094.   inherited Enabled:= Value;
  1095.   Update(0, upRepaint);
  1096. end;
  1097. procedure TMenuItem2000.SetVisible(Value: Boolean);
  1098. begin
  1099.   inherited Visible:= Value;
  1100.   Update(0, upForceRebuild);
  1101. end;
  1102. procedure TMenuItem2000.SetControl(Value: T_AM2000_ControlType);
  1103. begin
  1104.   if FControl <> Value then begin
  1105.     FControl:= Value;
  1106.     FControlOptions.Free;
  1107.     case FControl of
  1108.       ctlButton      :
  1109.         FControlOptions:= T_AM2000_ButtonOptions.Create(Self);
  1110.       ctlButtonArray :
  1111.         FControlOptions:= T_AM2000_ButtonArrayOptions.Create(Self);
  1112.       ctlBitmap     :
  1113.         FControlOptions:= T_AM2000_BitmapOptions.Create(Self);
  1114.       ctlEditbox     :
  1115.         FControlOptions:= T_AM2000_EditboxOptions.Create(Self);
  1116.       else
  1117.         FControlOptions:= T_AM2000_ControlOptions.Create(Self);
  1118.     end;
  1119.     Update(wm_SelectComponent, 0);
  1120.   end;
  1121. end;
  1122. function TMenuItem2000.IsOptionsStored: Boolean;
  1123. begin
  1124.   Result:= Count > 0;
  1125. end;
  1126. function TMenuItem2000.GetOptions: T_AM2000_MenuOptions;
  1127. begin
  1128.   if Assigned(FOptions)
  1129.   and (not (csLoading in ComponentState))
  1130.   and (((FOptions.ClassType = T_AM2000_MenuOptions) and ((Count > 0) or (AttachMenu <> nil)))
  1131.   or ((FOptions.ClassType = T_AM2000_BaseOptions) and (Count = 0)))
  1132.   then begin
  1133.     FOptions.Free;
  1134.     FOptions:= nil;
  1135.   end;
  1136.   if not Assigned(FOptions)
  1137.   then
  1138.     if (Count > 0)
  1139.     or (AttachMenu <> nil)
  1140.     or (csLoading in ComponentState)
  1141.     or (not (csDesigning in ComponentState))
  1142.     then FOptions:= T_AM2000_BaseOptions.Create
  1143.     else FOptions:= T_AM2000_MenuOptions.Create;
  1144.   Result:= FOptions;  
  1145. end;
  1146. procedure TMenuItem2000.SetOptions(Value: T_AM2000_MenuOptions);
  1147. begin
  1148.   if not Assigned(FOptions)
  1149.   then
  1150.     if Count > 0
  1151.     then FOptions:= T_AM2000_BaseOptions.Create
  1152.     else FOptions:= T_AM2000_MenuOptions.Create;
  1153.   FOptions.Assign(Value);
  1154. end;
  1155. function TMenuItem2000.GetCaption: String;
  1156. begin
  1157.   Result:= inherited Caption;
  1158. end;
  1159. function TMenuItem2000.GetEnabled: Boolean;
  1160. begin
  1161.   Result:= inherited Enabled;
  1162. end;
  1163. function TMenuItem2000.GetVisible: Boolean;
  1164. begin
  1165.   Result:= inherited Visible;
  1166. end;
  1167. function TMenuItem2000.GetWidth(Canvas: TCanvas): Integer;
  1168. begin
  1169.   Result:= FControlOptions.GetWidth(Canvas);
  1170. end;
  1171. function TMenuItem2000.GetHeight(ItemHeight: Integer): Integer;
  1172. begin
  1173.   Result:= FControlOptions.GetHeight(ItemHeight);
  1174. end;
  1175. procedure TMenuItem2000.Notification(AComponent: TComponent;
  1176.   Operation: TOperation);
  1177. begin
  1178.   inherited;
  1179.   if Operation = opRemove then begin
  1180.     if (AComponent = AttachMenu) then FAttachMenu:= nil;
  1181.     if (AComponent = PopupMenu) then FPopupMenu:= nil;
  1182.   end;
  1183. end;
  1184. {$IFDEF Delphi4OrHigher}
  1185. procedure TMenuItem2000.InitiateAction;
  1186. var
  1187.   I : Integer;
  1188. begin
  1189.   inherited;
  1190.   for I := 0 to Count - 1 do
  1191.     with Items[I] do
  1192.       if Visible then InitiateAction;
  1193. end;
  1194. function TMenuItem2000.GetAction: TBasicAction;
  1195. begin
  1196.   Result:= inherited Action;
  1197. end;
  1198. procedure TMenuItem2000.SetAction(Value: TBasicAction);
  1199. begin
  1200.   inherited Action:= Value;
  1201.   if Value <> nil then SetCaption(Caption);
  1202.   Update(wm_UpdateCaption, upForceRebuild);
  1203. end;
  1204. {$ENDIF}
  1205. procedure TMenuItem2000.Update(UpdateDesigner, UpdateMenuBar: Integer);
  1206. var
  1207.   hwnd: THandle;
  1208. begin
  1209.   if Parent = nil then Exit; 
  1210.   // update bitmap
  1211.   if (UpdateDesigner <> 0)    
  1212.   and (not (csLoading in ComponentState))
  1213.   then begin
  1214.     hwnd:= GetMnuDsgnHandle;
  1215.     if hwnd <> 0 then PostMessage(hwnd, UpdateDesigner, 0, LongInt(Self));
  1216.   end;
  1217.   // update menu bar
  1218.   if (not (csLoading in ComponentState))
  1219.   and (not (csDestroying in ComponentState))
  1220.   and IsTopLevelItem
  1221.   and (ActiveMenuBar <> nil)
  1222.   and ActiveMenuBar.HandleAllocated
  1223.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, UpdateMenuBar, 0);
  1224. end;
  1225. function TMenuItem2000.GetChecked: Boolean;
  1226. begin
  1227.   Result:= inherited Checked;
  1228. end;
  1229. procedure TMenuItem2000.SetChecked(Value: Boolean);
  1230. begin
  1231.   inherited Checked:= Value;
  1232.   Update(wm_UpdateBItmap, upForceRebuild);
  1233. end;
  1234. procedure TMenuItem2000.SetDefaultIndex(Value: Integer);
  1235. begin
  1236.   FDefaultBitmapIndex:= Value;
  1237.   Update(wm_UpdateBitmap, upForceRebuild);
  1238. end;
  1239. { TEditableMenuItem2000 }
  1240. function TEditableMenuItem2000.GetHandle: HMenu;
  1241. begin
  1242.   Result:= TMenu(Owner).Items.Handle;
  1243. end;
  1244. function TEditableMenuItem2000.GetCount: Integer;
  1245. begin
  1246.   Result:= TMenu(Owner).Items.Count;
  1247. end;
  1248. function TEditableMenuItem2000.GetItem(Index: Integer): TMenuItem2000;
  1249. begin
  1250.   // it's safe because AnimatedMenus/98 doesn't use TMenuItem anymore
  1251.   // Only TMenuItem2000
  1252.   Result:= TMenuItem2000(TMenu(Owner).Items[Index]);
  1253. end;
  1254. procedure TEditableMenuItem2000.Insert(Index: Integer; Item: TMenuItem2000);
  1255. begin
  1256.   TMenu(Owner).Items.Insert(Index, Item);
  1257. end;
  1258. procedure TEditableMenuItem2000.Delete(Index: Integer);
  1259. begin
  1260.   TMenu(Owner).Items.Delete(Index);
  1261. end;
  1262. function TEditableMenuItem2000.IndexOf(Item: TMenuItem2000): Integer;
  1263. begin
  1264.   Result:= TMenu(Owner).Items.IndexOf(Item);
  1265. end;
  1266. procedure TEditableMenuItem2000.Add(Item: TMenuItem2000);
  1267. begin
  1268.   TMenu(Owner).Items.Add(Item);
  1269. end;
  1270. procedure TEditableMenuItem2000.Remove(Item: TMenuItem2000);
  1271. begin
  1272.   TMenu(Owner).Items.Remove(Item);
  1273. end;
  1274. initialization
  1275.   RegisterClasses([TMenuItem2000, TEditableMenuItem2000]);
  1276. finalization
  1277.   Pattern.Free;
  1278. end.