【问题标题】:How to draw border for MaskedTextBox using custom color?如何使用自定义颜色为 MaskedTextBox 绘制边框?
【发布时间】:2016-09-09 07:29:04
【问题描述】:

我正在尝试创建一个带有边框颜色的蒙版文本框。

我尝试了下面的代码来实现它:

public class MaskedTextBoxWithBorder : UserControl
{
    MaskedTextBox maskedtextBox;

    public MaskedTextBoxWithBorder()
    {
        maskedtextBox = new MaskedTextBox()
        {
            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(maskedtextBox);
        this.Controls.Add(container);

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

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

    public override string Text
    {
        get
        {
            return maskedtextBox.Text;
        }
        set
        {
            maskedtextBox.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, maskedtextBox.PreferredHeight, specified);
    }
}

但问题是它不具备蒙版文本框的所有功能,例如设置蒙版类型等。

所以我像这样更改了我的代码:

public class MaskedTextBoxWithBorder : UserControl

现在我拥有了蒙版文本框的所有功能,但边框颜色不受影响。

有没有什么方法可以扩展 Masked 文本框以获取边框样式而不会丢失类似这样的功能,这是不可能的。

public class MaskedTextBoxWithBorder : UserControl, MaskedTestBox

【问题讨论】:

  • 你不需要那个容器控件。 UserControl 已经是一个容器控件。

标签: c# winforms maskedtextbox


【解决方案1】:

要绘制MaskedTextBox 的边框,您应该覆盖WndProc 并处理WM_NCPAINT 消息。然后获取控件的窗口 dc 并从该 dc 创建一个Graphics 对象,然后为控件绘制边框。此解决方案也已在ToolStripTextBox 中使用。该解决方案也可以应用于TextBox

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyMaskedTextBox : MaskedTextBox
{
    public const int WM_NCPAINT = 0x85;
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);
    [DllImport("user32.dll")]
    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_NCPAINT)
        {
            var hdc = GetWindowDC(this.Handle);
            using (var g = Graphics.FromHdcInternal(hdc))
            {
                g.DrawRectangle(Pens.Blue, new Rectangle(0, 0, Width - 1, Height - 1));
            }
            ReleaseDC(this.Handle, hdc);
        }
    }
}

【讨论】:

  • 还要了解如何更改焦点边框颜色,请查看this post
  • 另外here 是如何为TextBox 添加BorderColor 属性的示例。
  • 该帖子似乎回答了您的问题,如果您接受答案,那就太好了。否则,如果您在应用答案时遇到任何问题,请告诉我。还要确保查看 linked post,其中包含 BorderColor 属性的完整实现。
  • 感谢您的反馈,您可以在this post 中看到包含BorderColor 的更完整版本。
【解决方案2】:

TextBox 和 MaskedTextBox 控件只是 Win32 TextBox 控件的包装,因此所有者绘制它们(用于自定义边框、覆盖或其他任何东西)比通常要复杂一些。以下是你应该做的事情来实现你想要做的事情。

  1. 从 MaskedTextBox 派生:public class MaskedTextBoxWithBorder : MaskedTextBox
  2. 获取对 Win32 TextBox 消息流的访问权限(它会自行绘制以响应多条消息,因此您需要捕获所有消息,而不仅仅是标准的 WM_PAINT 消息)。
  3. 获取设备上下文句柄并将其转换为托管的 Graphics 对象以绘制边框。

请查看以下详细解释每个步骤的文章:Adding an Icon or Control to a TextBox or ComboBox

尽管本文讨论了基本的 TextBox 控件,但这并不重要。 TextBox 和 MaskedTextBox 都派生自 TextBoxBase 类,它实现了我们感兴趣的所有重要部分。

【讨论】:

  • 边框是在非客户区绘制的,使用自定义颜色绘制边框需要处理的唯一消息是WM_NCPAINT
【解决方案3】:

嗯,通常在给定的应用程序中,您只需更改一些属性,因此您可以简单地将一些额外的属性添加到您的用户控件中,以获得您希望能够更改的那些属性。

public class MaskedTextBoxWithBorder : UserControl
{
    MaskedTextBox maskedtextBox;

    // Other existing code...

    public string Mask
    {
        get { return maskedtextBox.Mask; }
        set { maskedtextBox.Mask = value; }
    }

    // Do same thing for other properties you want to change...
}

如果您真的想更改很多属性,那么其他解决方案可能更合适...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2022-01-20
    • 2016-12-17
    • 2013-08-27
    相关资源
    最近更新 更多