Search code examples
c#winformsmaskedtextbox

How to change text color of a MaskedTextBox on TextChange event?


I have following class derived from MaskedTextBox.
When the length of the text entered is less than the predefined text (000000000000, with length of 12), I want highlight the text in red, otherwise in green.

In my custom MaskedTextBox class, if the length of entered text is not 12 (not valid), I try to change the text color to either red or green in the OntextChange method override.
But the code I wrote does not work.

The color is always red and it does not change.

public partial class MFMaskedTextBox : System.Windows.Forms.MaskedTextBox
{
    private int lengthdefaultetext;

    protected override void OnCreateControl()
    {
        base.OnCreateControl();
        this.Mask = "0000-0000-0000";
        this.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
        this.Font = new System.Drawing.Font("Arial", 16);
        this.TextMaskFormat = System.Windows.Forms.MaskFormat.ExcludePromptAndLiterals;
        this.Text = "000000000000";
        lengthdefaultetext = this.Text.Length;
        this.ForeColor= System.Drawing.Color.Red;
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        if (this.Text.Length != lengthdefaultetext)
        {
            this.ForeColor= System.Drawing.Color.Red;
        }
        else
        {
            this.ForeColor = System.Drawing.Color.Green;
        }
    }

    protected override void OnClick(EventArgs eventargs) {
        base.OnClick(eventargs);
        this.Text = "";
    }
}

Solution

  • You're not setting the PromptChar, while the Control's Text (000000000000) is added right away, so lengthdefaultetext is always different than the Text length (12 and 14 respectively).

    Set the PromptChar to the intended '0' char (this.PromptChar = '0'), set ResetOnPrompt to false so it doesn't override AllowPromptAsInput (true as default) and use the MaskFull or MaskCompleted properties to verify whether the Mask has been filled, setting the color based on the value returned.

    InsertKeyMode is set to InsertKeyMode.Overwrite, to allow to overwrite the existing 0 chars (no need to delete one to input a new value when the Text is full).

    ► Moved the properties settings to the Control's default constructor. You should always have a default constructor. OnCreateControl or OnHandleCreated can be used to get/set properties that depends on the Control's handle existence (or its existence in relation to a container).

    If these numbers have special meaning when inserted in a specific sequence, you can create a custom MaskedTextProvider to validate the input against the Mask. A custom Provider can only be specified as argument in a MaskedTextBox constructor.

    using System.Drawing
    using System.Windows.Forms;
    
    public partial class MFMaskedTextBox : MaskedTextBox
    {
        public MFMaskedTextBox()
        {
            Font = new Font("Arial", 16);
            InsertKeyMode = InsertKeyMode.Overwrite;
            ResetOnPrompt = false;
            TextAlign = HorizontalAlignment.Center;
            TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
    
            PromptChar = '0';
            Text = "000000000000";
            Mask = "0000-0000-0000";
        }
    
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            ForeColor = MaskCompleted ? Color.Green : Color.Red;
        }
    }