2024年6月14日发(作者:)
C#自定义带关闭按钮的TabControl实例
2020年12月8日整理
作者:程序人生起波澜
【功能需求】
1.为TabControl控件加入关闭按钮
关闭按钮可由用户设置颜色属性
不需要加入关闭按钮时,可以让其不显示。
鼠标放在关闭按钮上时,显示关闭按钮区域
2.标签颜色实现渐变设置,美化标签
3.选中的Tab标签,显示不同的渐变色
标签,可显示图标及横向文本
【效果图如下】
【制作流程】
一.打开Visual Studio 我用的是2019版,新建项目Windows窗体控件库(.net
Framework)
二.在项目上添加自定义控件,名字根据自己需求,这里我命名为
三.设置项目属性,输出类型选择DLL类库,目标框架根据自己需求,建议目标框架.net
Framework 版本不要太高,4.0足够以后开发使用.
四.下面开始写代码:
删除原项目多余的UserControl1文件,编辑我们新建的自定义控件,切换到代码视图
首先,我们的控件继承原TabControl,因为我们以后要放到工具箱使用,再工具箱中显示的
图标也要换以下,这里我用原来的TabControl图标
[ToolboxBitmap(typeof(TabControl))]
也可以自定义图标如:[ToolboxBitmap(typeof(Label), "")]
1. namespace MyControl
2. {
3. [ToolboxBitmap(typeof(TabControl))]
4. public partial class MyTabControl : TabControl
5.
一.以下是使用的字段和属性,我会尽量把注释写清楚,方便大家理解
1. using System;
2. using c;
3. using entModel;
4. using g;
5. using g2D;
6. using ;
7. using ;
8. using ;
9. using ;
10. using ;
11.
12. namespace MyControl
13. {
14. [ToolboxBitmap(typeof(TabControl))]
15. public partial class MyTabControl : TabControl
16. {
17. //关闭按钮的区域
18. Rectangle rectClose;
19. //鼠标是否在关闭按钮上
20. bool above = false;
21. //Tab标签索引
22. int closeindex=1000;
23. //显示关闭按钮
24. private bool showclose_button = true;
25. //背景颜色
26. private Color _backColor = arent;
27. private Image _backgroundimage = null;
28. //边线颜色
29. private Color _lineColor = gb(157, 162, 168);
30. //默认标签渐变 a
31. private Color _ColorDefaultA = gb(231, 231, 231);
32. //默认标签渐变 b
33. private Color _ColorDefaultB = gb(255, 255, 255);
34. //鼠标点击渐变色a
35. private Color _ColorActivateA = gb(184, 203, 217);
36. //鼠标点击渐变色b
37. private Color _ColorActivateB = gb(255, 255, 255);
38. private Color closebutton = ;//默认关闭按钮的颜色
39. //默认关闭按钮获得焦点的颜色
40. private Color closebutton_focuse = ;
41. //关闭铵钮填充色 ,鼠标放上时显示的颜色
42.
43.
44. #region ---------属性------------
45.
46. [Description("背景色"), Category("自定义属性")]
47. public Color Backcolor
48. {
49. get { return this._backColor; }
50. set
51. {
52. this._backColor = value;
53. date();
54. }
55. }
56. [Description("背景图片"), Category("自定义属性")]
57. public Image Backgroundimage
58. {
59. get { return this._backgroundimage; }
60. set
61. {
62. this._backgroundimage = value;
63. date();
64. }
65. }
66. [Description("是否显示关闭按钮"), Category("自定义属性")]
67. public bool Showclose_button
68. {
69. get { return ose_button; }
70. set
71. {
72. ose_button = value;
73. date();
74. }
75. }
76.
77. [Description("设置边线的颜色"), Category("自定义属性")]
private Color closebutton_fill = lDark;
78. public Color linecolor
79. {
80. get { return this._lineColor; }
81. set
82. {
83. this._lineColor = value;
84. date();
85. }
86. }
87.
88. [Description("设置标签的渐变色A"), Category("自定义属性")]
89. public Color colordefaulta
90. {
91. get { return this._ColorDefaultA; }
92. set
93. {
94. this._ColorDefaultA = value;
95. date();
96. }
97. }
98.
99.
100. [Description("设置标签的渐变色B"), Category("自定义属性")]
101. public Color colordefaultb
102. {
103. get { return this._ColorDefaultB; }
104. set
105. {
106. this._ColorDefaultB = value;
107. date();
108. }
109. }
110.
111. [Description("点击标签的渐变色A"), Category("自定义属性")]
112. public Color coloractivatea
113. {
114. get { return this._ColorActivateA; }
115. set
116. {
117. this._ColorActivateA = value;
118. date();
119. }
120. }
121.
122.
123. [Description("点击标签的渐变色B"), Category("自定义属性")]
124. public Color coloractivateb
125. {
126. get { return this._ColorActivateB; }
127. set
128. {
129. this._ColorActivateB = value;
130. date();
131. }
132. }
133.
134. [Description("关闭按钮无操作的颜色"), Category("自定义属性")]
135. public Color closebuttonc
136. {
137. get { return utton; }
138. set
139. {
140. utton = value;
141. date();
142. }
143. }
144.
145. [Description("关闭按钮获昨焦点的颜色"), Category("自定义属性")]
146. public Color closebuttonfocuse
147. {
148. get { return utton_focuse; }
149. set
150. {
151. utton_focuse = value;
152. date();
153. }
154. }
155.
156. [Description("关闭按钮的填充色"), Category("自定义属性")]
157. public Color closebuttonfill
158. {
159. get { return utton_fill; }
160. set
161. {
162. utton_fill = value;
163. date();
164. }
165. }
166. #endregion
在属性上我们使用了
[Description("关闭按钮的填充色"), Category("自定义属性")]
这将在Visual Studio中控件的属性窗口中显示属性的描述信息,且该属性显示在“自定义属性”节点中。
二.接着修改控件的构造函数,这里主要是加上了样式设置,并开启缓冲区
1. private void SetStyles()
2. {
3. le(
4.
5. int |//使用自定义的绘制方式
6. zedDoubleBuffer |//则控件将首先绘制到缓冲区而不是直接绘
制到屏幕,这可以减少闪烁
7. ntingInWmPaint |//控件忽略窗口消息 WM_ERASEBKGND 以减
少闪烁
8. Redraw |//当控件大小发生变化时就重新绘制
9. tsTransparentBackColor, true);//控件接受 alpha 组件数
小于 255 个的 BackColor 来模拟透明度
10. Styles(); //强制将分配的样式重新应用到控件
11. }
12. public MyTabControl()
13. {
14. SetStyles();
15. ine = true;
16. de = ;
17.
18. InitializeComponent();
19.
20. }
三.使用Rect()方法,我们可以方便的得到标签的区域,由此获取关闭按钮
的区域。“关闭按钮”的大小我们以当前系统小图标大小的3/4为准,可以使用
和Height获取系统小图标尺寸。
代码如下:
1. ///
2. /// 获得绘制关闭按钮的区域
3. ///
4. ///
5. ///
6. private Rectangle GetCloseRect(Rectangle rect)
7. {
8. Rectangle closerect = new Rectangle(rect.X + - SystemInformat
, rect.Y + 5, *
3 / 4, * 3 / 4);
9. return closerect;
10. }
通过这段代码,我们就得到了Tab标签的“关闭按钮区域”(tp代表Tab标签索引)。
即rectClose = GetCloseRect(Rect(f(tp)));
由此重写鼠标MouseMove事件,实现鼠标移入、移出“关闭按钮区域”时,“关闭按钮
区域”颜色发生改变的代码。
1. protected override void OnMouseMove(MouseEventArgs e)
2. {
3.
4. Graphics pe = Graphics();
5. Point MousePOS = oClient(osition);
6. if (showclose_button == true)
7. {
8.
9. foreach (TabPage tp in es)
10. {
11. rectClose = GetCloseRect(Rect(f(
tp)));
12. above = ns(MousePOS);
13. if (above)
14. { //鼠标放在关闭区域时显示选中的关闭按钮
15. drawclose(pe, rectClose);
16. closeindex = f(tp); //记录当前标签索引
17. }
18. else
19. {
20. if (closeindex < nt)
21. if (closeindex == f(tp))
22. { //鼠标离开关闭区域时,重绘标签,
23. DrawTabPage(pe, Rect(closeindex), tp);
24. closeindex = nt+1;
25. }
26.
27. }
28. }
29. }
30. }
以上代码很好理解,其中多了两个方法
drawclose()和DrawTabPage(),代码的功能及注释如下:
1. ///
2. ///绘制选中的关闭按钮
3. ///
4. ///
5. /// 关闭按钮区域
6. private void drawclose(Graphics graphics, Rectangle rectclose)
7. {
8. Pen closepen = new Pen(closebutton_focuse, 1);
9. ctangle(new SolidBrush(closebutton_fill), rectclose);
10. ne(closepen, rectclose.X + 2, rectclose.Y + 2, rectclose.
X - 2 + , rectclose.Y + - 2);
11. ne(closepen, rectclose.X + 2, rectclose.Y - 2 + rectclose
.Height, rectclose.X - 2 + , rectclose.Y + 2);
12.
13. }
14. ///
15. /// 绘制tabpage标签
16. ///
17. ///
18. /// Tab标签区域
19. /// Tab标签索引
20. private void DrawTabPage(Graphics graphics, Rectangle rectangle, TabPage tp)
21. {
22. //绘制底纹
23.
24. StringFormat sf = new StringFormat();
25. int imagewidth = 0;
26. ng = isCharacter;
27. Flags = ;
28. if (ist != null)
29. imagewidth = ;
30. else
31. imagewidth = 0;
32. Rectangle rect = new Rectangle(rectangle.X, rectangle.Y ,
h, ); //标准区域
33. Point tabimage = new Point(rectangle.X + 5, rectangle.Y + 5);
34. Rectangle fontRect = new Rectangle(rectangle.X + 7 + imagewidth, rectang
le.Y + ( - ) / 2, - 2 - imagew
idth, );//文字区域
35. if ((tp))
36. {
37. //绘制边框
38. //填充颜色
39. ctangle(new LinearGradientBrush(new Point(rect.X, rec
t.Y), new Point(rect.X, rect.Y + ), _ColorActivateA, _ColorActiva
teB), rect);
40. ring(, , new SolidBrush(lor),
fontRect, sf); //文字绘制
41. ctangle(new Pen(_lineColor), rect);
42. }
43. else
44. {
45. //绘制边框
46. ctangle(new LinearGradientBrush(new Point(rect.X, rec
t.Y), new Point(rect.X, rect.Y + ), _ColorDefaultA, _ColorDefault
B), rect);
47. ring(, , new SolidBrush(lor),
fontRect, sf); //文字绘制
48. ctangle(new Pen(_lineColor), rect);
49. }
50. //绘制关闭按钮
51. if (showclose_button == true)
52. {
53. rectClose = GetCloseRect(rectangle);
54.
55. Pen closepen = new Pen(closebutton, 1);
56.
57. ne(closepen, rectClose.X + 2, rectClose.Y + 2, rectCl
ose.X - 2 + , rectClose.Y + - 2);
58. ne(closepen, rectClose.X + 2, rectClose.Y - 2 + rectC
, rectClose.X - 2 + , rectClose.Y + 2);
59. }
60. try
61. { ///如果有imagelist,则绘制imagelist图标
62. if (imagewidth != 0)
63. (graphics, tabimage, ndex);
64. }
65. catch{}
66. }
最后,我们需要重写OnPaint()方法:
1. protected override void OnPaint(PaintEventArgs pe)
2. {
3. t(pe);
4.
5. ingMode = ias;
6. olationMode = alityBilinear;
7.
8. //绘制背景
9.
10. Rectangle backrect = Rectangle;
11. ctangle(new SolidBrush(_backColor), backrect);
12. ctangle(new Pen(_backColor), backrect);
13. if(this._backgroundimage!=null)
14. age(this._backgroundimage,backrect);
15. //绘制边线
16. int height = + 3;
17. Rectangle r = new Rectangle(DisplayRectangle.X - 1, DisplayRectangle.Y -
1, + 1, + 1);
18. //绘制边框
19. ctangle(new Pen(_lineColor), r);
20.
21. //绘制Tab标签
22. Point MousePOS = oClient(osition);
23. foreach (TabPage tp in es)
24. {
25. if (showclose_button == true)
26. {
27. rectClose = GetCloseRect(Rect(f(t
p)));
28. above = ns(MousePOS);
29. DrawTabPage(cs, Rect(f(t
p)), tp);
30. if (above)
31. drawclose(cs, rectClose);
32. }
33. else
34. {
35. DrawTabPage(cs, Rect(f(t
p)), tp);
36. }
37. }
38. }
以上是全部代码,我们自定义的TabControl就完成了。我们编译成功后,将生成DLL文件,
加入工具箱,可以方便的使用了。
希望对大家学习有帮助!
发布评论