在winform下實(shí)現(xiàn)左右布局多窗口界面的方法
在web頁(yè)面上我們可以通過(guò)frameset,iframe嵌套框架很容易實(shí)現(xiàn)各種導(dǎo)航+內(nèi)容的布局界面,而在winform、WPF中實(shí)現(xiàn)其實(shí)也很容易,我這里就分享一個(gè):在winform下實(shí)現(xiàn)左右布局多窗口界面。
我這里說(shuō)的多窗口是指一個(gè)父窗口包含多個(gè)子窗口,在winform中實(shí)現(xiàn)這種效果很簡(jiǎn)單,即將某個(gè)窗口的IsMdiContainer設(shè)為true,然后將其它子窗口的MdiParent設(shè)為其父窗口對(duì)象即可,這樣就完成了一個(gè)多窗口界面,效果如下:
點(diǎn)擊NEW新打開(kāi)一個(gè)窗口,其效果如下:
請(qǐng)看我上圖紅色標(biāo)注的地方,Windows菜單項(xiàng)下面顯示的是當(dāng)前所有已打開(kāi)的子窗口,點(diǎn)擊某個(gè)菜單,即可快速切換到其它窗口,若關(guān)閉某個(gè)子窗口,與之相對(duì)應(yīng)的菜單項(xiàng)也會(huì)自動(dòng)被移除,實(shí)現(xiàn)這個(gè)功能也很簡(jiǎn)單,只需要將菜單的MdiWindowListItem屬性設(shè)為需要顯示活動(dòng)窗口列表的菜單項(xiàng)即可,如:this.menuStrip1.MdiWindowListItem = this.windowsToolStripMenuItem;
上述示例完整的實(shí)現(xiàn)代碼如下:
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();
}
}
相信實(shí)現(xiàn)上面這部份功能一般用過(guò)winform的人都會(huì)操作,我這里就當(dāng)是復(fù)習(xí)順便給新手一個(gè)參考,同時(shí)也為下面要實(shí)現(xiàn)的左右布局功能做一個(gè)鋪墊吧。
要實(shí)現(xiàn)左右布局,并且能夠支持可動(dòng)態(tài)調(diào)整左右占比的功能,非SplitContainer控件莫屬了,如果不了解該控件用法請(qǐng)自行在網(wǎng)上查找相關(guān)資料,我這里就不作說(shuō)明,如果要顯示W(wǎng)INDOWS已打開(kāi)的子窗口情況,同樣也需要用到MenuStrip控件,
最終設(shè)計(jì)的主窗口(FormMain)效果如下:
我這里因?yàn)橹皇茄菔荆圆藛慰丶衔抑惶砑恿藘蓚€(gè)菜單項(xiàng),分別為:WINDOWS,用于顯示W(wǎng)INDOWS已打開(kāi)的子窗口列表,NEW,用于打開(kāi)一個(gè)子窗口;SplitContainer控件全部采用默認(rèn)的,沒(méi)有放置任何控件在其中,如果用在正式系統(tǒng)中,一般左邊Panel1中會(huì)放置一個(gè)樹(shù)形菜單,右邊Panel2中保持空即可,因?yàn)檫@個(gè)是用來(lái)作為子窗口的容器。
控件層次結(jié)構(gòu)如下圖示:
界面設(shè)計(jì)好了,下面就實(shí)現(xiàn)最重要的兩個(gè)功能。
第一個(gè)功能:在右邊Panel2中顯示子窗口,實(shí)現(xiàn)代碼如下:
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();
}
簡(jiǎn)要說(shuō)明:
1.在窗口構(gòu)造函數(shù)中動(dòng)態(tài)的將IsMdiContainer設(shè)為true,當(dāng)然也可以設(shè)計(jì)視圖中設(shè)置;
2.編寫一個(gè)顯示寫子窗口的方法,方法中需注意的地方:childForm.MdiParent = this;childForm.Parent = splitContainer1.Panel2,意思是:將當(dāng)前窗口作為子窗口的父窗口,同時(shí)將Panel2指定為子窗口的父對(duì)象,這樣就能實(shí)現(xiàn)子窗口在Panel2中打開(kāi)了。
第二個(gè)功能:在WINDOWS菜單項(xiàng)下顯示已打開(kāi)的子窗口列表,這里實(shí)現(xiàn)就沒(méi)有像文章一開(kāi)始介紹的那樣簡(jiǎn)單,使用那個(gè)方法是無(wú)效的,需要我們來(lái)自行實(shí)現(xiàn),稍微有點(diǎn)復(fù)雜,但如果明白其實(shí)現(xiàn)原理,也就簡(jiǎn)單明白了。
實(shí)現(xiàn)思路:當(dāng)childForm加載到Panel2時(shí),會(huì)觸發(fā)Panel2.ControlAdded事件,當(dāng)childForm被關(guān)閉時(shí),會(huì)觸發(fā)Panel2.ControlRemoved事件,我們可以統(tǒng)一訂閱這兩個(gè)事件,當(dāng)childForm加載時(shí),那么就在WINDOWS菜單項(xiàng)下增加一個(gè)菜單項(xiàng),反之則移除該菜單項(xiàng),實(shí)現(xiàn)代碼如下:
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();
}
同時(shí)為了實(shí)現(xiàn)點(diǎn)擊WINDOWS菜單項(xiàng)的子菜單能夠快速切換子窗口,需要訂閱WINDOWS菜單項(xiàng)的DropDownItemClicked事件,當(dāng)然也可以為新增的子菜單項(xiàng)訂閱Click事件,實(shí)現(xiàn)代碼如下:
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;
}
}
這樣就基本實(shí)現(xiàn)了在WINDOWS菜單項(xiàng)下顯示已打開(kāi)的子窗口列表,并點(diǎn)擊指定的菜單項(xiàng)能夠切換當(dāng)前活動(dòng)的子窗口,但仍有一個(gè)不足的地方,那就是,當(dāng)直接點(diǎn)擊子窗口來(lái)切換當(dāng)前活動(dòng)窗口時(shí)(說(shuō)白了就是當(dāng)點(diǎn)擊某個(gè)子窗口標(biāo)題欄,該窗口就顯示在其它所有的子窗口最前面),WINDOWS菜單項(xiàng)下的子菜單勾選項(xiàng)沒(méi)有同步更新,一開(kāi)始想到的是用Activated事件來(lái)進(jìn)行處理,結(jié)果經(jīng)測(cè)試發(fā)現(xiàn)有效,該Activated事件在點(diǎn)擊子窗口標(biāo)題欄時(shí)并不會(huì)被觸發(fā),所以只能換種方法,經(jīng)過(guò)多次測(cè)試,發(fā)現(xiàn)當(dāng)窗口從后面切換到前面時(shí)(稱為Z順序改變),子窗口就會(huì)發(fā)生重繪,從而觸發(fā)Paint方法,我們可以訂閱該事件,并進(jìn)行處理,實(shí)現(xiàn)代碼如下:
private string currentChildFormName = null; //記錄當(dāng)前活動(dòng)子窗口名稱
childForm.Paint += (s, e) => {
var frm=s as Form;
if (!frm.Name.Equals(currentChildFormName) && this.splitContainer1.Panel2.Controls[0].Equals(frm)) //當(dāng)容器中第一個(gè)控件就是當(dāng)前的窗口,則表明該窗口處于所有窗口之上
{
CheckWindowsMenuItem("menu_" + frm.Name);
currentChildFormName = frm.Name;
}
};
最后貼出完整的實(shí)現(xiàn)代碼:
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)) //當(dāng)容器中第一個(gè)控件就是當(dāng)前的窗口,則表明該窗口處于所有窗口之上
{
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>();
}
}
}
以下是系統(tǒng)自動(dòng)生成的代碼:
namespace WindowsFormsApplication1
{
partial class FormMain
{
/// <summary>
/// 必需的設(shè)計(jì)器變量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的資源。
/// </summary>
/// <param name="disposing">如果應(yīng)釋放托管資源,為 true;否則為 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗體設(shè)計(jì)器生成的代碼
/// <summary>
/// 設(shè)計(jì)器支持所需的方法 - 不要
/// 使用代碼編輯器修改此方法的內(nèi)容。
/// </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();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem windowsToolStripMenuItem;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;
}
}
以下是效果演示截圖:
以上內(nèi)容給大家分享了在winform下實(shí)現(xiàn)左右布局多窗口界面的方法,有什么更好的實(shí)現(xiàn)方法可以在下方評(píng)論,不足之處也歡迎指出,謝謝!下面將給大家介紹在winform下實(shí)現(xiàn)左右布局多窗口界面的方法之續(xù)篇,感興趣的朋友繼續(xù)關(guān)注。
上一篇:C#讀寫指定編碼格式的文本文件
欄 目:C#教程
本文標(biāo)題:在winform下實(shí)現(xiàn)左右布局多窗口界面的方法
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/6658.html
您可能感興趣的文章
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新聞效果的方法
- 01-10C#實(shí)現(xiàn)多線程下載文件的方法
- 01-10C#實(shí)現(xiàn)Winform中打開(kāi)網(wǎng)頁(yè)頁(yè)面的方法
- 01-10winform實(shí)現(xiàn)創(chuàng)建最前端窗體的方法
- 01-10WinForm實(shí)現(xiàn)自定義右下角提示效果的方法
- 01-10.net2.0+ Winform項(xiàng)目實(shí)現(xiàn)彈出容器層
- 01-10winform 實(shí)現(xiàn)控制輸入法
- 01-10C#實(shí)現(xiàn)將窗體固定在顯示器的左上角且不能移動(dòng)的方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載


