Tinkerer_CardTracker
Tinkerer_CardTracker

Reputation: 3647

WinForm text box: MenuStrip keyboard shortcuts overriding OS-level copy/paste

Update: I've figured out the source of the issue, now trying to figure out the best fix

I've got a Form with a customized MenuStrip, with all sorts of bells and whistles. Of note here, is that many of my MenuStrip items have keyboard shortcuts - namely ones for Cut/Copy/Paste.

It appears that the presence of this MenuStrip is overriding (and therefore cancelling) the default Cut/Copy/Paste keyboard shortcut behaviors for my text boxes (and other controls).

All of them.

.

I can't really say I have a reason for the MenuStrip Cut/Copy/Paste options, besides the fact that I would expect to see them there. That's how Office type programs operate, and it's something the user (myself included) would expect.

I could remove the Cut/Copy/Paste options from the MenuStrip, but that would be admitting defeat! So how do I keep my overly engineered MenuStrip from forcing me to implement custom code for EVERY control that's Cut/Copy/Paste friendly?

.


** Original Post: **I've got a TextBox control in a toolbar which is to be used throughout my program. Imagine my surprise when native OS-level Copy/Paste events were not supported by default.

Sure, I could code something manually, but when I right-click on the control, Cut/Copy/Paste are already built in. How can I leverage this existing functionality?

I figure adding a KeyDown event with Ctrl+C, P, and X would be about the maximum I should have to code. For those events I just call a built-in method or something. That, or find a setting that enables native cut/copy/paste.

What am I overlooking/missing?

Upvotes: 2

Views: 1178

Answers (3)

eri0o
eri0o

Reputation: 2450

I had a similar problem and the solution done was to not register the shortcuts in the Edit menu entries, but instead, for each entry in the menu use the ShortcutKeyDisplayString property to have the text Ctrl+C, Ctrl+V and so on, and actually leave the shortcut entry blank. Now the entries are shown there and the copy and pasting with shortcut will work with the required entries.

The last piece of the puzzle is some soul may actually the darn menu entry, so something has to be done about that. The approach here, if someone does click the thing you have to run some command, the command is find out what control has focus and then do the action in the control specific to it. So, something like

Control c = GetFocusedControl();
TextBox tbox = c as TextBox;
if (tbox != null)
{
    if (cmd == CUT) tbox.Cut();
    else if (cmd == COPY) tbox.Copy();
    else if (cmd == PASTE) tbox.Paste();
    else if (cmd == UNDO) tbox.Undo();
    return;
}

this is not real code so you will have to adapt to whatever is your problem. For getting the control focus there are a few stackoverflow entries about it and you can also use GetFocus from user32.dll along.

Upvotes: 0

Tinkerer_CardTracker
Tinkerer_CardTracker

Reputation: 3647

Easy Solution: Use the SendKeys.Send() call within the Click event.

SendKeys.Send("^X"); 

I'm doing something a little more complicated, so here's the details: I'm making several Forms, which all share some custom controls: MenuStrip, StatusStrip, and a few other custom controls. I've decided to have the Forms all inherit from the same base class, to allow common implementation of lots of stuff.

public partial class CommonFormBase : Form
{
    private void Initialize()
    {
        //Bind click event for custom MenuStrip to events in the local Form
        CommonMenuStrip.Edit_Cut.Click += new EventHandler(Edit_Cut_Click);
        CommonMenuStrip.Edit_Copy.Click += new EventHandler(Edit_Copy_Click);
        CommonMenuStrip.Edit_Paste.Click += new EventHandler(Edit_Paste_Click);
    }

    //Implement Click events for the MenuStrip by calling local methods
    internal void Edit_Cut_Click(object sender, EventArgs e) { Cut(); }
    internal void Edit_Copy_Click(object sender, EventArgs e) { Copy(); }
    internal void Edit_Paste_Click(object sender, EventArgs e) { Paste(); }

    //Generic implementation of common commands for the CommonFormBase
    public virtual void Cut() { SendKeys.Send("^X"); }
    public virtual void Copy() { SendKeys.Send("^C"); }
    public virtual void Paste() { SendKeys.Send("^V"); }
}

I implemented the MenuStrip's click event at the Form level (not the MenuStrip level), but in that event I only call a generic method, which does all the code. In this example it's overkill, but I have other MenuStrip commands that will change in functionality for different child Forms, so I figured having them all work the same would be easier.

Anyway, this works almost perfectly! It seems to push the shortcut-key-activated MenuStrip_Click event to the underlying control (or maybe the Form?), which then implements default shortcut key events.

The only thing it does wrong is it only triggers ONCE when you do Ctrl + V + V + V... or hold Ctrl+V. Still, that's just a matter of the trigger not recognizing multiple events, not an issue with the solution itself.

Upvotes: 1

Mark Hall
Mark Hall

Reputation: 54532

Testing it out native copy and paste does work on a TextBox control unless you are overridding the ContextMenu or ContextMenuStrip, in that case you will need to use the ClipBoard Class to implement it yourself.


In looking at it further this MSDN Forum article discusses sending the Commands to the Native Textbox Control using the SendMessage Method. This is implemented in a Custom TextBox which sounds like what you are doing.

Small excerpt see article for further implementation:

protected void itemCut_Click(object sender, EventArgs e)
{
   SendMessage(this.Handle, TextBoxMessages.WM_CUT, 0, 0);
}


public static class TextBoxMessages
{
    public const int EM_UNDO = 0x00C7;
    public const int WM_CUT = 0x0300;
    public const int WM_COPY = 0x0301;
    public const int WM_PASTE = 0x0302;
}

Upvotes: 1

Related Questions