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。 |