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 }
从网上找到的代码,可以满足要求!