WinForm原生TacControl定制标签样式

因为工作需要一个UI所使用的TabControl标签页效果需要定制实现,开始在网上找到一个实现的Demo,原理是控件通过绘制方法实现定制的目的,绘制过程就是使用GDI+画图的过程,包装一个控件供复用

批注 2019-08-15 210340

  • 首先,在控件构造方法中设定控件的样式为用户绘制相关样式

声明控件由用户自行绘制,开打双缓冲防闪烁,全部绘制均在wm_paint消息中,控件尺寸变化时进行重绘

base.SetStyle(
                 ControlStyles.UserPaint |
                 ControlStyles.DoubleBuffer |
                 ControlStyles.OptimizedDoubleBuffer |
                 ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.ResizeRedraw, true);

  • 之后,设置标签页的样式

正常按标签的文本伸缩尺寸

this.SizeMode = TabSizeMode.Normal;
            this.Alignment = TabAlignment.Top;

  • 全部标签定制的效果均在OnPaint方法内实现

逐个标签页绘制,先画背景,再画文本,最后边框,边框实现上为一个梯形,使用Path对象实现

以下为Demo类源代码

public class PaintHeadTabControl : TabControl
     {
         private Color controlBackColor = Color.White;
         private Color tabPageBorderColor = Color.LightGray;
         private Color headNormalBorderColor = Color.LightGray;
         private Color headCurrentBorderColor = Color.FromArgb(75, 161, 239);
         private Color currentBgColor = Color.FromArgb(75, 161, 239);
         private Color normalBgColor = Color.FromArgb(248, 249, 253);
         private Font currentFont = new Font("微软雅黑", 11, FontStyle.Bold, GraphicsUnit.Pixel);
         private Color currentForeColor = Color.White;
         private Font normalFont = new Font("微软雅黑", 11, FontStyle.Regular, GraphicsUnit.Pixel);
         private Color normalForeColor = Color.FromArgb(106, 106, 106);

        public PaintHeadTabControl()
         {
             base.SetStyle(
                 ControlStyles.UserPaint |
                 ControlStyles.DoubleBuffer |
                 ControlStyles.OptimizedDoubleBuffer |
                 ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.ResizeRedraw, true);

            // deafult head size
             this.SizeMode = TabSizeMode.Normal;
             this.Alignment = TabAlignment.Top;
             //this.ItemSize = new Size(90, 25);
         }

        [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
         public new TabAlignment Alignment
         {
             get { return base.Alignment; }
             set { base.Alignment = value; }
         }

        [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
         public new TabSizeMode SizeMode
         {
             get { return base.SizeMode; }
             set { base.SizeMode = value; }
         }

        [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
         public new Size ItemSize
         {
             get { return base.ItemSize; }
             set { base.ItemSize = value; }
         }

        protected override void Dispose(bool disposing)
         {
             base.Dispose(disposing);

            if (disposing)
             {
                 if (this.currentFont != null)
                 {
                     this.currentFont.Dispose();
                     this.currentFont = null;
                 }

                if (this.normalFont != null)
                 {
                     this.normalFont.Dispose();
                     this.normalFont = null;
                 }
             }
         }


         /// <summary>
         /// on paint draw head
         /// </summary>
         /// <param name="e"></param>
         protected override void OnPaint(PaintEventArgs e)
         {
             base.OnPaint(e);

            var g = e.Graphics;

            // anti alias
             g.SmoothingMode = SmoothingMode.AntiAlias;

            // draw tab control bg
             this.DrawControlBg(g);

            // head
             for (int index = 0; index < this.TabCount; index++)
             {
                 var tab = this.TabPages[index];
                 var headbounds = this.GetTabRect(index);

                // is current
                 var isCurrent = index == this.SelectedIndex;

                // get draw path
                 using (var path = this.GetHeadDrawPath(headbounds))
                 {
                     // bg
                     this.DrawHeadBg(g, isCurrent, path);

                    // text
                     this.DrawHeadText(g, isCurrent, tab.Text, headbounds);

                    // border
                     this.DrawHeadBorder(g, isCurrent, path);
                 }
             }

            // tab border
             this.DrawTabPageBorder(g);
         }

        private void DrawControlBg(Graphics g)
         {
             using (var br = new SolidBrush(this.controlBackColor))
             {
                 g.FillRectangle(br, this.ClientRectangle);
             }
         }

        private void DrawHeadBg(Graphics g, bool isCurrent, GraphicsPath path)
         {
             if (isCurrent)
             {
                 using (var br = new System.Drawing.SolidBrush(currentBgColor))
                 {
                     g.FillPath(br, path);
                 }
             }
             else
             {
                 using (var br = new System.Drawing.SolidBrush(normalBgColor))
                 {
                     g.FillPath(br, path);
                 }
             }
         }

        private void DrawHeadText(Graphics g, bool isCurrent, string text, Rectangle headbounds)
         {
             using (var format = new System.Drawing.StringFormat()
             {
                 Alignment = StringAlignment.Center,
                 LineAlignment = StringAlignment.Center,
                 Trimming = StringTrimming.EllipsisCharacter
             })
             {
                 if (isCurrent)
                 {
                     using (var br = new SolidBrush(this.currentForeColor))
                     {
                         g.DrawString(text, this.currentFont, br, headbounds, format);
                     }
                 }
                 else
                 {
                     using (var br = new SolidBrush(this.normalForeColor))
                     {
                         g.DrawString(text, this.normalFont, br, headbounds, format);
                     }
                 }
             }
         }

        private void DrawHeadBorder(Graphics g, bool isCurrent, GraphicsPath path)
         {
             if (isCurrent)
             {
                 using (var borderPen = new Pen(this.headCurrentBorderColor))
                 {
                     g.DrawPath(borderPen, path);
                 }
             }
             else
             {
                 using (var borderPen = new Pen(this.headNormalBorderColor))
                 {
                     g.DrawPath(borderPen, path);
                 }
             }
         }

        private void DrawTabPageBorder(Graphics g)
         {
             if (this.SelectedIndex > -1)
             {
                 var tab = this.TabPages[this.SelectedIndex];
                 var bounds = tab.Bounds;

                using (var pen = new Pen(this.tabPageBorderColor, 2))
                 {
                     g.DrawRectangle(pen, bounds);
                 }
             }
         }

        private GraphicsPath GetHeadDrawPath(Rectangle headBounds)
         {
             var path = new System.Drawing.Drawing2D.GraphicsPath();
             var conerWidth = Math.Min(15, headBounds.Width / 6);
             var topConner = headBounds.Left + (headBounds.Width - conerWidth);
             path.AddLines(new Point[]{
                 new Point(){ X = headBounds.Left + 2, Y = headBounds.Y  },
                 new Point(){ X = topConner, Y = headBounds.Y  },
                 new Point(){ X = headBounds.Right, Y = headBounds.Bottom+1  },
                 new Point(){ X = headBounds.Left + 2, Y = headBounds.Bottom+1  },
                 new Point(){ X = headBounds.Left + 2, Y = headBounds.Y  },
             });

            return path;
         }
     }

posted @ 2019-08-15 21:15  xuchao4177  阅读(427)  评论(0)    收藏  举报