MFC SDI调用OpenDocument()重置主窗口大小 如何阻止该问题
解决方案
根因说明
MFC单文档框架执行CSingleDocTemplate::OpenDocumentFile时,会调用InitialUpdateFrame强制调整主窗口尺寸适配首次加载的视图,这个调用时机晚于你在InitInstance中设置窗口位置的逻辑,会直接覆盖已设置的大小、位置参数,运行中打开新文档时也会触发该逻辑导致窗口被重置。
修复步骤
1. 调整窗口位置加载时机(解决启动打开文档时尺寸重置)
将原InitInstance中加载窗口位置的逻辑后移,放到ProcessShellCommand执行完成之后,避免被框架的初始化逻辑覆盖:
BOOL CDisplayApp::InitInstance() { // 原有初始化代码:注册窗口类、注册文档模板等逻辑保留 // ... CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 禁用框架默认自动显示窗口逻辑 m_nCmdShow = SW_HIDE; if (!ProcessShellCommand(cmdInfo)) return FALSE; // 在这里加载并设置保存的窗口位置 LONG Ret; HKEY RegistryKey; DWORD type = REG_BINARY; WINDOWPLACEMENT sWP = {0}; sWP.length = sizeof(WINDOWPLACEMENT); DWORD sizewp = sizeof(WINDOWPLACEMENT); Ret = RegOpenKeyEx( HKEY_CURRENT_USER, _T("SOFTWARE\\Local AppWizard-Generated Applications\\display\\PreservedWindowPos"), 0, KEY_READ, &RegistryKey); BOOL bLoadPosSuccess = FALSE; if (Ret == ERROR_SUCCESS) { Ret = ::RegQueryValueEx(RegistryKey, _T("PosAndSize"), 0, &type, (LPBYTE)&sWP, &sizewp); if (Ret == ERROR_SUCCESS && sWP.length == sizeof(WINDOWPLACEMENT)) { m_pMainWnd->SetWindowPlacement(&sWP); bLoadPosSuccess = TRUE; } RegCloseKey(RegistryKey); } // 按保存的状态显示窗口 if (bLoadPosSuccess) m_pMainWnd->ShowWindow(sWP.showCmd); else m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; }
2. 重写InitialUpdateFrame方法(解决运行时打开新文档尺寸重置)
重写CMainFrame的InitialUpdateFrame方法,禁用窗口已显示后的自动尺寸调整逻辑:
- 首先在CMainFrame类头文件添加方法声明:
class CMainFrame : public CFrameWnd { // 原有类成员保留 // ... public: virtual void InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible) override; };
- 在CMainFrame的实现文件添加方法实现:
void CMainFrame::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible) { // 窗口已完成初始化显示后,打开新文档时不允许框架修改窗口尺寸 if (::IsWindowVisible(m_hWnd)) { CFrameWnd::InitialUpdateFrame(pDoc, FALSE); if (GetActiveView()) GetActiveView()->OnInitialUpdate(); } else { // 首次初始化走原有逻辑,由InitInstance控制窗口显示 CFrameWnd::InitialUpdateFrame(pDoc, bMakeVisible); } }
额外优化点
原有加载窗口位置的代码没有初始化WINDOWPLACEMENT的length字段,部分Windows版本下可能会导致SetWindowPlacement调用失败,上面的修复代码已经补充了该初始化逻辑。
内容的提问来源于stack exchange,提问作者WillDotson
相关产品推荐
相关产品推荐

