2012-04-19 10 views
9

Windos XP、Vistaおよび7で長年実績のあるDelphi 2007プロジェクトがあります。それはDelphi 5からのアップグレードだったので、 "MainFormOnTaskBar"はデフォルトで "false"でした(私はそれをDPRで変更していません)。このシナリオでは、システム全体のホットキーは、メインフォームのOnCreateイベントハンドラの次のコードで「システム全体」で動作しました。Delphi 2007 - "MainFormOnTaskBar:= True"を設定すると、システム全体のホットキーが「システム全体」ではありません。

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.) 

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

私は広範に'Netは、どのように/なぜ "MainFormOnTaskBar"が特定のサブフォーム/モーダルフォームの動作に影響するかに関する多くの記事を発見しました。しかし、私は上で説明した "System-Wide Hot Key"の問題には何の影響も見いだせませんでした。 MainFormOnTaskBarをtrueとfalseに設定してアプリケーションをテストして再テストしましたが、それ以外は全く同じです。上記のシステムワイドホットキーに関する問題がMainFormOnTaskBarフラグに関連していることを積極的に検証できます。

回避策に関するご案内をいただければ幸いです。私は両方の必要があります - システム全体のホットキーとタスクバー上の独自のボタンとフォーム。

ありがとうございます。

+0

* new *プロジェクトで複製できますか?私はできませんでした.. –

+0

これも再現できません。もっとコードを投稿できますか? (おそらく 'RegisterHotkey'呼び出しで' Self.Handle'を 'Application.Handle'に変更しようとしますか?' WM_HOTKEY'メッセージはアプリケーションのメッセージハンドラが何もしないのであなたのフォームに入ります –

+0

@KenWhite: 'Application.Handle'を使ってホットキーを登録すると、' WM_HOTKEY'メッセージはTFormに直接的または間接的に送られません。彼らは代わりに 'TApplication'に指示されるので、あなたは' TApplication.OnMessage'イベントおよび/または 'TApplication.HookMainWindow()'メソッドを使用しなければなりません。 –

答えて

14

TApplication.MainFormOnTaskbarは、システム全体のホットキーにはまったく影響しません。私はそれを積極的に確認することができます。アプリがフォーカスされているかどうかにかかわらず、MainFormOnTaskbarに設定されているかどうかにかかわらず、WM_HOTKEYメッセージを受け取ることができます。あなたが見ているものは、あなたの考えていることではありません。あなたがRegisterHotKey()呼び出した後

ほとんどの場合、フォームのHandleは単にあなたがWM_HOTKEYメッセージを受け取ることになるHWNDを失うので、あなたの背中の後ろに再作成されています。 OnCreateイベントを使用する代わりに、フォームの現在のHWNDのホットキーが常に登録されていることを確認するために、フォームのCreateWindowHandle()DestroyWindowHandle()メソッドをオーバーライドする必要があります(何らかのデータをフォームの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; 

より良いオプションは、ちょうどホットキーメッセージ(そして、あなたは再びOnCreateOnDestroyイベントを使用することができます)、などを処理するための個別の専用HWNDを割り当てるAllocateHWnd()を使用することです:

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; 
+1

+1の 'AllocHWnd'コードの例だけです。ニース - 私はそれが前にそれのように行われたことを見たことがない。私は、将来の参照のためにこれをマークします。 –

+0

@Remy:ありがとう、CreateWindowHandle()とDestroyWindowHandle()メソッド - それはトリックでした。だから、十分にあなたに感謝することはできません。私は "AllocateWnd()"を探求します - 私はそれにもっと教育が必要です!私はあなたの答えをUPしたいと思っていましたが、Stack Overflowは私がそうするために十分な "評判"を持っていないと言います。 – JayM

+0

@All:MainFormOnTaskBarフラグが原因であると主張し、私の主張をテストする時間を割いた皆さん、ありがとうございます。再び、私はこの地域社会の支持と喜んで助けに感謝します。 – JayM

関連する問題