Vs自带的TabControl太丑,想改造一下。

自定义TabControl,从TabControl派生一个自定义的标签控件GTabControl。



public class GTabControl :TabControl


在构造函数中添加如下代码:



1 base.SetStyle(
2 ControlStyles.UserPaint | // 控件将自行绘制,而不是通过操作系统来绘制
3 ControlStyles.OptimizedDoubleBuffer | // 该控件首先在缓冲区中绘制,而不是直接绘制到屏幕上,这样可以减少闪烁
4 ControlStyles.AllPaintingInWmPaint | // 控件将忽略 WM_ERASEBKGND 窗口消息以减少闪烁
5 ControlStyles.ResizeRedraw | // 在调整控件大小时重绘控件
6 ControlStyles.SupportsTransparentBackColor, // 控件接受 alpha 组件小于 255 的 BackColor 以模拟透明
7 true); // 设置以上值为 true
8 base.UpdateStyles();


这段代码的意思就像注释里说的,注意ControlStyles这个枚举是可以按位组合的,所以上面要用「或(|)」来进行连接,这样系统就会完全忽视TabControl这个基类的界面显示,而使用我们自己的方式来呈现UI。(一步一步玩控件:TabControl——从制作山寨Safari窗体开始)

以上是学习的过程。



1 using System.Drawing;
2 using System.Windows.Forms;
3 using System.Drawing.Drawing2D;
4 using System;
5 using System.Runtime.InteropServices;
6
7 namespace CSharpCustomTabControl
8 {
9 /// <summary>
10 /// Description of CustomTabControl.
11 /// </summary>
12 [ToolboxBitmap(typeof(TabControl))]
13 public class CustomTabControl : TabControl
14 {
15
16 public CustomTabControl() : base()
17 {
18 if (this._DisplayManager.Equals(TabControlDisplayManager.Custom)) {
19 this.SetStyle(ControlStyles.UserPaint, true);
20 this.ItemSize = new Size(0, 15);
21 this.Padding = new Point(9,0);
22 }
23
24 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
25 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
26 this.SetStyle(ControlStyles.ResizeRedraw, true);
27 this.ResizeRedraw = true;
28 }
29
30 TabControlDisplayManager _DisplayManager = TabControlDisplayManager.Custom;
31
32 [System.ComponentModel.DefaultValue(typeof(TabControlDisplayManager), "Custom")]
33 public TabControlDisplayManager DisplayManager {
34 get {
35 return this._DisplayManager;
36 }
37 set {
38 if (this._DisplayManager != value) {
39 if (this._DisplayManager.Equals(TabControlDisplayManager.Custom)) {
40 this.SetStyle(ControlStyles.UserPaint, true);
41 this.ItemSize = new Size(0, 15);
42 this.Padding = new Point(9,0);
43 } else {
44 this.ItemSize = new Size(0, 0);
45 this.Padding = new Point(6,3);
46 this.SetStyle(ControlStyles.UserPaint, false);
47 }
48 }
49 }
50 }
51
52 protected override void OnPaintBackground(PaintEventArgs pevent)
53 {
54 if (this.DesignMode == true) {
55 LinearGradientBrush backBrush = new LinearGradientBrush(
56 this.Bounds,
57 SystemColors.ControlLightLight,
58 SystemColors.ControlLight,
59 LinearGradientMode.Vertical);
60 pevent.Graphics.FillRectangle(backBrush, this.Bounds);
61 backBrush.Dispose();
62 } else {
63 this.PaintTransparentBackground(pevent.Graphics, this.ClientRectangle);
64 }
65 }
66
67 protected void PaintTransparentBackground(Graphics g, Rectangle clipRect)
68 {
69 if ((this.Parent != null)) {
70 clipRect.Offset(this.Location);
71 PaintEventArgs e = new PaintEventArgs(g, clipRect);
72 GraphicsState state = g.Save();
73 g.SmoothingMode = SmoothingMode.HighSpeed;
74 try {
75 g.TranslateTransform((float)-this.Location.X, (float)-this.Location.Y);
76 this.InvokePaintBackground(this.Parent, e);
77 this.InvokePaint(this.Parent, e);
78 }
79
80 finally {
81 g.Restore(state);
82 clipRect.Offset(-this.Location.X, -this.Location.Y);
83 }
84 }
85 else {
86 System.Drawing.Drawing2D.LinearGradientBrush backBrush = new System.Drawing.Drawing2D.LinearGradientBrush(this.Bounds, SystemColors.ControlLightLight, SystemColors.ControlLight, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
87 g.FillRectangle(backBrush, this.Bounds);
88 backBrush.Dispose();
89 }
90 }
91
92 protected override void OnPaint(PaintEventArgs e)
93 {
94
95 // Paint the Background
96 this.PaintTransparentBackground(e.Graphics, this.ClientRectangle);
97
98 this.PaintAllTheTabs(e);
99 this.PaintTheTabPageBorder(e);
100 this.PaintTheSelectedTab(e);
101 }
102
103 private void PaintAllTheTabs(System.Windows.Forms.PaintEventArgs e) {
104 if (this.TabCount > 0) {
105 for (int index = 0; index < this.TabCount ; index++){
106 this.PaintTab(e, index);
107 }
108 }
109 }
110
111 private void PaintTab(System.Windows.Forms.PaintEventArgs e, int index) {
112 GraphicsPath path = this.GetPath(index);
113 this.PaintTabBackground(e.Graphics, index, path);
114 this.PaintTabBorder(e.Graphics, index, path);
115 this.PaintTabText(e.Graphics, index);
116 this.PaintTabImage(e.Graphics, index);
117 }
118
119 private void PaintTabBackground(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path){
120 Rectangle rect = this.GetTabRect(index);
121 System.Drawing.Brush buttonBrush =
122 new System.Drawing.Drawing2D.LinearGradientBrush(
123 rect,
124 SystemColors.ControlLightLight,
125 SystemColors.ControlLight,
126 LinearGradientMode.Vertical);
127
128 if (index == this.SelectedIndex) {
129 buttonBrush = new System.Drawing.SolidBrush(SystemColors.ControlLightLight);
130 }
131
132 graph.FillPath(buttonBrush, path);
133 buttonBrush.Dispose();
134 }
135
136 private void PaintTabBorder(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path){
137 Pen borderPen = new Pen(SystemColors.ControlDark);
138
139 if (index == this.SelectedIndex) {
140 borderPen = new Pen(ThemedColors.ToolBorder);
141 }
142 graph.DrawPath(borderPen, path);
143 borderPen.Dispose();
144 }
145
146 private void PaintTabImage(System.Drawing.Graphics graph, int index){
147 Image tabImage = null;
148 if (this.TabPages[index].ImageIndex > -1 && this.ImageList != null) {
149 tabImage = this.ImageList.Images[this.TabPages[index].ImageIndex];
150 }else if (this.TabPages[index].ImageKey.Trim().Length > 0 && this.ImageList != null){
151 tabImage = this.ImageList.Images[this.TabPages[index].ImageKey];
152 }
153 if ( tabImage != null) {
154 Rectangle rect = this.GetTabRect(index);
155 graph.DrawImage(tabImage, rect.Right - rect.Height - 4, 4, rect.Height - 2, rect.Height - 2);
156 }
157 }
158
159 private void PaintTabText(System.Drawing.Graphics graph, int index)
160 {
161 Rectangle rect = this.GetTabRect(index);
162 Rectangle rect2 = new Rectangle(rect.Left + 8, rect.Top + 1, rect.Width - 6, rect.Height);
163 if (index == 0) rect2 = new Rectangle(rect.Left + rect.Height, rect.Top + 1, rect.Width - rect.Height, rect.Height);
164
165 string tabtext = this.TabPages[index].Text;
166
167 System.Drawing.StringFormat format = new System.Drawing.StringFormat();
168 format.Alignment = StringAlignment.Near;
169 format.LineAlignment = StringAlignment.Center;
170 format.Trimming = StringTrimming.EllipsisCharacter;
171
172 Brush forebrush = null;
173
174 if (this.TabPages[index].Enabled == false) {
175 forebrush = SystemBrushes.ControlDark;
176 }
177 else {
178 forebrush = SystemBrushes.ControlText;
179 }
180
181 Font tabFont = this.Font;
182 if (index == this.SelectedIndex) {
183 tabFont = new Font(this.Font, FontStyle.Bold);
184 if (index == 0) {
185 rect2 = new Rectangle(rect.Left + rect.Height, rect.Top + 1, rect.Width - rect.Height + 5, rect.Height);
186 }
187 }
188
189 graph.DrawString(tabtext, tabFont, forebrush, rect2, format);
190
191 }
192
193 private void PaintTheTabPageBorder(System.Windows.Forms.PaintEventArgs e) {
194 if (this.TabCount > 0) {
195 Rectangle borderRect= this.TabPages[0].Bounds;
196 borderRect.Inflate(1, 1);
197 ControlPaint.DrawBorder(e.Graphics, borderRect, ThemedColors.ToolBorder, ButtonBorderStyle.Solid);
198 }
199 }
200
201 private void PaintTheSelectedTab(System.Windows.Forms.PaintEventArgs e) {
202 Rectangle selrect;
203 int selrectRight = 0;
204
205 switch(this.SelectedIndex) {
206 case -1:
207 break;
208 case 0:
209 selrect = this.GetTabRect(this.SelectedIndex);
210 selrectRight = selrect.Right;
211 e.Graphics.DrawLine(SystemPens.ControlLightLight, selrect.Left + 2, selrect.Bottom + 1, selrectRight - 2, selrect.Bottom + 1);
212 break;
213 default:
214 selrect = this.GetTabRect(this.SelectedIndex);
215 selrectRight = selrect.Right;
216 e.Graphics.DrawLine(SystemPens.ControlLightLight, selrect.Left + 6 - selrect.Height, selrect.Bottom + 1, selrectRight - 2, selrect.Bottom + 1);
217 break;
218 }
219 }
220
221 private System.Drawing.Drawing2D.GraphicsPath GetPath(int index) {
222 System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
223 path.Reset();
224
225 Rectangle rect = this.GetTabRect(index);
226
227 if (index == 0){
228 path.AddLine(rect.Left + 1, rect.Bottom + 1, rect.Left + rect.Height, rect.Top + 2);
229 path.AddLine(rect.Left + rect.Height + 4, rect.Top, rect.Right - 3, rect.Top);
230 path.AddLine(rect.Right - 1, rect.Top + 2, rect.Right - 1, rect.Bottom + 1);
231 } else {
232 if (index == this.SelectedIndex) {
233 path.AddLine(rect.Left + 1, rect.Top + 5, rect.Left + 4, rect.Top + 2);
234 path.AddLine(rect.Left + 8, rect.Top, rect.Right - 3, rect.Top);
235 path.AddLine(rect.Right - 1, rect.Top + 2, rect.Right - 1, rect.Bottom + 1);
236 path.AddLine(rect.Right - 1, rect.Bottom + 1, rect.Left + 1, rect.Bottom + 1);
237 } else {
238 path.AddLine(rect.Left, rect.Top + 6, rect.Left + 4, rect.Top + 2);
239 path.AddLine(rect.Left + 8, rect.Top, rect.Right - 3, rect.Top);
240 path.AddLine(rect.Right - 1, rect.Top + 2, rect.Right - 1, rect.Bottom + 1);
241 path.AddLine(rect.Right - 1, rect.Bottom + 1, rect.Left, rect.Bottom + 1);
242 }
243
244 }
245 return path;
246 }
247
248 public enum TabControlDisplayManager {
249 Default,
250 Custom
251 }
252
253 [DllImport("user32.dll")]
254 private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
255
256 private const int WM_SETFONT = 0x30;
257 private const int WM_FONTCHANGE = 0x1d;
258
259 protected override void OnCreateControl()
260 {
261 base.OnCreateControl();
262 this.OnFontChanged(EventArgs.Empty);
263 }
264
265 protected override void OnFontChanged(EventArgs e)
266 {
267 base.OnFontChanged(e);
268 IntPtr hFont = this.Font.ToHfont();
269 SendMessage(this.Handle, WM_SETFONT, hFont, (IntPtr)(-1));
270 SendMessage(this.Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
271 this.UpdateStyles();
272 this.ItemSize = new Size(0, this.Font.Height + 2);
273 }
274
275 }
276 }


从网上找到的代码,可以满足要求!