将键盘事件从一个表单发送到另一个表单

时间:2010-06-01 14:27:50

标签: c# events forms mono keyboard

我的问题很简单:

我们的C#应用​​程序有一个带有菜单的MainForm和几个与菜单项相关联的键盘快捷键。

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

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

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

编辑: 我遇到的确切问题是从另一个表单触发具有相同快捷方式的菜单项。当然,如果添加新项目的菜单更改,则不会更新表单中的代码。

7 个答案:

答案 0 :(得分: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);
       } 
    }
}

答案 1 :(得分: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);
    }
}

答案 2 :(得分:0)

我认为您希望将父表单上的KeyPreview设置为true

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

编辑:

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

答案 3 :(得分:0)

ToolStrip.AllowMerge属性“获取或设置[...]是否可以合并多个MenuStripToolStripDropDownMenuToolStripMenuItem和其他类型。” (MSDN)。

这意味着你可以:

  

“使用AllowMerge属性启用多文档界面(MDI)子级,以便在MDI父级中组合各自的菜单。” (AllowMerge属性,备注,MSDN)

另见:

  1. MergeAction
  2. MergeIndex
  3. 我希望,这会帮助你得到你想要的东西。现在,我不知道这是否适用于Windows Forms,或者它是否也可以在Linux上运行。

答案 4 :(得分:0)

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

最简洁的方法是让每个表单公开与其操作菜单相关的事件。创建表单时,请相互订阅(或从子节点到MainForm或流程需要的任何方式)。单击菜单后,执行额外的事件,另一个表单将收到此信息。

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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