2010-06-01 25 views
4

我的问题很简单:发送键盘事件,以另一种形式

我们的C#应用​​程序有一个MainForm中有一个菜单,并在菜单项相关的几个快捷键。

现在我们还需要从某些子窗体中触发菜单条目。但是由于当其中一个子窗体处于活动状态时,MainForm处于非活动状态,因此快捷方式不起作用。

是否有一种简单的方法将所有键盘事件从子窗体传播到“所有者”窗体?或者只是针对另一种形式?

啊,我们不能使用一些低级别的窗口,因为我们需要在Mono/Linux上运行应用程序。

编辑: 我的确切问题是触发与另一种形式相同的快捷菜单项。当然,如果添加新项目的菜单更改,则不更新表单中的代码。

+0

我拼命地想这个问题的答案,以及我的编辑程序。 – Tesserex 2010-06-01 14:44:51

+0

IMessageFilter在Mono中可用,您可以将它用于主窗体。 – 2010-06-01 17:16:36

+0

hm ...不知道我们是否想处理这个消息对象..或者有没有简单的方法将这样的消息转换为事件? – thalm 2010-06-04 18:39:22

回答

1

这是固定的,对我来说:

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); 
    } 
} 
0

我想你想设置KeyPreview父窗体为true

当此属性设置为true,窗体将接收所有按键响应,KeyDown和KEYUP事件。在表单的事件处理程序完成键击处理之后,将键击分配给具有焦点的控件。例如,如果KeyPreview属性设置为true,并且当前选定的控件是一个TextBox,则在由该窗体的事件处理程序处理击键后,TextBox控件将接收按下的键。要仅处理表单级别的键盘事件并且不允许控件接收键盘事件,请将表单的KeyPress事件处理函数中的KeyPressEventArgs.Handled属性设置为true。

编辑:

this question答案可能会有所帮助:

+0

这只会导致窗体处理收到其控件的关键事件。 – SLaks 2010-06-01 14:37:05

+0

好主意,但它没有帮助,因为MainForm只是子表单的'所有者',而不是'。Parent'的.Net意义上的(我在帖子中的命名并不清楚,对不起)。当我尝试设置'Parent'属性时,我得到一个异常,因为表单是一个顶层控制..任何进一步的想法? – thalm 2010-06-01 14:51:12

+0

编辑我的答案,因为我第一次提供不会做你想做的。 – 2010-06-01 14:59:47

0

ToolStrip.AllowMerge属性 “中获取或设置[...]无论多MenuStripToolStripDropDownMenuToolStripMenuItem,和其他类型的可以结合起来。” (MSDN)。

这意味着您可以:

“使用AllowMerge属性启用多文档接口(MDI)的孩子各自的菜单在MDI父结合起来。” (AllowMerge属性,此言一出,MSDN)

参见:

  1. MergeAction
  2. MergeIndex

此,我希望,可以帮助你得到你想要的东西。现在,我不知道这是适用于Windows窗体,还是一旦构建就可以在Linux上运行。

+0

看到其他帖子,我们没有任何其他菜单加入或合并..或者你是怎么意思这可以解决问题? – thalm 2010-06-04 18:37:26

+0

您必须在MDI容器和子窗体上都有一个MenuStrip。然后,您允许它们合并,甚至替换某些相同的对等菜单。 – 2010-06-07 02:28:50

1

你试过类似的东西吗?

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); 
     } 
    } 
} 
+0

是的,我想这可以工作,我会试试看,并报告.. thnx! – thalm 2010-06-04 18:39:56

+0

你好再次,它不工作就像..我可以将键盘事件发送到MainForm,并调用OnKeyXXX事件,但这不会触发MenuItems中的事件..这真是一个奇怪的问题..我认为这会更容易... – thalm 2010-06-04 21:40:45

+0

也许尝试使用RaiseKeyEvent。 – 2010-06-04 22:18:47

0

我认为你是不活跃的,你的意思是说它没有焦点?

执行此操作最简单的方法是让每个表单暴露与正在操作的菜单相关的事件。当您创建表单时,将它们订阅给彼此(或从孩子到MainForm或以任何方式流向需要)。点击菜单后,执行您的额外事件,另一个表单将收到此信息。

这有帮助吗?我认为这比手动强制消息更好,因为它将是自我记录代码,表单需要彼此作出反应。

更“远离问题”的方法,你需要两种形式还是可以重构UI设计?

+0

你好,谢谢你的回复! 我们只有一个菜单,即主窗体,但其他窗体都应该可以用键盘快捷键触发菜单项。我们不需要另一种形式的另一个菜单,并且如果菜单项被点击,我们不需要通知其他形式。所以它没有真正的帮助.. – thalm 2010-06-04 18:35:21

+0

啊..是的..我可以重构UI设计。那么你的想法是什么? – thalm 2010-06-06 18:19:53

0

有很简单的方法来做到这一点。菜单项应该触发适当的方法调用。然后你可以在应用程序的任何地方调用这些方法。

+0

是的,我可以做到这一点,但我想用其他形式的键盘快捷键触发它们。我想只定义一次当然的快捷方式... – thalm 2010-06-06 18:21:13

0

而不是将主键快捷键绑定到主窗体上的菜单项,您可以创建一个对键快捷键作出反应的自定义键处理方法。把这个方法放在主窗体中。然后从关键事件的所有子窗体中调用此方法。 @Adam Driscoll的代码与这种方法非常相容。