views:

514

answers:

4

In a C# desktop application, I have a customer widget which contains a text box. I also have a menu item on a menu strip that has the Delete key as its short-cut key. The behaviour I'm finding is that pressing delete in the text box, which the user will expect to delete a character, is actually triggering the menu item and deleting the whole object they are working on.

Is there any way to let the text box have "first crack" at handling the key press rather than the menu item?

Thanks.

+1  A: 

I would change the shortcut key of your 'Delete the whole thing' menu item to Shift-Del or Ctrl-Del...or something that makes it a little more work for the user to delete the whole object.

If that's not an option, you could check the form's ActiveControl in the MenuStrip's delete code and if it's your TextBox, check the Textbox.SelectionStart value to get the position of the cursor in the text and manually delete the character:

if (myTextBox.Text.Length() >0) {
  int pos = myTextBox.SelectionStart;
  string txt = myTextBox.Text;
  if (pos < txt.Length()) {
     myTextBox.Text = txt.Substring(0,txt.Substring(0, pos-1) + txt.substring(pos+1);
  }
}
C-Pound Guru
@C-Pound Guru, For just the Delete key shortcut that's fine, but also do copy and paste (Ctrl-C, and Ctrl-V respectively). These are the standard short-cuts for these operations; changing them to Shift-Ctrl-C and Shift-Ctrl-V just so that the action is performed only when the user intends to perform the action on the main widget seems to make the application clunky and non-standard.The second option would be find if there was only one text box, but there are several widgets and adding an event to each one to try to guess the user's intent would be cumbersome.
Robert Gowland
+1  A: 

Are you handling the delete key at the form level? Either way, you could check for the widget having focus and then not handle the event. Even better would be to not use delete as a global shortcut, this seems along the lines of reassigning what ctrl+c, alt+f4, or tab do.

marr75
@marr75, the more I look at this issue, the more I agree that using Delete as a global shortcut was a bad idea; the amount of code we'd have to add in order to make sure that we perform the delete only when we suspect the customer wants it is staggering. Conversely, we could just handle the keypress when the widget we care about is active would get us very close to our original intention.
Robert Gowland
Correction to my previous comment: just handling the keypress when the widget we care about is active would not show the short-cut keys on the menu beside their respective actions so that is not a valid solution either.
Robert Gowland
@marr75, I have to disagree with the statement that using Delete as a short-cut key is a bad idea. We're simply applying it to a widget that doesn't have default handling. We have the exact same problem with Ctrl-C, Ctrl-V, and Ctrl-X, but lots of programs use those as short-cut keys to menu items, the difference is that they somehow are able to know when the user intends them to be applied to the main window rather than on a widget in a side-bar. (Actually, not all handle it well. We recently discovered that Microsoft Project has the same bug as us.)
Robert Gowland
A: 

Set KeyPreview to False on the Form.

The Customer Widget might be turning it on, so you may have to disable KeyPreview on the form when the text box gets focus (and re-enable it when it loses focus).

Otherwise, disabling it from the designer should work.

RBarryYoung
@RBarryYoung - Turns out KeyPreview is not on at the time that the call is made. The main menu must get some sort of special preview privilege separate from the main form.
Robert Gowland
+1  A: 

What we did

The solution we ended up using was to disable those menu items, thereby disabling their respective short-cut keys, when the control that those menu items were intended to act upon.

This solved the problem where clicking delete in an unrelated text box deletes the selected item in the main widget. However, it introduces the problem that the user has to click on the main widget in order to access those menu items. To counter this a little bit, I did make it such that the main widget regains focus when the panel with the hideable widgets is hidden.

I'm not advocating this solution, just including it for completeness.

What I would have liked

My ultimate solution would be to only perform the action only if:

  1. the main widget has focus, OR
  2. the even was triggered via clicking the menu item

but there doesn't seem to be a way to detect whether the even was triggered by a short-cut key within the framework.

Robert Gowland