- ベストアンサー
非アクティブのウィンドウを最前面に呼び出したい。
右ダブルクリックで呼び出すランチャプログラムを作成したいのですが、 システムフックをかけてWM_RBUTTONDBLCLKをアプリ側に送り,それに反応させる形でランチャのウィンドウを最前面に持ってきたいのですが上手くいきません。 フックされたメッセージが送られてきた場合の処理は以下のようになっています。 ~省略 case WM_USER+100: //ダブルクリックが送られてきた場合のメッセージコード //任意文字列を別ウィンドウのリストボックスに吐く自作関数 Add("dblclk"); //以下でウィンドウを最前面に持ってくる。 //lpにクリックされた座標が入っている SetWindowPos(hWnd , HWND_TOP,(int)LOWORD(lp),(int)HIWORD(lp), NULL,NULL,SWP_NOSIZE|SWP_SHOWWINDOW); SetForegroundWindow(hWnd); UpdateWindow(hWnd); break; ~省略 このコードの場合、ウィンドウの位置は変更されるのですが、最前面に来てくれません。 Add関数が呼ばれているのでフック自体は成功しているようなのですが、何かおかしな点はありますでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
★気になった点を2つとアドバイスを1つします。 ・1つ目は、 『(int)LOWORD(lp)』は『(SHORT)LOWORD(lp)』にするか、『GET_X_LPARAM(lp)』にします。 『GET_X_LPARAM(lp)』、『GET_Y_LPARAM(lp)』マクロ関数は『WindowsX.h』で定義されています。 ・2つ目は、 『SetWindowPos』関数の引数5、引数6が『NULL』ですが、ポインタではないので『0』とします。 ・3つ目は、 配置順序のハンドルを『HWND_TOP』ではなく『HWND_TOPMOST』にしてみたらどうでしょうか? つまり: SetForegroundWindow( hWnd ); ←先に記述 SetWindowPos( hWnd, HWND_TOPMOST, (SHORT)LOWORD(lp), (SHORT)HIWORD(lp), 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW ); UpdateWindow( hWnd ); 最後に: ・マウスの右ダブルクリックでランチャーを起動させる仕様ですが、通常の右メニューが出ると 右ダブルクリックの『WM_RBUTTONDBLCLK』がうまく表示できますか? ・『WM_RBUTTONDBLCLK』の次のタイミングの『WM_RBUTTONUP』でランチャーを表示するように してみたらどうなりますか?→いろいろ試してみて下さい。 ・以上。おわり。
その他の回答 (3)
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス ・『SetForegroundWindow( hWnd );』の部分を 『SetForegroundWindow( GetLastActivePopup(hWnd) );』としたら、どうなる? ・また、タスクトレイ(通知領域)の左クリックで問題なくウィンドウが前面に出るのならば 『SendMessage』関数などでタスクトレイの左クリックのメッセージを送信してみるのは? ・あと、非表示の『HWND_DESKTOP』で作られたウインドウを『CloseWindow』で最小化すると メモリがコンパクト化されると思います。 ・以上。3つほどアドバイスしてみました。→参考にして下さい。
お礼
ありがとうございます。 自分でもいろいろと調べてみた結果、 http://techtips.belution.com/ja/vc/0012/ を参考にして目的を達成することが出来ました。 タスクトレイのクリックで上手くいった理由は、タスクトレイをクリックすることで自分のアプリケーションがフォアグラウンドスレッドになっていたからのようです。 質問事項以外のことも親切に教えていただき、本当にありがとうございました。
- yonfa
- ベストアンサー率52% (22/42)
> このコードの場合、ウィンドウの位置は変更されるのですが、最前面に来てくれません。 指定したウィンドウが最前面に来ない、アクティブにならないということでよいでしょうか? ソース上であれこれ試しても効果なしの可能性が大です。 レジストリの設定で問題が解決しそうですのでお試しあれ。 HKEY_CURRENT_USER\Control Panel\Desktop キーの ForegroundLockTimeout の値を 0 に設定してみてください。 「ForegroundLockTimeout」で検索してもらえばいろいろ出てくると思います。
お礼
回答ありがとうございます。 今回の場合、新しく起動するウィンドウではなくランチャのウィンドウを最前面に持ってきたいため、この方法では解決できませんでした。 念のためForegroundLockTimeoutの値を確認してみましたところ、既に0に設定されていました。 言葉が足りずに申し訳ありません。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★また気になったので1つ補足要求いいですか? ・呼び出すランチャは『ショートカットメニュー』タイプですか? それとも『ダイアログ』タイプですか? ・以上。補足要求します。
補足
ショートカット、という形になると思います。 h = CreateWindow( szClassname, szClassname, ~WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL); hWnd= CreateWindow( szClassname, szClassname, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, h, NULL, hInstance, this); このようにしてタスクバー上のアイコンを殺して、その後通知領域にアイコンを登録しています。 また、hWndへ送られるメッセージのみを処理させています。 これを用いずに、普通にCreateWindowをしても結果に変化はありませんでした。 通知領域のアイコンを左クリックしたとき、 SetWindowPos(hWnd , HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); SetForegroundWindow(hWnd); UpdateWindow(hWnd); という処理をしていますが、この場合は問題なくウィンドウは最前面へ呼び出すことが出来ます。 これは書いておくべきでした。申し訳ありません。
お礼
回答ありがとうございます。 2つ目に付いては座標がマイナスの時のための処置と認識してよろしいのでしょうか? 「HWND_TOPMOST」を利用してやろうとしてみたのですが、この設定の場合指定したウィンドウを常に最前面とするので、直後にこれを解除するために SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); として最前面設定を解除するよう試みました。 しかし、この場合直前のアクティブウィンドウとアプリケーションのキャプションバーが両方ともアクティブ時の色となってしまい、アプリケーションのウィンドウを一度クリックしてから他の操作を行わないと最前面に固定されたままになってしまいます。 SetActiveWindow関数を用いてもこれは解消できませんでした。 最後に示唆していただいたように右メニューも出てしまうために、右クリックの入力を全てフックプロシージャ側で止めた後、WM_RBUTTONUPからランチャを呼び出すよう変更してテストしてみましたが、この場合も結果は同じでした。 HWND_TOPMOSTを用いれば最前面へ出てくるため、一旦この路線でいろいろ試してみます。