Tips of VC++ >
ウィンドウ >
前回のウィンドウ位置を復元する方法
★ 前へ戻る ★ 次へ進む ★
レジストリを使ってウィンドウの表示位置やサイズをプログラムの終了時に保存して、
次の起動時に読みこんで復元するやり方を説明します。
レジストリは簡単にアクセスするために
こちらで作ったクラスを使うことにします。
/*
* -------------
* place.cpp
* -------------
*/
#include "stdafx.h"
#include "registry.h"
const char szClassName[]="Place";
HMODULE hAppModule=NULL;
CRegistry appreg(szClassName);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void LoadWindowPlacement(LPWINDOWPLACEMENT);
void SaveWindowPlacement(LPWINDOWPLACEMENT);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
hAppModule=(HMODULE)hInstance;
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
wc.hCursor = ::LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW));
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = szClassName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
::RegisterClassEx(&wc);
HWND hWnd=::CreateWindow(szClassName,szClassName,
WS_OVERLAPPEDWINDOW,100,100,200,50,
NULL,NULL,hInstance,0);
if ( hWnd==NULL )
return 0;
WINDOWPLACEMENT wp;
::memset(&wp,0,sizeof(WINDOWPLACEMENT));
wp.length = sizeof(WINDOWPLACEMENT);
wp.showCmd = nCmdShow;
::SetRect(&wp.rcNormalPosition,
50,50,200,200);
LoadWindowPlacement(&wp);
::SetWindowPlacement(hWnd,&wp);
MSG msg;
while ( ::GetMessage(&msg,NULL,0,0) )
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND in_hWnd,
UINT in_Message,
WPARAM in_wParam,
LPARAM in_lParam)
{
WINDOWPLACEMENT wp;
switch ( in_Message )
{
case WM_CLOSE:
::memset(&wp,0,sizeof(WINDOWPLACEMENT));
wp.length=sizeof(WINDOWPLACEMENT);
::GetWindowPlacement(in_hWnd,&wp);
if ( ::IsZoomed(in_hWnd) )
wp.flags|=WPF_RESTORETOMAXIMIZED;
SaveWindowPlacement(&wp);
::DestroyWindow(in_hWnd);
break;
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
return ::DefWindowProc(in_hWnd,
in_Message,in_wParam,in_lParam);
}
return 0;
}
void LoadWindowPlacement(LPWINDOWPLACEMENT in_WndPlace)
{
appreg.LoadBinaryValue("WindowPlacement",
(LPBYTE)in_WndPlace,sizeof(WINDOWPLACEMENT));
}
void SaveWindowPlacement(LPWINDOWPLACEMENT in_WndPlace)
{
appreg.SetBinaryValue("WindowPlacement",
(LPBYTE)in_WndPlace,sizeof(WINDOWPLACEMENT));
}
あまり長くないので全ソースを載せてみました。
まず、ポイントとなるAPIと構造体があります。
typedef struct _WINDOWPLACEMENT { UINT length; UINT flags; UINT showCmd; POINT ptMinPosition; POINT ptMaxPosition; RECT rcNormalPosition; } WINDOWPLACEMENT; BOOL GetWindowPlacement( HWND hWnd, // ウィンドウのハンドル WINDOWPLACEMENT *lpwndpl // 位置データ ); BOOL SetWindowPlacement( HWND hWnd, // ウィンドウのハンドル CONST WINDOWPLACEMENT *lpwndpl // 位置データ );
WINDOWPLACEMENT構造体の中身を詳しく知る必要はありません。
ここには表示位置やサイズなどのレジストリに書き込むデータが詰まっているので
これをまとめて書きこめば楽です。
GetWindowPlacementでWINDOWPLACEMENT構造体を取得できます。
対するSetWindowPlacementはShowWindowみたいなものです。
ウィンドウを指定するWINDOWPLACEMENT構造体のデータによって
表示したり移動したりします。
CreateWindowの直後でWINDOWPLACEMENTを取得して、
ShowWindowを呼び出すところでSetWindowPlacementを使って
ウィンドウを表示しています。
このときレジストリに値がない場合もあるので、
そのときのためにあらかじめ構造体には初期値を入れておきます。
WINDOWPLACEMENT::showCmdにはWinMain関数の第四引数を入れておいてください。
次にWM_CLOSEでレジストリに現在のウィンドウの情報を保存します。
GetWindowPlacementで構造体を取得し、レジストリに書きこみます。
このときにウィンドウが最大化されているようであれば、
WINDOWPLACEMENT::flagsにWPF_RESTORETOMAXIMIZEDフラグを追加しておきます。