グローバルホットキーを登録したプロセスを確認してください。(Windows API)


114

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

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

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

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

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

回答:


20

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

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

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

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

他のアプリは、ショートカットキーを含めることができるため、ショートカットを確認してホットキーを決定しようとしました。これは、ホットキーの別の用語です。ただし、ほとんどのアプリケーションはこのプロパティを設定する傾向がないため、あまり返らない場合があります。そのルートに興味がある場合、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へのアクセス権がある場合は、Steve TeixeiraとXavier Pachecoによる 『Borland Delphi 6 Developer's Guide』のショートカット/シェルリンクの操作に関する優れたセクションがあります。上記の私の例は、そことこのサイトからの肉屋バージョンです。

お役に立てば幸いです。


59

1つの可能な方法は、Visual StudioツールSpy ++を使用することです

これを試してみてください:

  1. ツールを実行します(私にとってはにありますC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe
  2. メニューバーで、[ スパイ] -> [ログメッセージ]を選択します(またはCtrl+ キーを押しますM)。
  3. 追加ウィンドウフレームでシステム内のすべてのウィンドウをチェックします
  4. メッセージタブに切り替えます
  5. [ すべてクリア ]ボタンをクリックします
  6. WM_HOTKEYリストボックスで選択するか、メッセージグループのキーボードオンにします(ノイズの可能性が高い場合)。
  7. OKボタンをクリックします
  8. 問題のホットキーを押します(たとえば、Win+ R
  9. [ メッセージ(すべてのウィンドウ) ]ウィンドウでWM_HOTKEY行を選択し、右クリックして、コンテキストメニューで[ プロパティ... ]を選択します。
  10. メッセージのプロパティ ]ダイアログ、クリックしウィンドウハンドルのリンクを(これはメッセージを受け取ったウィンドウのハンドルになります)
  11. [ ウィンドウのプロパティ ]ダイアログの[ 同期 ]ボタンをクリックします。これにより、メインのSpy ++ウィンドウツリービューにウィンドウが表示されます。
  12. 上のウィンドウの[プロパティ ]ダイアログ、選択プロセス ]タブを
  13. [ プロセスID]リンクをクリックします。これは、(私はあなたのプロセスが表示されますWin+のR場合:EXPLORER

6
正解です。ただ、ノートその64ビット・アプリケーション用のメッセージのみのスパイ++漁獲量の64ビット版、あなたが表示されていない場合はそうWM_HOTKEYでメッセージメッセージログをホットキーを押した後、あなたはスパイの32ビットバージョンを実行する必要があります++ 。
David FerenczyRogožan2017

どうもありがとうございます!!!これが見つかるまで、基本的にいくつかのショートカットの使用をあきらめました。
thewindev

3
ステップ8では、ホットキーを要求しません。メッセージウィンドウは、ホットキーを押した後も空のままです。github.com/westoncampbell/SpyPlusPlus(Windows 10)の32ビットバージョンと64ビットバージョンを使用しました。
CoolMind

9

調査の結果、MSがホットキーの保存に使用する内部構造にアクセスする必要があるようです。ReactOSには、GetHotKey内部リストを反復し、パラメーターを呼び出しに一致させるホットキーを抽出することによって呼び出しを実装するクリーンルーム実装があります。

ReactOSの実装がMSの実装にどれだけ近いかに応じて、構造を見つけるためにメモリをざっと見ることができるかもしれませんが、それは私の頭の上にあります...

BOOL FASTCALL
GetHotKey (UINT fsModifiers,
           UINT vk,
           struct _ETHREAD **Thread,
           HWND *hWnd,
           int *id)
{
   PHOT_KEY_ITEM HotKeyItem;

   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
   {
      if (HotKeyItem->fsModifiers == fsModifiers &&
            HotKeyItem->vk == vk)
      {
         if (Thread != NULL)
            *Thread = HotKeyItem->Thread;

         if (hWnd != NULL)
            *hWnd = HotKeyItem->hWnd;

         if (id != NULL)
            *id = HotKeyItem->id;

         return TRUE;
      }
   }

   return FALSE;
}

はsysinternalsのこのスレッドがこの質問に関連する誰かによって尋ねられたと思いますが、私はとにかく2つを一緒に保つためにそれにリンクしたいと思いました。スレッドは非常に興味深く見えますが、MS内部にアクセスせずにこれを理解するには、いくつかの詳細な洞察が必要になると思います。


3

私の頭の上から、EnumWindowsですべてのウィンドウを列挙してみて、コールバックでWM_GETHOTKEYを各ウィンドウに送信してみてください。

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

WM_HOTKEYは、WM_GETHOTKEYおよびWM_SETHOTKEYホットキーとは無関係です。WM_HOTKEYメッセージは一般的なホットキーに対して送信され、WM_SETHOTKEYおよびWM_GETHOTKEYメッセージはウィンドウアクティベーションホットキーに関連しています。

注:ここにあなたが探している機能を持っていると主張するプログラムがあります。あなたはそれを逆コンパイルしてみることができます。


3
プログラムへのリンクは完全に壊れています。それはどんなプログラムでしたか?ホットキーが突然機能しなくなったり、煩わ​​しくなったりするため、どのプログラムが私のホットキーを登録したのかを調べたいことがよくあります。
James Oltmans、2011

(多くの場合、Wayback MachineはWebページが消えた場合に役立ちますが、ここでも404 Not Foundをミラーリングしているだけです:http : //web.archive.org/web/*/tds.diamondcs.com.au/dse/ detection / hotkeys.php
アーロン・トーマ

2

これはあなたに多くを伝えるようです:http//hkcmdr.anymania.com/help.html


1
そうですか?ドライバーを装ったDLL?エクスポートDLL関数hooの使用にはSetWindowHookEx2つのフック、1設定するWH_KEYBOARD_LLと1をWH_GETMESSAGE、残りはかなりMSDNに文書化されなければなりません...。
0xC0000022L 2011年

Windowsの8または10に、このアプリを使用しないでください
ジェフ・ランゲ

1

別のスレッドは、グローバルNTレベルのキーボードフックについて言及しています。

ウィンドウをロックするためのホットキー(Win + L)の再割り当て/上書き

多分あなたはその方法でフックを呼び出したプロセスのハンドルを取得することができ、それからプロセス名に解決することができます

(免責事項:私はそれを私のブックマークに入れました、実際に試したりテストしたりしていません)


0

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


-1

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

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


4
それをインストールして、それは少なくとも悪質な冗談のよ​​うに、モールを対象としたプログラムのようにウイルスのように振る舞った。あらゆる種類のウィンドウを開く、ボイスナレーターをアクティブにするなど
Flion

3
@Flion:superuser.com/a/191090/3617の説明を参照してください。基本的に、一部のホットキーユーティリティは、考えられるすべてのキーの組み合わせを調べて動作します。Windows 8以降では(そしてWindows 7ではそれほどではありませんが)、この調査手法は単にクエリするのではなく、すべてのキーの組み合わせをトリガーします
ブライアン

@Flion FWIW、Win7で使用して成功しました。しかし、ブライアンを正しく理解していれば、これはそれ以降のバージョンではうまく機能しない可能性があり、どれだけうまく機能するかも、定義されているカスタムホットキーに依存している可能性があります。
Gerhard
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.