グローバルホットキーを登録したプロセスを確認しますか? (Windows API)
-
06-07-2019 - |
質問
私が知る限り、Windowsは(RegisterHotkeyを介して)グローバルホットキーを登録したアプリケーションを通知するAPI関数を提供していません。 RegisterHotkeyがfalseを返した場合にのみホットキーが登録されていることがわかりますが、「所有者」ではありません。ホットキー。
直接APIがない場合、迂回方法はありますか? Windowsは、登録された各ホットキーに関連付けられたハンドルを保持します。この情報を取得する方法がないはずだというのは少し気が悪くなります。
機能しない可能性が高いものの例:登録済みのホットキーを送信(シミュレート)し、Windowsがそれを登録したプロセスに送信するホットキーメッセージをインターセプトします。まず、メッセージを傍受しても宛先ウィンドウハンドルが明らかになるとは思わない。第二に、たとえ可能であったとしても、ホットキーを送信すると、さまざまなプログラムからのあらゆる潜在的に望ましくないアクティビティがトリガーされるため、それは悪いことです。
重要なことは何もありませんが、そのような機能に対する頻繁なリクエストを目にし、UIやドキュメントのどこにも公開せずにホットキーを登録するアプリケーションの犠牲になりました。
(Delphiでの作業、WinAPIの見習いにすぎない、親切にしてください。)
解決
あなたの質問が私の興味をそそったので、少し掘り下げましたが、残念ながらあなたに適切な答えがありませんが、私は自分が持っているものを共有すると思いました。
このキーボードフックの作成例(Delphi) は1998年に作成されましたが、Delphi 2007ではいくつかの調整を加えてコンパイルできます。
これは、 SetWindowsHookEx
への呼び出しを持つDLLであり、キーストロークをインターセプトすることができるコールバック関数を通過します。この場合、楽しみのためにそれらをいじり、左カーソルを右に変更します。次に、単純なアプリがDLLを呼び出し、TTimerイベントに基づいて結果を報告します。興味があれば、Delphi 2007ベースのコードを投稿できます。
十分に文書化され、コメントが付けられており、キーを押す場所を決める基礎として使用できる可能性があります。キーストロークを送信したアプリケーションのハンドルを取得できた場合は、その方法で追跡できます。そのハンドルを使用すると、必要な情報を非常に簡単に取得できます。
ショートカットキーを含めることができるため、他のアプリはショートカットを使用してホットキーを決定しようとしましたが、これはホットキーの単なる用語です。ただし、ほとんどのアプリケーションはこのプロパティを設定する傾向がないため、あまり返されない場合があります。そのルートに興味がある場合、Delphiは IShellLink
COMインターフェイスにアクセスして、ショートカットをロードしてそのホットキーを取得するために使用できます:
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開発者ガイドのショートカット/シェルリンクの操作に関する優れたセクション。上記の私の例は、そこから屠殺されたバージョンとこのサイトです。
役立つことを願っています!
他のヒント
可能な方法の1つは、 Visual StudioツールSpy ++ 。
これを試してください:
- ツールを実行します(私にとっては、
C:\ Program Files(x86)\ Microsoft Visual Studio \ 2017 \ Community \ Common7 \ Tools \ spyxx_amd64.exe
にあります) - メニューバーで、スパイ->を選択します。 ログメッセージ... (または Ctrl + M を押します)
- 追加ウィンドウフレームでシステム内のすべてのウィンドウをチェック
- [メッセージ]タブに切り替える
- すべてクリアボタンをクリック
- リストボックスで
WM_HOTKEY
を選択するか、メッセージグループでキーボードをチェックします(ノイズが多い場合はOK) >
- [ OK ]ボタンをクリック
- 問題のホットキー( Win + R など)を押します
- メッセージ(すべてのウィンドウ)ウィンドウで
WM_HOTKEY
行を選択し、右クリックして、コンテキストメニューでプロパティ... を選択します - メッセージプロパティダイアログで、ウィンドウハンドルリンクをクリックします(これはメッセージを受信したウィンドウのハンドルになります)
- ウィンドウのプロパティダイアログの同期ボタンをクリックします。これにより、メインのSpy ++ウィンドウツリービューにウィンドウが表示されます。
- [ウィンドウのプロパティ]ダイアログで、[プロセス]タブを選択します
- プロセスID リンクをクリックします。プロセスが表示されます(私の Win + R の場合:
EXPLORER
)
調査の結果、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内部にアクセスせずにこれを理解するために、深部への飛び込みが必要になると思われます。
頭の先から、すべてのウィンドウをEnumWindowsで列挙してから、コールバックでWM_GETHOTKEYを各ウィンドウに送信してみてください。
編集:どうやら私はそれについて間違っていた。 MSDN には詳細情報があります:
WM_HOTKEYは、WM_GETHOTKEYおよびWM_SETHOTKEYホットキーとは無関係です。 WM_HOTKEYメッセージは汎用ホットキー用に送信され、WM_SETHOTKEYおよびWM_GETHOTKEYメッセージはウィンドウアクティベーションホットキーに関連しています。
注:こちらは、機能を提供することを目的としたプログラムですあなたは探している。逆コンパイルしてみてください。
これは多くのことを伝えているようです: http://hkcmdr.anymania.com/help.html
別のスレッドは、NTレベルのグローバルキーボードフックに言及しています:
ホットキーの再割り当て/上書き(Win + L)ウィンドウをロックするには
たぶん、そのようにフックを呼び出したプロセスのハンドルを取得でき、それをプロセス名に解決できます
(免責事項:ブックマークに保存しましたが、実際に試したりテストしたりしていません)
VB6でサブクラス化を呼び出すために使用した、独自のプロセス内の任意のウィンドウでメッセージのストリームをインターセプトできることを知っています。 (関数、おそらくSetWindowLongを覚えていませんが?)自分のプロセス外のウィンドウでこれを行うことができるかどうかはわかりません。しかし、この投稿のために、あなたがそれを行う方法を見つけると仮定しましょう。次に、すべてのトップレベルウィンドウのメッセージをインターセプトし、WM_HOTKEYメッセージを監視します。すぐにすべてのキーを知ることはできませんが、キーが押されると、どのアプリケーションがそれらを使用しているかを簡単に把握できます。結果をディスクに保存し、モニターアプリケーションを実行するたびにリロードした場合、アプリケーションのパフォーマンスを徐々に向上させることができます。
これは、Windows APIに関する質問の一部には正確に回答しませんが、グローバルホットキーのリストと「所有する」アプリケーションに関する質問の一部には回答します。それら。
http://hkcmdr.anymania.com/ の無料のホットキーエクスプローラーには、すべてのグローバルのリストが表示されます。ホットキーとそれらを所有するアプリケーション。これは、数秒以内に、アプリケーション固有のショートカットキーが機能しなくなった理由とその修正方法(登録されたアプリで登録済みのグローバルホットキーを再構成することにより)を見つけるのに役立ちました。