C# 如何拥有主窗体';s菜单是否处理OwnedForms上的事件?
我有一个C# 如何拥有主窗体';s菜单是否处理OwnedForms上的事件?,c#,winforms,C#,Winforms,我有一个Main表单,上面有一个MenuStrip,我使用该MenuStrip打开新的表单,如下所示: var target = new Target(); target.Owner = this; target.Show(); 这正是我所希望的:表单总是显示在主表单的前面 我遇到的问题是,当其中一个拥有的表单s具有焦点时,我无法通过键盘访问菜单提示。我希望CTRL+S触发保存功能,就像当Main窗体具有焦点时一样 这可能吗?有没有更好的方法来解决这个问题?很抱歉耽搁了您,但是如果您仍然有问题
Main
表单
,上面有一个MenuStrip
,我使用该MenuStrip
打开新的表单
,如下所示:
var target = new Target();
target.Owner = this;
target.Show();
这正是我所希望的:表单
总是显示在主
表单
的前面
我遇到的问题是,当其中一个拥有的表单
s具有焦点时,我无法通过键盘访问菜单提示
。我希望CTRL+S触发保存功能,就像当Main
窗体具有焦点时一样
这可能吗?有没有更好的方法来解决这个问题?很抱歉耽搁了您,但是如果您仍然有问题或正在寻找其他方法,请参阅下面的内容
在主窗体中:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child = new ChildForm();
// KeyPreview can be set in the properties of the child form instead
child.KeyPreview = true;
child.KeyPressed += Child_KeyPressed;
child.ShowDialog();
}
private void Child_KeyPressed(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
// Save Pressed
}
}
}
然后在您的子表单中:
public partial class ChildForm : Form
{
public event EventHandler<KeyEventArgs> KeyPressed;
public ChildForm()
{
InitializeComponent();
}
private void Child1_KeyUp(object sender, KeyEventArgs e)
{
KeyPressed?.Invoke(sender, e);
}
}
公共部分类子窗体:窗体
{
按下公共事件处理程序键;
公共子表单()
{
初始化组件();
}
私有void Child1\u KeyUp(对象发送方,KeyEventArgs e)
{
按键?.Invoke(发送方,e);
}
}
多亏了Troy Mac1ure的指导。这是一个解决方案,让我可以使用主菜单中的快捷键
ownedForm.KeyPreview = true;
ownedForm.KeyDown += OwnedForm_KeyDown;
private void OwnedForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
foreach (ToolStripMenuItem menuItem in menu.Items)
{
foreach (ToolStripMenuItem item in menuItem.DropDownItems.OfType<ToolStripMenuItem>())
{
if (item.ShortcutKeys == e.KeyData)
{
item.PerformClick();
return;
}
}
}
}
}
ownedForm.KeyPreview=true;
ownedForm.KeyDown+=ownedForm\u KeyDown;
私有void OwnedForm_KeyDown(对象发送方,KeyEventArgs e)
{
如果(如控制)
{
foreach(菜单项中的ToolStripMenuItem菜单项)
{
foreach(menuItem.DropDownItems.OfType()中的ToolStripMenuItem项)
{
if(item.ShortcutKeys==e.KeyData)
{
item.PerformClick();
回来
}
}
}
}
}
这不处理Alt菜单激活,但Paint.NET也不处理,因此我认为这是一个很好的选择。两种主要方法。您可以为父窗体订阅的每个子窗体编写一个键事件处理程序(最简单),也可以使用API调用创建一个键捕获。如果您可以完全控制子窗体,我建议使用第一种方法。@TroyMac1ure在该关键事件处理程序中执行什么操作?覆盖,将WS\u EX\u NOACTIVATE
添加到参数ExStyle
:并将WS\u child
添加到标准样式
:。添加WS_EX_TOOLWINDOW
,可以让它显得过火,以明确它不是标准表单。表单不会被激活,也不会窃取焦点(即使在单击/选择时)。@Jimi:这是可行的,但代价是要求拥有的表单保留在主表单上。有没有一种方法可以让主窗体响应菜单可能执行的任何操作,同时仍然让所拥有的窗体离开主窗体?如果你在一个工具窗口上,想想Paint.NET是如何工作的。这或多或少是一样的。您只需设置this.TopMost=true工具窗口构造函数中的代码>。即使它是一个孩子,它也会在窗体上悬停。唯一的问题是您需要处理ToolWindow标题。如果你点击它,表单仍然被激活(窃取焦点)。有不同的方法来克服这一点。简单的方法是隐藏Toowindow标题并构建一个假标题,然后使用该标题拖动表单。另一个是处理所有的NC
命中测试。另一个是实现IMessageFilter
,并将加速器发送/封送给家长;这给了我足够的方向去我需要的地方。