winforms 更改文本框的边框颜色

2skhul33  于 2022-11-16  发布在  其他
关注(0)|答案(8)|浏览(276)

如何在用户单击文本框或聚焦文本框时更改文本框的BorderColor?

jv2fixgn

jv2fixgn1#

可以处理TextBoxWM_NCPAINT消息,如果控件具有焦点,可以在控件的非工作区绘制边框。可以使用任何颜色绘制边框:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ExTextBox : TextBox
{
    [DllImport("user32")]
    private static extern IntPtr GetWindowDC(IntPtr hwnd);
    private const int WM_NCPAINT = 0x85;
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_NCPAINT && this.Focused)
        {
            var dc = GetWindowDC(Handle);
            using (Graphics g = Graphics.FromHdc(dc))
            {
                g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
            }
        }
    }
}

结果

当控件成为焦点时,绘制边框完全没有闪烁:

文本框的BorderColor属性

在当前的帖子中,我只是改变了焦点上的边框颜色。您也可以添加一个BorderColor属性到控件中。然后您可以在设计时或运行时根据需要改变边框颜色。我已经发布了一个更完整的TextBox版本,它具有BorderColor属性:在以下帖子中:

scyqe7ek

scyqe7ek2#

试试这个

bool focus = false;
private void Form1_Paint(object sender, PaintEventArgs e)
{
    if (focus)
    {
        textBox1.BorderStyle = BorderStyle.None;
        Pen p = new Pen(Color.Red);
        Graphics g = e.Graphics;
        int variance = 3;
        g.DrawRectangle(p, new Rectangle(textBox1.Location.X - variance, textBox1.Location.Y - variance, textBox1.Width + variance, textBox1.Height +variance ));
    }
    else
    {
        textBox1.BorderStyle = BorderStyle.FixedSingle;
    }
}

private void textBox1_Enter(object sender, EventArgs e)
{
    focus = true;
    this.Refresh();
}

private void textBox1_Leave(object sender, EventArgs e)
{
    focus = false;
    this.Refresh();
}
jobtbby3

jobtbby33#

这是设置TextBox边框颜色的最终解决方案:

public class BorderedTextBox : UserControl
{
    TextBox textBox;

    public BorderedTextBox()
    {
        textBox = new TextBox()
        {
            BorderStyle = BorderStyle.FixedSingle,
            Location = new Point(-1, -1),
            Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                     AnchorStyles.Left | AnchorStyles.Right
        };
        Control container = new ContainerControl()
        {
            Dock = DockStyle.Fill,
            Padding = new Padding(-1)
        };
        container.Controls.Add(textBox);
        this.Controls.Add(container);

        DefaultBorderColor = SystemColors.ControlDark;
        FocusedBorderColor = Color.Red;
        BackColor = DefaultBorderColor;
        Padding = new Padding(1);
        Size = textBox.Size;
    }

    public Color DefaultBorderColor { get; set; }
    public Color FocusedBorderColor { get; set; }

    public override string Text
    {
        get { return textBox.Text; }
        set { textBox.Text = value; }
    }

    protected override void OnEnter(EventArgs e)
    {
        BackColor = FocusedBorderColor;
        base.OnEnter(e);
    }

    protected override void OnLeave(EventArgs e)
    {
        BackColor = DefaultBorderColor;
        base.OnLeave(e);
    }

    protected override void SetBoundsCore(int x, int y,
        int width, int height, BoundsSpecified specified)
    {
        base.SetBoundsCore(x, y, width, textBox.PreferredHeight, specified);
    }
}
92dk7w1h

92dk7w1h4#

WinForms从来就不擅长这个,这有点麻烦。
您可以尝试的一种方法是在Panel中嵌入TextBox,然后根据此处的焦点管理绘图:

public class BorderTextBox : Panel {
  private Color _NormalBorderColor = Color.Gray;
  private Color _FocusBorderColor = Color.Blue;

  public TextBox EditBox;

  public BorderTextBox() {
    this.DoubleBuffered = true;
    this.Padding = new Padding(2);

    EditBox = new TextBox();
    EditBox.AutoSize = false;
    EditBox.BorderStyle = BorderStyle.None;
    EditBox.Dock = DockStyle.Fill;
    EditBox.Enter += new EventHandler(EditBox_Refresh);
    EditBox.Leave += new EventHandler(EditBox_Refresh);
    EditBox.Resize += new EventHandler(EditBox_Refresh);
    this.Controls.Add(EditBox);
  }

  private void EditBox_Refresh(object sender, EventArgs e) {
    this.Invalidate();
  }

  protected override void OnPaint(PaintEventArgs e) {
    e.Graphics.Clear(SystemColors.Window);
    using (Pen borderPen = new Pen(this.EditBox.Focused ? _FocusBorderColor : _NormalBorderColor)) {
      e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
    }
    base.OnPaint(e);
  }
}
zlwx9yxi

zlwx9yxi5#

使用OnPaint在控件上绘制自定义边框是不错的。但是要知道如何使用OnPaint来提高效率,并将渲染时间降到最低。如果您在使用自定义绘制例程时遇到GUI滞后的问题,请阅读以下内容:What is the right way to use OnPaint in .Net applications?
因为PraVn的公认答案可能看起来很简单,但实际上效率很低。使用自定义控件,就像上面答案中张贴的那样要好得多。
也许性能在您的应用程序中不是问题,因为它很小,但对于具有大量自定义OnPaint例程的较大应用程序来说,使用Pravn显示的方式是一种错误的方法。

li9yvcax

li9yvcax6#

将文本框边框样式设置为None,然后将此代码写入容器窗体“paint”事件

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);
}
mwyxok5s

mwyxok5s7#

With PictureBox1
    .Visible = False
    .Width = TextBox1.Width + 4
    .Height = TextBox1.Height + 4
    .Left = TextBox1.Left - 2
    .Top = TextBox1.Top - 2
    .SendToBack()
    .Visible = True
End With
wgeznvg7

wgeznvg78#

下面是我的完整Flat TextBox控件,它支持主题,包括在正常和聚焦状态下的自定义边框颜色。
该控件使用了Reza Aghaeihttps://stackoverflow.com/a/38405319/5514131提到的相同概念,但是FlatTextBox控件的自定义性更强,并且没有闪烁。
控件会以更好的方式行程WM_NCPAINT视窗消息,以协助消除闪烁。

Protected Overrides Sub WndProc(ByRef m As Message)

    If m.Msg = WindowMessage.WM_NCPAINT AndAlso _drawBorder AndAlso Not DesignMode Then 'Draw the control border

        Dim w As Integer
        Dim h As Integer
        Dim clip As Rectangle
        Dim hdc As IntPtr

        Dim clientRect As RECT = Nothing
        GetClientRect(Handle, clientRect)

        Dim windowRect As RECT = Nothing
        GetWindowRect(Handle, windowRect)

        w = windowRect.Right - windowRect.Left
        h = windowRect.Bottom - windowRect.Top

        clip = New Rectangle(CInt((w - clientRect.Right) / 2), CInt((h - clientRect.Bottom) / 2), clientRect.Right, clientRect.Bottom)

        hdc = GetWindowDC(Handle)

        Using g As Graphics = Graphics.FromHdc(hdc)

            g.SetClip(clip, CombineMode.Exclude)

            Using sb = New SolidBrush(BackColor)
                g.FillRectangle(sb, 0, 0, w, h)
            End Using

            Using p = New Pen(If(Focused, _borderActiveColor, _borderNormalColor), BORDER_WIDTH)
                g.DrawRectangle(p, 0, 0, w - 1, h - 1)
            End Using

        End Using

        ReleaseDC(Handle, hdc)

        Return

    End If

    MyBase.WndProc(m)

End Sub

我已经删除了默认的BorderStyle属性,并将其替换为一个简单的布尔值DrawBorder属性,该属性控制是否在控件周围绘制边框。
使用BorderNormalColor属性指定TextBox没有焦点时的边框颜色,使用BorderActiveColor属性指定控件获得焦点时的边框颜色。
FlatTextBox附带了两个主题VS2019 DarkVS2019 Light,请使用Theme属性在这两个主题之间切换。
用VB.NET编写的完整FlatTextBox控件代码https://gist.github.com/ahmedosama007/37fe2004183a51a4ea0b4a6dcb554176

相关问题