Web 應用常用 `
public partial class FormMdi : Form { private int _formCount = 0; public FormMdi() { InitializeComponent(); // 關鍵:將 Windows 選單項指派給 MdiWindowListItem,自動管理子視窗列表 menuStrip1.MdiWindowListItem = windowsToolStripMenuItem; } private void newToolStripMenuItem_Click(object sender, EventArgs e) { ShowChildForm<FormChild>(); } private void ShowChildForm<TForm>() where TForm : Form, new() { var child = new TForm { Name = "frm" + Guid.NewGuid().ToString("N"), Text = $"Child Form - {++_formCount}", MdiParent = this, WindowState = FormWindowState.Maximized }; child.Show(); } }
關鍵在於設定子視窗的 `Parent` 屬性為 `splitContainer1.Panel2`:
public partial class FormMain : Form { private int _formCount = 0; private string _activeChildName; public FormMain() { InitializeComponent(); IsMdiContainer = true; // 訂閱 Panel2 控制項增減事件,動態維護 Windows 選單 splitContainer1.Panel2.ControlAdded += Panel2_ControlChanged; splitContainer1.Panel2.ControlRemoved += Panel2_ControlChanged; windowsToolStripMenuItem.DropDownItemClicked += WindowsToolStripMenuItem_DropDownItemClicked; } private void ShowChildForm<TForm>() where TForm : Form, new() { var child = new TForm { Name = "frm" + Guid.NewGuid().ToString("N"), Text = $"Child Form - {++_formCount}", MdiParent = this, Parent = splitContainer1.Panel2, // **核心:限制在 Panel2 顯示** WindowState = FormWindowState.Maximized }; // 監聽 Paint 事件,同步 Windows 選單勾選狀態(解決點擊標題列切換未同步問題) child.Paint += (s, e) => { var frm = s as Form; if (frm != null && !frm.Name.Equals(_activeChildName) && splitContainer1.Panel2.Controls[0].Equals(frm)) { CheckWindowsMenuItem("menu_" + frm.Name); _activeChildName = frm.Name; } }; child.Show(); } // ... 事件處理方法見下文 }
private void Panel2_ControlChanged(object sender, ControlEventArgs e) { var frm = e.Control as Form; if (frm == null) return; string menuName = "menu_" + frm.Name; bool exists = splitContainer1.Panel2.Controls.Contains(frm); if (exists) // 子視窗新增 { var menuItem = GetMenuItem(menuName); if (menuItem != null) { menuItem.Checked = true; frm.BringToFront(); frm.Focus(); } else { windowsToolStripMenuItem.DropDownItems.Add(new ToolStripMenuItem { Text = frm.Text, Name = menuName, Tag = frm, Checked = true }); } } else // 子視窗關閉 { var menuItem = GetMenuItem(menuName); if (menuItem != null) { windowsToolStripMenuItem.DropDownItems.Remove(menuItem); menuItem.Dispose(); } } } private ToolStripMenuItem GetMenuItem(string menuName) { var items = windowsToolStripMenuItem.DropDownItems.Cast<ToolStripMenuItem>(); items.ToList().ForEach(m => m.Checked = false); // 取消其他勾選 return items.Where(m => m.Name == menuName).SingleOrDefault(); }
private void WindowsToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) { var menuItem = GetMenuItem(e.ClickedItem.Name); menuItem.Checked = true; var childForm = menuItem.Tag as Form; childForm?.BringToFront(); childForm?.Focus(); } private void CheckWindowsMenuItem(string menuName) { var menuItem = GetMenuItem(menuName); if (menuItem != null) menuItem.Checked = true; }
完整代碼包含:
(完整代碼較長,核心邏輯已在上文展示,專案中可直接複製調適。)
與標準 MDI 差異:
結合 `IsMdiContainer`、`SplitContainer`、動態事件訂閱,即可構建專業級左右分欄 MDI 界面。核心在於:
此架構清晰、擴展性強,是 WinForms 桌面應用的經典選擇。
回顧經典網遊奇跡 MU,其超酷絢麗魔法效果曾打動無數玩家。本
3.1 圖形裝置介面(GDI)架構 第二章已初步使用圖形裝置
C 語言處理 Excel 轉 JSON 實戰 工作中常需將
前言:為什麼選擇 Ice? Ice (Internet Co