5

我试图在系统托盘中放置一个图标,然后给它一个全局键盘快捷键来执行一项功能。

我正在使用 RegisterHotKey 设置全局键盘快捷键,如果与图标关联的主窗体可见,它就可以工作。但如果表单不可见,则永远不会调用 WndProc 方法。

有任何想法吗?

编辑:我所说的“隐藏”是指将以下内容添加到主表单中:

protected override void OnLoad(EventArgs e)
{
    hotKey = new GlobalHotkey(GlobalHotkey.WIN, Keys.T, this);
    bool registered = hotKey.Register();
    Visible = false;
    ShowInTaskbar = false;
    base.OnLoad(e);
}

“已注册”显示为“true”,如果我省略“Visible = false;”,快捷键可以正常工作 和“ShowInTaskbar = false;”。

4

2 回答 2

5

问题在于将 ShowInTaskbar 设置为 false 会更改窗口句柄,这意味着传递给 RegisterHotkey 的 hwnd 不再有效。

设置 ShowInTaskBar注册热键工作正常。

于 2012-05-12T07:00:32.277 回答
4

Winforms 解决了 winapi 中一个非常严格的限制。窗口的某些属性只能在创建窗口时指定,以后不能更改。或者换句话说,它们是在本机 CreateWindowEx() 调用中指定的。

它通过再次调用 CreateWindowEx() 来解决它。或者换句话说,销毁现有窗口并重新创建它。这是一个绝妙的技巧,但它确实有一些副作用。例如,当新窗口自行绘制时,您会看到一点点闪烁。例如,在 TreeView 上可以看到一些更大的副作用。重新创建时,所有节点都会崩溃。很难避免,与原始窗口相关的状态太多了。对于窗体,ShowInTaskbar 属性就是这样一个属性。还有 RightToLeft、FormBorderStyle、ControlBox 等。

最相关的副作用是您遇到的副作用。重新创建窗口总是不可避免地改变 Handle 属性。当您使用 RegisterHotKey() 或使用它的库时,就会出错,winapi 调用使用窗口句柄。因此,当 Winforms 销毁该窗口时,将不再有回调。

这很容易修复,您只是使用了错误的事件处理程序。改为在方法的覆盖中调用OnHandleCreated。它在重新创建窗口时重新运行。另一个简单但不那么可靠的解决方法是仅在构造函数中设置 ShowInTaskbar 之类的属性。

于 2012-05-12T12:03:05.993 回答