Nithin B
Nithin B

Reputation: 680

How to draw border for MaskedTextBox using custom color?

I am trying to create a masked textbox to have a border colors.

I tried this below code to achieve it:

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

But the problem is it does not have the all features of the masked text box like setting mask type etc.

So I changed my code like this:

public class MaskedTextBoxWithBorder : UserControl

Now I have all features of Masked text box but border colors are not affected.

Is there any way to extend Masked textbox to get border style without losing features something like this which is not possible.

public class MaskedTextBoxWithBorder : UserControl, MaskedTestBox

Upvotes: 2

Views: 954

Answers (3)

Reza Aghaei
Reza Aghaei

Reputation: 125322

To draw border of MaskedTextBox you should override WndProc and handle WM_NCPAINT message. Then get the window dc of the control and create a Graphics object from that dc, then draw border for control.This solution has been used also in ToolStripTextBox. The solution can be applied also on a 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);
        }
    }
}

Upvotes: 2

Phil1970
Phil1970

Reputation: 2624

Well, usually in a given application, you only change a few property so you might simply add some extra property to your user control for those properties you want to be able to change.

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

If you really want to change a lot of properties, then other solutions might be more appropriate...

Upvotes: 0

Timo Salomäki
Timo Salomäki

Reputation: 7189

TextBox and MaskedTextBox controls are only wrappers of Win32 TextBox controls so owner drawing them (for custom borders, overlays or anything else) is a bit more complex than normally. Here's what you should do to achieve what you're trying to do.

  1. Derive from MaskedTextBox: public class MaskedTextBoxWithBorder : MaskedTextBox
  2. Get access to the message stream for the Win32 TextBox (it draws itself in response to multiple messages so you need to catch them all, not just the standard WM_PAINT message).
  3. Get the handle to the device context and transform it into a managed Graphics object to draw the border.

Take a look at the following article that explains each step in detail: Adding an Icon or Control to a TextBox or ComboBox

Even though the article discusses the basic TextBox control, it doesn't matter. Both TextBox and MaskedTextBox derive from the TextBoxBase class, which implements all the important parts we're interested in.

Upvotes: 2

Related Questions