トップ回答者
アクティブだったWindowのハンドルを求める方法

質問
-
回答
-
> "GetActiveWindow()" でタスクバーのメニューを操作する前にアクティブだったWindowのハンドルが取れるものと思っていたのですが、うまく動いてくれません。
通知領域に表示されているアイコンを操作するためには、タスクバーがアクティブにならないとダメです。
で、タスクバーもまたウィンドウなので、期待通りの動作は得られないことになります。>タスクバーのメニューを操作する前にアクティブだったWindowのハンドルが取れる方法をご教示下さい。
グローバルをフックしかけて、アクティブウィンドウの履歴(過去数件?)をとっておくとかかな?- 回答としてマーク K.Ika 2012年4月23日 5:15
すべての返信
-
> "GetActiveWindow()" でタスクバーのメニューを操作する前にアクティブだったWindowのハンドルが取れるものと思っていたのですが、うまく動いてくれません。
通知領域に表示されているアイコンを操作するためには、タスクバーがアクティブにならないとダメです。
で、タスクバーもまたウィンドウなので、期待通りの動作は得られないことになります。>タスクバーのメニューを操作する前にアクティブだったWindowのハンドルが取れる方法をご教示下さい。
グローバルをフックしかけて、アクティブウィンドウの履歴(過去数件?)をとっておくとかかな?- 回答としてマーク K.Ika 2012年4月23日 5:15
-
みなさん参考になる情報 ありがとうございます。やはり、単純にはいかないのですね。
ショートカットでのウィンドウ切替 ([Alt]+[Tab] ) 後、ショートカットで メニュー選択 の様なことも想定していますので CBT HOOK に挑戦してみようかと思います。
頂いたキーワードで検索しているうちにZオーダー というものが目に入ってきました。
実際に試していませんので全く見当違いかもしれませんが
デスクトップのウィンドウをZオーダー 順に読み出し、非表示ウィンドウやダイアログ形式のウィンドウを除いた最初のウィンドウがアクティブウィンドウだったというのは無理があるでしょうか。 -
初歩的な質問で恐縮なのですが OS に現在のアクティブウインドウを尋ねル方法は GetForegroundWindow(); でよろしいでしょうか?
自分のプログラム内のフォームが アクティブのとき以外は hWnd が 0 になってしまうのですが、やり方がまずいのでしょうか。
private void button2_Click(object sender, EventArgs e)
{
if (hHook == 0)
{
// Create an instance of HookProc.
WNDHookProcedure = new HookProc(Form1.WNDHookProc);
hHook = SetWindowsHookEx(WH_CBT,
WNDHookProcedure,
GetModuleHandle(null),
GetCurrentThreadId());}
}public static int WNDHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{if (nCode == HCBT_ACTIVATE)
{hWnd = GetForegroundWindow();
int id;
GetWindowThreadProcessId(hWnd, out id);
Process process = Process.GetProcessById(id);
WndTxt = hWnd.ToString();
WndName = process.ProcessName;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}private void button3_Click(object sender, EventArgs e)
{
MessageBox.Show(WndName);}
-
GetForegroundWindow, SetForegroundWindow は、三世代ぐらい前の Win95/NT3.51 時代の機能で、色々と制約を受けているのでうまく動かないかもしれませんね。
GetGUIThreadInfo
http://msdn.microsoft.com/ja-jp/library/cc364710.aspxとかでどうでしょう?
ちなみに、テストコードなので省略されているのかもしれませんが、SetWindowHookEx に渡した CBT のコールバック用の delegate は GCHandle クラスを使って root 化するか、unhook するまでメンバ変数等に保存しておく必要があります。
button2_click のような実装の場合、ボタンを押してフックを開始した後で作成された delegate をだれも保持していないため、GC によって delegate が回収されると二度とコールバックが呼ばれなくなります。(場合によっては、異常終了することもあります)
-
-