WinFormsUI(转xiaisidinen)

DockPanel Suite使用非常简单,它主要含有两个类DockContent和DockPanel。

DockContent是可停靠式选项卡的基类,所有可停靠的选项卡控件都必须基础自它。它是Form的子类,也就是说,可停靠的选项卡是一个个单独的窗体。

DockPanel继承自Panel,是可停靠选项卡的容器。

下面将以一个简单的多文档编辑器为例,介绍如何使用DockPanel Suite库。

新建一个WinForm的项目,加入WinFormsUI的引用 
创建主窗口,将主窗口的IsMdiContainer属性设置为true。在主窗口中加置一个DockPanel控件,并设置其Dock属性为DockStyle.Fill。 
创建文档编辑器选项卡窗口TextForm(本例中的文档编辑器窗口中只有一个简单的textbox),将TextForm的基类有Form修改为DockContent。 
在主窗口中添加File菜单,并添加new命令。 
        int count = 1;
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TextForm t = new TextForm();
            t.Text = "文档" + count++;
            t.Show(dockPanel1);
        }

运行效果如下,是不是比较酷?

可能细心的读者已经看出来以上程序的一些不足的地方:

选项卡的标题都是"TextForm",而不是我在代码中预期的"文档1"、"文档2"的形式。 
选项卡过于灵活(文档选项卡可以被拖动到任意地方),这往往是我们需要限制的,比如说工具选项卡是不希望能拖到屏幕中央的,而文档选项卡是不希望拖到屏幕的四周而能自动隐藏的。 
这些问题是很容易解决的,当选项卡继承自DockContent后,在属性设置中就会多出Docking选项,如下图所示。通过这些属性的设置,可以灵活的定制我们的选项卡。

对于问题1,需要把TabText属性设置为null,这样选项的标题就会随着Text属性而改变了。对于问题2,只要设置其合适的DockAreas即可。

另外值得一提的是,可停靠式选项卡和主窗口是一种父窗口和mdi窗口间的关系,因此mdi窗口的那些特性(如获取活动选项卡、选项卡菜单和主窗口菜单合并等)也可以用在这里,这里就不多介绍了。

最后介绍一下选项卡的位置的保存和恢复。

选项卡的位置的保存和恢复可以通过DockPanel的SaveAsXml函数和LoadFromXml函数实现,这两个函数使用非常简单,参看一下控件中的例子很容易使用。如果选项卡需要自定义序列化数据,只需要覆盖GetPersistString函数即可。

试用了一段时间这个库后,总体感觉是美观、大方、强大、简单易用。这些都是非常难得的。就是在选项卡较多的时候,改变窗口大小不是很流畅。当然,这个和.net的winform控件本身不如c++效率高有关(不过在我用过的.net停靠控件中效率也算一流的)。希望今后能看到更多或开发像这样的.net精品项目。

一些小改进:

1、当双击Tab时,原先是直接把当前Tab所表示的这个窗体,从主窗体的框架上分离现来,成为一个浮动的窗体。这不是我想要的,我把它改成了双击关闭。
在DockPaneStripBase的WndProc方法里,对于左键双击消息重新作了处理(下面注释掉的一行是原先的写法,它下面那行是改的):

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == (int)Win32.Msgs.WM_LBUTTONDBLCLK)
            {
                base.WndProc(ref m);

                int index = HitTest();
                if (DockPane.DockPanel.AllowEndUserDocking && index != -1)
                {
                    IDockContent content = Tabs[index].Content;
                    if (content.DockHandler.CheckDockState(!content.DockHandler.IsFloat) != DockState.Unknown)
                        //content.DockHandler.IsFloat = !content.DockHandler.IsFloat; 
                        content.DockHandler.Close();
                }

                return;
            }

            base.WndProc(ref m);
            return;
        }

2、很多窗体都在Tab中有个右键菜单,右击的里面有关闭,所以最好继承一下DockContent,让其它窗体只要继承这个就有了这个右键菜单

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WeifenLuo.WinFormsUI.Docking
{
    public class DockContentEx : WeifenLuo.WinFormsUI.Docking.DockContent
    {
        public DockContentEx()
        {
            ContextMenuStrip cms = new System.Windows.Forms.ContextMenuStrip();
            ToolStripMenuItem tsmiClose = new System.Windows.Forms.ToolStripMenuItem();
            // 
            // cms
            // 
            tsmiClose.Name = "cms";
            tsmiClose.Size = new System.Drawing.Size(98, 22);
            tsmiClose.Text = "关闭";
            tsmiClose.Click += new System.EventHandler(this.tsmiClose_Click);
            // 
            // tsmiClose
            // 
            cms.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            tsmiClose});
            cms.Name = "tsmiClose";
            cms.Size = new System.Drawing.Size(99, 26);

            this.TabPageContextMenuStrip = cms;
        }

        private void tsmiClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}


posted @ 2009-08-12 23:07  好俊的功夫啊  阅读(993)  评论(0编辑  收藏  举报