第13回 ウインドウサイズを前回利用時と同じにする

ImageViewer13_01.gif
起動時のウインドウサイズを前回利用したときと同じサイズで開くようにする。
ソフト終了時にレジストリにウインドウサイズを保存、ソフト起動時にレジストリからウインドウサイズを読み込んで表示する。

まずはソフト終了時のウインドウサイズをレジストリへ保存するため取得する。MainFrm.hを開き、終了時のウインドウサイズを保存するための変数_rectWindowとWM_DESTROYのメッセージハンドラを追加する。
	CRect	_rectWindow;
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)

ImageViewer13_02.gif そしてウインドウ破棄(ソフト終了)時に実行されるOnDestroyを追加する。ここではソフトを終了するときに最大化もしくは最小化していない場合にウインドウサイズを取得している。つまり最大化もしくは最小化しているときはウインドウサイズを取得しない。
	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		bHandled = FALSE;

		//最小化・最大化されていなければウインドウ破壊前にウインドウサイズを保存しておく
		if(IsIconic() == FALSE && IsZoomed() == FALSE)
			GetWindowRect(&_rectWindow);

		return	0;
	}
ImageViewer13_03.gif 次にImageViewer.cppでRun関数の前にレジストリにデータを読み書きする処理を追加する。 レジストリへの書き込みはATLライブラリのCRegKeyを利用する。
//レジストリからのデータ読み込み
bool	LoadRegistry(LPCTSTR pszValueName,void* pData,ULONG nSize)
{
	LONG	nRet;
	ULONG	nSizeRead;
	CRegKey	cRegistry;

	if(pData == NULL)
		return	false;

	//レジストリキーがなければ失敗
	nRet = cRegistry.Open(HKEY_CURRENT_USER,_T("software\\usefullcode\\ImageViewer"),KEY_READ);
	if(nRet != ERROR_SUCCESS)
		return	false;

	nSizeRead = nSize;
	nRet = cRegistry.QueryBinaryValue(pszValueName,pData,&nSizeRead);
	if(nRet == ERROR_SUCCESS && nSizeRead != nSize)
		nRet = ERROR_INVALID_DATA;

	cRegistry.Close();

	return	(nRet == ERROR_SUCCESS) ? true : false;
}


//レジストリへのデータ書き込み
bool	SaveRegistry(LPCTSTR pszValueName,const void* pData,ULONG nSize)
{
	LONG	nRet;
	CRegKey	cRegistry;

	if(pData == NULL)
		return	false;

	//レジストリキーがなければ作成(複数階層でも作成される)
	nRet = cRegistry.Create(HKEY_CURRENT_USER,_T("software\\usefullcode\\ImageViewer"),REG_NONE,REG_OPTION_NON_VOLATILE,KEY_WRITE);
	if(nRet != ERROR_SUCCESS)
		return	false;

	nRet = cRegistry.SetBinaryValue(pszValueName,pData,nSize);

	cRegistry.Close();

	return	(nRet == ERROR_SUCCESS) ? true : false;
}

ImageViewer13_04.gif
次にRun関数内を変更する。この関数はウインドウの生成から終了までを担っている。


ImageViewer13_05.gif
Run関数をこのように修正する。ウインドウ生成処理前にレジストリからウインドウサイズを読み込む。その際、読み込んだウインドウサイズをそのまま表示に利用するのではなく、現在の画面解像度と比較してウインドウが画面の中に納まる場合のみ利用している。

これで実行すると終了時にウインドウサイズがレジストリに書き込まれ、次回から同じサイズで起動するようになる。
int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);

	CMainFrame wndMain;

	bool	ret;
	RECT	rect;

	//ウインドウサイズの読み込み
	ret = LoadRegistry(_T("window_rect"),&rect,sizeof(RECT));
	if(ret)
	{
		//現在のスクリーン内にrectが完全に収まるかチェック。はみ出すならfalse
		if(rect.left < 0 || rect.right > ::GetSystemMetrics(SM_CXSCREEN))
			ret = false;
		if(rect.top < 0 || rect.bottom > ::GetSystemMetrics(SM_CYSCREEN))
			ret = false;
	}

	HWND	hWndRet;

	if(ret)
		hWndRet = wndMain.CreateEx(0,rect);
	else
		hWndRet = wndMain.CreateEx();
	if(hWndRet == NULL)
	{
		ATLTRACE(_T("メイン ウィンドウの作成に失敗しました!\n"));
		return 0;
	}

	wndMain.ShowWindow(nCmdShow);

	int nRet = theLoop.Run();

	//ウインドウサイズの保存
	if(wndMain._rectWindow.Width() > 0 && wndMain._rectWindow.Height() > 0)
		SaveRegistry(_T("window_rect"),&wndMain._rectWindow,sizeof(RECT));

	_Module.RemoveMessageLoop();
	return nRet;
}

プロジェクトファイルをダウンロード


カテゴリー「画像表示ソフトを作る」 のエントリー