原理:MDI窗口有一个叫MdiClient的窗口对象作为主背景窗口,要修改MDI窗口的背景就是修改该MdiClient对象的背景
一个MDI应用的主框架窗口包含一个特殊的子窗口称为MDICLIENT窗口。MDICLIENT窗口负责管理主框架窗口的客户区。
MDICLIENT窗口本身有自己的子窗口即由CMDIChildWnd派生的文档窗口,也就是MDI子窗口。
MDI主框架窗口负责管理MDICLIENT子窗口。当控制条(菜单条,状态条等)发生变化时,MDI主框架窗口重新配置MDICLIENT窗口。
MDICLIENT子窗口负责管理全部的MDI子窗口。父窗口负责将某些命令传递到子窗口。
因此,消息队列发向MDI子窗口的消息由MDICLIENT窗口负责传递,发向MDICLIENT窗口和MDI子窗口的消息由主框架窗口负责传递。
这样,我们可以在主框架窗口截获关于MDICLIENT窗口的重画消息然后加入自己设计的代码。
对MDI客户窗口编程有一定的难度。原因是MDIFrameWnd的客户区完全被MDICLIENT窗口覆盖掉了。
这样,MDI主窗口类MDIFrameWnd的背景色和光标都不起作用。
同时,微软并不支持将MDICLIENT窗口作为子类,MDICLIENT窗口只能使用标准的背景色和光标。
方法:MdiClient是作为MDI窗口的一个ChildControl的形式存在的,因此我们可以通过遍历MDI窗口的Controls对象集来获得
步骤:
1、在Properties/Resources.resx中添加名称为"bj"的背景图片
2、在Main方法中添加BackgroundNoSplash();
public Main()
{
InitializeComponent();
//给MDI 父窗体添加背景和解决闪烁的问题
BackgroundNoSplash();
}
以下代码复制到MDI主窗体代码中
// 主窗体背景设置
MdiClient mdiClient = new MdiClient(); //结合上面的说明来看:定义一个MdiClient
string webMessage="原理:MDI窗口有一个叫MdiClient的窗口对象作为主背景窗口,要修改MDI窗口的背景就是修改该MdiClient对象的背景。一个MDI 应用的主框架窗口包含一个特殊的子窗口称为MDICLIENT窗口。";
//一个在主窗体上显示的通知消息文本
private void BackgroundNoSplash()
{
foreach (Control var in this.Controls) //遍历控件集合
{
if (var is MdiClient) //找到MdiClient控件
{
mdiClient = var as MdiClient;//把Control类型的var转换为MdiClient类型
break;//一旦找到MdiClient就跳出循环
}
}
if (mdiClient != null)
{
mdiClient.Paint += new PaintEventHandler(OnMdiClientPaint);//调用OnMdiClientPaint事件
System.Reflection.MethodInfo mi = (mdiClient as Control).GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
mi.Invoke(mdiClient, new object[] { ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer
| ControlStyles.ResizeRedraw, true });
//双缓冲解决闪烁
}
}
private void OnMdiClientPaint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(Properties.Resources.bj, new Rectangle(0, 0, mdiClient.Width, mdiClient.Height));//绘制image,图片是资源里的bj,并指定位置和高宽
//绘制右下角的版本号文本,如果你不需要可以删除
string ver = "版本:1.0.0.2";
SizeF sizef = e.Graphics.MeasureString(ver, this.Font);//计算绘制ver文本所需的大小
g.DrawString(ver, this.Font, new SolidBrush(Color.White), mdiClient.Width - sizef.Width-2, mdiClient.Height - sizef.Height-2);
//绘制通知信息,如果你不需要可以删除,这里显示的文本,可以自动换行
SizeF size = e.Graphics.MeasureString(webMessage, this.Font, mdiClient.Width);//计算绘制webMessage文本所需的大小,并定义窗口的宽度为绘制的最大宽度
RectangleF rf = new RectangleF(10, 10, size.Width, size.Height);//实例化一个矩形框,宽度为窗口宽度稍小点
// g.DrawRectangle(Pens.Red, rf.Left, rf.Top, rf.Width, rf.Height);
g.DrawString(webMessage, this.Font, Brushes.White, rf);//在矩形框里绘制文本
}