Delphi XE3 WM_HOTKEY 如何判断热键何时被释放?

3
我正在尝试在一个通信程序中编写一个“咳嗽按钮”,但该程序不总是处于焦点状态。我已经编写了代码来静音和取消静音麦克风(MMDevApi),并且它运行得非常完美。我设置了一个全局热键,这个热键可以很好地设置静音。现在问题来了。我如何告诉程序当热键被释放时?我尝试了在代码中使用计时器,但它的行为很奇怪。我按住我的热键,麦克风立即静音,然后在计时器的间隔之后,它会取消静音,持续时间似乎是计时器间隔的一半,然后再次静音并保持静音状态。如果没有计时器,它将完美地静音并保持静音状态。我真的不想(或认为这样做没有用)按下第二个键来取消静音麦克风。
//here is my register hot key code ! 
CoughKeyWnd := AllocateHwnd(CoughKeyWndProc);
CoughKey := GlobalAddAtom('CoughKey');
  if CoughKey <> 0 then
    RegisterHotKey(CoughKeyWnd, CoughKey, MOD_CONTROL, VK_OEM_3);

//the procedure
procedure TForm1.CoughKeyWndProc(var Message: TMessage);
begin
 if Message.Msg = WM_HOTKEY then
  begin // to prevent recalling mute 
    if CoughOn = FALSE then
 begin
   CoughOn := True;
   CoughOff.SetMute(1,@GUID_NULL);
 end;
  Timer1.Enabled := FALSE;
  Timer1.Enabled := True;
end
   else
    begin
      Message.Result := DefWindowProc(CoughKeyWnd, Message.Msg, Message.WParam, Message.LParam);
    end;

//and finally the ontimer ! 
procedure TForm1.JvTimer1Timer(Sender: TObject);
begin
  CoughOff.SetMute(0,@GUID_NULL);
  Timer1.Enabled := False;
  CoughOn := False;

end;

你无法获取那些信息。 - David Heffernan
2
我认为这完全不可能。WM_HOTKEY 通知是在按下后发送的,而不是松开后发送的。我会添加一个 [winapi] 标签来扩大你的问题的受众范围,并确认我的想法。 - Free Consulting
我很难理解为什么你需要检测按键抬起的事件。为什么不能直接响应热键呢? - David Heffernan
1个回答

3

如果您的计时器在第二个WM_HOTKEY被检索之前过期,但在连续检索消息时不会过期,则会出现这种行为。第一个和第二个消息之间的时间范围大于连续消息之间的时间范围。这是因为键盘延迟大约为(典型值为250毫秒),而键盘重复间隔更长。

要使您的方法起作用,请增加计时器间隔,例如两倍的键盘延迟。您可以使用SystemParametersInfo来获取键盘延迟的近似值。或者,在麦克风保持静音状态的最小时间框架内,然后开始观察重复的热键消息以重新启用计时器。尽管如此,这种方法仍然有点不可靠,热键消息可能因任何原因而延迟。最好在计时器处理程序中使用GetKeyState来测试按键是否仍按下。

如果您不想使用计时器,可以在按下热键时安装键盘钩子或注册原始输入。


一定要使用键盘钩子或注册原始输入,而不是使用热键。它们将为您提供按下和松开键的通知。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接