记录窗口的位置和大小

来源:互联网 发布:mackeeper mac破解版 编辑:程序博客网 时间:2024/04/26 17:37
2007年05月15日 星期二 下午 10:07
大多数的应用程序都会记录下上次退出时,窗口的位置和大小。以便在下次打开时恢复。对于在MFC的应用程序中,如何简单地实现这个功能,转一篇日本网站上的文章
From:http://www.geocities.jp/dolanpura/vctips/window/winpossave.htm

翻译如下:
///////////////////////////////////////////////////////////////////////////////
无模对话框的情况

BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
LoadWindowPosition(this);
return TRUE;
}

void CMyDlg::OnDestroy()
{
SaveWindowPosition(this);
CDialog::OnDestroy();
}

///////////////////////////////////////////////////////////////////////////////
MainFrm的情况

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;

:(省略)

LoadWindowPosition(this, "MainFrm");
return 0;
}

void CMainFrame::OnDestroy()
{
SaveWindowPosition(this, "MainFrm");
CFrameWnd::OnDestroy();
}

"*.h"
///////////////////////////////////////////////////////////////////////////////
void SaveWindowPosition(CWnd* pWnd, LPCSTR lpszSection = NULL);
void LoadWindowPosition(CWnd* pWnd, LPCSTR lpszSection = NULL);

"*.c"
///////////////////////////////////////////////////////////////////////////////
//保存窗口信息
void SaveWindowPosition(CWnd* pWnd, LPCSTR lpszSection/* = NULL*/)
{
//Section名(省略的情况下就使用窗口的Caption)
CString strWinName;
if (lpszSection == NULL)
pWnd->GetWindowText(strWinName);
else
strWinName = lpszSection;

//获得窗口的位置信息
WINDOWPLACEMENT info;
pWnd->GetWindowPlacement(&info);

//写入注册表
CWinApp* pApp = AfxGetApp();
pApp->WriteProfileInt(strWinName, "ptMinPosition.x", info.ptMinPosition.x);
pApp->WriteProfileInt(strWinName, "ptMinPosition.y", info.ptMinPosition.y);
pApp->WriteProfileInt(strWinName, "ptMaxPosition.x", info.ptMaxPosition.x);
pApp->WriteProfileInt(strWinName, "ptMaxPosition.y", info.ptMaxPosition.y);
pApp->WriteProfileInt(strWinName, "rcNormalPosition.left", info.rcNormalPosition.left);
pApp->WriteProfileInt(strWinName, "rcNormalPosition.top", info.rcNormalPosition.top);
pApp->WriteProfileInt(strWinName, "rcNormalPosition.right", info.rcNormalPosition.right);
pApp->WriteProfileInt(strWinName, "rcNormalPosition.bottom", info.rcNormalPosition.bottom);
pApp->WriteProfileInt(strWinName, "showCmd", pWnd->IsWindowVisible());
}

///////////////////////////////////////////////////////////////////////////////
//恢复窗口信息
//
void LoadWindowPosition(CWnd* pWnd, LPCSTR lpszSection/* = NULL*/)
{
//Section名(省略的情况下就使用窗口的Caption)
CString strWinName;
if (lpszSection == NULL)
pWnd->GetWindowText(strWinName);
else
strWinName = lpszSection;

//取得窗口的信息,记录启动时的大小
//同时也初始化了WINDOWPLACEMENT结构体
WINDOWPLACEMENT info;
pWnd->GetWindowPlacement(&info);
CRect rect = info.rcNormalPosition;
CSize size = rect.Size();

//从注册表读出信息
CWinApp* pApp = AfxGetApp();
info.showCmd = pApp->GetProfileInt(strWinName,"showCmd",0);
info.ptMinPosition.x = pApp->GetProfileInt(strWinName,"ptMinPosition.x",0);
info.ptMinPosition.y = pApp->GetProfileInt(strWinName,"ptMinPosition.y",0);
info.ptMaxPosition.x = pApp->GetProfileInt(strWinName,"ptMaxPosition.x",0);
info.ptMaxPosition.y = pApp->GetProfileInt(strWinName,"ptMaxPosition.y",0);
info.rcNormalPosition.left = pApp->GetProfileInt(strWinName,"rcNormalPosition.left",0);
info.rcNormalPosition.top = pApp->GetProfileInt(strWinName,"rcNormalPosition.top",0);
info.rcNormalPosition.right = pApp->GetProfileInt(strWinName,"rcNormalPosition.right",640);
info.rcNormalPosition.bottom = pApp->GetProfileInt(strWinName,"rcNormalPosition.bottom",640);
rect = info.rcNormalPosition;

if (size.cx <= 0 || size.cy <= 0) //要是Size很奇怪,就维持启动时的大小
return;

if (!((pWnd->GetStyle()) & WS_THICKFRAME))
//Size不可改变的窗口
{
if (size != rect.Size())
//大小被改变
{
info.rcNormalPosition.right = info.rcNormalPosition.left + size.cx;
info.rcNormalPosition.bottom = info.rcNormalPosition.top + size.cy;
}
}

pWnd->SetWindowPlacement(&info);
}

补充一下:
1.要把信息写入注册表,而不是.INI文件,必须调用CWinApp.SetRegistryKey()。
2.窗口信息会写入到HKEY_CURRENT_USER/Software/XXX/
   .INI的话,C:/Windows/XXX.ini。
3.和GetProfileInt,WriteProfileInt同名的API,会把信息写入Win.ini。但看了看MFC源码,CWinApp的这两
   个方法实际上调用的是GetPrivateProfileInt和WritePrivateProfileString,所以没有问题。
4.上面这个例子并没有处理最大化和最小化的情况。要完美一点,还需要记录info.showCmd。