views:

110

answers:

6

Hello,

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 need 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.

A: 

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:

Sam Holder
This only causes the form to handle key events received its controls.
SLaks
Good idea, but it didn't help, as the the MainForm is only the 'Owner' of the Child Forms, but not the 'Parent' in .Net sense (my naming in the post wasn't clear about that, sorry). When I try to set the 'Parent' property i get an exception, because a Form is a toplevel Control.. any further ideas?
thalm
edited my answer as what I first provided doesn't do what you want.
Sam Holder
the solution you suggested in your edit looks similar to Adam Driscolls solution, i will try that.
thalm
A: 

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.

Will Marcouiller
see the other post, we dont have any other menus to join or merge.. or how did you mean this could solve the problem?
thalm
You have to have a MenuStrip on both the MDI container and the child form. Then, you allow them to merge, even replace certain of the equivalent menus from each other.
Will Marcouiller
+1  A: 

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);
       } 
    }
}
Adam Driscoll
yes, i guess this could work, i will try it out and report back.. thnx!
thalm
hello again, its not working like that.. i can send the keyboard events to the MainForm, and call the OnKeyXXX event, but this does not trigger the Events in the MenuItems.. this is really a strange problem.. i thought this would be easier...
thalm
Maybe try using RaiseKeyEvent.
Adam Driscoll
A: 

Hi,

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?

Adam
hello, thanks for your reply!we have only one menu, that is in the main form, but every other form should be able to trigger the menu items with keyboard shortcuts too. we dont need another menu in another form and we dont need to notify other forms if a menu item was clicked. so it doesnt really help..
thalm
ah.. and yes.. i could refactor the UI design. what would be your idea then?
thalm
A: 

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

Tomas Voracek
yes, i can do that, but i want to trigger them with the same keyboard shortcuts from other forms. and i want to define the shortcut only once of course...
thalm
A: 

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.

agsamek