使用TRzMenuController控件只是為了增加主菜單的皮膚效果,可清除此控件
主控程序的主窗口單元要實現(xiàn)的需求如下:
1.自動識別并加載各個已經(jīng)注冊的插件;
2.自動識別并加載各個已經(jīng)注冊的插件中的各個模塊(自動生成系統(tǒng)的主菜單,自動生成各菜單項的點擊事件);
unit uMainForm;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Menus, Loader, Buttons, uInterface, DB ,Masks, ExtCtrls, ToolWin, ADODB, RzCommon;
type TMainForm = class(TForm) mainmenu1: TMainMenu; cdsLibrary: TADOTable; cdsMenu: TADOTable; N11: TMenuItem; RzMenuController1: TRzMenuController; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } FDllsPath: string; FDllList: TStringList; FLoaders: array of TLoader; FLoadersContainer: TStringList; procedure RunForm(DLLName, aClassName: string); procedure CreateMenu(Dataset: TDataSet; Menu: TMainMenu); procedure MenuItemClick(Sender: TObject); public { Public declarations } end;
var MainForm: TMainForm;
implementation
uses uDM;
{$R *.dfm}
procedure TMainForm.MenuItemClick(Sender: TObject); begin if cdsMenu.Locate('ModuleId', TMenuItem(Sender).Hint, []) then // TMenuItem(Sender).Hint=ModuleId RunForm(cdsMenu.FieldByName('DLL').AsString, cdsMenu.FieldByName('ClassName').AsString); end;
procedure TMainForm.RunForm(DLLName, aClassName: string); var i: Integer; begin if DLLName = '' then Exit; if aClassName = '' then Exit; i := FLoadersContainer.IndexOf(DLLName); if i = -1 then Exit; TLoader(FLoadersContainer.Objects[i]).ModelServiceInts.Cmd(PChar(aClassName)); end;
procedure TMainForm.CreateMenu(Dataset: TDataSet; Menu: TMainMenu); var p, m: TMenuItem; begin if not Dataset.Active then Exit; if Dataset.IsEmpty then Exit; if Menu = nil then Exit; Menu.Items.Clear; p := nil; Dataset.First; while not Dataset.Eof do // 此算法要求MODULEID必須可以排序 begin m := TMenuItem.Create(self); m.Hint := Dataset.FieldByName('ModuleId').AsString; m.Caption := Dataset.FieldByName('ModuleName').AsString; if (Dataset.FieldByName('ParentId').AsString = '') or // one level's root node (Dataset.FieldByName('ParentId').AsString = Dataset.FieldByName('ModuleId').AsString) then begin p := m; Menu.Items.Add(m); end else if (Dataset.FieldByName('ParentId').AsString <> '') and // second level's root node (Dataset.FieldByName('ClassName').AsString = '') then begin p.Add(m); p := m; end else begin // son node p.Add(m); m.OnClick := MenuItemClick; end; Dataset.Next; end; end;
procedure TMainForm.FormCreate(Sender: TObject); var i: Integer; begin cdsLibrary.IndexFieldNames := 'DLL'; if cdsLibrary.IsEmpty then raise Exception.Create('沒有注冊任何插件'); cdsMenu.IndexFieldNames := 'ModuleId'; if cdsMenu.IsEmpty then raise Exception.Create('沒有注冊任何菜單項');
FDllsPath := ExtractFilePath(Application.ExeName); // load plugins FDllList := TStringList.Create; FLoadersContainer := TStringList.Create; SetLength(FLoaders, cdsLibrary.RecordCount); i := 0; cdsLibrary.First; while not cdsLibrary.Eof do begin FLoaders[i] := TLoader.Create(FDllsPath + cdsLibrary.FieldByName('DLL').AsString); FLoadersContainer.AddObject(ExtractFileName(FDllsPath + cdsLibrary.FieldByName('DLL').AsString), FLoaders[i]); cdsLibrary.Next; i := i + 1; end;
CreateMenu(cdsMenu, mainmenu1); // load menu items end;
procedure TMainForm.FormDestroy(Sender: TObject); var i: Integer; begin for I := Low(FLoaders) to High(FLoaders) do begin if Assigned(FLoaders[i]) then FLoaders[i].Free; end; FreeAndNil(FDllList); FreeAndNil(FLoadersContainer); end;
end.
|