Sdílet prostřednictvím


Setting Alignment in TextBoxes...No Looking Glass Required

In yesterday's post I stated that "non-character keys do not trigger KeyPress events." While that is perfectly true, I misunderstood what was meant by a non-character key. In the non-managed Win32 world, pressing a key generates a WM_KEYDOWN, one or more WM_CHAR messages, and a WM_KEYUP message. The managed KeyPress event corresponds to the WM_CHAR message. Windows generates WM_CHAR messages for keys that are mapped to ASCII characters by the keyboard driver. Since pressing the Enter key generates an ASCII character code (0xA, 0xD, or both), a KeyPress event is generated for it.

So, while the code I posted yesterday works, it can be simplified by eating the Enter key in the textbox's KeyPress event handler rather than using the form's KeyPreview.

 
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ('\r' == e.KeyChar)
            {
                // Supress enter key
                e.Handled = true;
            }
        }

In addition, since the textbox is no longer dependent on the form for functionality, I can package it up in it's own class.

 
    public class TextBoxWithAlignment : TextBox
    {
        // Remember whether user wants the textbox to act like a 
        // single-line or multiline textbox.
        //
        private bool multiline = false;

        public TextBoxWithAlignment()
        {
            // The underlying control will always be a multiline textbox
            //
            base.Multiline = true;
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            // When the user wants a single-line textbox,
            // eat carriage returns
            //
            if (!this.multiline && '\r' == e.KeyChar)
            {
                e.Handled = true;
            }
            base.OnKeyPress(e);
        }

        // Override the Multiline property to use the internal multiline flag
        //
        public override bool Multiline
        {
            get
            {
                return this.multiline;
            }
            set
            {
                this.multiline = value;
            }
        }
    }

Pretty nifty, IMHO.

Cheers
Dan