效果图:
NET提供TabControl控件的选项卡太丑陋,功能也太少了,虽然它允许你重写它的选项卡绘制方法来进行美化,但是它是使用默认win32 api 去创建和管理选项卡的,能修改的范围有限。因此我重新用c#开发开发该控件,选项卡部分逻辑完全由c#语言来管理,这也是这个控件的重点。
微软说开源.NET,我发现他没有百分百开源,至少在ndp开源项目找不到System.Design的开源代码。我通过查看 “ndp开源项目” 和反编译 “控件设计器项目” 参考他的设计来重新编写了增强版的TabControl控件。这个控件有两个程序集 :
“WinformControlLibraryExtension.ComplexityPropertys” (控件复杂属性定义)
“WinformControlLibraryExtension” (控件)
要使用 TabControlUpGradesExt 控件 ,你必须要手动添加“WinformControlLibraryExtension”到你的VS的工具箱。这个程序集可以用“项目方式”或“DLL”方式 引用到你的项目,如果添加后页面报错你要手动添加“WinformControlLibraryExtension.ComplexityPropertys” DLL到你项目引用里,因为这个程序集没有自动帮你添加到你的项目里。注意“WinformControlLibraryExtension.ComplexityPropertys” 这个项目只能通过编辑后“DLL”方式添加到你的项目里面。这是因为在这个程序集里面有 BackGauge.cs 、RoundedCorner.cs 两个复杂属性机构体定义,因为如果是以“项目方式”添加“WinformControlLibraryExtension.ComplexityPropertys” 到你的项目,当你在VS设计器编辑好窗体保存时会报错,提示你自定义复杂属性无法序列化导致保存不了,最后窗体Designer.cs有代码丢失损坏。这是很严重的事。这个问题我看过国外论坛也有人遇过,因为在“项目方式”下引用,编译时产生了两个版本的WinformControlLibraryExtension.ComplexityPropertys 导致VS识别出错,他们问过团队,承认是VS的bug来的,说在之前某个版本已经修复了,但是我在vs2019还是出现这种情况。难道他们说修复后也只能通过DLL方式应用。
TabControlUpGradesExt 控件和我以往写的控件有些区别,这些区别主要是“控件由父子两种控件组成”、“子控件的集合属性也和以往的简单类控件里的集合属性写法有区别”、“按照VS试图设计器提供的基类为父子控件编写对应的设计器”。 TabControlUpGradesExt 主体控件是基于 Control 控件基础类开发的。 TabPageUpGradesExt 子控件是继承 Panel 控件基础类开发的。
设计图:
该控件增加的功能包括以下:
1.菜单栏可以添加全局自定义按钮。
2.选项卡的布局方式有3种:横向布局、纵向布局,垂直布局。
3.每个选项可以添加:自定义图标、关闭按钮、自定义按钮。
4.选项的文本显示方式有3种:横向显示、纵向显示,垂直显示。
5.每个选项可以独立设置间距。
6.选项预留绘制事件让开发者可以根据自身情况进一步美化控件。
7.根据系统的缩放比例自动缩放控件防止失真。
该控件文件包括以下:
ControlCommom.cs (控件通用工具类)
WindowNavigate.cs (win 32 api 方法封装)
DotsPerInchHelper.cs (系统缩放比例帮助类)
CollectionEditorExt.cs (让设计器拥有编辑"集合属性"编辑功能)
ColorEditorExt.cs(让设计器拥有编辑"透明颜色属性"功能)
EmptyConverter.cs (让设计器拥有编辑"对象颜色属性"功能)
TabControlUpGradesExtDesigner.cs (让设计器拥有编辑“TabControlUpGradesExt”控件)
TabPageUpGradesExtDesigner.cs(让设计器拥有编辑“TabPageUpGradesExt”控件)
BackGauge.cs (自定义左右边距复杂属性)
BackGaugeConverter.cs (让设计器拥有编辑“自定义左右边距复杂属性”功能)
RoundedCorner.cs (自定义圆角复杂属性)
RoundedCornerConverter.cs(让设计器拥有编辑“自定义圆角复杂属性”功能)
TabControlUpGradesExt.cs (控件中父控件)
TabPageUpGradesExt.cs(控件中子控件)
控件最复杂的地方就是每个部件Rectangle 的计算。控件选项卡逻辑原理大致如下:
1.UpdateEveryOneTabItemSize() (计算每一个选项及内部部件的Size)
2.UpdateMenuBarRectangle() (更新菜单区Rectangle、更新全局自定义按钮区域及部件Rectangle、更新导航栏区域及部件Rectangle和显示状态、更新TabItems的总显示区域)
3.UpdateEveryOneTabItemRectangle() (更新每个选项及内部部件Rectangle)
4.ReplenishTabItemToRectangleForLeft() (自动根据TabItems的总显示区判断是否把左边已隐藏的选项添加到显示区)
5.ReplenishSelectTabItemToRectangle() (自动把已选中选项显示在TabItems的总显示区中)
6.UpdateTabMainDisplayRectangleByTabItemsDisplayRectangle() (根据菜单Rectangle更新TabPage主体区域Rectangle)
控件初始化:1、2、3、4、5、6
控件ReSize:2、3、4、5、6
导航栏按钮:3
选项选中更改事件:5
TabControlUpGradesExt控件新增的属性 TabControlUpGradesExt控件新增事件 TabPageUpGradesExt控件新增的属性
控件菜单布局效果:
利用 MenuBarAlignment 、 TabItemVerticalLayout 、 TabItemTextVerticalLayout 属性可以进行以下布局:
控件选项自定义绘制效果:
通过 MenuBarDrawBackgroundBefore 、MenuBarDrawBackgroundAfter 、TabItemCreateCustomPathBefore 、TabItemDrawBackgroundAfter、 绘制事件可以让选项卡绘制出自定义风格。在绘制时要注意事件参数Graphics 属性Set访问器是公开的,这就意味你对Graphics的属性修改后要把它还原成原来值,不然他会影响控件的其他绘制。还有在计算要绘制范围时计算也要乘以系统当前的缩放比例 e.DPIScale.XScale ,不然你绘制出来的东西尺寸是不对的。
控件选项小部件效果:
选项的小部件包括:
1.图标:可以统一设置显示状态,也可以独立设置选项的图标是否显示。
2.自定义按钮:可以为每个选项添加不同数量的独立按钮,按钮分为“Button”、“CheckButton”两种。
3.关闭按钮:可以统一设置显示状态,也可以独立设置选项的关闭按钮是否显示。还可以统一设置关闭按钮所在的位置。
控件选项事件讲解:
TabItemDeselecting (TabItem取消选中事件)
TabItemDeselected (TabItem取消选后事件)
TabItemSelecting (TabItem选中时事件)
TabItemSelected (TabItem选中后事件)
SelectedIndexChanged (TabItem选中索引更改后事件)
当鼠标、键盘、代码设置SelectedIndex 来切换激活选项时触发事件顺序:
TabItemDeselecting => TabItemDeselected => TabItemSelecting =>TabItemSelected => SelectedIndexChanged
当移除选项卡时触发事件顺序:
TabItemSelecting =>TabItemSelected => SelectedIndexChanged