MFC, SDI app, 为啥视图的布局不能通过代码改变?

Posted

技术标签:

【中文标题】MFC, SDI app, 为啥视图的布局不能通过代码改变?【英文标题】:MFC, SDI app, Why the layout of views cannot be changed via code?MFC, SDI app, 为什么视图的布局不能通过代码改变? 【发布时间】:2022-01-16 16:55:15 【问题描述】:

我是 MFC 的新手。我刚刚使用向导创建了一个 SDI 应用程序,然后尝试修改生成的代码来控制每个视图、工具栏或菜单的布局:

...
m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)
...
DockPane(&m_wndToolBar); // m_wndToolBar is a tool bar
...
DockPane(&m_wndFileView);
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
DockPane(&m_wndOutput);
// w_wndFileView, m_wndClassView, m_wndOutput are some views.
...

但它似乎不起作用:窗口总是表现得好像它们记得用户上次操作的内容。例如,最后 3 行代码创建了 3 个视图,如下所示:

我运行代码并关闭,然后修改为:

DockPane(&m_wndFileView);
DockPane(&m_wndOutput);
m_wndClassView.AttachToTabWnd(&m_wndOutput, DM_SHOW, TRUE, &pTabbedBar);

我想应该是这个样子但是失败了(这个截图不是运行结果,我手动改了布局):

它保持上次关闭时的布局(如图1)。此外,可以记住任何用户手动更改布局。所以为什么?谁说要这样做的?

【问题讨论】:

【参考方案1】:

默认情况下,MFC SDI(和 MDI)应用程序“记住”同一应用程序运行之间的框架、菜单和侧窗格配置,这是通过在 Windows 注册表中写入/读取条目来实现的。通常,对于由 Visual Studio 向导生成的名为“MySDIApp”的应用程序,此信息将位于名为1 的注册表项中:

HKEY_CURRENT_USER\SOFTWARE\Local AppWizard-Generated Applications\MySDIApp

在此,将有一个名为“Workspace”的子项,该子项将包含许多子条目,名称格式为“Pane-0123”、“MFCToolBar-456”等。要“清除”所有这些记住的设置,您只需使用注册表编辑器删除“Workspace”键即可。

或者,您可以以编程方式删除该键,方法是在OnInitInstance 成员的应用程序类覆盖中添加如下代码(代码应插入到所指示的向导生成的行之间) :

BOOL CMySDIApp::InitInstance()

    // Other wizard-generated and user code ...

    SetRegistryKey(_T("Local AppWizard-Generated Applications")); // Wizard-generated
    // Delete the remembered Workspace settings ...
    HKEY sk;
    CString kn;
    kn.Format(L"SOFTWARE\\%s\\%s", m_pszRegistryKey, m_pszAppName);
    if (RegOpenKeyEx(HKEY_CURRENT_USER, kn, 0, KEY_ALL_ACCESS, &sk) == ERROR_SUCCESS) 
        SHDeleteKey(sk, L"WorkSpace");
        RegCloseKey(sk);
    
    LoadStdProfileSettings(4);  // Wizard-generated

    // More wizard-generated and user code ...
    return TRUE;


1您可以通过使用注册表编辑器并搜索名为“BasePane--1”的条目来找到实际注册表项;这似乎是向导生成的(和其他)MFC 应用程序的“工作区”条目的第一个子键。

【讨论】:

非常感谢! PS:对这个问题的其他观众的评论:我试图删除 SetRegistryKey() 的调用而不是上面的代码,但由于运行时异常错误而失败。似乎它通过该功能做了一些其他必要的工作。

以上是关于MFC, SDI app, 为啥视图的布局不能通过代码改变?的主要内容,如果未能解决你的问题,请参考以下文章

在 SDI mfc 应用程序中从视图访问模式对话框

在 sdi view MFC 中重新绘制区域(区域)

MFC SDI 和对话框

MFC SDI 应用程序解析自定义参数

MFC中CDialog 的OnKeyDown()为啥不好使?

C++ MFC SDI 复制/粘贴不起作用