With great power comes great responsibility. When you assign a keyboard shortcut to a SandBar menu item, every press of that keyboard shortcut will trigger that menu item's Activate instead of whatever it would have done previously. The exception is when the focus is contained in a well-written native .net control, in which case SandBar will pass the keystroke to that control if it indicates it wants to process it. Unfortunately most of the out-of-the-box .net controls are merely wrappers for win32 controls so do not have this rich functionality.
Clipboard shortcuts are the most common place for application authors to forget about handling every situation gracefully. Depending on the complexity of your form one of any number of different controls could have the focus when a keyboard shortcut is activated. Those controls could be .net or win32. For instance, what if the user is midway through editing text in a label in a TreeView or ListView control. If they decide to use your Edit menu to cut some text, they will expect it to work. A great deal of .net programs will fall short at this point.
There is no good managed way to deal with clipboard commands and focused controls, unfortunately. When integrating proper clipboard support you will need to use a little platform invoke to make sure things are done smoothly and in a manner the user would expect. Here's the flow of what happens on a clipboard shortcut press:
User activates keyboard shortcut (Ctrl-X)
SandBar catches the shortcut and asks the active control whether it would like to handle it (if yes, finish here)
SandBar activates the menu item that corresponds to the shortcut
Your application queries the focus and attempts to find a .net control that corresponds
Your application calls a method on the control if it's of a known type OR as a last resort sends the WM_CUT message
Using this system you can ensure the greatest compatibility between your menus and the rest of Windows. In a large MDI application you might choose to pass the message on to your active document (which might implement an IClipboard interface) for special processing. What's important is that if you cannot handle the shortcut specially, you pass the message on by sending a window message to the focused control.
Here is a snippet of code that should be used as a skeleton framework for handling clipboard shortcut activations. It handles win32 controls as well as extended support for .net TextBox and RichTextBox controls.
[code]
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]
private static extern IntPtr GetFocus();
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
private const int WM_CUT = 0x300;
private const int WM_COPY = 0x301;
private const int WM_PASTE = 0x302;
private const int WM_UNDO = 0x304;
private void mnuEditCut_Activate(object sender, System.EventArgs e)
{
Control focusedControl = GetFocusedControl();
if (focusedControl is TextBoxBase)
((TextBoxBase)focusedControl).Cut();
else if (focusedControl is MyControlType)
{
// Special application processing for this event
}
else
SendMessage(new HandleRef(this, GetFocus()), WM_CUT, 0, 0);
}
private void mnuEditCopy_Activate(object sender, System.EventArgs e)
{
Control focusedControl = GetFocusedControl();
if (focusedControl is TextBoxBase)
((TextBoxBase)focusedControl).Copy();
else if (focusedControl is MyControlType)
{
// Special application processing for this event
}
else
SendMessage(new HandleRef(this, GetFocus()), WM_COPY, 0, 0);
}
private void mnuEditPaste_Activate(object sender, System.EventArgs e)
{
Control focusedControl = GetFocusedControl();
if (focusedControl is TextBoxBase)
((TextBoxBase)focusedControl).Paste();
else if (focusedControl is MyControlType)
{
// Special application processing for this event
}
else
SendMessage(new HandleRef(this, GetFocus()), WM_PASTE, 0, 0);
}
private void mnuEditUndo_Activate(object sender, System.EventArgs e)
{
Control focusedControl = GetFocusedControl();
if (focusedControl is TextBoxBase)
((TextBoxBase)focusedControl).Undo();
else if (focusedControl is MyControlType)
{
// Special application processing for this event
}
else
SendMessage(new HandleRef(this, GetFocus()), WM_UNDO, 0, 0);
}
private void mnuEditRedo_Activate(object sender, System.EventArgs e)
{
Control focusedControl = GetFocusedControl();
if (focusedControl is RichTextBox)
((RichTextBox)focusedControl).Redo();
else if (focusedControl is MyControlType)
{
// Special application processing for this event
}
else
SendMessage(new HandleRef(this, GetFocus()), WM_UNDO, 0, 0); // Win32 has no WM_REDO, so we'll just send another WM_UNDO
}
private Control GetFocusedControl()
{
// Try and find the .net control instance with the focus
IntPtr focus = GetFocus();
if (focus == IntPtr.Zero)
return null;
else
return Control.FromHandle(focus);
}
[/code]