开发者

Send Keyboard Events from one Form to another Form

my question is quite simple:

Our C# application has one MainForm with a menu and several keyboard shortcuts associated with the menu entries.

Now we nee开发者_运维知识库d to trigger the menu entries from some child forms too. But since the MainForm is inactive when one of the child forms is active, the shortcuts do not work.

Is there a simple way to propagate all keyboard events from the child form to the 'Owner' form? Or just to another form in general?

Ah, and we cannot use some low level windows stuff, because we need to run the application on Mono/Linux too.

EDIT: The exact problem i have is to trigger the menu items with the same shortcut from another form. Of course without updating code in the forms if the menu changes of new items are added.


This is what fixed it for me:

public class MainForm : Form
{
    public bool ProcessCmdKeyFromChildForm(ref Message msg, Keys keyData)
    {
        Message messageCopy = msg;
        messageCopy.HWnd = this.Handle; // We need to assign our own Handle, otherwise the message is rejected!

        return ProcessCmdKey(ref messageCopy, keyData);
    }
}

public class MyChildForm : Form
{
    private MainForm mMainForm;

    public MyChildForm(MainForm mainForm)
    {
        mMainForm = mainForm;
    }

    // This is meant to forward accelerator keys (eg. Ctrl-Z) to the MainForm
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (mMainForm.ProcessCmdKeyFromChildForm(ref msg, keyData))
        {
            return true;
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }
}


Did you try something like this?

ParentForm : Form
{
    public NotifyKeyPress(KeyPressEventArgs e)
    {
         OnKeyPress(e);
    }
}

ChildForm : Form
{
    ParentForm _parent;
    public ChildForm(ParentForm parent)
    {
       _parent = parent;
       KeyPress += KeyPressHandler;
    }

    public KeyPressHandler(object sender, KeyPressEventArgs e)
    {
       if (_parent != null)
       {
           _parent.NotifyKeyPress(e);
       } 
    }
}


I think you want to set KeyPreview on the parent form to true

When this property is set to true, the form will receive all KeyPress, KeyDown, and KeyUp events. After the form's event handlers have completed processing the keystroke, the keystroke is then assigned to the control with focus. For example, if the KeyPreview property is set to true and the currently selected control is a TextBox, after the keystroke is handled by the event handlers of the form the TextBox control will receive the key that was pressed. To handle keyboard events only at the form level and not allow controls to receive keyboard events, set the KeyPressEventArgs.Handled property in your form's KeyPress event handler to true.

EDIT:

the answer in this question might be helpful:


The ToolStrip.AllowMerge property "gets or sets [...] whether multiple MenuStrip, ToolStripDropDownMenu, ToolStripMenuItem, and other types can be combined." (MSDN).

This means that you can:

"Use the AllowMerge property to enable multiple-document interface (MDI) children to combine their respective menus in the MDI parent." (AllowMerge property, Remark, MSDN)

See also:

  1. MergeAction
  2. MergeIndex

This, I hope, will help you get what you want. Now, I don't know if this is proper to Windows Forms or if it shall work on Linux too once built.


I presume by inactive you mean that it doesn't have focus?

The cleanest way to do this is to have each form expose events that relate to their menus being manipulated. When you create the forms, subscribe them to each other (or from child to MainForm or whatever way the flow needs to go). When the menu is clicked, execute your extra event and the other form will receive this.

Does that help? I believe that this is better than trying to force a message manually as it will be self-documenting code that the forms need to react to each other.

A more "away from the problem" approach, do you need two forms or can you refactor the UI design?


There is much simpler way to do this. Menu items should trigger appropriate method calls. Then you can call these methods anywhere in application.


Instead of binding key shortcuts to menu items on the main form you can create a custom key-processing method that reacts to the key shortcuts. Put this method in the main form. Then invoke this method from all child forms on a key event. @Adam Driscoll's code is much compatible with this approach.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜