Change border color in TextBox C#

前端 未结 4 1966
面向向阳花
面向向阳花 2020-11-28 10:42

I have the following code:

public class OurTextBox : TextBox
{
    public OurTextBox()
        : base()
    {
        this.SetStyle(ControlStyles.UserPaint,          


        
相关标签:
4条回答
  • 2020-11-28 11:31

    There are several ways to do this and none are ideal. This is just the nature of WinForms. However, you have some options. I will summarise:

    One way you can achieve what you want is by embedding a TextBox in a Panel as follows.

    public class BorderedTextBox : Panel 
    {
        private TextBox textBox;
        private bool focusedAlways = false;
        private Color normalBorderColor = Color.Gray;
        private Color focusedBorderColor = Color.Red;
    
        public BorderTextBox() 
        {
            this.DoubleBuffered = true;
            this.Padding = new Padding(2);
    
            this.TextBox = new TextBox();
            this.TextBox.AutoSize = false;
            this.TextBox.BorderStyle = BorderStyle.None;
            this.TextBox.Dock = DockStyle.Fill;
            this.TextBox.Enter += new EventHandler(this.TextBox_Refresh);
            this.TextBox.Leave += new EventHandler(this.TextBox_Refresh);
            this.TextBox.Resize += new EventHandler(this.TextBox_Refresh);
            this.Controls.Add(this.TextBox);
        }
    
        private void TextBox_Refresh(object sender, EventArgs e) 
        {
            this.Invalidate();
        }
    
        protected override void OnPaint(PaintEventArgs e) 
        {
            e.Graphics.Clear(SystemColors.Window);
            using (Pen borderPen = new Pen(this.TextBox.Focused || FocusedAlways ? 
                focusedBorderColor : normalBorderColor)) 
            {
                e.Graphics.DrawRectangle(borderPen, 
                    new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
            }
            base.OnPaint(e);
        }
    
        public TextBox TextBox
        {
            get { return textbox; }
            set { textbox = value; }
        }
    
        public bool FocusedAlaways
        {
            get { return focusedAlways; }
            set { focusedAlways = value; }
        }
    }
    

    You can also do this without overriding any controls, but the above method is better. The above will draw a border when the control gets focus. if you want the border on permanently, set the FocusedAlways property to True.

    I hope this helps.

    0 讨论(0)
  • 2020-11-28 11:33

    You have to draw text manually as well.

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Pen penBorder = new Pen(Color.Gray, 1);
        Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
        e.Graphics.DrawRectangle(penBorder, rectBorder);
    
        Rectangle textRec = new Rectangle(e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
        TextRenderer.DrawText(e.Graphics, Text, this.Font, textRec, this.ForeColor, this.BackColor, TextFormatFlags.Default);
    }
    

    Alternatively you can try to use e.Graphics.DrawString() method if TextRenderer is not giving you desired results (I always have better results with this approach thou).

    0 讨论(0)
  • 2020-11-28 11:33

    To change border color of TextBox you can override WndProc method and handle WM_NCPAINT message. Then get the window device context of the control using GetWindowDC because we want to draw to non-client area of control. Then to draw, it's enough to create a Graphics object from that context, then draw border for control.

    To redraw the control when the BorderColor property changes, you can use RedrawWindow method.

    Code

    Here is a TextBox which has a BorderColor property. The control uses BorderColor if the property values is different than Color.Transparent and BorderStyle is its default value Fixed3d.

    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    public class MyTextBox : TextBox {
        const int WM_NCPAINT = 0x85;
        const uint RDW_INVALIDATE = 0x1;
        const uint RDW_IUPDATENOW = 0x100;
        const uint RDW_FRAME = 0x400;
        [DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("user32.dll")]
        static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprc, IntPtr hrgn, uint flags);
        Color borderColor = Color.Blue;
        public Color BorderColor {
            get { return borderColor; }
            set { borderColor = value;
                RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
                    RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
            }
        }
        protected override void WndProc(ref Message m) {
            base.WndProc(ref m);
            if (m.Msg == WM_NCPAINT && BorderColor != Color.Transparent &&
                BorderStyle == System.Windows.Forms.BorderStyle.Fixed3D) {
                var hdc = GetWindowDC(this.Handle);
                using (var g = Graphics.FromHdcInternal(hdc))
                using (var p = new Pen(BorderColor))
                    g.DrawRectangle(p, new Rectangle(0, 0, Width - 1, Height - 1));
                ReleaseDC(this.Handle, hdc);
            }
        }
        protected override void OnSizeChanged(EventArgs e) {
            base.OnSizeChanged(e);
            RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
                   RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
        }
    }
    

    Result

    Here is the result using different colors and different states. All states of border-style is supported as you can see in below image and you can use any color for border:

    Download

    You can clone or download the working example:

    • Download Zip
    • Github repository
    0 讨论(0)
  • 2020-11-28 11:41

    set Text box Border style to None then write this code to container form "paint" event

        private void Form1_Paint(object sender, PaintEventArgs e)
            {
    System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X, TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height);
    
                    rect.Inflate(1, 1); // border thickness
                    System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect, Color.DeepSkyBlue, ButtonBorderStyle.Solid);
    
    }
    
    0 讨论(0)
提交回复
热议问题