【发布时间】:2010-05-27 20:25:25
【问题描述】:
任何人都知道如何在 MDI 应用程序中合并两个同名菜单。
更准确地说,在 MDI 主窗体中,我有一个名为“文件”的菜单,其中有一个名为“加载项目”的子菜单。 在 MDI 子窗体中,我有一个名为“文件”的菜单,其中包含一个名为“保存项目”的子菜单。
如何强制我的应用程序在“文件”菜单下同时显示“加载”和“保存”子菜单?
-
PS:设置相同的 GoupIndex 值将不起作用。
【问题讨论】:
任何人都知道如何在 MDI 应用程序中合并两个同名菜单。
更准确地说,在 MDI 主窗体中,我有一个名为“文件”的菜单,其中有一个名为“加载项目”的子菜单。 在 MDI 子窗体中,我有一个名为“文件”的菜单,其中包含一个名为“保存项目”的子菜单。
如何强制我的应用程序在“文件”菜单下同时显示“加载”和“保存”子菜单?
-
PS:设置相同的 GoupIndex 值将不起作用。
【问题讨论】:
要合并您的菜单,请使用以下过程:
procedure MergeMenus(var SrcMenu, DstMenu: TMainMenu);
var
i, i2, i3: Integer;
Menu: TMenuItem;
begin
for i := 0 to SrcMenu.Items.Count - 1 do
begin
for i2 := 0 to DstMenu.Items.Count - 1 do
begin
if (SrcMenu.Items[i].Name = DstMenu.Items[i2].Name) and
(SrcMenu.Items[i].Count > 0) and (DstMenu.Items[i].Count > 0) then
begin
for i3 := 0 to SrcMenu.Items[i].Count - 1 do
begin
Menu := TMenuItem.Create(DstMenu.Owner);
// copy another properties if necessery
Menu.Name := SrcMenu.Items[i].Items[i3].Name;
Menu.Caption := SrcMenu.Items[i].Items[i3].Caption;
Menu.ShortCut := SrcMenu.Items[i].Items[i3].ShortCut;
Menu.OnClick := SrcMenu.Items[i].Items[i3].OnClick;
DstMenu.Items[i].Add(Menu);
end;
end;
end;
end;
end;
像这样在 MDIChildForm 的 OnCreate 事件中调用它:
procedure TMDIChild.FormCreate(Sender: TObject);
begin
MergeMenus(YourMainForm.MainMenu1, Self.MainMenu1);
end;
如果两个不同的 MainMenus 具有相同名称的 MenuItems,它将起作用。另请注意,如果您的 DstMenu 没有所有者(但我猜它有并且它是您的 MDICHildForm),则可能存在内存泄漏。
【讨论】:
手动合并是调用 FormMain.MainMenu.Merge(SubForm.MainMenu) 及其对应的 FormMain.MainMenu.UnMerge(SubForm.MainMenu)。
但您不应该需要它,因为如果您的表单的 FormStyles 正确设置为 fsMDIForm 和 fsMDIChild,那么菜单合并应该是自动的。
话虽如此,我不确定使用内置菜单合并是否可以实现您想要的。
根据 GroupIndex 帮助(和一些实验),子窗体中的菜单项用相同的 GroupIndex 替换主窗体上的项。只有当子窗体上的菜单项的 GroupIndex 落在主窗体上的 GroupIndex 值之间时,才会插入菜单。因此,子窗体上的文件菜单将始终替换主窗体上的文件菜单。仅当您给 File 菜单的不同 GroupIndex 值时,主窗体的 File 菜单才会保留,但是您有两个 File 菜单...
所以,我认为唯一的解决方案是手动插入和删除子窗体的菜单项,或者始终将它们放在主菜单上并根据活动的 MDIChild 启用/禁用它们。甚至可能显示/隐藏它们。
就我个人而言,我会选择让它们一直存在并根据活动的 MDIChild 启用/禁用它们,因为我不喜欢“反弹”(改变位置)的菜单项。
【讨论】: