我有一个Delphi 2007项目,多年来在Windos XP,Vista和“7”上运行良好。它是Delphi 5的升级版,因此默认情况下“MainFormOnTaskBar”为“false”(我从未在DPR中更改过它)。在这种情况下,系统范围的热键在“系统范围内”工作,主代码的OnCreate事件处理程序中包含以下代码。
HotKey_xyz := GlobalAddAtom('Hotkey_xyz');
if NOT RegisterHotKey(Self.Handle, HotKey_xyz, MOD_CONTROL, VK_F12) then
ShowMessage('Unable to register Control-F12 as system-wide hot key') ;
(I have GlobalDeleteAtom() and UnregisterHotKey() in Form.OnDestroy as expected.)
现在,我需要一个Form来在任务栏上显示自己的按钮,所以我在DPR中设置了“Application.MainFormOnTaskBar:= True”。这按预期工作。但是,这会产生副作用,即Control-F12在系统范围内不起作用,只有在我的应用程序具有焦点时才会起作用(因此,它不再是“系统范围的”。)
我已经广泛搜索过'Net已经找到很多关于如何/为什么“MainFormOnTaskBar”会影响某些子表单/模态表单行为的文章。但是,我没有发现它对我上面描述的“系统级热键”问题的影响。我已经测试并重新测试了我的应用程序,MainFormOnTaskBar设置为true和false,而其他所有都保持完全相同。我可以肯定地验证上述系统级热键问题与MainFormOnTaskBar标志有关。
我将非常感谢有关解决方案的任何指导。我确实需要两个 - 一个系统范围的热键和一个在任务栏上有自己的按钮的表单。
非常感谢你。
答案 0 :(得分:14)
TApplication.MainFormOnTaskbar
对系统范围的热键完全没有影响。我可以肯定地证实这一点。我能够收到WM_HOTKEY
消息,无论MainFormOnTaskbar
被设置为什么,无论应用程序是否集中,等等。所以无论你看到的是什么都不是你认为发生的事情。
最有可能的是,在您致电Handle
后,表单的RegisterHotKey()
只是在您的背后重新创建,因此您将丢失将收到HWND
消息的WM_HOTKEY
。不应使用OnCreate
事件,而应覆盖表单的CreateWindowHandle()
和DestroyWindowHandle()
方法,以确保无论发生什么情况,始终为表单的当前HWND
注册热键对它(你应该总是这样做,只要你将任何类型的数据绑定到表格的Handle
),例如:
type
TForm1 = class(TForm)
private
HotKey_xyz: WORD;
procedure WMHotKey(var Message: TMessage); message WM_HOTKEY;
protected
procedure CreateWindowHandle(const Params: TCreateParams); override;
procedure DestroyWindowHandle; override;
end;
procedure TForm1.CreateWindowHandle(const Params: TCreateParams);
begin
inherited;
HotKey_xyz := GlobalAddAtom('Hotkey_xyz');
if HotKey_xyz <> 0 then
RegisterHotKey(Self.Handle, HotKey_xyz, MOD_CONTROL, VK_F12);
end;
procedure TForm1.DestroyWindowHandle(const Params: TCreateParams);
begin
if HotKey_xyz <> 0 then
begin
UnregisterHotKey(Self.Handle, HotKey_xyz);
GlobalDeleteAtom(HotKey_xyz);
HotKey_xyz := 0;
end;
inherited;
end;
procedure TForm1.WMHotKey(var Message: TMessage);
begin
...
end;
更好的选择是使用AllocateHWnd()
分配一个单独的专用HWND
来处理热键消息(然后您可以再次使用OnCreate
和OnDestroy
个事件),例如:
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
HotKey_xyz: WORD;
HotKeyWnd: HWND;
procedure HotKeyWndProc(var Message: TMessage);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
HotKeyWnd := AllocateHwnd(HotKeyWndProc);
HotKey_xyz := GlobalAddAtom('Hotkey_xyz');
if HotKey_xyz <> 0 then
RegisterHotKey(HotKeyWnd, HotKey_xyz, MOD_CONTROL, VK_F12);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if HotKey_xyz <> 0 then
begin
UnregisterHotKey(HotKeyWnd, HotKey_xyz);
GlobalDeleteAtom(HotKey_xyz);
HotKey_xyz := 0;
end;
if HotKeyWnd <> 0 then
begin
DeallocateHWnd(HotKeyWnd);
HotKeyWnd := 0;
end;
end;
procedure TForm1.HotKeyWndProc(var Message: TMessage);
begin
if Message.Msg = WM_HOTKEY then
begin
...
end else
Message.Result := DefWindowProc(HotKeyWnd, Message.Msg, Message.WParam, Message.LParam);
end;