132

私が知る限り、Windows はどのアプリケーションがグローバル ホットキーを (RegisterHotkey 経由で) 登録したかを示す API 関数を提供していません。RegisterHotkey が false を返した場合にのみ、ホットキーが登録されていることを確認できますが、ホットキーの「所有者」はわかりません。

直接的な API がない場合、回り道はありますか? Windows は、登録された各ホットキーに関連付けられたハンドルを保持しています。この情報を取得する方法がないことは、少し腹立たしいことです。

動作しない可能性が高いものの例: 登録済みのホットキーを送信 (シミュレート) し、Windows がそれを登録したプロセスに送信するホットキー メッセージをインターセプトします。まず、メッセージをインターセプトしても宛先ウィンドウ ハンドルが明らかになるとは思いません。第二に、たとえそれが可能であったとしても、ホットキーを送信すると、さまざまなプログラムからあらゆる種類の望ましくない可能性のあるアクティビティがトリガーされるため、行うのは悪いことです.

重要なことではありませんが、私はそのような機能に対する要求を頻繁に見てきました。また、UI やドキュメントのどこにも開示せずにホットキーを登録するアプリケーションの犠牲者になったこともあります。

(Delphi で作業しており、WinAPI の見習いにすぎません。親切にしてください。)

4

7 に答える 7

21

あなたの質問が私の興味をそそったので、私は少し掘り下げました、そして残念ながら私はあなたに適切な答えを持っていませんが、私は私が持っているものを共有したいと思いました。

1998年に書かれた(Delphiで)キーボードフックを作成するこの例を見つけましたが、Delphi2007ではいくつかの調整を加えてコンパイルできます。

SetWindowsHookExこれは、コールバック関数を通過する呼び出しを含むDLLであり、キーストロークをインターセプトできます。この場合、楽しみのためにそれらをいじったり、左カーソルを右に変更したりします。次に、単純なアプリがDLLを呼び出し、レポートを返します。 TTimerイベントに基づく結果。興味があれば、Delphi2007ベースのコードを投稿できます。

これは十分に文書化され、コメントが付けられており、キーを押す場所を特定するための基礎として使用できる可能性があります。キーストロークを送信したアプリケーションのハンドルを取得できれば、その方法で追跡できます。そのハンドルを使用すると、必要な情報を非常に簡単に取得できます。

他のアプリは、ショートカットキーを含めることができるため、ショートカットを使用してホットキーを決定しようとしました。これは、ホットキーの単なる別の用語です。ただし、ほとんどのアプリケーションはこのプロパティを設定する傾向がないため、あまり返されない可能性があります。そのルートに興味がある場合、DelphiはIShellLinkCOMインターフェイスにアクセスできます。このインターフェイスを使用して、ショートカットをロードし、そのホットキーを取得できます。

uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;

procedure GetShellLinkHotKey;
var
  LinkFile : WideString;
  SL: IShellLink;
  PF: IPersistFile;

  HotKey : Word;
  HotKeyMod: Byte;
  HotKeyText : string;
begin
  LinkFile := 'C:\Temp\Temp.lnk';

  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));

  // The IShellLink implementer must also support the IPersistFile
  // interface. Get an interface pointer to it.
  PF := SL as IPersistFile;

  // Load file into IPersistFile object
  OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));

  // Resolve the link by calling the Resolve interface function.
  OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));

  // Get hotkey info
  OleCheck(SL.GetHotKey(HotKey));

  // Extract the HotKey and Modifier properties.
  HotKeyText := '';
  HotKeyMod := Hi(HotKey);

  if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
    HotKeyText := 'ALT+';
  if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
    HotKeyText := HotKeyText + 'CTRL+';
  if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
    HotKeyText := HotKeyText + 'SHIFT+';
  if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
    HotKeyText := HotKeyText + 'Extended+';

  HotKeyText := HotKeyText + Char(Lo(HotKey));

  if (HotKeyText = '') or (HotKeyText = #0) then
    HotKeyText := 'None';

  ShowMessage('Shortcut Key - ' + HotKeyText);
end;

Safari Books Onlineにアクセスできる場合は、SteveTeixeiraとXavierPachecoによるBorlandDelphi6開発者ガイドにショートカット/シェルリンクの操作に関する優れたセクションがあります。上記の私の例は、そことこのサイトからの屠殺されたバージョンです。

お役に立てば幸いです。

于 2009-05-20T09:43:13.683 に答える
3

思いつきで、EnumWindows を使用してすべてのウィンドウを列挙し、コールバックで各ウィンドウに WM_GETHOTKEY を送信してみてください。

編集:明らかに私はそれについて間違っていました。MSDNには詳細情報があります。

WM_HOTKEY は、WM_GETHOTKEY および WM_SETHOTKEY ホット キーとは無関係です。WM_HOTKEY メッセージは汎用ホット キーに対して送信されますが、WM_SETHOTKEY および WM_GETHOTKEY メッセージはウィンドウ アクティブ化ホット キーに関連しています。

注:これは、探している機能を備えていると主張するプログラムです。逆コンパイルしてみてください。

于 2009-05-19T01:46:53.087 に答える
1

VB6 でサブクラス化と呼んでいた、独自のプロセス内の任意のウィンドウでメッセージのストリームをインターセプトできることを私は知っています。(私は関数を覚えていませんが、おそらく SetWindowLong?) 独自のプロセス外のウィンドウに対してこれを実行できるかどうかはわかりません。しかし、この投稿のために、それを行う方法を見つけたと仮定しましょう。次に、すべての最上位ウィンドウのメッセージを傍受し、WM_HOTKEY メッセージを監視します。すぐにすべてのキーを知ることはできませんが、キーを押すと、どのアプリケーションがキーを使用しているかを簡単に把握できます。結果をディスクに保持し、モニター アプリケーションを実行するたびに再読み込みすると、時間の経過とともにアプリケーションのパフォーマンスを向上させることができます。

于 2009-05-07T19:28:25.150 に答える
0

これは、Windows API に関する質問の一部に正確に回答するものではありませんが、グローバル ホットキーのリストとそれらを「所有する」アプリケーションに関する質問の一部には回答します。

http://hkcmdr.anymania.com/にある無料の Hotkey Explorer には、すべてのグローバル ホットキーとそれらを所有するアプリケーションのリストが表示されます。これは、アプリケーション固有のショートカット キーが機能しなくなった理由と、それを修正する方法 (登録されたアプリで登録済みのグローバル ホットキーを再構成することによって) を数秒以内に理解するのに役立ちました。

于 2014-12-27T17:56:11.800 に答える