- ベストアンサー
最大化時のフルスクリーン
いつもお世話になっております。 VS2005 を使ってWindowsアプリケーションの実装を行っています。 最大化時にフルスクリーンにしたくプログラムを作成しているのですが、 WndProc内で下記のプログラムを実行し、 最大化アイコンをクリックするとバグ?が起きてしまいます。 -------------------------------------------------- case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); if(wParam == SIZE_MAXIMIZED){ //最大化されたら ShowWindow(hWnd, SW_SHOWNORMAL); //(1)ウィンドウを元のサイズに戻す //(2)アプリケーションのウィンドウのフレームを「なし」にする GetWindowLong(hWnd, GWL_STYLE); //ウインドウ・スタイルの取得 SetWindowLong(hWnd, GWL_STYLE, WS_POPUP); //ウインドウ・スタイルの設定 SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); ShowWindow(hWnd, SW_MAXIMIZE); //(3)ウィンドウ最大化 } return 0; -------------------------------------------------- 実行したアプリケーションの右上の最大化ボタンを押すと、 見た感じではif文の中を繰り返し行っているような・・・ 元のサイズに戻って最大化になってを数秒繰り返して 最後にペイントして停止します。(高速なため確かではありません) 上記プログラムをどう直したらよいのでしょう。 ご教授お願いいたします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 APIの中には、内部的にSendMessage(hWnd, WM_???, wParam, lParam)を呼ぶものがあります。 場合によっては、メッセージ内で再帰が発生して、ウィンドウの挙動がおかしくなったり、スタックオーバーフローで吹き飛んだりするので要注意です。 後、ウィンドウスタイルのフラグを変えた時、必ずSetWindowPos()にSWP_FRAMECHANGEDのフラグを渡して呼び出してください。此れを怠るとウィンドウの外観に反映されません。 WM_SYSCOMMANDメッセージの「wParam == SC_MAXIMIZE」で処理してください。 http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static DWORD _S_dwStyle = 0; static DWORD _S_dwExStyle = 0; static RECT _S_rcWindow = {0}; switch(message) { case WM_SYSCOMMAND: //最大化ボタンが押された if(wParam == SC_MAXIMIZE) { //スタイルを変える _S_dwStyle = ::SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE); _S_dwExStyle = ::SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); ::GetWindowRect(hWnd, &_S_rcWindow); //先に最大化させる ::ShowWindow(hWnd, SW_MAXIMIZE); //ディスプレイのサイズを取る RECT rc = {0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)}; //クライアント領域でデスクトップを覆い尽くす ::SetWindowPos(hWnd, NULL, rc.left, rc.top, rc.right, rc.bottom, SWP_FRAMECHANGED | SWP_NOZORDER); return 0; } break; //元のサイズに戻す case WM_LBUTTONDOWN: //最大化されていれば元に戻す if(::IsZoomed(hWnd)) { ::SetWindowLong(hWnd, GWL_STYLE, _S_dwStyle); ::SetWindowLong(hWnd, GWL_EXSTYLE, _S_dwExStyle); ::SetWindowPos(hWnd, NULL, _S_rcWindow.left, _S_rcWindow.top, _S_rcWindow.right - _S_rcWindow.left, _S_rcWindow.bottom - _S_rcWindow.top, SWP_FRAMECHANGED | SWP_NOZORDER); ::ShowWindow(hWnd, SW_RESTORE); } break; case WM_CLOSE: ::DestroyWindow(hWnd); return 0; case WM_NCDESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hWnd, message, wParam, lParam); }
その他の回答 (1)
- koi1234
- ベストアンサー率53% (1866/3459)
外れてたらごめんなさい そのコードだとWM_SIZEのメッセージ処理がループしませんか? > SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); > ShowWindow(hWnd, SW_MAXIMIZE); //(3)ウィンドウ最大化 辺りで その関数で再度 WM_SIZE メッセージが飛ぶと思うんですが・・・ 結果スタック破壊してるんじゃないですか?
補足
早いご回答ありがとうございます。 やはり、WM_SIZE内で最大化処理を行ってしまうと 処理はループしていまうんですね。なるほど。 勉強になりました。 本当にありがとうございました。
お礼
再びコメント失礼します。 試行錯誤していたところ、問題解決いたしましたので ここに報告させていただきます。 switch case文内に最大化処理を行い、 DefWindowProc(hWnd, msg, wParam, lParam) に渡してやることで問題解決いたしました。 とてもC++について勉強させて頂きました。 ありがとうございました。
補足
早いご回答ありがとうございます。 早速上記ログラムを使用して実行したところ、 うまく最大化時にフルスクリーンにすることができました。 とても助かりました。 しかし、その他の機能 ・ウィンドウの移動 ・右上の最小化ボタン ・右上の閉じるボタン ・左上のメニューボタン(私のプログラムには「設定」機能もあり) 等全ての機能がまったく効かなくなりました。 そこでWM_SYSCOMMANDの部分をコメントアウトしたところ、 フルスクリーンはできませんがその他の機能は効くようです。 新たにWM_SYSCOMMAND内で、SC_MOVEやSC_MINIMIZEを定義?しないと いけないのでしょうか。この場で質問してしまいごめんなさい。 お願いします。