亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

在winform下實現左右布局多窗口界面的方法

2020-01-24 01:15:25
字體:
來源:轉載
供稿:網友

在web頁面上我們可以通過frameset,iframe嵌套框架很容易實現各種導航+內容的布局界面,而在winform、WPF中實現其實也很容易,我這里就分享一個:在winform下實現左右布局多窗口界面。

我這里說的多窗口是指一個父窗口包含多個子窗口,在winform中實現這種效果很簡單,即將某個窗口的IsMdiContainer設為true,然后將其它子窗口的MdiParent設為其父窗口對象即可,這樣就完成了一個多窗口界面,效果如下:


點擊NEW新打開一個窗口,其效果如下:


請看我上圖紅色標注的地方,Windows菜單項下面顯示的是當前所有已打開的子窗口,點擊某個菜單,即可快速切換到其它窗口,若關閉某個子窗口,與之相對應的菜單項也會自動被移除,實現這個功能也很簡單,只需要將菜單的MdiWindowListItem屬性設為需要顯示活動窗口列表的菜單項即可,如:this.menuStrip1.MdiWindowListItem = this.windowsToolStripMenuItem;

上述示例完整的實現代碼如下:

public partial class FormMdi : Form{private int formCount = 0;public FormMdi(){InitializeComponent();this.menuStrip1.MdiWindowListItem = this.windowsToolStripMenuItem;}private void newToolStripMenuItem_Click(object sender, EventArgs e){ShowChildForm<FormChild>();}private void ShowChildForm<TForm>() where TForm : Form, new(){TForm childForm = new TForm();childForm.Name = "frm" + Guid.NewGuid().ToString("N");childForm.Text = string.Format("Child Form -{0}", ++formCount);childForm.MdiParent = this;childForm.WindowState = FormWindowState.Maximized;childForm.Show();}}

相信實現上面這部份功能一般用過winform的人都會操作,我這里就當是復習順便給新手一個參考,同時也為下面要實現的左右布局功能做一個鋪墊吧。

要實現左右布局,并且能夠支持可動態調整左右占比的功能,非SplitContainer控件莫屬了,如果不了解該控件用法請自行在網上查找相關資料,我這里就不作說明,如果要顯示WINDOWS已打開的子窗口情況,同樣也需要用到MenuStrip控件,

最終設計的主窗口(FormMain)效果如下:


我這里因為只是演示,所以菜單控件上我只添加了兩個菜單項,分別為:WINDOWS,用于顯示WINDOWS已打開的子窗口列表,NEW,用于打開一個子窗口;SplitContainer控件全部采用默認的,沒有放置任何控件在其中,如果用在正式系統中,一般左邊Panel1中會放置一個樹形菜單,右邊Panel2中保持空即可,因為這個是用來作為子窗口的容器。

控件層次結構如下圖示:


界面設計好了,下面就實現最重要的兩個功能。

第一個功能:在右邊Panel2中顯示子窗口,實現代碼如下:

public FormMain(){this.IsMdiContainer = true;}private void ShowChildForm<TForm>() where TForm : Form, new(){TForm childForm = new TForm();childForm.Name = "frm" + Guid.NewGuid().ToString("N");childForm.Text = string.Format("Child Form -{0}", ++formCount);childForm.MdiParent = this;childForm.Parent = splitContainer1.Panel2;childForm.WindowState = FormWindowState.Maximized;childForm.Show();}

簡要說明:

1.在窗口構造函數中動態的將IsMdiContainer設為true,當然也可以設計視圖中設置;

2.編寫一個顯示寫子窗口的方法,方法中需注意的地方:childForm.MdiParent = this;childForm.Parent = splitContainer1.Panel2,意思是:將當前窗口作為子窗口的父窗口,同時將Panel2指定為子窗口的父對象,這樣就能實現子窗口在Panel2中打開了。

第二個功能:在WINDOWS菜單項下顯示已打開的子窗口列表,這里實現就沒有像文章一開始介紹的那樣簡單,使用那個方法是無效的,需要我們來自行實現,稍微有點復雜,但如果明白其實現原理,也就簡單明白了。

實現思路:當childForm加載到Panel2時,會觸發Panel2.ControlAdded事件,當childForm被關閉時,會觸發Panel2.ControlRemoved事件,我們可以統一訂閱這兩個事件,當childForm加載時,那么就在WINDOWS菜單項下增加一個菜單項,反之則移除該菜單項,實現代碼如下:

this.splitContainer1.Panel2.ControlAdded += Panel2_ControlChanged;this.splitContainer1.Panel2.ControlRemoved += Panel2_ControlChanged;void Panel2_ControlChanged(object sender, ControlEventArgs e){var frm = e.Control as Form;string menuName = "menu_" + frm.Name;bool exists = this.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 menuItems = windowsToolStripMenuItem.DropDownItems.Cast<ToolStripMenuItem>();menuItems.ToList().ForEach(m => m.Checked = false);return menuItems.Where(m => m.Name == menuName).SingleOrDefault();}

同時為了實現點擊WINDOWS菜單項的子菜單能夠快速切換子窗口,需要訂閱WINDOWS菜單項的DropDownItemClicked事件,當然也可以為新增的子菜單項訂閱Click事件,實現代碼如下:

windowsToolStripMenuItem.DropDownItemClicked += windowsToolStripMenuItem_DropDownItemClicked;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;}} 

這樣就基本實現了在WINDOWS菜單項下顯示已打開的子窗口列表,并點擊指定的菜單項能夠切換當前活動的子窗口,但仍有一個不足的地方,那就是,當直接點擊子窗口來切換當前活動窗口時(說白了就是當點擊某個子窗口標題欄,該窗口就顯示在其它所有的子窗口最前面),WINDOWS菜單項下的子菜單勾選項沒有同步更新,一開始想到的是用Activated事件來進行處理,結果經測試發現有效,該Activated事件在點擊子窗口標題欄時并不會被觸發,所以只能換種方法,經過多次測試,發現當窗口從后面切換到前面時(稱為Z順序改變),子窗口就會發生重繪,從而觸發Paint方法,我們可以訂閱該事件,并進行處理,實現代碼如下:

private string currentChildFormName = null; //記錄當前活動子窗口名稱childForm.Paint += (s, e) => { var frm=s as Form;if (!frm.Name.Equals(currentChildFormName) && this.splitContainer1.Panel2.Controls[0].Equals(frm)) //當容器中第一個控件就是當前的窗口,則表明該窗口處于所有窗口之上{CheckWindowsMenuItem("menu_" + frm.Name);currentChildFormName = frm.Name;}}; 

最后貼出完整的實現代碼:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace WindowsFormsApplication1{public partial class FormMain : Form{private int formCount = 0;private string currentChildFormName = null;public FormMain(){InitializeComponent();this.IsMdiContainer = true;this.splitContainer1.Panel2.ControlAdded += Panel2_ControlChanged;this.splitContainer1.Panel2.ControlRemoved += Panel2_ControlChanged;windowsToolStripMenuItem.DropDownItemClicked += windowsToolStripMenuItem_DropDownItemClicked;}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 FormMain_Load(object sender, EventArgs e){ShowChildForm<FormChild>();}private void ShowChildForm<TForm>() where TForm : Form, new(){TForm childForm = new TForm();childForm.Name = "frm" + Guid.NewGuid().ToString("N");childForm.Text = string.Format("Child Form -{0}", ++formCount);childForm.MdiParent = this;childForm.Parent = splitContainer1.Panel2;childForm.WindowState = FormWindowState.Maximized;childForm.Paint += (s, e) => { var frm=s as Form;if (!frm.Name.Equals(currentChildFormName) && this.splitContainer1.Panel2.Controls[0].Equals(frm)) //當容器中第一個控件就是當前的窗口,則表明該窗口處于所有窗口之上{CheckWindowsMenuItem("menu_" + frm.Name);currentChildFormName = frm.Name;}};childForm.Show();}private void CheckWindowsMenuItem(string menuName){var menuItem = GetMenuItem(menuName);if (menuItem != null){menuItem.Checked = true;}}void Panel2_ControlChanged(object sender, ControlEventArgs e){var frm = e.Control as Form;string menuName = "menu_" + frm.Name;bool exists = this.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 menuItems = windowsToolStripMenuItem.DropDownItems.Cast<ToolStripMenuItem>();menuItems.ToList().ForEach(m => m.Checked = false);return menuItems.Where(m => m.Name == menuName).SingleOrDefault();}private void newToolStripMenuItem_Click(object sender, EventArgs e){ShowChildForm<FormChild>();}}} 

以下是系統自動生成的代碼:

namespace WindowsFormsApplication1{partial class FormMain{/// <summary>/// 必需的設計器變量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的資源。/// </summary>/// <param name="disposing">如果應釋放托管資源,為 true;否則為 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗體設計器生成的代碼/// <summary>/// 設計器支持所需的方法 - 不要/// 使用代碼編輯器修改此方法的內容。/// </summary>private void InitializeComponent(){this.menuStrip1 = new System.Windows.Forms.MenuStrip();this.windowsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();this.splitContainer1 = new System.Windows.Forms.SplitContainer();this.menuStrip1.SuspendLayout();((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();this.splitContainer1.SuspendLayout();this.SuspendLayout();// // menuStrip1// this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.windowsToolStripMenuItem,this.newToolStripMenuItem});this.menuStrip1.Location = new System.Drawing.Point(0, 0);this.menuStrip1.MdiWindowListItem = this.windowsToolStripMenuItem;this.menuStrip1.Name = "menuStrip1";this.menuStrip1.Size = new System.Drawing.Size(1069, 25);this.menuStrip1.TabIndex = 1;this.menuStrip1.Text = "menuStrip1";// // windowsToolStripMenuItem// this.windowsToolStripMenuItem.Name = "windowsToolStripMenuItem";this.windowsToolStripMenuItem.Size = new System.Drawing.Size(73, 21);this.windowsToolStripMenuItem.Text = "Windows";this.windowsToolStripMenuItem.Click += new System.EventHandler(this.windowsToolStripMenuItem_Click);// // newToolStripMenuItem// this.newToolStripMenuItem.Name = "newToolStripMenuItem";this.newToolStripMenuItem.Size = new System.Drawing.Size(46, 21);this.newToolStripMenuItem.Text = "New";this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click);// // splitContainer1// this.splitContainer1.BackColor = System.Drawing.SystemColors.ActiveCaption;this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;this.splitContainer1.Location = new System.Drawing.Point(0, 25);this.splitContainer1.Name = "splitContainer1";// // splitContainer1.Panel2// this.splitContainer1.Panel2.BackColor = System.Drawing.SystemColors.ScrollBar;this.splitContainer1.Size = new System.Drawing.Size(1069, 526);this.splitContainer1.SplitterDistance = 356;this.splitContainer1.TabIndex = 2;// // FormMain// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1069, 551);this.Controls.Add(this.splitContainer1);this.Controls.Add(this.menuStrip1);this.MainMenuStrip = this.menuStrip1;this.Name = "FormMain";this.Text = "FormMain";this.Load += new System.EventHandler(this.FormMain_Load);this.menuStrip1.ResumeLayout(false);this.menuStrip1.PerformLayout();((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();this.splitContainer1.ResumeLayout(false);this.ResumeLayout(false);this.PerformLayout();}#endregionprivate System.Windows.Forms.MenuStrip menuStrip1;private System.Windows.Forms.ToolStripMenuItem windowsToolStripMenuItem;private System.Windows.Forms.SplitContainer splitContainer1;private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;}}

以下是效果演示截圖:

以上內容給大家分享了在winform下實現左右布局多窗口界面的方法,有什么更好的實現方法可以在下方評論,不足之處也歡迎指出,謝謝!下面將給大家介紹在winform下實現左右布局多窗口界面的方法之續篇,感興趣的朋友繼續關注。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本欧美精品在线| 91精品中国老女人| 欧美裸体xxxxx| 在线日韩欧美视频| 国产精品国产亚洲伊人久久| 久久全球大尺度高清视频| 色伦专区97中文字幕| 欧美乱大交xxxxx另类电影| 国产在线播放不卡| 国产日韩欧美91| 成人中文字幕+乱码+中文字幕| 亚洲欧美在线第一页| 最新69国产成人精品视频免费| 51精品国产黑色丝袜高跟鞋| 日韩欧美黄色动漫| 欧美视频在线视频| 欧美在线视频观看免费网站| 国产aⅴ夜夜欢一区二区三区| 日韩免费在线视频| 青青草一区二区| 91豆花精品一区| 91精品国产91久久久久久最新| 久久国产精品影片| 黑人巨大精品欧美一区二区一视频| 日韩人体视频一二区| 亚洲一区久久久| 亚洲美女又黄又爽在线观看| 欧美成人激情视频| 国产成人在线精品| 久久亚洲国产精品成人av秋霞| 欧美肥老妇视频| 97在线免费观看视频| 91国语精品自产拍在线观看性色| 亚洲精品欧美日韩专区| 精品网站999www| 国产在线a不卡| 欧美xxxx18性欧美| 91九色单男在线观看| 日韩成人xxxx| 日韩av在线网页| 91性高湖久久久久久久久_久久99| 97久久久免费福利网址| 国产精品久久久999| 日韩在线视频导航| 欧洲亚洲免费在线| 久久国产精品电影| 久久频这里精品99香蕉| 成人黄色免费网站在线观看| 国产福利视频一区二区| 88国产精品欧美一区二区三区| 97超级碰碰碰| 中文字幕在线看视频国产欧美在线看完整| 亚洲第一区中文字幕| 日韩经典中文字幕| 欧美疯狂做受xxxx高潮| 国产精品一区二区性色av| 欧美成人午夜激情在线| 日韩色av导航| 亚洲va久久久噜噜噜久久天堂| 亚洲一区二区三区777| 懂色av中文一区二区三区天美| 久久成人av网站| 久久躁狠狠躁夜夜爽| 国产伊人精品在线| 精品国产31久久久久久| 国产成人免费91av在线| 91久久综合亚洲鲁鲁五月天| 欧美第一黄网免费网站| 国产精品久久久久久久av电影| 国产精品爱啪在线线免费观看| 91av在线影院| 日韩av影院在线观看| 亚洲国产精久久久久久| 欧美专区福利在线| 日韩欧美在线一区| 日韩精品在线观看视频| 91精品啪aⅴ在线观看国产| 欧美一区二区大胆人体摄影专业网站| 国产精品爱久久久久久久| 国产精品久久久久免费a∨| 亚洲女在线观看| 欧美有码在线观看| 国产一区二区视频在线观看| 久久激情五月丁香伊人| 亚洲欧美成人在线| 亚洲综合精品一区二区| 成人福利视频在线观看| 国产精品91免费在线| 色综合天天综合网国产成人网| 日韩第一页在线| 日本精品一区二区三区在线| 国产精品jizz在线观看麻豆| 久久久久久久国产| 精品久久久久久国产| 一区二区在线视频| 亚洲香蕉av在线一区二区三区| 国产成人精品999| 亚洲自拍偷拍区| 91精品国产91久久久久| 久久久精品视频在线观看| 欧美电影免费在线观看| 91免费版网站入口| 亚洲精品国产欧美| 国产精品狼人色视频一区| 中文字幕欧美视频在线| 成人黄色大片在线免费观看| 夜色77av精品影院| 色哟哟网站入口亚洲精品| 91老司机精品视频| 全色精品综合影院| 欧美伊久线香蕉线新在线| 亚洲最新在线视频| 亚洲精品视频久久| 成人国产精品一区二区| 亚洲美女视频网站| 久久精品视频在线播放| 久久久久久高潮国产精品视| 国产精品成人久久久久| 在线观看成人黄色| 97精品国产aⅴ7777| 国产精品福利在线观看| 揄拍成人国产精品视频| 日韩一区二区欧美| 亚洲精品99久久久久| 国产一区红桃视频| 81精品国产乱码久久久久久| 色噜噜亚洲精品中文字幕| 欧美激情久久久久久| 日韩精品在线视频美女| 久久久国产精品视频| 国语自产偷拍精品视频偷| 久久国产精彩视频| 一区二区三区国产视频| 一区二区三区视频免费在线观看| 国产一区二区三区在线观看网站| 亚洲视频在线观看视频| 亚洲毛片在线观看| 91产国在线观看动作片喷水| 日韩美女视频免费看| 992tv成人免费视频| 日韩在线播放一区| 欧美久久精品一级黑人c片| 大量国产精品视频| 精品国产一区av| 91国自产精品中文字幕亚洲| 国产亚洲一区精品| 国产精品久久久久久久app| 欧美美女操人视频| 国产99久久精品一区二区 夜夜躁日日躁| 国内精品久久久久| 78m国产成人精品视频| 日韩禁在线播放| www.久久草.com| 亚洲欧美一区二区精品久久久| 亚洲图片在区色| 精品美女久久久久久免费| 国内免费久久久久久久久久久| 久久久人成影片一区二区三区观看| 欧美日韩国产在线播放| 欧美国产中文字幕| 欧美视频中文字幕在线| 国产婷婷97碰碰久久人人蜜臀| 久久久久国产精品免费网站| 日韩视频精品在线|