本文的示例代码为可以从这里下载 
  
1           概述 

微软Visual Studio.NET开发工具推出已经好几年了,这个开发工具一推出就以其易用性和强大功能深受开发者的喜爱。尤其是.NET环境使得不同开发语言如C#、VB.NET以及C++.NET之间的交互变得非常容易。因此涌现了许多在.NET下开发的控件库,可以供不同的开发语言调用。MagicLibrary就是其中比较优秀的一个用于界面设计的控件库,可以用来开发类似.Net Studio这样具有停靠窗口风格的界面。该库的源代码及使用说明可以从http://www.codeproject.com/cs/miscctrl/magicdocking.asp 下载,感兴趣的读者还可以通过研究该源代码学习其实现原理。 

下图是用该库开发的一个示例界面: 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_控件


 

图1 示例界面 

2           实现方法 

下面介绍该示例的实现步骤 

2.1          安装MagicLibrary 

从网上下载MagicLibrary,安装后得到几个目录,分别是帮助文件目录,程序文件目录,源代码目录。程序的开发和以后分发过程中唯一需要的是程序文件目录下的MagicLibrary.dll文件。 

2.2          生成解决方案 

l          在.Net Studio中生成解决方案MagicStudio,工程类型是Visual C#,Windows应用程序。 

l          在MagicStudio解决方案的引用中加入MagicLibrary.dll库(图 1-1) 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_控件_02


 

图 1-1 在工程中添加引用 

l          添加控件到工具箱 

在工具面板上添加MagicLibrary的控件,如图1-2,在工具箱面板上右键单击,选择弹出菜单中的“添加/移除项”,然后在弹出的窗口中点击“浏览”按纽,选取MagicLibrary.dll文件,确定后会在工具箱面板上出现几个新的控件,如图1-3所示。 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_visual studio_03

                                       

开发Visual Studio风格的用户界面--MagicLibrary使用指南_ui_04


                        

图1-2 在工具面板上添加控件                             图1-3 工具面板上的新控件 

l          添加TabControl控件 

将解决方案MagicStudio的主窗口命名为MainForm,然后将工具面板上新增的TabControl控件拖到主窗口上,如下图所示 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_ide_05

图1-4 解决方案MagicStudio的主窗口MainForm 

l          添加子窗口 

生成WinForm的“解决方案资源管理器”窗口、“类视图”窗口、“代码编辑”窗口,如下图所示 

  

开发Visual Studio风格的用户界面--MagicLibrary使用指南_visual studio_06

                                  

开发Visual Studio风格的用户界面--MagicLibrary使用指南_控件_07

                   图1-5 解决方案资源管理器窗口             图1-6 类视图窗口 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_ide_08

图1-7 代码编辑窗口 

2.3          编辑MagicStudio主窗口MainForm所在的文件MagicStudio.cs的程序代码 

l          加入using语句 

using Crownwood.Magic.Common; 

using Crownwood.Magic.Docking; 

l          MagicStudio主窗口MainForm类里定义DockingManager对象: 

     private DockingManager dockManager; 

l          在MainForm的构造函数里添加初始化代码 

DockingManager的数据成员OuterControl,InnerControl用来决定DockingManager所在的窗口上哪些区域不受到DockingManager停靠窗口的影响 

Docking Manager不会影响在OuterControl对象以后加入主窗口的对象的窗口区域 

Docking Manager也不会影响在InnerControl对象以前加入主窗口的对象的窗口区域 

例如: 

              在InitailizeComponet()中,下面的语句决定了将主窗口上的控件加入主窗口时的顺序 

              this.Controls.Add(this.centerPanel); 

              this.Controls.Add(this.statusBar); 

              this.Controls.Add(this.toolBar1); 

dockManager.OuterControl=statusBar; 

dockManager.InnerControl=centerPanel; 

上面代码决定了在centerPanel(包括centerPanel)以前加入的控件和在statusBar(包括statursBar)后面加入的控件的显示区域不受到dockManager停靠窗口的影响 

如果是 

              this.Controls.Add(this.centerPanel); 

              this.Controls.Add(this.toolBar1); 

              this.Controls.Add(this.statusBar); 

dockManager.OuterControl=statusBar; 

dockManager.InnerControl=centerPanel 

则程序实际运行的结果如图,停靠窗口和工具栏在一个高度上,可见toolBar1的显示区域受到了DockManager停靠窗口的影响 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_停靠窗口_09

图2 控件顺序对界面效果的影响 

l          生成停靠窗口 

要在主窗口的四周生成可以伸缩的停靠窗口,需要先生成两个Content对象,然后把“解决方案资源管理器”窗口和“类视图”窗口各用一个Content对象包装起来,把Content对象停靠在DockManager对象管理的WindowContent上。WindowContent自动管理窗口停靠。代码如下: 

//生成用来包装窗口的Content 
Content solutionExplorerContent=new Content(dockManager); 
 //用Content对象包装要管理的窗口 
solutionExplorerContent.Control=new SolutionExplorer(); 
 //设置停靠窗口属性 
//获取"解决方案资源管理器"窗口的初始窗口尺寸 
Size solutionExplorerSize=solutionExplorerContent.Control.Size; 
 //设置当停靠窗口收缩成标签时标签上的标题 
solutionExplorerContent.Title="解决方案资源管理器"; 
//设置停靠窗口展开时的标题 
solutionExplorerContent.FullTitle="解决方案资源管理器-Exam"; 
//设置Content停靠窗口从标签状态滑动出来成为窗口状态时窗口大小 
solutionExplorerContent.AutoHideSize=solutionExplorerSize; 
//设置停靠窗口被“钉”在DockManager管理窗口上时的尺寸 
solutionExplorerContent.DisplaySize=solutionExplorerSize; 
//设定停靠窗口收缩时标签上显示的小图标,viewImgs是用户事先定义好的ImageList类型变量 
solutionExplorerContent.ImageList=viewImgs; 
solutionExplorerContent.ImageIndex=0; 
 将停靠窗口Content加入DockManager的管理队列 
dockManager.Contents.Add(solutionExplorerContent); 
//用AddContentWithState()显示Content停靠窗口, 
//State.DockRight表明了是将窗口停靠在整个DockManager管理区域的右边 
//可选的还有State.DockLeft,State.DockTop,State.DockBottom,State.Floating; 
//返回值是WindowContent类型的变量,是用来容纳多个Content对象 
WindowContent wc=dockManager.AddContentWithState( 
solutionExplorerContent,State.DockRight); 
 //假设前面已经设置了classViewContent的属性,下面将classViewContent加入停靠 
dockManager.Contents.Add(classViewContent); 
//将classViewContent加入到“资源管理器”窗口所在的WindowContent中 
dockManager.AddContentToWindowContent(classViewContent,wc);

完整的程序代码如下: 

 

public MainForm() 
         { 
              InitializeComponent(); 
               //生成IDE风格的管理窗口 
              dockManager=new DockingManager(this,VisualStyle.IDE); 
               dockManager.OuterControl=statusBar; 
              dockManager.InnerControl=centerPanel; 
              
              centerPanel.IDEPixelBorder=true; 
               //生成Conten对象,该对象就是DockingManager管理的浮动窗口 
              Content solutionExplorerContent=new Content(dockManager); 
              solutionExplorerContent.Control=new SolutionExplorer(); 
              Size solutionExplorerSize=solutionExplorerContent.Control.Size; 
               solutionExplorerContent.Title="解决方案资源管理器"; 
              solutionExplorerContent.FullTitle="解决方案资源管理器-Exam"; 
              solutionExplorerContent.AutoHideSize=solutionExplorerSize; 
              solutionExplorerContent.DisplaySize=solutionExplorerSize; 
              solutionExplorerContent.ImageList=viewImgs; 
              solutionExplorerContent.ImageIndex=0; 
               Content classViewContent=new Content(dockManager); 
              classViewContent.Control=new ClassView(); 
              Size classViewSize=classViewContent.Control.Size; 
               classViewContent.Title="类视图"; 
              classViewContent.FullTitle="类视图-Exam"; 
              classViewContent.AutoHideSize=classViewSize; 
              classViewContent.DisplaySize=classViewSize; 
              classViewContent.ImageList=viewImgs; 
              classViewContent.ImageIndex=1; 
               //设置浮动窗口的属性,title是窗口收缩以后的标题 
              //FullTitle是窗口显示时的标题 
              //将浮动窗口和具体在浮动窗口中被包含的面板联系起来 
              dockManager.Contents.Add(solutionExplorerContent); 
WindowContent wc=dockManager.AddContentWithState( 
solutionExplorerContent,State.DockRight); 
              dockManager.Contents.Add(classViewContent); 
              dockManager.AddContentToWindowContent(classViewContent,wc); 
       }

2.4          在主窗口上加入TabControl类型的多窗口面板控件centerPanel 

l          添加控件 

从工具栏新添加的控件中(图1-3)拖动一个TabControl控件到MainForm主窗口上,如下图所示: 

开发Visual Studio风格的用户界面--MagicLibrary使用指南_ide_10

图 3  添加TabControl控件 

l          TabControl控件的属性 

Appearance:决定控件的外观,可能的取值MultiDocument,MultiForm,MultiBox 

HideTabsMode:决定TabControl面板控件隐藏和显示的方式 

ShowAlways:总是显示 

HideAlways:总是不显示 

HideUsingLogical:根据逻辑判断显示或隐藏 

HideWithoutMouse:当鼠标不在控件上时隐藏 

IDEPixelBorder:决定是否在TabControl面板控件四周画边框 

ShowArrows:决定是否显示面板右上角的箭头 

ShowClose:决定是否显示面板右上角的关闭按纽 

l          在中央面板centerPanel上显示代码编辑窗口CodeEditor 

需要首先生成一个TabPage对象,然后用TabPage把代码编辑窗口CodeEditor包装起来,最后把TabPage对象加入到centerPanel的TabPages管理队列中去 

private void newCodeForm_Click(object sender, System.EventArgs e) 
     { 
         Crownwood.Magic.Controls.TabPage page=new Crownwood.Magic.Controls.TabPage(); 
         page.Title="Exam.cs"; 
         page.Control=new CodeEditor(); 
         centerPanel.TabPages.Add(page); 
     }

3           结论 

     如上所述,使用MagicLibrary这样的库函数在.NET环境下确实可以非常方便地实现一个精致的界面,使用户可以将注意力集中在和自己应用相关的部分,从而极大地提高了开发效率。