つい集めてしまうものはなんですか?

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

上記プログラムをどう直したらよいのでしょう。
ご教授お願いいたします。

A 回答 (2件)

 こんばんは。



 APIの中には、内部的にSendMessage(hWnd, WM_???, wParam, lParam)を呼ぶものがあります。
 場合によっては、メッセージ内で再帰が発生して、ウィンドウの挙動がおかしくなったり、スタックオーバーフローで吹き飛んだりするので要注意です。
 後、ウィンドウスタイルのフラグを変えた時、必ずSetWindowPos()にSWP_FRAMECHANGEDのフラグを渡して呼び出してください。此れを怠るとウィンドウの外観に反映されません。

 WM_SYSCOMMANDメッセージの「wParam == SC_MAXIMIZE」で処理してください。
 http://msdn.microsoft.com/en-us/library/ms646360 …


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);
}

この回答への補足

早いご回答ありがとうございます。

早速上記ログラムを使用して実行したところ、
うまく最大化時にフルスクリーンにすることができました。
とても助かりました。

しかし、その他の機能
 ・ウィンドウの移動
 ・右上の最小化ボタン
 ・右上の閉じるボタン
 ・左上のメニューボタン(私のプログラムには「設定」機能もあり)
等全ての機能がまったく効かなくなりました。

そこでWM_SYSCOMMANDの部分をコメントアウトしたところ、
フルスクリーンはできませんがその他の機能は効くようです。

新たにWM_SYSCOMMAND内で、SC_MOVEやSC_MINIMIZEを定義?しないと
いけないのでしょうか。この場で質問してしまいごめんなさい。
お願いします。

補足日時:2010/01/13 13:26
    • good
    • 0
この回答へのお礼

再びコメント失礼します。

試行錯誤していたところ、問題解決いたしましたので
ここに報告させていただきます。

switch case文内に最大化処理を行い、
 DefWindowProc(hWnd, msg, wParam, lParam)
に渡してやることで問題解決いたしました。

とてもC++について勉強させて頂きました。
ありがとうございました。

お礼日時:2010/01/13 14:50

外れてたらごめんなさい


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

この回答への補足

早いご回答ありがとうございます。

やはり、WM_SIZE内で最大化処理を行ってしまうと
処理はループしていまうんですね。なるほど。

勉強になりました。
本当にありがとうございました。

補足日時:2010/01/13 13:34
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報