TMainMenu 动态构建菜单项
TMainMenu build menu item dynamic
在我的系统上,主菜单是完全动态的,是根据数据库中的数据构建的。
我有一个特定的情况,有些菜单项需要 assembled 才能显示。
假设我的菜单有以下主要项目:
文件 - 客户 - 报告 - 关于
当我单击 报告 菜单项时,它们必须 assemble 显示之前的项目。
我分析了 TMainMenu、TMenu 和 TMenuItem 中的代码 class。不幸的是,我还没有找到解决问题的简单方法。
是否存在一种在显示之前创建这些项目的方法?
你可以使用一个技巧。您需要在 Reports 下添加一个虚拟 TMenuItem
并将其 Visible
属性 设置为 False
。然后将 OnClick
事件添加到 Reports 项目并在那里执行填充逻辑。在添加新项目之前,您必须删除现有项目,但您应该保持虚拟项目完好无损。
类似于:
procedure TForm1.ReportItemClick(Sender: TObject);
var
Item: TMenuItem;
I: Integer;
begin
// Delete all items but first - dummy - one
for I := ReportItem.Count - 1 downto 1 do
ReportItem.Items[I].Free;
Item := TMenuItem.Create(ReportItem);
Item.Caption := 'abc';
// Item.OnClick := ...
// or
// Item.Action := ...
ReportItem.Add(Item);
Item := TMenuItem.Create(ReportItem);
Item.Caption := '123';
// Item.OnClick := ...
// or
// Item.Action := ...
ReportItem.Add(Item);
end;
让我们假设您有一个 DS (TDataSet) 如何加载所有数据报告。在您放下报告菜单的那一刻,您可以调用 UpdateMenuReport。
type
TMenuArray = array of TMenuItem;
var MyMenu: TMenuArray;
procedure TMain.MyClickPopupMenu(Sender: TObject);
begin
case TMenuItem(TMenuItem(Sender).Parent).Tag of
// do Something
end;
end;
procedure TMain.UpdateMenuReport;
procedure InitMyMenu(var AMenu: TMenuArray);
var i: Integer;
begin
if Length(AMenu)>0 then for i:= 0 to Length(AMenu)-1 do AMenu[i].Free;
SetLength(AMenu, 0);
end;
var j, i: integer;
begin
InitMyMenu(MyMenu);
Reports.Clear;
if DS.Active and (DS.RecordCount > 0) then
begin
SetLength(MyMenu, DS.RecordCount);
for i:= 0 to DS.RecordCount-1 do
begin
MyMenu[i] := TMenuItem.Create(Self);
MyMenu[i].Name := 'Reports_'+ IntToStr(i);
MyMenu[i].Caption := DS.FieldByname('NOM_REPORT').AsString;
MyMenu[i].Tag := DS.FieldByname('ID').AsInteger;
MyMenu[i].OnClick := MyClickPopupMenu;
end;
end;
end;
在我的系统上,主菜单是完全动态的,是根据数据库中的数据构建的。
我有一个特定的情况,有些菜单项需要 assembled 才能显示。
假设我的菜单有以下主要项目:
文件 - 客户 - 报告 - 关于
当我单击 报告 菜单项时,它们必须 assemble 显示之前的项目。
我分析了 TMainMenu、TMenu 和 TMenuItem 中的代码 class。不幸的是,我还没有找到解决问题的简单方法。
是否存在一种在显示之前创建这些项目的方法?
你可以使用一个技巧。您需要在 Reports 下添加一个虚拟 TMenuItem
并将其 Visible
属性 设置为 False
。然后将 OnClick
事件添加到 Reports 项目并在那里执行填充逻辑。在添加新项目之前,您必须删除现有项目,但您应该保持虚拟项目完好无损。
类似于:
procedure TForm1.ReportItemClick(Sender: TObject);
var
Item: TMenuItem;
I: Integer;
begin
// Delete all items but first - dummy - one
for I := ReportItem.Count - 1 downto 1 do
ReportItem.Items[I].Free;
Item := TMenuItem.Create(ReportItem);
Item.Caption := 'abc';
// Item.OnClick := ...
// or
// Item.Action := ...
ReportItem.Add(Item);
Item := TMenuItem.Create(ReportItem);
Item.Caption := '123';
// Item.OnClick := ...
// or
// Item.Action := ...
ReportItem.Add(Item);
end;
让我们假设您有一个 DS (TDataSet) 如何加载所有数据报告。在您放下报告菜单的那一刻,您可以调用 UpdateMenuReport。
type
TMenuArray = array of TMenuItem;
var MyMenu: TMenuArray;
procedure TMain.MyClickPopupMenu(Sender: TObject);
begin
case TMenuItem(TMenuItem(Sender).Parent).Tag of
// do Something
end;
end;
procedure TMain.UpdateMenuReport;
procedure InitMyMenu(var AMenu: TMenuArray);
var i: Integer;
begin
if Length(AMenu)>0 then for i:= 0 to Length(AMenu)-1 do AMenu[i].Free;
SetLength(AMenu, 0);
end;
var j, i: integer;
begin
InitMyMenu(MyMenu);
Reports.Clear;
if DS.Active and (DS.RecordCount > 0) then
begin
SetLength(MyMenu, DS.RecordCount);
for i:= 0 to DS.RecordCount-1 do
begin
MyMenu[i] := TMenuItem.Create(Self);
MyMenu[i].Name := 'Reports_'+ IntToStr(i);
MyMenu[i].Caption := DS.FieldByname('NOM_REPORT').AsString;
MyMenu[i].Tag := DS.FieldByname('ID').AsInteger;
MyMenu[i].OnClick := MyClickPopupMenu;
end;
end;
end;