9

私は、Windos XP、Vista、および「7」で何年も正常に実行されているDelphi2007プロジェクトを持っています。これはDelphi5からのアップグレードであったため、「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.)

ここで、タスクバーに独自のボタンを表示するフォームが必要なので、DPRで「Application.MainFormOnTaskBar:=True」を設定します。これは期待どおりに機能します。ただし、これにはControl-F12がシステム全体で機能しないという副作用があり、アプリケーションにフォーカスがある場合にのみ機能します(したがって、「システム全体」ではなくなります)。

私は広範囲に検索しました。ネットは、「MainFormOnTaskBar」が特定のサブフォーム/モーダルフォームの動作にどのように/なぜ影響するかに関する多くの記事を見つけました。ただし、上記の「システム全体のホットキー」の問題への影響については何も見つかりませんでした。MainFormOnTaskBarをtrueとfalseに設定してアプリケーションをテストおよび再テストしましたが、他のすべてはまったく同じです。システム全体のホットキーに関する上記の問題がMainFormOnTaskBarフラグに関連していることを確実に確認できます。

回避策に関するガイダンスをいただければ幸いです。システム全体のホットキーと、タスクバーに独自のボタンがあるフォームの両方が必要です。

どうもありがとうございます。

4

1 に答える 1

15

TApplication.MainFormOnTaskbarシステム全体のホットキーにはまったく影響しません。確かに確認できます。WM_HOTKEY何が設定されていても、アプリがフォーカスされているかどうかに関係なく、メッセージを受信できますMainFormOnTaskbar。したがって、表示されているものは、あなたが思っていることではありません。

ほとんどの場合、フォームHandleは、電話をかけた後、単に背中の後ろで再作成されているため、メッセージを受信するフォームRegisterHotKey()が失われます。イベントを使用する代わりに、フォームとメソッドをオーバーライドして、フォームに何が起こってもホットキーが常にフォームの現在の値に登録されるようにする必要があります(フォームに何らかのデータを関連付けるときは常にそれを行う必要があります)、例えば:HWNDWM_HOTKEYOnCreateCreateWindowHandle()DestroyWindowHandle()HWNDHandle

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()専用の別のを割り当てるために使用することです(その後、およびイベントを再度使用できます)。例:HWNDOnCreateOnDestroy

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;
于 2012-04-19T01:15:54.087 に答える