VC2008 Express Edition, SDK, Vista SP1 です。
アプリケーションの終了時のウィンドウサイズを保存して、
アプリケーションの起動時に終了時のウィンドウサイズを復帰したいです。
現在、WM_CLOSE 時にGetWindowPlacement()で
WINDOWPLACEMENT構造体をファイルに書き込み、
WM_CREATE 時にファイルからWINDOWPLACEMENT構造体を取得し、
SetWindowPlacement()でウィンドウサイズを復帰させています。
このようなやり方だと、ウィンドウが最大化(最大化ボタンが押された状態)のときに終了
すると、次にアプリケーションを起動すると、ウィンドウサイズは最大化されるのです
が、最大化ボタンが押された状態にはなりません。
分かる方いらっしゃいましたら、よろしくお願いします。
最大化した状態で書き出したWINDOWPLACEMENT構造体のflagsメンバとshowCmdメンバはど
うなっているのでしょうか?
http://hp.vector.co.jp/authors/VA023539/tips/window/003.htm
によると、flagsは自分で処理する必要がある…のかも知れませんが。
瀬戸っぷさん、回答ありがとうございます。
最大化した状態で閉じると、flags == 2(WPF_RESTORETOMAXIMIZED),
showCmd == 3(SW_SHOWMAXIMIZED) です。
ご紹介いただいたサイトのように保存時に
if (IsZoomed(in_hWnd) )
wp.flags|=WPF_RESTORETOMAXIMIZED;
としましたが、現象は変わらずでした。><
WinUser.hより
#define SW_HIDE 0
#define SW_SHOWNORMAL 1
#define SW_NORMAL 1
#define SW_SHOWMINIMIZED 2
#define SW_SHOWMAXIMIZED 3
#define SW_MAXIMIZE 3
#define SW_SHOWNOACTIVATE 4
#define SW_SHOW 5
#define SW_MINIMIZE 6
#define SW_SHOWMINNOACTIVE 7
#define SW_SHOWNA 8
#define SW_RESTORE 9
#define SW_SHOWDEFAULT 10
#define SW_FORCEMINIMIZE 11
#define SW_MAX 11
#define WPF_SETMINPOSITION 0x0001
#define WPF_RESTORETOMAXIMIZED 0x0002
#if(_WIN32_WINNT >= 0x0500)
#define WPF_ASYNCWINDOWPLACEMENT 0x0004
#endif /* _WIN32_WINNT >= 0x0500 */
CreateWindow()の後のコードってどうなっているんでしょうか?
メッセージループに入るまであたりのコードです。
WM_CREATEあたりでブレークポイントで停止して、Spy++などで通知されるメッセージを監
視してみてはどうでしょう?
# ExpressEditionにSpy++がついているかは…ちょっと疑問ですな。
# 英語ですが…下記のツールでもメッセージの監視とかできるようです。
# http://www.windows-spy.com/
VS2008を使ってるならメインフレームをCMDIFrameWndExから派生させ、
それらのめんどくさいことを全てやらないというのも、
ひとつの方法です(勝手にやってくれます)。
WM_CREATEでSetWindowPlacement()するとうまく行かないようです。
# 最大化状態/最小化状態の場合は復元時のサイズが上書きされてしま模様。
WM_CREATEの後にもOSから様々なメッセージが飛んできますので、その際にどこかが書き
換えられてしまうのでしょう。
ShowWindow()の位置でSetWindowPlacement()すると正しく動作しました。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200211/02110063.txt
過去ログにありました……。
# SetWindowPlacementで検索したら見つかった。
瀬戸っぷさん、仲澤@失業者さん、おかげさまで解決しました!
ウィンドウサイズの保存・復帰って意外に難しいんですね。
大変勉強になりました。
ひょっとして同じことで悩んでいる人がいるかもしれないのでまとめてみました
(過去ログをまとめただけです)
[sdkでのウィンドウサイズの保存と復帰]
[保存時]
WM_CLOSEぐらいで
WINDOWPLACEMENT構造体をGetWindowPlacement()で取得したあと、以下のif文でshowCmdを
変更したあとにファイルやレジストリに保存
(このif文をいれないと、最小化で終了すると、最小化のまま起動します)
if( wp.showCmd == SW_MINIMIZE || wp.showCmd == SW_SHOWMINIMIZED ){
if( wp.flags == WPF_RESTORETOMAXIMIZED ){
wp.showCmd = SW_SHOWMAXIMIZED;
}else{
wp.showCmd = SW_RESTORE;
}
}
[復帰時]
メインウィンドウのCreateWindowEx()の直後にWINDOWPLACEMENT構造体をファイルやレジ
ストリからロードし、SetWindowPlacement()を呼ぶ。このとき、またif文が必要です。
if( WINDOWPLACEMENT構造体が取得できた? ){
// 以前にソフトを起動した事がある時はここを通る
SetWindowPlacement(hWnd, &wp);
}else{
// インストール後、初めてソフトを起動時
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
}
チェック忘れていました。
解決済みですが、別法を見つけましたので記します
WinMain()
{
HWND hWnd = CreateWindow( WS_OVERLAPPEDWINDOW );
ShowWindow(hWnd, SW_SHOW); // nCmdShowではありません
}
case WM_CREATE:
if(LoadWp(wp)) // wp:WINDOWPLACEMENT, wpをロードできたら
{
bool maxed = wp.showCmd == SW_SHOWMAXIMIZED;
wp.showCmd = SW_HIDE;
SetWindowPlacement(hWnd, &wp);
if(maxed)
SetWindowLong(hWnd, GWL_STYLE,
GetWindowLong(hWnd, GWL_STYLE) | WS_MAXIMIZE);
}
break;