使用TRzMenuController控件只是为了增加主菜单的皮肤效果,可清除此控件
主控程序的主窗口单元要实现的需求如下:
1.自动识别并加载各个已经注册的插件;
2.自动识别并加载各个已经注册的插件中的各个模块(自动生成系统的主菜单,自动生成各菜单项的点击事件);
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.