主控程序之主窗体
使用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.
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/archive/2012/02/19/2358370.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?