• c#控件编写 (2)重写一个TabControl


    在重写TabControl的时候我们最先想到的是设置

    this.DrawMode = TabDrawMode.OwnerDrawFixed;

    然后重写

    protected override void OnDrawItem(DrawItemEventArgs e)
    {
         base.OnDrawItem(e);
    }

    这样重写后只是重写选项卡上的区域,这个区域并不包括边框,这样我们所重写的和边框不搭调,也无法达到我们想要的功能 。

            而更好的方法是重写整个控件

    设置控件由用户绘制

    private void SetStyles()
            {
                base.SetStyle(
                    ControlStyles.UserPaint |
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.SupportsTransparentBackColor, true);
                base.UpdateStyles();
            }

    关键的地方在 ControlStyles.UserPaint 设置为true

    重写OnPaint

      protected override void OnPaint(PaintEventArgs pe)
            {
                base.OnPaint(pe);
    
                pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                pe.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
               // pe.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
                //绘制背景
    
                Rectangle rect = this.ClientRectangle; 
                pe.Graphics.FillRectangle(new TextureBrush(Properties.Resources.bg), rect); 
    
                //绘制边线 
                int height = this.ItemSize.Height+3;
                Rectangle r = new Rectangle(DisplayRectangle.X - 1, DisplayRectangle.Y - 1, DisplayRectangle.Width + 1, DisplayRectangle.Height + 1);
    
                // pe.Graphics.DrawLine(new Pen(Color.FromArgb(157, 162, 168)), new Point(rect.X, rect.Y + height), new Point(rect.Right, rect.Y + height));
                pe.Graphics.DrawRectangle(new Pen(_lineColor), r);
                //绘制边框  
    
                //绘制标头
    
                foreach (TabPage tp in this.TabPages)
                {
                    DrawTabPage(pe.Graphics, this.GetTabRect(this.TabPages.IndexOf(tp)),tp);
                } 
            }

    this.GetTabRect函数可以获取的标签的位置,这个为我们重绘标签提供了很好的帮助

    重绘标签 

      private void DrawTabPage(Graphics graphics, Rectangle rectangle, TabPage tp)
            {
                //绘制底纹  
    
                StringFormat sf = new StringFormat();
                
                sf.Trimming = StringTrimming.EllipsisCharacter;
                sf.FormatFlags = StringFormatFlags.NoWrap;
                Rectangle rect = new Rectangle (rectangle.X ,rectangle .Y +2,rectangle .Width ,rectangle .Height -2); //标准区域
                Rectangle fontRect = new Rectangle(rectangle.X + 5, rectangle.Y+5, rectangle.Width - 10, tp .Font .Height);//文字区域
               
                if (this.SelectedTab.Equals(tp))
                {
                    rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
                    fontRect = new Rectangle(rectangle.X + 5, rectangle.Y + 5, rectangle.Width - 25, rectangle.Height - 7);
               
                    //绘制边框   
                    graphics.FillPath(new LinearGradientBrush(new Point(rect.X, rect.Y), new Point(rect.X, rect.Y + rect.Height), _ColorActivateA, _ColorActivateB), CreateTabPath(rect)); //填充颜色
                    graphics.DrawString(tp.Text, tp.Font, new SolidBrush(tp.ForeColor), fontRect, sf); //文字绘制
     
                    graphics.DrawPath(new Pen(_lineColor), CreateTabPath(rect));//绘制实边线  
    
                    //掩盖下部的绘制 
                    graphics.DrawLine(new Pen(_ColorActivateB, 3), rect.X, rect.Bottom + 1, rect.X + rect.Width, rect.Bottom + 1);
    
                    //绘制图片
                    Rectangle rectClose = GetCloseRect(rectangle);
                }
                else
                {
                    //绘制边框   
                    graphics.FillPath(new LinearGradientBrush (new Point (rect .X,rect .Y ),new Point (rect .X,rect .Y +rect .Height ),_ColorDefaultA,_ColorDefaultB), CreateTabPath(rect)); //填充颜色
                    graphics.DrawString(tp.Text, tp.Font, new SolidBrush(tp.ForeColor), fontRect, sf); //文字绘制
                   // graphics.DrawPath(new Pen(Color.Wheat, 2), CreateTabPath(rect));//绘制高光边线
                    graphics.DrawPath(new Pen(_lineColor), CreateTabPath(rect));//绘制实边线  
                }
             

    绘制关闭标签按钮

            我们给标签加上了一个鼠标移上去显示关闭按钮的功能   重写OnMouseMove的功能

        bool CloseEX = false;
            protected override void OnMouseMove(MouseEventArgs e)
            {
    
                if (TabPageMouseClose(e.Location) != CloseEX)
                {
                    CloseEX = !CloseEX;
                    this.Invalidate();
                }
     
                base.OnMouseMove(e);
            }

      在鼠标移动过快的时候,会导致关闭按钮没有刷新,所有我们要在鼠标离开控件的时候让CloseEx=False并重绘制。

    好到这一步我们就完成我我们的绘制工作 。我在绘制的时候使用了渐变画刷用了5个参数来标识每个指定的颜色

    private Color _lineColor = Color.FromArgb(157, 162, 168); //边线颜色 
    private Color _ColorDefaultA = Color.FromArgb(231, 231, 231);//默认标签渐变 a
    private Color _ColorDefaultB = Color.FromArgb(255, 255, 255);//默认标签渐变 b
    private Color _ColorActivateA = Color.FromArgb(184, 203, 217);//点击渐变a
    private Color _ColorActivateB = Color.FromArgb(255, 255, 255);//点击渐变a
  • 相关阅读:
    【美团技术团队文章--学习笔记】之 Java动态追踪技术探究
    mq
    为啥要读写分离
    算法 数据结构
    对扩展开放,对修改关闭
    redis 事务
    准实时数仓设计方案
    Scala Puzzlers 系列(一):占位符的使用
    【面试题】大数据开发岗位
    Hive 分区和分桶
  • 原文地址:https://www.cnblogs.com/ac1985482/p/2699988.html
Copyright © 2020-2023  润新知