9

我有以下代码:

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

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

这很完美,但在获得焦点之前它不会显示文本。

有谁能够帮我?怎么了?

预先感谢。

4

4 回答 4

34

要更改边框颜色,TextBox您可以覆盖WndProc方法并处理WM_NCPAINT消息。然后获取控件的窗口设备上下文,GetWindowDC因为我们要绘制到控件的非客户区。然后绘制,从该上下文创建一个对象就足够了Graphics,然后为控制绘制边框。

要在属性更改时重绘控件BorderColor,可以使用RedrawWindow方法。

代码

这是一个TextBox具有BorderColor属性的。BorderColor如果属性值不同于Color.Transparent并且BorderStyle是其默认值,则控件使用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);
    }
}

结果

这是使用不同颜色和不同状态的结果。如下图所示,支持所有边框样式状态,您可以使用任何颜色作为边框:

在此处输入图像描述

下载

您可以克隆或下载工作示例:

于 2016-09-09T22:25:03.893 回答
6

您还必须手动绘制文本。

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

或者,如果没有给你想要的结果,你可以尝试使用e.Graphics.DrawString()方法(我总是用这种方法得到更好的结果)。TextRenderer

于 2013-07-04T09:10:46.083 回答
1

将文本框边框样式设置为无,然后将此代码写入容器表单“绘制”事件

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

}
于 2014-01-22T21:10:50.830 回答
1

有几种方法可以做到这一点,但没有一种是理想的。这只是 WinForms 的本质。但是,您有一些选择。我将总结:

您可以实现所需的一种方法是将 a 嵌入 aTextBoxPanel,如下所示。

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

您也可以在不覆盖任何控件的情况下执行此操作,但上述方法更好。当控件获得焦点时,上面将绘制一个边框。如果您希望永久启用边框,请将FocusedAlways属性设置为True.

我希望这有帮助。

于 2013-07-04T09:19:17.390 回答