アプリケーションをすばやく切り替えるための小さなトリック
前文
長い間、私はLogitechマウス-MX300およびMX310を使用してきました。 ホイールの上に追加のボタンがあり、さまざまな機能を掛けることができます。 古いドライバー(MouseWare)では、これらの機能の中に「Recall Application」があり、それは前のアクティブウィンドウに切り替わりました。Alt+ Tabを1回押すとほぼ同じです。 私はすぐにこの機会が好きでした。あるウィンドウに切り替え、そこで何かをする(たとえば、行をコピーする)後、戻る(それぞれ、このコピーした行を貼り付ける)必要がある場合がよくあります。 この場合、Alt + Tabはあまり便利ではありません(Ctrl + Cの組み合わせから左手を取り除いてから、Ctrl + Vを押すと前の位置に戻る必要があるため)。
しかし、私は自分でWindows XP x64をインストールしましたが、MouseWareは64ビットシステムでは使用できないことがわかりました。 MX310の場合、より新しいSetPointユーティリティが発見されましたが、Recall Application機能はもうありません。 幸い、Alt + Tabを設定して目的のボタンへのショートカットを送信できましたが、切り替え時のタスクリストウィンドウの点滅は少し面倒でした。 だから、怠lazを克服して、この欠点を取り除くのに役立つ小さなユーティリティを書くことができました。
アンブラ
実際、ユーティリティに必要なものは1つだけです。バックグラウンドでハングし、ボタンを押すことに関する信号を受信した後、「隣接」ウィンドウに切り替えます。 タスクは、私が最初に思ったほど簡単ではありませんでした。 SetPointで使用可能なアクションのリストには、「6番目のボタンを押すことに関する信号を送信する」などのアクションがないため、ボタンを押すことに関する信号を直接受信することはできません。 そのため、ボタンを押すだけで、キーの組み合わせをエミュレートすると、プログラムはすでにこの組み合わせをキャッチできます。 当然、通常の作業では未使用のものを選択する必要があります。 Ctrl + Alt + Shift + Zを選択しました。
2番目の問題は、適切なウィンドウを選択することでした。 GetWindow呼び出し(hwnd、GW_HWNDNEXT)を使用してアプリケーションのZスタックをナビゲートできますが、これらのウィンドウの中には、切り替える必要のないウィンドウが多数あります。 たとえば、非表示。 表示されているウィンドウのみを残す場合でも、通常のAlt + Tabリストにない他のトップレベルウィンドウが多数あります。 ここでは満足のいく解決策が見つかりませんでした。
Stack overflowで1つのオプションをGoogleで検索できました
が 、ウィンドウの正しいリストを取得できませんでした。
TaskSwitchXPのソースコードもありますが、私のニーズに合わせてコードを調整しようとして失敗しました(追加のウィンドウがリストに追加されました)。 コードを完全に理解できなかったので、何か間違ったことをしたか、コードが元々そのような不適切な使用のために設計されていませんでした。 (ただし、引き続き対処します。)最後に、私は独自の調査を実施し、「正しい」ウィンドウを選択するための経験的条件を決定しました(これらの条件を最後にリストします)。 結果のプログラムコードは1ページに収まります。
int WinMainCRTStartup(void) { if (!RegisterHotKey(NULL, 0, MOD_CONTROL | MOD_SHIFT | MOD_ALT, 'Z')) return 1; MSG msg = {0}; while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_HOTKEY) { HWND current_wnd = GetForegroundWindow(); if (current_wnd == NULL) continue;
小さな技術的なコメント
- この関数はWinMainCRTStartupと呼ばれます 。これは、CRTがここに含まれていないため、オフにしたためです。 その結果、コンパイルされたプログラムは3072バイトを消費します。 これについてはRSDNで詳細を読むことができます。
- 「右」ウィンドウを選択するための経験的条件は次のとおりです。 ウィンドウは:
- 見えるようにする
- 拡張スタイルWS_EX_TOOLWINDOWを持たないでください。
- このウィンドウの所有者ウィンドウは不在または非表示にする必要があります。
- 「間違った」ウィンドウが現在のウィンドウである場合の状況に対処するには、最初のサイクル(「ルート」所有者ウィンドウの検索)が必要です。 たとえば、ABBYY Lingvoプログラムでは、カードウィンドウを含むすべてのウィンドウが「間違っています」。これらはトップレベルウィンドウであり、それぞれが可視性フラグを持ち、寸法がゼロのダミーウィンドウによって所有されています。 現在のウィンドウがこのようなウィンドウカードである場合、GetWindowサイクル(current_wnd、GW_HWNDNEXT)はまずこの最も架空のLingvoウィンドウに入り、正式に「正しい」ため、アクティブにします。 つまり 別のアプリケーションへの切り替えは発生しません。 ループの代わりにGetAncestor(current_wnd、GA_ROOTOWNER)を使用することは可能ですが、この場合、ウィンドウの可視性は考慮されず、結果は正しくありません。
- 残念ながら、この発見的アルゴリズムは理想的ではありません。 特に、Excel 2003ウィンドウでは正しく動作しません(1つのウィンドウで簡単にループします)。 確かに、これは部分的にExcel自体の障害であり、ウィンドウを完全に理解できない方法で整理するため、標準のAlt + Tabでも1つのウィンドウにループすることができ、このサイクルをスキップするにはTabを2回押す必要があります。 私はまだこの謎に対処する予定です。 また、キーボード入力をインターセプトすると、キーの組み合わせがホストシステムではなく仮想マシンに送られるため、仮想マシンにも注意する必要があります。
- 現在のバージョンは、プログラムからの正しい出口を提供していません(したがって、一般的に言えば、プログラムの最後でUnregisterHotKeyを呼び出すことは不要ですが、美しさのために残しました:-))。 プログラムを定期的に終了したいが、プロセスを強制終了したくない場合は、別のグローバルキーボードショートカットの登録を追加し、メッセージ処理サイクルにチェックを挿入し、どの組み合わせが押されたか、Ctrl + Alt + Shift + Zでない場合-ループから抜け出す。
Source: https://habr.com/ru/post/J105312/
All Articles