2012-05-11 35 views
5

我试图在系统托盘中放入一个图标,然后为其提供全局键盘快捷键以执行功能。RegisterHotKey无法使用隐形窗体(c#)

我正在使用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); 
} 

“注册”是显示为“真”,在弹出的快捷键工作正常,如果我省略“可见=假”;和“ShowInTaskbar = false;”。

+2

你可以展示你试过的代码示例吗? – ImGreg

+0

是的,显示您的代码,因为如果RegisterHotKey HWND参数不可见,则应该没有区别,消息仍然处理 –

+0

在创建窗口之前,您将无法注册热键。这是你“可见”的意思吗? –

回答

4

Winforms在winapi中实现了非常严格的限制。窗口的某些属性只能在创建窗口时指定,并且以后不能更改。换句话说,它们是在原生CreateWindowEx()调用中指定的。

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

最相关的副作用就是你遇到的副作用。重新创建窗口总是会不可避免地改变Handle属性。当你使用RegisterHotKey()或者使用它的库时,那个错误就是winapi调用使用窗口句柄。所以当Winforms破坏这个窗口时,永远不会有回调。

这很容易解决,你只是使用错误的事件处理程序。改为使用OnHandleCreated方法的覆盖拨打电话。当窗口被重新创建时,它会重新运行。另一个简单的解决方法是,只是在构造函数中设置像ShowInTaskbar这样的属性。

4

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

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