这里只讲在 MDI 中,子菜单与父菜单合并的简单方法。

首先在 MDI 的主窗体中:

1. 在主窗体构造函数中,添加如下代码,注意要在 InitializeComponent 调用之后,如:

//Add File Menu

MenuItem miFile = mnuMain.MenuItems.Add("&File");

miFile.MergeOrder=1;

miFile.MergeType = MenuMerge.MergeItems;

MenuItem miAddDoc = new MenuItem( "&Add Document",

new EventHandler( this .FileAdd_Clicked),

Shortcut.CtrlA );

miAddDoc.MergeOrder=100;

MenuItem miExit = new MenuItem( "E&xit",

new EventHandler( this .FileExit_Clicked),

Shortcut.CtrlX );

miExit.MergeOrder=110;

miFile.MenuItems.Add(miAddDoc);

miFile.MenuItems.Add("-"); // Give a seperator

miFile.MenuItems.Add(miExit);

//Add Window Menu

MenuItem miWindow = mnuMain.MenuItems.Add("&Window");

miWindow.MergeOrder = 10;

miWindow.MenuItems.Add( "&Cascade",

new EventHandler( this .WindowCascade_Clicked));

miWindow.MenuItems.Add( "Tile &Horizontal",

new EventHandler( this .WindowTileH_Clicked));

miWindow.MenuItems.Add( "Tile &Vertical",

new EventHandler( this .WindowTileV_Clicked));

miWindow.MdiList = true ; //Adds the MDI Window List to the bottom of the menu

2. 然后为相应的 Menu_Click 事件定义函数,如:

#region MENU_CLICK_MESSAGE_HANDLE

//File->Add Menu item handler

protected void FileAdd_Clicked( object sender, System.EventArgs e)

{

AddMDIChild() ; //Create new MDI child window

}

//File->Exit Menu item handler

protected void FileExit_Clicked( object sender, System.EventArgs e)

{

this .Close();

}

//Window->Cascade Menu item handler

protected void WindowCascade_Clicked( object sender, System.EventArgs e)

{

this .LayoutMdi(MdiLayout.Cascade);

}

//Window->Tile Horizontally Menu item handler

protected void WindowTileH_Clicked( object sender, System.EventArgs e)

{

this .LayoutMdi(MdiLayout.TileHorizontal);

}

//Window->Tile Vertically Menu item handler

protected void WindowTileV_Clicked( object sender, System.EventArgs e)

{

this .LayoutMdi(MdiLayout.TileVertical);

}

#endregion {MENU_CLICK_MESSAGE_HANDLE}

3. 创建子窗体,如:

//Add a new child window if it doesn t exist; else set focus on it

private void AddMDIChild()

{

// MyChildForm is the one I'm looking for

MDIChild myMDIChild = null ;

foreach (Form f in this .MdiChildren)

{

if (f is MDIChild)

{

// found it

myMDIChild = (MDIChild) f;

break ;

}

}

if ( myMDIChild != null )

{

myMDIChild.Show();

myMDIChild.Focus();

}

else

{

myMDIChild = new MDIChild();

myMDIChild.MdiParent = this ;

myMDIChild.Show();

myMDIChild.Focus();

}

}

当完成上面的步骤后,主窗体运行的效果如下图所示:

然后在子窗体中,具体操作如下:

1. 在子窗体构造函数中,添加如下代码,同样要在 InitializeComponent 调用之后,如:

//Add File Menu

MenuItem miFile = mnuChildMain.MenuItems.Add("&File");

miFile.MergeType = MenuMerge.MergeItems;

miFile.MergeOrder = 1;

MenuItem miLoadDoc = miFile.MenuItems.Add( "&Load Document",

new EventHandler( this .LoadDocument_Clicked) );

miLoadDoc.MergeOrder = 105;

//Add Formatting Menu

MenuItem miFormat = mnuChildMain.MenuItems.Add("F&ormat");

miFormat.MergeType = MenuMerge.Add;

miFormat.MergeOrder = 5;

//Font Face sub-menu

miSansSerif = new MenuItem("&1." + sansSerifFontFamily.Name,

new EventHandler( this .FormatFont_Clicked));

miSerif = new MenuItem("&2." + serifFontFamily.Name,

new EventHandler( this .FormatFont_Clicked));

miMonoSpace = new MenuItem("&3." + monoSpaceFontFamily.Name,

new EventHandler( this .FormatFont_Clicked));

miSansSerif.Checked = true ;

miFormatFontChecked = miSansSerif ;

miSansSerif.DefaultItem = true ;

miFormat.MenuItems.Add( "Font &Face"

, ( new MenuItem[]{ miSansSerif, miSerif, miMonoSpace })

);

//Font Size sub-menu

miSmall = new MenuItem("&Small", new EventHandler( this .FormatSize_Clicked));

miMedium = new MenuItem("&Medium", new EventHandler( this .FormatSize_Clicked));

miLarge = new MenuItem("&Large", new EventHandler( this .FormatSize_Clicked));

miMedium.Checked = true ;

miMedium.DefaultItem = true ;

miFormatSizeChecked = miMedium ;

miFormat.MenuItems.Add( "Font &Size"

, ( new MenuItem[]{ miSmall, miMedium, miLarge })

);

2. 然后为相应的 Menu_Click 事件定义函数,如:

#region MENU_CLICK_MESSAGE_HANDLE

//File->Load Document Menu item handler

protected void LoadDocument_Clicked( object sender, System.EventArgs e)

{

MessageBox.Show( this .Text) ;

}

//Format->Font Menu item handler

protected void FormatFont_Clicked( object sender, System.EventArgs e)

{

MenuItem miClicked = (MenuItem)sender;

miClicked.Checked = true ;

miFormatFontChecked.Checked = false ;

miFormatFontChecked = miClicked ;

if (miClicked == miSansSerif)

{

currentFontFamily = sansSerifFontFamily ;

}

else if (miClicked == miSerif)

{

currentFontFamily = serifFontFamily ;

}

else

{

currentFontFamily = monoSpaceFontFamily ;

}

rtbDoc.Font = new Font(currentFontFamily, fontSize);

}

//Format->Size Menu item handler

protected void FormatSize_Clicked( object sender, System.EventArgs e)

{

MenuItem miClicked = (MenuItem)sender;

miClicked.Checked = true ;

miFormatSizeChecked.Checked = false ;

miFormatSizeChecked = miClicked;

if (miClicked == miSmall)

{

fontSize = FontSizes.Small ;

}

else if (miClicked == miLarge)

{

fontSize = FontSizes.Large ;

}

else

{

fontSize = FontSizes.Medium ;

}

rtbDoc.Font = new Font(currentFontFamily, fontSize);

}

#endregion {MENU_CLICK_MESSAGE_HANDLE}

3. 窗体的私有成员:

private struct FontSizes

{

public static float Small = 8f;

public static float Medium = 12f;

public static float Large = 24f;

}

private float fontSize = FontSizes.Medium;

private MenuItem miFormatFontChecked;

private MenuItem miFormatSizeChecked;

private MenuItem miSmall ;

private MenuItem miMedium ;

private MenuItem miLarge ;

private MenuItem miSansSerif ;

private MenuItem miSerif ;

private MenuItem miMonoSpace ;

private FontFamily currentFontFamily ;

private FontFamily monoSpaceFontFamily;

private FontFamily sansSerifFontFamily;

private System.Windows.Forms.MainMenu mnuChildMain;

private FontFamily serifFontFamily;

这样,子窗体的代码也完成了,展现的效果如下图所示:

其实在做 MDI 子窗体上的菜单要和主窗体上的菜单合并,主要是设置每个菜单的 MergeOrder ,对于每个菜单的 MergeOrder 设置不同的值,从而达到合并后的效果。以下用表格说明:

注:红色表示每个菜单的 MergeOrder

合并后的效果如下:

注:红色表示每个菜单的 MergeOrder

所以如果想在 MDI 子窗体上的菜单和主窗体上的菜单合并后,达到所预期的效果,就必须好好涉及它们之间的 MergeOrder ,大致如下:

1. 如果和主窗体原有的菜单列进行合并,首先把根菜单的 MergeOrder 设置与主窗体相应菜单一样的 MergeOrder 值,同时设置 MenuItem MergeType MenuMerge.MergeItems ,合并后在此列菜单中的位置,就看每个菜单的 MergeOrder 了。

2. 如果想在主窗体添加新的菜单列, MenuItem MergeType MenuMerge. Add ,菜单列插入的 位置,要看其 MergeOrder 了。