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文件,

加入工具箱,可以方便的使用了。

希望对大家学习有帮助!