如何在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 | ||
File(1) |
Window(10) |
File(1) |
Format(5) |
AddDocument( 100) |
|
Load Document(105) |
|
Exit(110) |
|
|
|
注:红色表示每个菜单的MergeOrder值
合并后的效果如下:
合并后的菜单 | ||
File(1) |
Format(5) |
Window(10) |
AddDocument( 100) |
|
|
Load Document(105) |
|
|
Exit(110) |
|
|
注:红色表示每个菜单的MergeOrder值
所以如果想在MDI子窗体上的菜单和主窗体上的菜单合并后,达到所预期的效果,就必须好好涉及它们之间的MergeOrder,大致如下:
1. 如果和主窗体原有的菜单列进行合并,首先把根菜单的MergeOrder设置与主窗体相应菜单一样的MergeOrder值,同时设置MenuItem的MergeType为MenuMerge.MergeItems,合并后在此列菜单中的位置,就看每个菜单的MergeOrder了。
2. 如果想在主窗体添加新的菜单列,MenuItem的MergeType为MenuMerge. Add,菜单列插入的位置,要看其MergeOrder了。