使用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.