2

I have a C# WinForms sample application, demonstrating interesting key handling issue. That's very simple: there is just a Form and TextBox on it. I set TextBox ReadOnly property to true.

enter image description here

I have the next code in my Form:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyData.HasFlag(Keys.R))
        {
            MessageBox.Show("There is 'R' key in KeyDown event");
        }
    }
}

When I press Ctrl-R keys, the MessageBox doesn't show up. But if I set ReadOnly property of TextBox to true, the MessageBox appears. The same thing happens, when I press Shift-R or Alt-R on ReadOnly TextBox.

enter image description here

Any ideas, what is special with ReadOnly TextBox and Ctrl-R combination?

jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
Artem Kachanovskyi
  • 1,839
  • 2
  • 18
  • 27

4 Answers4

3

There is a patch in the TextBoxBase.ProcessCmdKey() method, it fixes a problem with certain short-cut keys still modifying the text when the control's ReadOnly property is set. They are Ctrl+R, Ctrl+J, Ctrl+E and Ctrl+L.

Afaik, this patch is a bit too crude, it should only apply to RichTextBox.

This problem is fixable by overriding the TextBox class and restore the normal behavior of these keys. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox, replacing your original textbox.

using System;
using System.Windows.Forms;

class MyTextBox : TextBox {
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        if (keyData == (Keys.Control | Keys.R) ||
            keyData == (Keys.Control | Keys.L) ||
            keyData == (Keys.Control | Keys.E) ||
            keyData == (Keys.Control | Keys.J)) return false;
        return base.ProcessCmdKey(ref msg, keyData);
    }
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Small edit: I added a **ReadOnly** `&& keyData == (Keys.Control | Keys.R)..` to that check – Artem Kachanovskyi Oct 07 '14 at 11:53
  • That isn't actually necessary, but ala. – Hans Passant Oct 07 '14 at 18:31
  • This doesn't fix the issue for menu shortcuts, though, because they _should_ be handled by this. – Nyerguds Feb 17 '16 at 13:37
  • The only workaround I found was to both use this replaced TextBox _and_ to catch KeyDown events on my textboxes, filtering out the calls whose source was a TextBox with ReadOnly set, and then calling the menu function for that specific key combination (Ctrl+E in my case). – Nyerguds Feb 17 '16 at 13:47
1

It appears this is a known issue. You'd have to ask Microsoft for the why of it... http://social.msdn.microsoft.com/Forums/en-US/941c9759-5531-49fe-9ebb-7fc6d812b0fd/ctrle-not-working-in-a-read-only-text-box?forum=csharplanguage

General advice: If you want to detect a specific character, then use KeyPress(). It is called after translation from the keyboard key to the character set.

private void textBox1_KeyPress(Object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 'R')
        MessageBox.Show("Hit an 'R'");
}

To handle keyboard "shortcuts", change the test:

if (ModifierKeys == Keys.Control && e.KeyChar == 'R')
DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
  • Thank you, that's a good point. But I need to handle keyboard shortcut. `KeyDown` fits more for that purpose. – Artem Kachanovskyi Oct 07 '14 at 11:46
  • Neither is better than the other, just suit the approach to the handler you choose. Again, it comes down to wanting the physical keyboard key versus the _character_. – DonBoitnott Oct 07 '14 at 14:51
0

You might look at the ShortCutsEnabled property.

As already seen on this post: Why are some textboxes not accepting Control + A shortcut to select all by default

Community
  • 1
  • 1
Piggeldy
  • 16
  • 1
0

For CTRL+R combination

private void KeyDown(object sender, KeyEventArgs e)
{
  if (e.Control && e.KeyCode == Keys.R)
  {
    //your code
  }
}
jayvee
  • 160
  • 2
  • 17
  • This didn't help. Works for, let's say, Shift-R, but not Ctrl-R. – Artem Kachanovskyi Oct 07 '14 at 09:53
  • What do you mean? Of course the above code will work if the user press CTRL+R not Shift+R. If you want to include Shift you can use `e.Shift && e.KeyCode == Keys.R)` – jayvee Oct 07 '14 at 09:58
  • I meant if you set the `TextBox` `ReadOnly = true`, `if (e.Control && e.KeyCode == Keys.R)` doesn't work for Ctrl-R, but `e.Shift && e.KeyCode == Keys.R)` works for Shift-R. – Artem Kachanovskyi Oct 07 '14 at 09:59
  • I see. The another option here is to transfer your KeyDown event in `Form_KeyDown(object sender, KeyEventArgs e)` and Set the form properties `KeyPreview = true` – jayvee Oct 07 '14 at 11:16