views:

219

answers:

2

If I do not create an "Edit->Copy" menu item and assign it the shortcut keys "CTRL+C", then I can select a control (RichTextBox, DataGridView, etc..) and hit "CTRL+C" and the control itself will handle the copy. I can copy text out, and paste it into notepad, etc..

Now throughout my whole form, I have a lot of controls. But I have a custom control that I want to make clear that I handle Copy functionality for. So I added the ShortcutKey CTRL+C to Edit->Copy, and by default it is set to Enabled.

Now, I have to implement an event handler for the 'click' event on that menu item. If I explicitly put in code to handle the copy, then it works:

public void menuEditCopy_Click(object sender, EventArgs e)
{
    myCustomControl.Copy();
}

However, now Copy does not work on any other type of control. My first inclination was to find out the type of control that has focus, and implement a limited set of copy code for each of them:

public void menuEditCopy_Click(object sender, EventArgs e)
{
    if (this.ActiveControl is MyCustomControl)
    {
        ((MyCustomControl)this.ActiveControl).Copy();
    }
    else if (this.ActiveControl is RichTextBox)
    {
        ((RichTextBox)this.ActiveControl).Copy();
    }
}

etc...

However, my controls are added to a SplitContainer, and debugging shows that this.ActiveControl is set to the splitcontainer instance, not the control, even though I know that control is selected.

So my last thought is to literally check if every control has focus:

public void menuEditCopy_Click(object sender, EventArgs e)
{
    if (myCustomControl.Focused)
    {
        myCustomControl.Copy();
    }
    else if (richTextBox1.Focused)
    {
        richTextBox1.Copy();
    }
}

I would like to avoid this if possible, it is a lot of controls, and if I add a new control, I would need to update it. Is there a better way of doing this?

Thanks

+1  A: 

A SplitContainer implements ContainerControl, so you could check for either one and look for it's ActiveControl instead. ContainerControl is the base class, so I would go for that - you might catch another type of container as well:

private void DoCopy(Control control)
{
    if(control is ContainerControl)
        DoCopy(control.SelectedControl);
    else if(control is MyCustomControl)
        ((MyCustomControl)control).Copy();
    else if(control is RichTextBox)
        ((RichTextBox)control).Copy();
    else
        throw new NotSupportedException("The selected control can't copy!");
}

void menuEditCopy_Click(object sender, EventArgs e)
{
    DoCopy(this.ActiveControl);
}
lc
A: 

You could try settting the KeyPreview property of your form to true. Then you could set up a handler for the form's KeyDown event which would look like the following:

private void Form_KeyDown(object sender, KeyEventArgs e)
{
    if(e.Modifiers == Keys.Control && e.KeyCode == Keys.C)
    {
        if (ActiveControl.GetType() == typeof(MyCustomControl))
        {
            ((MyCustomControl)ActiveControl).Copy();
            e.Handled = true;
        }
    }
}

Here you are specifying that you have handled the Ctrl-C event by setting the event args Handled property to true. Else, if you leave it as false, the Ctrl-C key press will be handled as per usual by each individual control.

Because we have set the KeyPreview to true the form's handler gets to see each key press before any other control that it contains and can decide to deal with the key press itself or else allow it to be handled in the same way as if the form had never previewed it.

I think as well it would be necessary to remove the short-cut key from your menu item (although you could still manually put the text "Ctrl+C" next to your menu item name) for this to work, otherwise your menu item will hijack the key stroke.

Clive