主控程序之主窗体

使用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/p/2358370.html