来自C#中键盘钩子事件的ShowDialog()

时间:2008-10-07 01:15:15

标签: c# keyboard-hook

我想在触发键盘挂钩事件时调用ShowDialog(),但我遇到了一些困难:

  • ShowDialog()阻止,所以我无法从钩子触发事件中调用它,因为它会阻止操作系统。
  • 我可以开始一个新线程并从那里调用ShowDialog(),但是我得到了一些令人讨厌的异常。我想我不能在任何其他线程中调用ShowDialog()
  • 我可以启动一个计时器:在接下来的50毫秒内调用ShowDialog()(这是一个讨厌的黑客BTW,我宁愿不这样做)。但随后计时器在一个新线程中触发,然后我遇到了上一个子弹中解释的相同问题。

有办法吗?

6 个答案:

答案 0 :(得分:2)

问题可能在于您尝试将UI放在非UI线程中。使您的事件从另一个线程触发,并从您的UI线程调用运行ShowDialog()的方法。

基本上,您希望将UI保留在UI线程上,并将其他任何内容移至后台线程。

查看Gekki Software了解一些细节(有数以万计的其他人 - 这恰好是我在研究档案中找到的第一个)。

答案 1 :(得分:1)

我不确定ShowDialog,但是当你在后台线程中尝试使用UI时遇到异常时,这意味着你应该使用UI调度程序。

尝试使用调用showdialog的委托调用您控制的任何UI对象的BeginInvoke方法(如果您在Windows窗体上)。

此外,请确保尝试(在此之前)在show对话框方法中将引用传递给有效的所有者。

答案 2 :(得分:0)

如果没有“讨厌的例外”,很难说出发生了什么。我认为这是因为你的线程不是STA线程,并且UI对象在实例化时抛出异常。将新线程的公寓模型设置为STA而不是MTA,看看是否有帮助。

如果你不知道区别是什么,你应该做一些阅读,例如 Multithreaded Apartments (MSDN)。

答案 3 :(得分:0)

你真的应该可以从KeyPress类型事件中显示对话框。

此外,如果您从另一个线程使用ShowDialog(),它将不是模态的(没有父级)。它与使用Show()相同。

答案 4 :(得分:0)

试试这个:

void MyKeyboardHookHandler(...)
{
     WindowsFormsSynchronizationContext.Current.Post(state =>
     {
         Form f = new Form();
         f.ShowDialog();
     }, null);
}

答案 5 :(得分:-1)

ShowDialog()将阻止你的应用程序的线程,但这就是它应该做的事情。如果您不希望表单阻止您的应用程序,请改为调用Show()。

ShowDialog()不会“阻止操作系统”,所以不要不愿意使用它。