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

Delphi控件源码

开发平台:

C++ Builder

  1. {*******************************************************}
  2. {                                                       }
  3. {       AnimatedMenus/2000                              }
  4. {       T_AM2000_MenuDesigner Component Unit            }
  5. {                                                       }
  6. {       Copyright (c) 1997-99 AnimatedMenus.com         }
  7. {       All rights reserved.                            }
  8. {                                                       }
  9. {*******************************************************}
  10. unit am2000designer;
  11. {$I am2000.inc}
  12. interface
  13. uses
  14.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  15.   StdCtrls, CommCtrl, ComCtrls, ExtCtrls,
  16.   Buttons, Menus, Registry, LibHelp, DsgnIntf,
  17.   {$IFDEF Delphi3OrHigher} ExtDlgs, {$ENDIF}
  18.   {$IFDEF Delphi4OrHigher} ImgList, {$ENDIF}
  19.   {$IFDEF Delphi5OrHigher} Contnrs, {$ENDIF}
  20.   am2000menuitem, am2000popupmenu, am2000mainmenu, am2000cache, am2000,
  21.   am2000utils;
  22. type
  23.   T_AM2000_TreeView4 = class;
  24. {$IFNDEF Delphi4OrHigher}
  25.   TCustomDrawTarget = (dtControl, dtItem, dtSubItem);
  26.   TCustomDrawStage = (cdPrePaint, cdPostPaint, cdPreErase, cdPostErase);
  27.   TCustomDrawState = set of (cdsSelected, cdsGrayed, cdsDisabled, cdsChecked,
  28.     cdsFocused, cdsDefault, cdsHot, cdsMarked, cdsIndeterminate);
  29.   TTVCustomDrawItemEvent = procedure(Sender: TCustomTreeView; Node: TTreeNode;
  30.     State: TCustomDrawState; var DefaultDraw: Boolean) of object;
  31. {$ENDIF}
  32.   // menu designer
  33.   T_AM2000_MenuDesigner = class(TPropertyEditor)
  34.   public
  35.     function GetValue: string; override;
  36.     function GetAttributes: TPropertyAttributes; override;
  37.     procedure Edit; override;
  38.   end;
  39.   // component editor
  40.   T_AM2000_ComponentEditor = class(TComponentEditor)
  41.   public
  42.     function GetVerbCount: Integer; override;
  43.     function GetVerb(Index: Integer): String; override;
  44.     procedure ExecuteVerb(Index: Integer); override;
  45.     procedure Edit; override;
  46.   end;
  47.   // dialog for menu designer
  48.   T_AM2000_MenuDesignerDlg = class(TForm)
  49.     Panel1: TPanel;
  50.     ButtonNewMenuItem: TSpeedButton;
  51.     ButtonNewSubMenu: TSpeedButton;
  52.     Bevel1: TBevel;
  53.     ButtonDelete: TSpeedButton;
  54.     Bevel2: TBevel;
  55.     ButtonLevelUp: TSpeedButton;
  56.     ButtonMoveUp: TSpeedButton;
  57.     ButtonMoveDown: TSpeedButton;
  58.     ButtonLevelDown: TSpeedButton;
  59.     PopupMenu20001: TPopupMenu2000;
  60.     DefaultBitmaps1: TMenuItem2000;
  61.     N2: TMenuItem2000;
  62.     None1: TMenuItem2000;
  63.     ButtonArray1: TMenuItem2000;
  64.     OpenDialog1: TOpenDialog;
  65.     SaveDialog1: TSaveDialog;
  66.     NewItem1: TMenuItem2000;
  67.     NewSubmenuItem1: TMenuItem2000;
  68.     MenuItem3: TMenuItem2000;
  69.     ImageListBitmaps1: TMenuItem2000;
  70.     None2: TMenuItem2000;
  71.     ButtonArray2: TMenuItem2000;
  72.     DefaultBitmapsMenu: TPopupMenu2000;
  73.     ImageListMenu: TPopupMenu2000;
  74.     LoadBitmapFromFile1: TMenuItem2000;
  75.     SaveBitmapToFile1: TMenuItem2000;
  76.     AM2000MenuDesigner4: TMenuItem2000;
  77.     ExpandAll1: TMenuItem2000;
  78.     CollapseAll1: TMenuItem2000;
  79.     AM2000MenuDesigner8: TMenuItem2000;
  80.     Open1: TMenuItem2000;
  81.     SaveAs1: TMenuItem2000;
  82.     InsStdMnu: TMenuItem2000;
  83.     AM2000MenuDesigner2: TMenuItem2000;
  84.     DefaultBitmaps: TImageList;
  85.     AM2000MenuDesigner5: TMenuItem2000;
  86.     Delete1: TMenuItem2000;
  87.     Bevel3: TBevel;
  88.     ButtonStayOnTop: TSpeedButton;
  89.     MenuTree: T_AM2000_TreeView4;
  90.     SelectAll2: TMenuItem2000;
  91.     DeselectAll1: TMenuItem2000;
  92.     N1: TMenuItem2000;
  93.     btnCut: TSpeedButton;
  94.     btnCopy: TSpeedButton;
  95.     btnPaste: TSpeedButton;
  96.     Bevel4: TBevel;
  97.     ShortCuts1: TMenuItem2000;
  98.     N3: TMenuItem2000;
  99.     procedure MenuTree1Change(Sender: TObject; Node: TTreeNode);
  100.     procedure FormShow(Sender: TObject);
  101.     procedure FormHide(Sender: TObject);
  102.     procedure CollapseAll1Click(Sender: TObject);
  103.     procedure ExpandAll1Click(Sender: TObject);
  104.     procedure ButtonNewMenuItemClick(Sender: TObject);
  105.     procedure ButtonNewSubMenuClick(Sender: TObject);
  106.     procedure MenuTree1Edited(Sender: TObject; Node: TTreeNode;
  107.       var S: String);
  108.     procedure ButtonDeleteClick(Sender: TObject);
  109.     procedure FormKeyUp(Sender: TObject; var Key: Word;
  110.       Shift: TShiftState);
  111.     procedure ButtonMoveDownClick(Sender: TObject);
  112.     procedure ButtonMoveUpClick(Sender: TObject);
  113.     procedure ButtonLevelUpClick(Sender: TObject);
  114.     procedure ButtonLevelDownClick(Sender: TObject);
  115.     procedure LoadFromFile2Click(Sender: TObject);
  116.     procedure SaveToFile2Click(Sender: TObject);
  117.     procedure SaveAsTemplate1Click(Sender: TObject);
  118.     procedure MenuTree1MouseUp(Sender: TObject; Button: TMouseButton;
  119.       Shift: TShiftState; X, Y: Integer);
  120.     procedure LoadBitmapFromFileClick(Sender: TObject);
  121.     procedure PopupMenu20001Popup(Sender: TObject);
  122.     procedure SaveBitmapToFileClick(Sender: TObject);
  123.     procedure None1Click(Sender: TObject);
  124.     procedure ButtonArray1Click(Sender: TObject);
  125.     procedure ButtonArray2Click(Sender: TObject);
  126.     procedure FormDestroy(Sender: TObject);
  127.     procedure AM2000MenuDesigner6Click(Sender: TObject);
  128.     procedure AM2000MenuDesigner7Click(Sender: TObject);
  129.     procedure MenuTree1Editing(Sender: TObject; Node: TTreeNode;
  130.       var AllowEdit: Boolean);
  131.     procedure ButtonStayOnTopClick(Sender: TObject);
  132.     procedure ImageListMenuPopup(Sender: TObject);
  133.     procedure MenuTreeChanging(Sender: TObject; Node: TTreeNode;
  134.       var AllowChange: Boolean);
  135.     procedure MenuTreeMouseDown(Sender: TObject; Button: TMouseButton;
  136.       Shift: TShiftState; X, Y: Integer);
  137.     procedure MenuTreeCustomDrawItem(Sender: TCustomTreeView;
  138.       Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
  139.     procedure FormCreate(Sender: TObject);
  140.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  141.     procedure DeselectAll1Click(Sender: TObject);
  142.     procedure btnCutClick(Sender: TObject);
  143.     procedure SelectAll2Click(Sender: TObject);
  144.     procedure FormActivate(Sender: TObject);
  145.     procedure btnCopyClick(Sender: TObject);
  146.     procedure btnPasteClick(Sender: TObject);
  147.     procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  148.       Y: Integer);
  149.     procedure ShortCuts1Click(Sender: TObject);
  150.   private
  151.     Updating: Boolean;
  152.     TempFolder: String;
  153.     FMenu: TMenu;
  154.     ShiftFirstIndex: Integer;
  155.     LastSelected: TTreeNode;
  156.     SelectedList, // list of selected nodes
  157.     MenuItemList, // list of menu items in the node
  158.     TreeNodeList  // list of tree nodes from MenuItemList
  159.                 : TList;
  160. {$IFDEF Delphi3OrHigher}
  161.     OpenPictureDialog1: TOpenPictureDialog;
  162.     SavePictureDialog1: TSavePictureDialog;
  163. {$ELSE}
  164.     OpenPictureDialog1: TOpenDialog;
  165.     SavePictureDialog1: TSaveDialog;
  166. {$ENDIF}
  167.     procedure CheckConstraints;
  168.     procedure InsertTemplateMenuClick(Sender: TObject);
  169.     procedure SetMenu(const Value: TMenu);
  170.     procedure InvalidateNode(Node: TTreeNode);
  171.     procedure InvalidateList;
  172.     procedure wmSelectComponent(var Msg: TMessage); message wm_SelectComponent;
  173.     procedure wmUpdateCaption(var Msg: TMessage);   message wm_UpdateCaption;
  174.     procedure wmUpdateBitmap(var Msg: TMessage);   message wm_UpdateBitmap;
  175.     procedure UpdateSelections;
  176.     procedure ClearSelections;
  177.     procedure CopySelections;
  178.   protected
  179. {$IFDEF Delphi4OrHigher}
  180.     Designer: IFormDesigner;
  181. {$ELSE}
  182.     Designer: TFormDesigner;
  183. {$ENDIF}
  184.     procedure Loaded; override;
  185.   public
  186.     property Menu: TMenu read FMenu write SetMenu;
  187.   end;
  188.   T_AM2000_TreeView4 = class(TCustomTreeView)
  189.   private
  190.     FCanvas: TCanvas;
  191.     FCanvasChanged: Boolean;
  192.     FOnCustomDrawItem: TTVCustomDrawItemEvent;
  193.     procedure CanvasChanged(Sender: TObject);
  194.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  195.     function GetNodeFromItem(const Item: TTVItem): TTreeNode;
  196.   protected
  197.     function CustomDrawItem(Node: TTreeNode; State: TCustomDrawState;
  198.       Stage: TCustomDrawStage
  199. {$IFDEF Delphi5OrHigher}
  200. ;     var PaintImages: Boolean
  201. {$ENDIF}
  202.     ): Boolean;
  203. {$IFDEF Delphi4OrHigher}
  204.     override;
  205. {$ELSE}
  206.     virtual;
  207. {$ENDIF}
  208.     function IsCustomDrawn(Target: TCustomDrawTarget; Stage: TCustomDrawStage): Boolean;
  209.     procedure CreateParams(var Params: TCreateParams); override;
  210.   public
  211.     constructor Create(AOwner: TComponent); override;
  212.     destructor Destroy; override;
  213.     property Canvas: TCanvas read FCanvas;
  214.   published
  215.     property Items;
  216.     property OnChanging;
  217.     property OnChange;
  218.     property Align;
  219.     property OnDragDrop;
  220.     property OnDragOver;
  221.     property OnStartDrag;
  222.     property OnEndDrag;
  223.     property OnMouseDown;
  224.     property OnMouseMove;
  225.     property OnMouseUp;
  226.     property OnDblClick;
  227.     property OnKeyDown;
  228.     property OnKeyPress;
  229.     property OnKeyUp;
  230.     property OnEdited;
  231.     property OnEditing;
  232.     property PopupMenu;
  233.     property Font;
  234.     property Color;
  235.     property OnCustomDrawItem: TTVCustomDrawItemEvent read FOnCustomDrawItem write FOnCustomDrawItem;
  236.   end;
  237. var
  238.   MenuDesignerDlg : T_AM2000_MenuDesignerDlg;
  239. implementation
  240. uses
  241.   Consts, TypInfo, 
  242.   {$IFDEF Delphi2} Ole2, {$ELSE} ShlObj, ActiveX, {$ENDIF}
  243.   {$IFDEF Delphi3orHigher} am2000shortcut, {$ENDIF}
  244.   am2000menubar, am2000const, am2000options;
  245. {$R *.DFM}
  246. const
  247.   MENU_REGISTRY_KEY : String = 'SoftwareAnimatedMenus.comAnimatedMenus/2000Folders';
  248. const
  249.   SOkToDeleteThese = 'Ok to delete these ';
  250.   SSelectedItems = ' selected items?';
  251. {$IFDEF Delphi2}
  252. type
  253.   TSHItemID = record
  254.     cb: Word;                         
  255.     abID: array[0..0] of Byte;        
  256.   end;
  257.   PItemIDList = ^TItemIDList;
  258.   TItemIDList = record
  259.      mkid: TSHItemID;
  260.    end;
  261.   TBrowseInfo = record
  262.     hwndOwner: HWND;
  263.     pidlRoot: PItemIDList;
  264.     pszDisplayName: PAnsiChar;  
  265.     lpszTitle: PAnsiChar;      
  266.     ulFlags: UINT;           
  267.     lpfn: Pointer;
  268.     lParam: LPARAM;         
  269.     iImage: Integer;        
  270.   end;
  271.   function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList;
  272.     stdcall; external 'shell32.dll' name 'SHBrowseForFolderA';
  273.   function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL;
  274.     stdcall; external 'shell32.dll' name 'SHGetPathFromIDListA';
  275. {$ENDIF}
  276. procedure DrawImageList(Item: TMenuItem2000; ImageList: TImageList);
  277. var
  278.   DX, DY, X, Y: Integer;
  279. begin
  280.   DX:= ImageList.Width +4;
  281.   DY:= ImageList.Height +4;
  282.   with Item.AsButtonArray do begin
  283.     Count:= ImageList.Count;
  284.     Columns:= 9;
  285.     Rows:= Count div Columns;
  286.     if (Count mod Columns) <> 0 then Rows:= Rows +1;
  287.     Bitmap.Width:= Columns * DX;
  288.     Bitmap.Height:= Rows * DY;
  289.     with Bitmap.Canvas do begin
  290.       Brush.Color:= clFuchsia;
  291.       Brush.Style:= bsSolid;
  292.       FillRect(ClipRect);
  293.     end;
  294.     for X:= 0 to Columns do
  295.       for Y:= 0 to Rows do
  296.         ImageList_Draw(ImageList.Handle, X + Y * Columns, Bitmap.Canvas.Handle,
  297.           X * DX +2, Y * DY +2, ild_Transparent);
  298.   end;
  299. end;
  300. { T_AM2000_MenuDesigner }
  301. procedure T_AM2000_MenuDesigner.Edit;
  302. begin
  303.   if not Assigned(MenuDesignerDlg) then
  304.     MenuDesignerDlg:= T_AM2000_MenuDesignerDlg.Create(Application);
  305.   MenuDesignerDlg.Designer:= Designer;
  306.   MenuDesignerDlg.Menu:= TMenu(GetComponent(0));
  307.   MenuDesignerDlg.Show;
  308. end;
  309. function T_AM2000_MenuDesigner.GetValue: string;
  310. begin
  311.   Result:= '(Menu2000)';
  312. end;
  313. function T_AM2000_MenuDesigner.GetAttributes: TPropertyAttributes;
  314. begin
  315.   Result:= [paDialog, paReadOnly];
  316. end;
  317. { T_AM2000_ComponentEditor }
  318. procedure T_AM2000_ComponentEditor.Edit;
  319. begin
  320.   if not Assigned(MenuDesignerDlg) then
  321.     MenuDesignerDlg:= T_AM2000_MenuDesignerDlg.Create(Application);
  322.   MenuDesignerDlg.Designer:= Designer;
  323.   MenuDesignerDlg.Menu:= TMenu(Component);
  324.   MenuDesignerDlg.Show;
  325. end;
  326. function T_AM2000_ComponentEditor.GetVerbCount: Integer;
  327. begin
  328.   Result:= inherited GetVerbCount + 1;
  329. end;
  330. function T_AM2000_ComponentEditor.GetVerb(Index: Integer): String;
  331. begin
  332.   if Index = 0
  333.   then Result:= 'AM2000 Menu Designer...'
  334.   else Result:= inherited GetVerb(Index -1);
  335. end;
  336. procedure T_AM2000_ComponentEditor.ExecuteVerb(Index: Integer);
  337. begin
  338.   if Index = 0 then Edit;
  339. end;
  340. { TMenuDesignerDlg }
  341. procedure T_AM2000_MenuDesignerDlg.CheckConstraints;
  342. var
  343.   P: Boolean;
  344.   S: TTreeNode;
  345.   function IsClipboardObject: Boolean;
  346.     // checks is object in lcipboard
  347.   begin
  348.     Result:= LowerCase(Copy(Trim(PasteFromClipboard), 1, 6)) = 'object';
  349.   end;
  350. begin
  351.   S:= MenuTree.Selected;
  352.   P:= (S <> nil) and (S.Parent <> nil);
  353.   ButtonDelete.Enabled:= P and (SelectedList.Count > 0);
  354.   ButtonLevelUp.Enabled:= P and (S.Parent.Parent <> nil);
  355.   ButtonMoveUp.Enabled:= P and ((S.GetPrevSibling <> nil) or (S.Parent.GetPrevSibling <> nil));
  356.   ButtonMoveDown.Enabled:=  P and ((S.GetNextSibling <> nil) or (S.Parent.GetNextSibling <> nil));
  357.   ButtonLevelDown.Enabled:= P;
  358.   DefaultBitmaps1.Enabled:= P;
  359.   ImageListBitmaps1.Enabled:= P and (not ButtonArray2.AsButtonArray.Bitmap.Empty);
  360.   LoadBitmapFromFile1.Enabled:= P;
  361.   SaveBitmapToFile1.Enabled:= P;
  362.   NewItem1.Enabled:= P;
  363.   ButtonNewMenuItem.Enabled:= P;
  364.   // cut/copy/paste
  365.   btnPaste.Enabled:= P and IsClipboardFormatAvailable(cf_Text) and IsClipboardObject;
  366.   btnCut.Enabled:= ButtonDelete.Enabled;
  367.   btnCopy.Enabled:= (SelectedList.Count > 0);
  368. end;
  369. procedure T_AM2000_MenuDesignerDlg.InvalidateNode(Node: TTreeNode);
  370. var
  371.   R: TRect;
  372. begin
  373.   if (Node = nil) or Updating then Exit;
  374.   try
  375.     R:= Node.DisplayRect(False);
  376.     InvalidateRect(MenuTree.Handle, @R, False)
  377.   except
  378.   end;
  379. end;
  380. procedure T_AM2000_MenuDesignerDlg.InvalidateList;
  381. var
  382.   I: Integer;
  383. begin
  384.   for I:= 0 to SelectedList.Count -1 do
  385.     InvalidateNode(TTreeNode(SelectedList[I]));
  386. end;
  387. procedure T_AM2000_MenuDesignerDlg.MenuTree1Change(Sender: TObject;
  388.   Node: TTreeNode);
  389. var
  390.   M: TMenuItem2000;
  391.   S: String;
  392.   B: Boolean;
  393.   N: TTreeNode;
  394. begin
  395.   CheckConstraints;
  396.   if (not (Assigned(Node) and Assigned(Node.Data)))
  397.   or (Updating)
  398.   then Exit;
  399.   try
  400.     S:= '';
  401.     if TObject(Node.Data) is TMenuItem2000 then begin
  402.       M:= TMenuItem2000(Node.Data);
  403.       while Assigned(M) and (M.Caption <> '') do begin
  404.         if S <> ''then S:= ' | ' + S;
  405.         S:= M.Caption + S;
  406.         M:= M.Parent;
  407.       end;
  408.     end;
  409.     // set item index at ButtonArray1
  410.     if Assigned(Node.Data) then
  411.       with TMenuItem2000(Node.Data) do begin
  412.         IgnoreRepaintFloating:= True;
  413.         ButtonArray1.AsButtonArray.ItemIndex:= DefaultIndex;
  414.         ButtonArray2.AsButtonArray.ItemIndex:= ImageIndex;
  415.         IgnoreRepaintFloating:= False;
  416.         B:= (DefaultIndex = -1) and (ImageIndex = -1);
  417.         None1.AsButton.Down:= B;
  418.         None2.AsButton.Down:= B;
  419.       end;
  420.   except
  421.   end;
  422.   // custom draw support
  423.   if Node = nil then Exit;
  424.   // shift
  425.   if GetKeyState(vk_Shift) < 0
  426.   then begin
  427.     InvalidateList;
  428.     SelectedList.Clear;
  429.     N:= Node;
  430.     while (N <> nil) and (N.AbsoluteIndex <> ShiftFirstIndex)
  431.     do begin
  432.       SelectedList.Add(N);
  433.       InvalidateNode(N);
  434.       if N.AbsoluteIndex < ShiftFirstIndex
  435.       then N:= N.GetNextVisible
  436.       else N:= N.GetPrevVisible;
  437.     end;
  438.     if N <> nil then begin
  439.       SelectedList.Add(N);
  440.       InvalidateNode(N);
  441.     end;
  442.   end
  443.   else
  444.   // control
  445.   if GetKeyState(vk_Control) < 0
  446.   then begin
  447.     if Node <> nil then begin
  448.       if SelectedList.IndexOf(Node) = -1
  449.       then SelectedList.Add(Node)
  450.       else SelectedList.Remove(Node);
  451.       InvalidateNode(Node);
  452.     end;
  453.   end
  454.   // none
  455.   else begin
  456.     ShiftFirstIndex:= -1;
  457.     InvalidateList;
  458.     SelectedList.Clear;
  459.     SelectedList.Add(Node);
  460.     InvalidateNode(Node);
  461.   end;
  462.   UpdateSelections;
  463. end;
  464. procedure T_AM2000_MenuDesignerDlg.MenuTreeChanging(Sender: TObject;
  465.   Node: TTreeNode; var AllowChange: Boolean);
  466. var
  467.   N: TTreeNode;
  468. begin
  469.   N:= MenuTree.Selected;
  470.   // check keys
  471.   if (GetKeyState(vk_Shift) < 0)
  472.   and (N <> nil)
  473.   and (ShiftFirstIndex = -1)
  474.   then ShiftFirstIndex:= N.AbsoluteIndex;
  475. end;
  476. procedure T_AM2000_MenuDesignerDlg.MenuTreeCustomDrawItem(
  477.   Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
  478.   var DefaultDraw: Boolean);
  479. var
  480.   txtRect, R: TRect;
  481.   Bitmap: HBitmap;
  482.   NumGlyphs, BitmapIndex, DX: Integer;
  483.   mi: TMenuItem2000;
  484.   img: TImageList;
  485. begin
  486.   DX:= -20;
  487.   Bitmap:= 0;
  488.   BitmapIndex:= -1;
  489.   DefaultDraw:= False;  
  490.   with T_AM2000_TreeView4(Sender), Canvas, Node do begin
  491.     txtRect:= DisplayRect(True);
  492.     Font.Assign(T_AM2000_TreeView4(Sender).Font);
  493.     if (SelectedList.IndexOf(Node) <> -1)
  494.     and (Node.Parent <> nil)
  495.     then begin
  496.       Brush.Color:= clHighlight;
  497.       Font.Color:= clHighlightText;
  498.     end
  499.     else begin
  500.       Brush.Color:= T_AM2000_TreeView4(Sender).Color;
  501.     end;
  502.     // selection
  503.     FillRect(DisplayRect(False));
  504.     // caption
  505.     R:= txtRect;
  506.     R.Right:= Width;
  507.     DrawText(Canvas.Handle, PChar(Text), Length(Text), R, dt_SingleLine + dt_VCenter);
  508.     if HasChildren
  509.     then begin // draw button
  510.       Dec(DX, 13);
  511.       R:= Rect(0, 0, 9, 9);
  512.       OffsetRect(R, txtRect.Left -14, (txtRect.Bottom + txtRect.Top) div 2 -5);
  513.       Brush.Color:= T_AM2000_TreeView4(Sender).Color;
  514.       FillRect(R);
  515.       Brush.Color:= clBtnShadow;
  516.       FrameRect(R);
  517.       Pen.Color:= T_AM2000_TreeView4(Sender).Font.Color;
  518.       Pen.Style:= psSolid;
  519.       if Expanded then begin
  520.         PolyLine([Point(R.Left +2, R.Top +4), Point(R.Right -2, R.Top +4)]);
  521.       end
  522.       else begin
  523.         PolyLine([Point(R.Left +4, R.Top +2), Point(R.Left +4, R.Bottom -2)]);
  524.         PolyLine([Point(R.Left +2, R.Top +4), Point(R.Right -2, R.Top +4)]);
  525.       end;
  526.     end;
  527.     mi:= TMenuItem2000(Data);
  528.     if mi = nil then Exit;
  529.     // draw bitmap
  530. {$IFDEF Delphi4OrHigher}
  531.     img:= TImageList(TMainMenu(FMenu).Images);
  532. {$ELSE}
  533.     if FMenu is TMainMenu2000
  534.     then
  535.       img:= TMainMenu2000(FMenu).Images
  536.     else
  537.     if FMenu is TPopupMenu2000
  538.     then
  539.       img:= TPopupMenu2000(FMenu).Images
  540.     else
  541.       img:= nil;
  542. {$ENDIF}
  543.     if (mi is TMenuItem2000)
  544.     and (TMenuItem2000(mi).IsBitmapAssigned)
  545.     then
  546.       Bitmap:= TMenuItem2000(mi).GetBitmapEx.Handle
  547.     else
  548.     if
  549.     (img <> nil) and
  550. {$IFDEF Delphi4OrHigher}
  551.     (mi.ImageIndex <> -1)
  552. {$ELSE}
  553.     (mi is TMenuItem2000) and (TMenuItem2000(mi).ImageIndex <> -1)
  554. {$ENDIF}
  555.     then
  556.       BitmapIndex:= TMenuItem2000(mi).ImageIndex
  557.     else
  558. {$IFDEF Delphi4OrHigher}
  559.       Bitmap:= mi.Bitmap.Handle;
  560. {$ELSE}
  561.       Bitmap:= 0;
  562. {$ENDIF}
  563.     if mi is TMenuItem2000
  564.     then NumGlyphs:= TMenuItem2000(mi).NumGlyphs
  565.     else NumGlyphs:= 0;
  566.     if (Bitmap = 0)
  567.     and (BitmapIndex = -1)
  568.     and mi.Checked
  569.     then
  570.       if mi.RadioItem
  571.       then Bitmap:= bmpRadioItem
  572.       else Bitmap:= bmpCheckMark;
  573.     if (Bitmap <> 0) or (BitmapIndex <> -1)
  574.     then begin
  575.       R:= Rect(0, 0, 16, 16);
  576.       OffsetRect(R, txtRect.Left + DX, (txtRect.Bottom + txtRect.Top) div 2 -9);
  577.       DrawBitmap(Canvas, Bitmap, BitmapIndex, NumGlyphs, 0, [], nil, R, img);
  578.     end;
  579. //    DeleteObject(Bitmap);
  580.   end;
  581. end;
  582. procedure T_AM2000_MenuDesignerDlg.MenuTreeMouseDown(Sender: TObject;
  583.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  584. var
  585.   N: TTreeNode;
  586. begin
  587.   N:= nil;
  588.   with MenuTree do begin
  589.     if not (htOnButton in GetHitTestInfoAt(X, Y))
  590.     then N:= GetNodeAt(X, Y);
  591.     if (N <> nil)
  592.     and (N = Selected)
  593.     then begin
  594.       if (GetKeyState(vk_Control) < 0)
  595.       and (N = LastSelected)
  596.       then begin
  597.         if SelectedList.IndexOf(N) = -1
  598.         then SelectedList.Add(N)
  599.         else SelectedList.Remove(N);
  600.         TreeView_EndEditLabelNow(N.Handle, True);
  601.         UpdateSelections;
  602.       end
  603.       else
  604.         if SelectedList.IndexOf(N) = -1
  605.         then begin
  606.           InvalidateList;
  607.           SelectedList.Clear;
  608.           SelectedList.Add(N);
  609.         end
  610.     end
  611.     else
  612.       Selected:= N;
  613.     InvalidateNode(LastSelected);
  614.     InvalidateNode(N);
  615.     LastSelected:= N;  
  616.   end;
  617.   CheckConstraints;
  618. end;
  619. procedure T_AM2000_MenuDesignerDlg.Loaded;
  620. var
  621.   Reg: TRegistry;
  622.   SI: TSearchRec;
  623.   I, Res, DX, DY, X, Y: Integer;
  624.   mici: T_AM2000_MenuItemCacheItem;
  625. //  BlankColor: ColorRef;
  626. //  hbmp: HBitmap;
  627.   B: Boolean;
  628.   lpbi: TBrowseInfo;
  629.   pid2: PItemIDList;
  630.   z: array [0..MAX_PATH] of Char;
  631. begin
  632.   inherited;
  633.   // load autobitmaps & autohints
  634. //  BlankColor:= ColorToRGB(clFuchsia);
  635.   Res:= 0;
  636.   for I:= 0 to MenuItemCache.Count -1 do
  637.     with T_AM2000_MenuItemCacheItem(TStringList(MenuItemCache).Objects[I]) do
  638.       if (Bitmap <> 0) and IsDefault
  639.       then Inc(Res);
  640.   with ButtonArray1.AsButtonArray do begin
  641.     X:= 0;
  642.     Y:= 0;
  643.     DX:= 20;
  644.     DY:= 20;
  645.     Columns:= 9;
  646.     Rows:= Res div Columns;
  647.     if Res mod Columns <> 0 then Rows:= Rows +1;
  648.     Bitmap.Width:= Columns * DX;
  649.     Bitmap.Height:= Rows * DY;
  650.     Bitmap.Canvas.Brush.Color:= clBtnFace;
  651.     Bitmap.Canvas.FillRect(Bitmap.Canvas.ClipRect);
  652.     for I:= 0 to MenuItemCache.Count -1 do begin
  653.       mici:= T_AM2000_MenuItemCacheItem(TStringList(MenuItemCache).Objects[I]);
  654.       if (mici.Bitmap <> 0)
  655.       and (mici.IsDefault)
  656.       then begin
  657.         TransBlt(Bitmap.Canvas, X * DX +2, Y * DY + 2, 0, 1, mici.Bitmap);
  658.         if mici.Hint <> ''
  659.         then Hints.Add(mici.Hint)
  660.         else Hints.Add(TStringList(MenuItemCache)[I]);
  661.         Inc(X);
  662.         if X >= Columns then begin
  663.           Inc(Y);
  664.           X:= 0;
  665.         end;
  666.       end;
  667.     end;
  668.   end;
  669. {$IFDEF Delphi3OrHigher}
  670.   // set flat property
  671.   ButtonNewMenuItem.Flat:= True;
  672.   ButtonNewSubMenu.Flat:= True;
  673.   ButtonDelete.Flat:= True;
  674.   ButtonLevelUp.Flat:= True;
  675.   ButtonMoveUp.Flat:= True;
  676.   ButtonMoveDown.Flat:= True;
  677.   ButtonLevelDown.Flat:= True;
  678.   ButtonStayOnTop.Flat:= True;
  679.   btnCut.Flat:= True;
  680.   btnCopy.Flat:= True;
  681.   btnPaste.Flat:= True;
  682. {$ENDIF}
  683.   // load menu templates
  684.   Reg:= TRegistry.Create;
  685.   B:= Reg.OpenKey(MENU_REGISTRY_KEY, False);
  686.   if not B then begin
  687.     FillChar(lpbi, SizeOf(lpbi), 0);
  688.     lpbi.hwndOwner:= Application.MainForm.Handle;
  689.     lpbi.lpszTitle:= SBrowseForMenuTemplateFolder;
  690.     pid2:= SHBrowseForFolder(lpbi);
  691.     if pid2 = nil then Exit;
  692.     Reg.OpenKey(MENU_REGISTRY_KEY, True);
  693.     SHGetPathFromIDList(pid2, z);
  694.     TempFolder:= StrPas(z);
  695.     Reg.WriteString('MenuTemplatesFolder', TempFolder);
  696.     CoTaskMemFree(pid2);
  697.   end
  698.   else
  699.     TempFolder:= Reg.ReadString('MenuTemplatesFolder');
  700.   // scan template files
  701.   if (Length(TempFolder) > 0)
  702.   and (TempFolder[Length(TempFolder)] <> '')
  703.   then AppendStr(TempFolder, '');
  704.   Res:= FindFirst(TempFolder + '*.mnu', faAnyFile, SI);
  705.   while Res = 0 do begin
  706.     InsStdMnu.Add(NewItem(ChangeFileExt(SI.Name, ''), 0,
  707.       False, True, InsertTemplateMenuClick, 0, ''));
  708.     Res:= FindNext(SI);
  709.   end;
  710.   FindClose(SI);
  711.   Reg.Free;
  712. end;
  713. procedure T_AM2000_MenuDesignerDlg.FormShow(Sender: TObject);
  714. begin
  715.   // create and initialize dialogs
  716. {$IFDEF Delphi3OrHigher}
  717.   OpenPictureDialog1:= TOpenPictureDialog.Create(Self);
  718.   SavePictureDialog1:= TSavePictureDialog.Create(Self);
  719. {$ELSE}
  720.   OpenPictureDialog1:= TOpenDialog.Create(Self);
  721.   SavePictureDialog1:= TSaveDialog.Create(Self);
  722. {$ENDIF}
  723.   with OpenPictureDialog1 do begin
  724.     DefaultExt:= 'bmp';
  725.     Filter:= SBitmapDialogFilter;
  726.     Options:= [ofHideReadOnly, ofPathMustExist, ofFileMustExist];
  727.     Title:= SOpenBitmapDialogTitle;
  728.   end;
  729.   with SavePictureDialog1 do begin
  730.     DefaultExt:= 'bmp';
  731.     FileName:= 'Untitled-1.bmp';
  732.     Filter:= SBitmapDialogFilter;
  733.     Options:= [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist];
  734.     Title:= SSaveBitmapDialogTitle;
  735.   end;
  736. end;
  737. procedure T_AM2000_MenuDesignerDlg.FormHide(Sender: TObject);
  738. begin
  739.   Designer:= nil;
  740. end;
  741. procedure T_AM2000_MenuDesignerDlg.FormCreate(Sender: TObject);
  742. begin
  743.   Updating:= False;
  744.   SelectedList:= TList.Create;
  745.   MenuItemList:= TList.Create;
  746.   TreeNodeList:= TList.Create;
  747. end;
  748. procedure T_AM2000_MenuDesignerDlg.FormDestroy(Sender: TObject);
  749. begin
  750.   Updating:= True;
  751.   SelectedList.Free;
  752.   MenuItemList.Free;
  753.   TreeNodeList.Free;
  754.   MenuDesignerDlg:= nil;
  755. end;
  756. procedure T_AM2000_MenuDesignerDlg.CollapseAll1Click(Sender: TObject);
  757. begin
  758.   MenuTree.FullCollapse;
  759. end;
  760. procedure T_AM2000_MenuDesignerDlg.ExpandAll1Click(Sender: TObject);
  761. begin
  762.   MenuTree.FullExpand;
  763. end;
  764. procedure T_AM2000_MenuDesignerDlg.ButtonNewMenuItemClick(Sender: TObject);
  765. var
  766.   N, N1: TTreeNode;
  767.   M, M1: TMenuItem2000;
  768. begin
  769.   N:= MenuTree.Selected;
  770.   if (not Assigned(N))
  771.   or (not Assigned(N.Parent)) then Exit;
  772.   // clear selection
  773.   InvalidateList;
  774.   SelectedList.Clear;
  775.   SelectedList.Add(N);
  776.   InvalidateNode(N);
  777.   M:= TMenuItem2000(N.Data);
  778.   M1:= TMenuItem2000.Create(Menu.Owner);
  779.   M1.Caption:= SDefaultMenuItemCaption;
  780.   if Designer <> nil
  781.   then M1.Name:= Designer.UniqueName('MenuItem');
  782.   if (N.GetNextSibling <> nil) then begin
  783.     N1:= MenuTree.Items.Insert(N.GetNextSibling, SDefaultMenuItemCaption);
  784.     M.Parent.Insert(M.MenuIndex +1, M1);
  785.   end
  786.   else begin
  787.     N1:= MenuTree.Items.Add(N, SDefaultMenuItemCaption);
  788.     M.Parent.Add(M1);
  789.   end;
  790.   if Designer <> nil then begin
  791.     Designer.Modified;
  792.     Designer.SelectComponent(M1);
  793.   end;
  794.   if ActiveMenuBar <> nil
  795.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  796.   N1.Selected:= True;
  797.   N1.Data:= M1;
  798.   TreeNodeList.Add(N1);
  799.   MenuItemList.Add(N1.Data);
  800.   // customdraw
  801.   InvalidateList;
  802.   SelectedList.Clear;
  803.   SelectedList.Add(N1);
  804.   InvalidateNode(N1);
  805.   if ActiveMenuBar <> nil
  806.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  807.   N1.EditText;
  808.   CheckConstraints;
  809. end;
  810. procedure T_AM2000_MenuDesignerDlg.ButtonNewSubMenuClick(Sender: TObject);
  811. var
  812.   N: TTreeNode;
  813.   M: TMenuItem2000;
  814. begin
  815.   if not Assigned(MenuTree.Selected) then Exit;
  816.   N:= MenuTree.Items.AddChild(MenuTree.Selected, SDefaultMenuItemCaption);
  817.   // clear selection
  818.   InvalidateList;
  819.   SelectedList.Clear;
  820.   SelectedList.Add(N);
  821.   InvalidateNode(N);
  822.   M:= TMenuItem2000.Create(Menu.Owner);
  823.   M.Caption:= SDefaultMenuItemCaption;
  824.   
  825.   if Designer <> nil
  826.   then M.Name:= Designer.UniqueName('MenuItem');
  827.   TMenuItem2000(MenuTree.Selected.Data).Add(M);
  828.   MenuTree.Selected.Expand(False);
  829.   if Designer <> nil then begin
  830.     Designer.SelectComponent(M);
  831.     Designer.Modified;
  832.   end;
  833.   if ActiveMenuBar <> nil
  834.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  835.   N.Selected:= True;
  836.   N.Data:= M;
  837.   TreeNodeList.Add(N);
  838.   MenuItemList.Add(N.Data);
  839.   // customdraw
  840.   InvalidateList;
  841.   SelectedList.Clear;
  842.   SelectedList.Add(N);
  843.   InvalidateNode(N);
  844.   if ActiveMenuBar <> nil
  845.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  846.   N.EditText;
  847.   CheckConstraints;
  848. end;
  849. procedure T_AM2000_MenuDesignerDlg.MenuTree1Edited(Sender: TObject; Node: TTreeNode;
  850.   var S: String);
  851. var
  852.   M: TMenuItem2000;
  853.   S1, S2: String;
  854. begin
  855.   if Node.Parent <> nil then begin
  856.     // generate menu item capion
  857.     M:= TMenuItem2000(Node.Data);
  858.     M.Caption:= S;
  859.     S1:= S;
  860.     while (M.Parent <> nil) do begin
  861.       M:= M.Parent;
  862.       S1:= M.Caption + S1;
  863.     end;
  864.     if Designer <> nil then begin
  865.       // set menu item name
  866.       S1:= GetValidName(S1);
  867.       if S1 = '' then S1:= 'N';
  868.       S2:= Designer.UniqueName(S1);
  869.       if (S1[1] = 'T') and (S2[1] <> 'T')
  870.       then S2:= 'T' + S2;
  871.       TMenuItem2000(Node.Data).Name:= S2;
  872.       Designer.Modified;
  873.       Designer.SelectComponent(TMenuItem2000(Node.Data));
  874.     end;
  875.     if ActiveMenuBar <> nil
  876.     then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  877.   end;
  878. end;
  879. procedure T_AM2000_MenuDesignerDlg.ButtonDeleteClick(Sender: TObject);
  880. begin
  881.   if (SelectedList.Count > 1)
  882.   and (MessageDlg(SOkToDeleteThese + IntToStr(SelectedList.Count) + SSelectedItems, mtConfirmation,
  883.     mbOkCancel, 0) <> mrOk)
  884.   then Exit;
  885.   ClearSelections;
  886.   LastSelected:= nil;
  887. end;
  888. procedure T_AM2000_MenuDesignerDlg.FormKeyUp(Sender: TObject; var Key: Word;
  889.   Shift: TShiftState);
  890. var
  891.   S: String;
  892. begin
  893.   if MenuTree.IsEditing
  894.   then
  895.     case Key of
  896.       vk_Return:
  897.         ButtonNewMenuItemClick(nil);
  898.       vk_Escape:
  899.         if MenuTree.Selected.Text = SDefaultMenuItemCaption
  900.         then ButtonDeleteClick(nil);
  901.     end
  902.   else
  903.     case Key of
  904.       vk_Insert:
  905.         ButtonNewMenuItemClick(nil);
  906.       vk_Delete:
  907.         ButtonDeleteClick(nil);
  908.       vk_F2:
  909.         if ssCtrl in Shift
  910.         then begin
  911.           S:= TMenuItem2000(MenuTree.Selected.Data).Caption;
  912.           MenuTree1Edited(nil, MenuTree.Selected, S);
  913.         end
  914.         else MenuTree.Selected.EditText;
  915.       vk_Up:
  916.         if ssCtrl in Shift
  917.         then ButtonMoveUpClick(nil);
  918.       vk_Down:
  919.         if ssCtrl in Shift
  920.         then ButtonMoveDownClick(nil);
  921.       vk_Right:
  922.         if ssCtrl in Shift
  923.         then ButtonLevelDownClick(nil);
  924.       vk_Left:
  925.         if ssCtrl in Shift
  926.         then ButtonLevelUpClick(nil);
  927.     end;
  928.   CheckConstraints;
  929. end;
  930. procedure T_AM2000_MenuDesignerDlg.ButtonMoveDownClick(Sender: TObject);
  931. var
  932.   N, N1: TTreeNode;
  933.   M, M1: TMenuItem2000;
  934. begin
  935.   N:= MenuTree.Selected;
  936.   if (not Assigned(N))
  937.   or (not Assigned(N.Parent)) then Exit;
  938.   // clear selection
  939.   InvalidateList;
  940.   SelectedList.Clear;
  941.   SelectedList.Add(N);
  942.   InvalidateNode(N);
  943.   N1:= N.GetNextSibling;
  944.   // updating
  945.   Updating:= True;
  946.   MenuTree.Items.BeginUpdate;
  947.   if Assigned(N1)
  948.   then begin
  949.     N1:= N1.GetNextSibling;
  950.     if Assigned(N1)
  951.     then N.MoveTo(N1, naInsert)
  952.     else N.MoveTo(N.Parent, naAddChild);
  953.     with TMenuItem2000(N.Data) do MenuIndex:= MenuIndex +1;
  954.   end
  955.   else begin
  956.     N1:= N.Parent.GetNextSibling;
  957.     if Assigned(N1) then begin
  958.       N.MoveTo(N1, naAddChildFirst);
  959.       M:= TMenuItem2000(N.Data);
  960.       M1:= M.Parent.Parent.Items[M.Parent.MenuIndex +1];
  961.       M.Parent.Remove(M);
  962.       M1.Insert(0, M);
  963.     end
  964.   end;
  965.   MenuTree.Items.EndUpdate;
  966.   Updating:= False;
  967.   CheckConstraints;
  968.   if ActiveMenuBar <> nil
  969.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  970.   
  971. end;
  972. procedure T_AM2000_MenuDesignerDlg.ButtonMoveUpClick(Sender: TObject);
  973. var
  974.   N, N1: TTreeNode;
  975.   M, M1: TMenuItem2000;
  976. begin
  977.   N:= MenuTree.Selected;
  978.   if (not Assigned(N))
  979.   or (not Assigned(N.Parent)) then Exit;
  980.   // clear selection
  981.   InvalidateList;
  982.   SelectedList.Clear;
  983.   SelectedList.Add(N);
  984.   InvalidateNode(N);
  985.   N1:= N.GetPrevSibling;
  986.   if N1 = N.Parent then Exit;
  987.   // updating
  988.   Updating:= True;
  989.   MenuTree.Items.BeginUpdate;
  990.   if Assigned(N1) then begin
  991.     N.MoveTo(N1, naInsert);
  992.     with TMenuItem2000(N.Data) do MenuIndex:= MenuIndex -1;
  993.   end
  994.   else begin
  995.     N1:= N.Parent.GetPrevSibling;
  996.     if Assigned(N1) then begin
  997.       N.MoveTo(N1, naAddChild);
  998.       M:= TMenuItem2000(N.Data);
  999.       M1:= M.Parent.Parent.Items[M.Parent.MenuIndex -1];
  1000.       M.Parent.Remove(M);
  1001.       M1.Add(M);
  1002.     end;
  1003.   end;
  1004.   MenuTree.Items.EndUpdate;
  1005.   Updating:= False;
  1006.   CheckConstraints;
  1007.   if ActiveMenuBar <> nil
  1008.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1009. end;
  1010. procedure T_AM2000_MenuDesignerDlg.ButtonLevelUpClick(Sender: TObject);
  1011. var
  1012.   N, N1: TTreeNode;
  1013.   M, M1: TMenuItem2000;
  1014.   I: Integer;
  1015. begin
  1016.   N:= MenuTree.Selected;
  1017.   if (not Assigned(N))
  1018.   or (not Assigned(N.Parent))
  1019.   or (not Assigned(N.Parent.Parent)) then Exit;
  1020.   // clear selection
  1021.   InvalidateList;
  1022.   SelectedList.Clear;
  1023.   SelectedList.Add(N);
  1024.   InvalidateNode(N);
  1025.   N1:= N.Parent.GetNextSibling;
  1026.   // updating
  1027.   Updating:= True;
  1028.   MenuTree.Items.BeginUpdate;
  1029.   M:= TMenuItem2000(N.Data);
  1030.   M1:= M.Parent.Parent;
  1031.   I:= M.Parent.MenuIndex;
  1032.   M.Parent.Remove(M);
  1033.   if Assigned(N1) then begin
  1034.     N.MoveTo(N1, naInsert);
  1035.     M1.Insert(I +1, M);
  1036.   end
  1037.   else begin
  1038.     N.MoveTo(N.Parent.Parent, naAddChild);
  1039.     M1.Add(M);
  1040.   end;
  1041.   MenuTree.Items.EndUpdate;
  1042.   Updating:= False;
  1043.   CheckConstraints;
  1044.   if ActiveMenuBar <> nil
  1045.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1046. end;
  1047. procedure T_AM2000_MenuDesignerDlg.ButtonLevelDownClick(Sender: TObject);
  1048. var
  1049.   N, N1: TTreeNode;
  1050.   M, M1, M2: TMenuItem2000;
  1051.   I: Integer;
  1052. begin
  1053.   N:= MenuTree.Selected;
  1054.   if (not Assigned(N))
  1055.   or (not Assigned(N.Parent)) then Exit;
  1056.   // clear selection
  1057.   InvalidateList;
  1058.   SelectedList.Clear;
  1059.   SelectedList.Add(N);
  1060.   InvalidateNode(N);
  1061.   // treeview...
  1062.   N1:= N.GetPrevSibling;
  1063.   // updating
  1064.   Updating:= True;
  1065.   MenuTree.Items.BeginUpdate;
  1066.   // menu...
  1067.   M:= TMenuItem2000(N.Data);
  1068.   M1:= M.Parent;
  1069.   I:= M.MenuIndex;
  1070.   M.Parent.Remove(M);
  1071.   if Assigned(N1)
  1072.   then begin
  1073.     N.MoveTo(N1, naAddChild);
  1074.     M1[I -1].Add(M);
  1075.   end
  1076.   else begin
  1077.     N1:= MenuTree.Items.AddChildFirst(N.Parent, SDefaultMenuItemCaption);
  1078.     N.MoveTo(N1, naAddChild);
  1079.     M2:= TMenuItem2000.Create(Menu.Owner);
  1080.     M2.Caption:= SDefaultMenuItemCaption;
  1081.     if Designer <> nil
  1082.     then M2.Name:= Designer.UniqueName('MenuItem');
  1083.     M2.Add(M);
  1084.     M1.Insert(0, M2);
  1085.     N1.Data:= M2;
  1086.     TreeNodeList.Add(N1);
  1087.     MenuItemList.Add(N1.Data);
  1088.   end;
  1089.   MenuTree.Items.EndUpdate;
  1090.   Updating:= False;
  1091.   CheckConstraints;
  1092.   if ActiveMenuBar <> nil
  1093.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1094.   
  1095. end;
  1096. procedure T_AM2000_MenuDesignerDlg.wmUpdateCaption(var Msg: TMessage);
  1097. var
  1098.   I: Integer;
  1099. begin
  1100.   // get menu item index
  1101.   I:= MenuItemList.IndexOf(Pointer(Msg.LParam));
  1102.   // get tree node
  1103.   if I <> -1 then InvalidateNode(TTreeNode(TreeNodeList[I]));
  1104. end;
  1105. procedure T_AM2000_MenuDesignerDlg.wmUpdateBitmap(var Msg: TMessage);
  1106. var
  1107.   I: Integer;
  1108. begin
  1109.   // get menu item index
  1110.   I:= MenuItemList.IndexOf(Pointer(Msg.LParam));
  1111.   // get tree node
  1112.   if I <> -1 then InvalidateNode(TTreeNode(TreeNodeList[I]));
  1113. end;
  1114. procedure T_AM2000_MenuDesignerDlg.LoadFromFile2Click(Sender: TObject);
  1115.   // loads menu from file
  1116. var
  1117.   M, M1: TMenuItem2000;
  1118. begin
  1119.   if (MenuTree.Selected = nil)
  1120.   or (not OpenDialog1.Execute)
  1121.   then Exit;
  1122.   M:= TMenuItem2000(MenuTree.Selected.Data);
  1123.   M1:= TMenuItem2000.Create(Menu.Owner);
  1124.   ReadComponentResFile(OpenDialog1.Filename, M1);
  1125.   M.Insert(0, M1);
  1126.   Menu:= Menu;
  1127.   if Designer <> nil
  1128.   then Designer.Modified;
  1129.   if ActiveMenuBar <> nil
  1130.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1131. end;
  1132. procedure T_AM2000_MenuDesignerDlg.InsertTemplateMenuClick(Sender: TObject);
  1133.   // loads a template menu
  1134. var
  1135.   S: String;
  1136.   M, M1: TMenuItem2000;
  1137. begin
  1138.   S:= TempFolder + TMenuItem2000(Sender).Caption + '.mnu';
  1139.   if (MenuTree.Selected = nil)
  1140.   or (not FileExists(S))
  1141.   then Exit;
  1142.   M:= TMenuItem2000(MenuTree.Selected.Data);
  1143.   M1:= TMenuItem2000.Create(Menu.Owner);
  1144.   ReadComponentResFile(S, M1);
  1145.   M.Insert(0, M1);
  1146.   Menu:= Menu;
  1147.   if Designer <> nil
  1148.   then Designer.Modified;
  1149.   // update menu bar
  1150.   if ActiveMenuBar <> nil
  1151.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1152. end;
  1153. procedure T_AM2000_MenuDesignerDlg.SaveToFile2Click(Sender: TObject);
  1154.   // saves menu to a file
  1155. begin
  1156.   if (not SaveDialog1.Execute)
  1157.   then Exit;
  1158.   with MenuTree.Selected do
  1159.     WriteComponentResFile(SaveDialog1.Filename, TMenuItem2000(Data));
  1160. end;
  1161. procedure T_AM2000_MenuDesignerDlg.SaveAsTemplate1Click(Sender: TObject);
  1162.   // saves menu as an template
  1163. begin
  1164.   SaveDialog1.InitialDir:= TempFolder;
  1165.   if not SaveDialog1.Execute
  1166.   then Exit;
  1167.   with MenuTree.Selected do
  1168.     WriteComponentResFile(SaveDialog1.Filename, TMenuItem2000(Data));
  1169. end;
  1170. procedure T_AM2000_MenuDesignerDlg.MenuTree1MouseUp(Sender: TObject;
  1171.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1172.   // pops up a right-click menu
  1173. var
  1174.   N: TTreeNode;
  1175. begin
  1176.   if (Button <> mbRight)
  1177.   then Exit;
  1178.   N:= MenuTree.GetNodeAt(X, Y);
  1179.   if N <> nil
  1180.   then
  1181.     with MenuTree.ClientToScreen(Point(X, Y)) do
  1182.       PopupMenu20001.Popup(X, Y);
  1183. end;
  1184. procedure T_AM2000_MenuDesignerDlg.LoadBitmapFromFileClick(Sender: TObject);
  1185. begin
  1186.   if not OpenPictureDialog1.Execute
  1187.   then Exit;
  1188.   with TMenuItem2000(MenuTree.Selected.Data) do
  1189.     Bitmap.LoadFromFile(OpenPictureDialog1.Filename);
  1190.   if Designer <> nil
  1191.   then Designer.Modified;
  1192.   if ActiveMenuBar <> nil
  1193.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1194. end;
  1195. procedure T_AM2000_MenuDesignerDlg.SaveBitmapToFileClick(Sender: TObject);
  1196. begin
  1197.   if not SavePictureDialog1.Execute
  1198.   then Exit;
  1199.   with TMenuItem2000(MenuTree.Selected.Data) do
  1200.     Bitmap.SaveToFile(SavePictureDialog1.Filename);
  1201. end;
  1202. procedure T_AM2000_MenuDesignerDlg.PopupMenu20001Popup(Sender: TObject);
  1203.   // restore bitmap indexes
  1204. var
  1205.   il: TImageList;
  1206. begin
  1207.   if Assigned(MenuTree.Selected) then
  1208.     with TMenuItem2000(MenuTree.Selected.Data) do begin
  1209.       IgnoreRepaintFloating:= True;
  1210.       ButtonArray1.AsButtonArray.ItemIndex:= DefaultIndex;
  1211.       IgnoreRepaintFloating:= False;
  1212.       None1.AsButton.Down:= (not IsBitmapAssigned);
  1213.     end;
  1214.   // load bitmaps from menu's imagelist
  1215.   il:= nil;
  1216.   if Menu is TMainMenu2000 then il:= TImageList(TCustomMainMenu2000(Menu).Images);
  1217.   if Menu is TPopupMenu2000 then il:= TImageList(TCustomPopupMenu2000(Menu).Images);
  1218.   ImageListBitmaps1.Enabled:= (MenuTree.Selected <> nil)
  1219.     and (MenuTree.Selected.Parent <> nil)
  1220.     and (il <> nil)
  1221.     and (il.Count > 0);
  1222. end;
  1223. procedure T_AM2000_MenuDesignerDlg.None1Click(Sender: TObject);
  1224.   // remove the bitmap
  1225. begin
  1226.   if None1.AsButton.Down then Exit;
  1227.   None1.AsButton.Down:= True;
  1228.   None2.AsButton.Down:= True;
  1229.   with MenuTree.Selected, TMenuItem2000(Data) do begin
  1230.     DefaultIndex:= -1;
  1231.     ImageIndex:= -1;
  1232.     if IsBitmapAssigned then begin
  1233.       Bitmap.Handle:= 0;
  1234.     end;
  1235.     if Designer <> nil then begin
  1236.       Designer.Modified;
  1237.       Designer.SelectComponent(TMenuItem2000(Data));
  1238.     end;
  1239.     if ActiveMenuBar <> nil
  1240.     then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1241.     
  1242.   end;
  1243. end;
  1244. procedure T_AM2000_MenuDesignerDlg.ButtonArray1Click(Sender: TObject);
  1245.   // assigns default bitmaps
  1246. begin
  1247.   with ButtonArray1.AsButtonArray, MenuTree.Selected, TMenuItem2000(Data)
  1248.   do begin
  1249.     DefaultIndex:= ItemIndex;
  1250.     ImageIndex:= -1;
  1251.     None2.AsButton.Down:= False;
  1252.     ButtonArray2.AsButtonArray.ItemIndex:= -1;
  1253.     if Designer <> nil then begin
  1254.       Designer.SelectComponent(TMenuItem2000(Data));
  1255.       Designer.Modified;
  1256.     end;
  1257.     if ActiveMenuBar <> nil
  1258.     then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1259.   end;
  1260. end;
  1261. procedure T_AM2000_MenuDesignerDlg.ButtonArray2Click(Sender: TObject);
  1262.   // assigns imagelist's bitmap
  1263. begin
  1264.   with ButtonArray2.AsButtonArray, MenuTree.Selected, TMenuItem2000(Data)
  1265.   do begin
  1266.     DefaultIndex:= -1;
  1267.     ImageIndex:= ItemIndex;
  1268.     None1.AsButton.Down:= False;
  1269.     ButtonArray1.AsButtonArray.ItemIndex:= -1;
  1270.     if Designer <> nil then begin
  1271.       Designer.SelectComponent(TMenuItem2000(Data));
  1272.       Designer.Modified;
  1273.     end;
  1274.     if ActiveMenuBar <> nil
  1275.     then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1276.   end;
  1277. end;
  1278. procedure T_AM2000_MenuDesignerDlg.SetMenu(const Value: TMenu);
  1279.   procedure AddMenu(M: TMenuItem2000; T: TTreeNodes; N: TTreeNode);
  1280.   var
  1281.     I: Integer;
  1282.     N1: TTreeNode;
  1283.   begin
  1284.     for I:= 0 to M.Count -1 do begin
  1285.       N1:= T.AddChild(N, M[I].Caption);
  1286.       N1.Data:= M[I];
  1287.       TreeNodeList.Add(N1);
  1288.       MenuItemList.Add(N1.Data);
  1289.       if M[I].Count > 0 then AddMenu(M[I], T, N1);
  1290.     end;
  1291.   end;
  1292. var
  1293.   N: TTreeNode;
  1294.   MI: TMenuItem2000;
  1295. begin
  1296.   // updating
  1297.   Updating:= True;
  1298.   MenuTree.Items.BeginUpdate;
  1299.   // init menu tree items
  1300.   MenuTree.Items.Clear;
  1301.   SelectedList.Clear;
  1302.   MenuItemList.Clear;
  1303.   TreeNodeList.Clear;
  1304.   FMenu:= Value;
  1305.   if FMenu = nil then Exit;
  1306.   try
  1307.     MI:= nil;
  1308.     if Menu is TCustomMainMenu2000 then MI:= TCustomMainMenu2000(Menu).Items2000;
  1309.     if Menu is TCustomPopupMenu2000 then MI:= TCustomPopupMenu2000(Menu).Items2000;
  1310.     N:= MenuTree.Items.Add(nil, 'AnimatedMenus/2000');
  1311.     N.Data:= MI;
  1312.     TreeNodeList.Add(N);
  1313.     MenuItemList.Add(N.Data);
  1314.     AddMenu(MI, MenuTree.Items, N);
  1315.     MenuTree.Items[0].Expand(False);
  1316.   except
  1317.   end;
  1318.   MenuTree.Items.EndUpdate;
  1319.   Updating:= False;
  1320.   LastSelected:= nil;
  1321. end;
  1322. procedure T_AM2000_MenuDesignerDlg.AM2000MenuDesigner6Click(
  1323.   Sender: TObject);
  1324. begin
  1325.   // updating
  1326.   Updating:= True;
  1327.   MenuTree.Items.BeginUpdate;
  1328.   MenuTree.FullExpand;
  1329.   MenuTree.Items.EndUpdate;
  1330.   Updating:= False;
  1331. end;
  1332. procedure T_AM2000_MenuDesignerDlg.AM2000MenuDesigner7Click(
  1333.   Sender: TObject);
  1334. begin
  1335.   // updating
  1336.   Updating:= True;
  1337.   MenuTree.Items.BeginUpdate;
  1338.   MenuTree.FullCollapse;
  1339.   MenuTree.Items.EndUpdate;
  1340.   Updating:= False;
  1341. end;
  1342. procedure T_AM2000_MenuDesignerDlg.MenuTree1Editing(Sender: TObject;
  1343.   Node: TTreeNode; var AllowEdit: Boolean);
  1344. begin
  1345.   AllowEdit:= Node.Parent <> nil;
  1346. end;
  1347. procedure T_AM2000_MenuDesignerDlg.ButtonStayOnTopClick(Sender: TObject);
  1348. begin
  1349.   SelectedList.Clear;
  1350.   if ButtonStayOnTop.Down
  1351.   then FormStyle:= fsStayOnTop
  1352.   else FormStyle:= fsNormal;
  1353.   if MenuTree.Items.Count > 0 then
  1354.     MenuTree.Items[0].Expand(False);
  1355. end;
  1356. procedure T_AM2000_MenuDesignerDlg.ImageListMenuPopup(Sender: TObject);
  1357. var
  1358.   il: TImageList;
  1359. begin
  1360.   // load bitmaps from menu's imagelist
  1361.   il:= nil;
  1362.   if Menu is TMainMenu2000 then il:= TImageList(TCustomMainMenu2000(Menu).Images);
  1363.   if Menu is TPopupMenu2000 then il:= TImageList(TCustomPopupMenu2000(Menu).Images);
  1364.   if (il = nil) or (il.Count = 0)
  1365.   then begin
  1366.     ImageListBitmaps1.Enabled:= False;
  1367.     ButtonArray2.AsButtonArray.Bitmap.Width:= 0;
  1368.   end
  1369.   else begin
  1370.     DrawImageList(ButtonArray2, il);
  1371.     ImageListBitmaps1.Enabled:= True;
  1372.   end;
  1373. end;
  1374. procedure T_AM2000_MenuDesignerDlg.FormClose(Sender: TObject;
  1375.   var Action: TCloseAction);
  1376. begin
  1377.   Action:= caFree;
  1378. end;
  1379. procedure T_AM2000_MenuDesignerDlg.wmSelectComponent(var Msg: TMessage);
  1380. begin
  1381.   if Designer <> nil
  1382.   then begin
  1383.     Designer.SelectComponent(TMenuItem2000(Msg.LParam));
  1384.     Designer.Modified;
  1385.   end;
  1386. end;
  1387. procedure T_AM2000_MenuDesignerDlg.DeselectAll1Click(Sender: TObject);
  1388. begin
  1389.   InvalidateList;
  1390.   SelectedList.Clear;
  1391. end;
  1392. procedure T_AM2000_MenuDesignerDlg.UpdateSelections;
  1393. var
  1394.   I: Integer;
  1395. {$IFDEF Delphi5OrHigher}
  1396.   S: TDesignerSelectionList;
  1397. {$ELSE}
  1398.   S: TComponentList;
  1399. {$ENDIF}
  1400. begin
  1401.   if Designer = nil then Exit;
  1402.   if SelectedList.Count > 1
  1403.   then begin
  1404. {$IFDEF Delphi5OrHigher}
  1405.     S:= TDesignerSelectionList.Create;
  1406. {$ELSE}
  1407.     S:= TComponentList.Create;
  1408. {$ENDIF}
  1409.     for I:= 0 to SelectedList.Count -1 do
  1410.       S.Add(TMenuItem2000(TTreeNode(SelectedList[I]).Data));
  1411.     Designer.SetSelections(S);
  1412.     S.Free;
  1413.   end
  1414.   else
  1415.     Designer.SelectComponent(TMenuItem2000(TTreeNode(SelectedList[0]).Data));
  1416. end;
  1417. procedure T_AM2000_MenuDesignerDlg.ClearSelections;
  1418.   // removes selections
  1419. var
  1420.   N: TTreeNode;
  1421.   SL1: TList;
  1422.   I: Integer;
  1423.   function RemoveFromSelList(Node: TTreeNode): Integer;
  1424.     // remove node and its children
  1425.   var
  1426.     I, C: Integer;
  1427.   begin
  1428.     Result:= 0;
  1429.     if (Node = nil) then Exit;
  1430.     C:= SL1.Count;
  1431.     SL1.Remove(Node);
  1432.     I:= 0;
  1433.     while I < SL1.Count -1 do begin
  1434.       if Node.IndexOf(TTreeNode(SL1[I])) <> -1
  1435.       then Dec(I, RemoveFromSelList(TTreeNode(SL1[I])));
  1436.       Inc(I);
  1437.     end;
  1438.     Result:= C - SL1.Count;
  1439.   end;
  1440. begin
  1441.   // updating
  1442.   Updating:= True;
  1443.   MenuTree.Items.BeginUpdate;
  1444.   SL1:= TList.Create;
  1445.   for I:= 0 to SelectedList.Count -1 do
  1446.     SL1.Add(SelectedList[I]);
  1447.   SelectedList.Clear;
  1448.   while SL1.Count > 0 do begin
  1449.     N:= TTreeNode(SL1[0]);
  1450.     RemoveFromSelList(N);
  1451.     TMenuItem2000(N.Data).Free;
  1452.     N.Free;
  1453.   end;
  1454.   SL1.Free;
  1455.   MenuTree.Items.EndUpdate;
  1456.   Updating:= False;
  1457.   CheckConstraints;
  1458.   if Designer <> nil
  1459.   then Designer.Modified;
  1460.   if ActiveMenuBar <> nil
  1461.   then PostMessage(ActiveMenuBar.Handle, wm_UpdateMenuBar, upForceRebuild, 0);
  1462.   
  1463. end;
  1464. procedure T_AM2000_MenuDesignerDlg.CopySelections;
  1465. var
  1466.   S, S2: String;
  1467.   M1, M2: TMemoryStream;
  1468.   I: Integer;
  1469. begin
  1470.   if SelectedList.Count = 0 then Exit;
  1471.   S:= '';
  1472.   M1:= TMemoryStream.Create;
  1473.   M2:= TMemoryStream.Create;
  1474.   for I:= 0 to SelectedList.Count -1 do begin
  1475.     // write menu item into m1
  1476.     M1.WriteComponent(TMenuItem2000(TTreeNode(SelectedList[I]).Data));
  1477.     M1.Seek(0, 0);
  1478.     // ObjectResourceToText
  1479.     ObjectBinaryToText(M1, M2);
  1480.     M2.Seek(0, 0);
  1481.     // convert M2 to S2
  1482.     SetLength(S2, M2.Size);
  1483.     M2.ReadBuffer(PChar(S2)^, M2.Size);
  1484.     // add S2 to S
  1485.     AppendStr(S, S2);
  1486.   end;
  1487.   M1.Free;
  1488.   M2.Free;
  1489.   if S <> '' then CopyToClipboard(S);
  1490.   
  1491. end;
  1492. procedure T_AM2000_MenuDesignerDlg.btnCutClick(Sender: TObject);
  1493. begin
  1494.   CopySelections;
  1495.   ClearSelections;
  1496.   CheckConstraints;
  1497. end;
  1498. procedure T_AM2000_MenuDesignerDlg.btnCopyClick(Sender: TObject);
  1499. begin
  1500.   CopySelections;
  1501.   CheckConstraints;
  1502. end;
  1503. procedure T_AM2000_MenuDesignerDlg.btnPasteClick(Sender: TObject);
  1504. var
  1505.   S: String;
  1506.   M1, M2: TMemoryStream;
  1507.   N, N1: TTreeNode;
  1508.   M, MI1: TMenuItem2000;
  1509.   procedure InsertChildNodes(Node: TTreeNode; Item: TMenuItem);
  1510.   var
  1511.     I: Integer;
  1512.     N: TTreeNode;
  1513.   begin
  1514.     for I:= 0 to Item.Count -1 do begin
  1515.       N:= MenuTree.Items.AddChild(Node, Item[I].Caption);
  1516.       N.Data:= Item[I];
  1517.       TreeNodeList.Add(N);
  1518.       MenuItemList.Add(N.Data);
  1519.       InsertChildNodes(N, Item[I]);
  1520.     end;
  1521.   end;
  1522. begin
  1523.   // selection
  1524.   N:= MenuTree.Selected;
  1525.   if (not Assigned(N))
  1526.   or (not Assigned(N.Parent)) then Exit;
  1527.   // clear selection
  1528.   // updating
  1529.   Updating:= True;
  1530.   MenuTree.Items.BeginUpdate;
  1531.   InvalidateList;
  1532.   SelectedList.Clear;
  1533.   MI1:= nil;
  1534.   M1:= TMemoryStream.Create;
  1535.   M2:= TMemoryStream.Create;
  1536.   try
  1537.     // load component
  1538.     S:= PasteFromClipboard;
  1539.     // store to stream
  1540.     M1.WriteBuffer(PChar(S)^, Length(S));
  1541.     M1.Seek(0, 0);
  1542.     while M1.Position < M1.Size do begin
  1543.       MI1:= TMenuItem2000.Create(Menu.Owner);
  1544.       // convert into component
  1545.       ObjectTextToBinary(M1, M2);
  1546.       M2.Seek(0, 0);
  1547.       // readcomponent
  1548.       M2.ReadComponent(MI1);
  1549.       // insert into menu and tree
  1550.       M:= TMenuItem2000(N.Data);
  1551.       if (N.GetNextSibling <> nil) then begin
  1552.         N1:= MenuTree.Items.Insert(N.GetNextSibling, MI1.Caption);
  1553.         M.Parent.Insert(M.MenuIndex +1, MI1);
  1554.       end
  1555.       else begin
  1556.         N1:= MenuTree.Items.Add(N, MI1.Caption);
  1557.         M.Parent.Add(MI1);
  1558.       end;
  1559.       N1.Data:= MI1;
  1560.       TreeNodeList.Add(N1);
  1561.       MenuItemList.Add(N1.Data);
  1562.       InsertChildNodes(N1, MI1);
  1563.       // select
  1564.       SelectedList.Add(N1);
  1565.       // remove reference
  1566.       MI1:= nil;
  1567.     end;
  1568.   except
  1569.     M1.Free;
  1570.     M2.Free;
  1571.     MI1.Free;
  1572.     MenuTree.Items.EndUpdate;
  1573.     Updating:= False;
  1574.     raise;
  1575.   end;
  1576.   M1.Free;
  1577.   M2.Free;
  1578.   MenuTree.Items.EndUpdate;
  1579.   Updating:= False;
  1580. end;
  1581. procedure T_AM2000_MenuDesignerDlg.SelectAll2Click(Sender: TObject);
  1582. var
  1583.   I: Integer;
  1584. begin
  1585.   SelectedList.Clear;
  1586.   with MenuTree.Items do begin
  1587.     BeginUpdate;
  1588.     for I:= 0 to Count -1 do
  1589.       SelectedList.Add(Item[I]);
  1590.     EndUpdate;
  1591.   end;
  1592. end;
  1593. procedure T_AM2000_MenuDesignerDlg.FormActivate(Sender: TObject);
  1594. begin
  1595.   CheckConstraints;
  1596. end;
  1597. procedure T_AM2000_MenuDesignerDlg.Panel1MouseMove(Sender: TObject;
  1598.   Shift: TShiftState; X, Y: Integer);
  1599. begin
  1600. //  Panel1.ShowHint:= True;
  1601. end;
  1602. { T_AM2000_TreeView4 }
  1603. {$IFNDEF Delphi4OrHigher}
  1604. const
  1605. { =============== GENERIC WM_NOTIFY EVENTS FOR TREEVIEWS ==================== }
  1606.   NM_CUSTOMDRAW            = NM_FIRST-12;
  1607.   NM_HOVER                 = NM_FIRST-13;
  1608.   NM_NCHITTEST             = NM_FIRST-14;   // uses NMMOUSE struct
  1609.   NM_KEYDOWN               = NM_FIRST-15;   // uses NMKEY struct
  1610.   NM_RELEASEDCAPTURE       = NM_FIRST-16;
  1611.   NM_SETCURSOR             = NM_FIRST-17;   // uses NMMOUSE struct
  1612.   NM_CHAR                  = NM_FIRST-18;   // uses NMCHAR struct
  1613. { ==================== CUSTOM DRAW ========================================== }
  1614. const
  1615.   // custom draw return flags
  1616.   // values under 0x00010000 are reserved for global custom draw values.
  1617.   // above that are for specific controls
  1618.   CDRF_DODEFAULT          = $00000000;
  1619.   CDRF_NEWFONT            = $00000002;
  1620.   CDRF_SKIPDEFAULT        = $00000004;
  1621.   CDRF_NOTIFYPOSTPAINT    = $00000010;
  1622.   CDRF_NOTIFYITEMDRAW     = $00000020;
  1623.   CDRF_NOTIFYSUBITEMDRAW  = $00000020;  // flags are the same, we can distinguish by context
  1624.   CDRF_NOTIFYPOSTERASE    = $00000040;
  1625.   // drawstage flags
  1626.   // values under = $00010000 are reserved for global custom draw values.
  1627.   // above that are for specific controls
  1628.   CDDS_PREPAINT           = $00000001;
  1629.   CDDS_POSTPAINT          = $00000002;
  1630.   CDDS_PREERASE           = $00000003;
  1631.   CDDS_POSTERASE          = $00000004;
  1632.   // the = $000010000 bit means it's individual item specific
  1633.   CDDS_ITEM               = $00010000;
  1634.   CDDS_ITEMPREPAINT       = CDDS_ITEM or CDDS_PREPAINT;
  1635.   CDDS_ITEMPOSTPAINT      = CDDS_ITEM or CDDS_POSTPAINT;
  1636.   CDDS_ITEMPREERASE       = CDDS_ITEM or CDDS_PREERASE;
  1637.   CDDS_ITEMPOSTERASE      = CDDS_ITEM or CDDS_POSTERASE;
  1638.   CDDS_SUBITEM            = $00020000;
  1639.   // itemState flags
  1640.   CDIS_SELECTED       = $0001;
  1641.   CDIS_GRAYED         = $0002;
  1642.   CDIS_DISABLED       = $0004;
  1643.   CDIS_CHECKED        = $0008;
  1644.   CDIS_FOCUS          = $0010;
  1645.   CDIS_DEFAULT        = $0020;
  1646.   CDIS_HOT            = $0040;
  1647.   CDIS_MARKED         = $0080;
  1648.   CDIS_INDETERMINATE  = $0100;
  1649. type
  1650.   tagNMCUSTOMDRAWINFO = packed record
  1651.     hdr: TNMHdr;
  1652.     dwDrawStage: DWORD;
  1653.     hdc: HDC;
  1654.     rc: TRect;
  1655.     dwItemSpec: DWORD;  // this is control specific, but it's how to specify an item.  valid only with CDDS_ITEM bit set
  1656.     uItemState: UINT;
  1657.     lItemlParam: LPARAM;
  1658.   end;
  1659.   PNMCustomDraw = ^TNMCustomDraw;
  1660.   TNMCustomDraw = tagNMCUSTOMDRAWINFO;
  1661.   tagNMTTCUSTOMDRAW = packed record
  1662.     nmcd: TNMCustomDraw;
  1663.     uDrawFlags: UINT;
  1664.   end;
  1665.   PNMTTCustomDraw = ^TNMTTCustomDraw;
  1666.   TNMTTCustomDraw = tagNMTTCUSTOMDRAW;
  1667.   tagNMTVCUSTOMDRAW = packed record
  1668.     nmcd: TNMCustomDraw;
  1669.     clrText: COLORREF;
  1670.     clrTextBk: COLORREF;
  1671.     iLevel: Integer;
  1672.   end;
  1673.   PNMTVCustomDraw = ^TNMTVCustomDraw;
  1674.   TNMTVCustomDraw = tagNMTVCUSTOMDRAW;
  1675. {$ENDIF}
  1676. constructor T_AM2000_TreeView4.Create(AOwner: TComponent);
  1677. begin
  1678.   inherited Create(AOwner);
  1679.   FCanvas:= TControlCanvas.Create;
  1680.   TControlCanvas(FCanvas).Control:= Self;
  1681. end;
  1682. destructor T_AM2000_TreeView4.Destroy;
  1683. begin
  1684.   FCanvas.Free;
  1685.   inherited Destroy;
  1686. end;
  1687. procedure T_AM2000_TreeView4.CreateParams(var Params: TCreateParams);
  1688. const
  1689.   TVS_NOTOOLTIPS  = $0080;
  1690. begin
  1691.   inherited;
  1692.   with Params do Style:= Style or TVS_NOTOOLTIPS;
  1693. end;
  1694. function T_AM2000_TreeView4.GetNodeFromItem(const Item: TTVItem): TTreeNode;
  1695. begin
  1696.   with Item do
  1697.     if (state and TVIF_PARAM) <> 0 then Result:= Pointer(lParam)
  1698.     else Result:= Items.GetNode(hItem);
  1699. end;
  1700. procedure T_AM2000_TreeView4.CNNotify(var Message: TWMNotify);
  1701. var
  1702.   Node: TTreeNode;
  1703.   TmpItem: TTVItem;
  1704. {$IFDEF Delphi5OrHigher}
  1705.   PaintImages: Boolean;
  1706. {$ENDIF}
  1707. begin
  1708.   with Message do
  1709.     case NMHdr^.code of
  1710.       NM_CUSTOMDRAW:
  1711.         with PNMCustomDraw(NMHdr)^ do
  1712.         begin
  1713.           Result:= CDRF_DODEFAULT;
  1714.           if dwDrawStage = CDDS_PREPAINT then
  1715.           begin
  1716.             Result:= Result or CDRF_NOTIFYITEMDRAW
  1717.           end
  1718.           else if dwDrawStage = CDDS_ITEMPREPAINT then
  1719.           begin
  1720.             FillChar(TmpItem, SizeOf(TmpItem), 0);
  1721.             TmpItem.hItem:= HTREEITEM(dwItemSpec);
  1722.             Node:= GetNodeFromItem(TmpItem);
  1723.             if Node <> nil then
  1724.             begin
  1725.               FCanvas.Handle:= hdc;
  1726.               FCanvas.Font:= Font;
  1727.               FCanvas.Brush:= Brush;
  1728.               FCanvas.Font.OnChange:= CanvasChanged;
  1729.               FCanvas.Brush.OnChange:= CanvasChanged;
  1730.               CustomDrawItem(Node,
  1731.                 TCustomDrawState(Word(uItemState)), cdPrePaint
  1732. {$IFDEF Delphi5OrHigher}
  1733. ,               PaintImages
  1734. {$ENDIF}
  1735.                 );
  1736.               Result:= Result or CDRF_SKIPDEFAULT;
  1737.               FCanvas.Handle:= 0;
  1738.               if IsCustomDrawn(dtItem, cdPostPaint) then
  1739.                 Result:= Result or CDRF_NOTIFYPOSTPAINT;
  1740.             end;
  1741.           end;
  1742.         end;
  1743.       else
  1744.         inherited;
  1745.     end;
  1746. end;
  1747. procedure T_AM2000_TreeView4.CanvasChanged;
  1748. begin
  1749.   FCanvasChanged:= True;
  1750. end;
  1751. function T_AM2000_TreeView4.IsCustomDrawn(Target: TCustomDrawTarget; Stage: TCustomDrawStage): Boolean;
  1752. begin
  1753.   if Stage = cdPrePaint
  1754.   then
  1755.     if Target = dtItem
  1756.     then Result:= Assigned(FOnCustomDrawItem)
  1757.     else Result:= False
  1758.   else
  1759.     Result:= False;
  1760. end;
  1761. function T_AM2000_TreeView4.CustomDrawItem(Node: TTreeNode; State: TCustomDrawState;
  1762.   Stage: TCustomDrawStage
  1763. {$IFDEF Delphi5OrHigher}
  1764. ;  var PaintImages: Boolean
  1765. {$ENDIF}
  1766.   ): Boolean;
  1767. begin
  1768.   Result:= True;
  1769.   if Assigned(FOnCustomDrawItem) then FOnCustomDrawItem(Self, Node, State, Result);
  1770. {$IFDEF Delphi5OrHigher}
  1771.   PaintImages:= False;
  1772. {$ENDIF}
  1773. end;
  1774. procedure T_AM2000_MenuDesignerDlg.ShortCuts1Click(Sender: TObject);
  1775. {$IFDEF Delphi3OrHigher}
  1776. var
  1777.   ShortCutEditor: T_AM2000_ShortCutEditor;
  1778.   S: String;
  1779.   mi: TMenuItem2000;
  1780. {$ENDIF}
  1781. begin
  1782. {$IFDEF Delphi3OrHigher}
  1783.   if (MenuTree.Selected = nil)
  1784.   and (SelectedList.Count = 0)
  1785.   then Exit;
  1786.   if (MenuTree.Selected <> nil)
  1787.   then mi:= TMenuItem2000(MenuTree.Selected.Data)
  1788.   else mi:= TMenuItem2000(SelectedList[0]);
  1789.   ShortCutEditor:= T_AM2000_ShortCutEditor.Create(Self);
  1790.   S:= mi.ShortCut;
  1791.   if ShortCutEditor.EditShortCuts(S) then begin
  1792.     mi.ShortCut:= S;
  1793.     if Designer <> nil then begin
  1794.       Designer.Modified;
  1795.       Designer.SelectComponent(mi);
  1796.     end;
  1797.   end;
  1798.   ShortCutEditor.Free;
  1799. {$ENDIF}
  1800. end;
  1801. end.