• ベストアンサー

最大化時のフルスクリーン

いつもお世話になっております。 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文の中を繰り返し行っているような・・・ 元のサイズに戻って最大化になってを数秒繰り返して 最後にペイントして停止します。(高速なため確かではありません) 上記プログラムをどう直したらよいのでしょう。 ご教授お願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんばんは。  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); }

mymusic54
質問者

お礼

再びコメント失礼します。 試行錯誤していたところ、問題解決いたしましたので ここに報告させていただきます。 switch case文内に最大化処理を行い、  DefWindowProc(hWnd, msg, wParam, lParam) に渡してやることで問題解決いたしました。 とてもC++について勉強させて頂きました。 ありがとうございました。

mymusic54
質問者

補足

早いご回答ありがとうございます。 早速上記ログラムを使用して実行したところ、 うまく最大化時にフルスクリーンにすることができました。 とても助かりました。 しかし、その他の機能  ・ウィンドウの移動  ・右上の最小化ボタン  ・右上の閉じるボタン  ・左上のメニューボタン(私のプログラムには「設定」機能もあり) 等全ての機能がまったく効かなくなりました。 そこでWM_SYSCOMMANDの部分をコメントアウトしたところ、 フルスクリーンはできませんがその他の機能は効くようです。 新たにWM_SYSCOMMAND内で、SC_MOVEやSC_MINIMIZEを定義?しないと いけないのでしょうか。この場で質問してしまいごめんなさい。 お願いします。

その他の回答 (1)

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.2

外れてたらごめんなさい そのコードだとWM_SIZEのメッセージ処理がループしませんか? >    SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); >    ShowWindow(hWnd, SW_MAXIMIZE); //(3)ウィンドウ最大化 辺りで その関数で再度 WM_SIZE メッセージが飛ぶと思うんですが・・・ 結果スタック破壊してるんじゃないですか?

mymusic54
質問者

補足

早いご回答ありがとうございます。 やはり、WM_SIZE内で最大化処理を行ってしまうと 処理はループしていまうんですね。なるほど。 勉強になりました。 本当にありがとうございました。