C++ 使用菜单按钮将视图一分为二?(MFC)

C++ 使用菜单按钮将视图一分为二?(MFC),c++,mfc,sdi,C++,Mfc,Sdi,我编写了一个MFC程序,可以读取文件、存储数据,并在客户端视图中将其绘制为文本 我想制作一个菜单按钮View->Split,将客户端区域分成两个,分别滚动显示相同数据的视图 我在网上看到了一些关于CWndSplitter的内容,并阅读了一些文档,但没有一个文档被证明是有用的,因为他们讨论了使用OnCreate和删除默认视图以使其工作。这不是一个选择。我希望保留默认视图,但如果用户单击按钮,则将其一分为二 我目前已经创建了一个CWndSplitter成员变量,并在SDI-1View.cpp中定义了

我编写了一个MFC程序,可以读取文件、存储数据,并在客户端视图中将其绘制为文本

我想制作一个菜单按钮View->Split,将客户端区域分成两个,分别滚动显示相同数据的视图

我在网上看到了一些关于CWndSplitter的内容,并阅读了一些文档,但没有一个文档被证明是有用的,因为他们讨论了使用OnCreate和删除默认视图以使其工作。这不是一个选择。我希望保留默认视图,但如果用户单击按钮,则将其一分为二

我目前已经创建了一个CWndSplitter成员变量,并在SDI-1View.cpp中定义了一个菜单按钮事件处理程序。当被调用时,它只会导致屏幕闪烁,第二次单击会使程序崩溃

void CSDI1View::OnViewSplit32778()
{
// TODO: Add your command handler code here

/*
int rows = 2;
int columns = 1;
if (!m_wndSplitter.CreateStatic(this, rows, columns))
    return;

if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL) ||
    (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL)))
{
    m_wndSplitter.DestroyWindow();
    return;
}
*/
}
有人能告诉我将客户端视图一分为二的正常方法是什么吗?我只想将其集成到事件处理程序中。 任何帮助都将不胜感激

谢谢

----------------编辑-----------------

感谢xMRi提供的大纲,现在我的Split button事件处理程序中有以下代码,但它仍然不能正常工作

void CMainFrame::OnViewSplit()
{
// TODO: Add your command handler code here
//calculate client size 
CRect cr;
GetClientRect(&cr);

if (!m_mainSplitter.CreateStatic(this, 2, 1))
{
    MessageBox(_T("Error setting up splitter frames! (CreateStatic)"),
        _T("Init Error!"), MB_OK | MB_ICONERROR);
    return;
}

// Set the parent of the splitter window to the current view
CSDI1View * view = CSDI1View::GetView();
m_mainSplitter.SetParent(this);
view->SetParent(&m_mainSplitter);

// Create a CCreateContext
CCreateContext cc;
CRuntimeClass* prt = RUNTIME_CLASS(CSDI1View);
cc.m_pNewViewClass = prt;
cc.m_pCurrentDoc = view->GetDocument();
cc.m_pNewDocTemplate = NULL;
cc.m_pLastView = NULL;
cc.m_pCurrentFrame = this;

if (!m_mainSplitter.CreateView(0, 0,
    cc.m_pNewViewClass,
    CSize(cr.Width(), cr.Height()/2), &cc))
{
    MessageBox(_T("Error setting up splitter frames! (CreateView 1)"),
        _T("Init Error!"), MB_OK | MB_ICONERROR);
    return;
}

if (!m_mainSplitter.CreateView(1, 0,
    cc.m_pNewViewClass,
    CSize(cr.Width(), cr.Height()/2), &cc))
{
    MessageBox(_T("Error setting up splitter frames! (CreateView 2)"),
        _T("Init Error!"), MB_OK | MB_ICONERROR);
    return;
}

m_bInitSplitter = TRUE;
}

单击view->split按钮后,我会弹出一个调试断言错误弹出窗口,对CreateView的第一次调用返回FALSE,显示我的messagebox:Error setting splitter frames!CreateView 1

静态拆分器用于静态拆分,即始终拆分的窗口。当您希望在拆分的每个窗格中显示不同的视图时,通常会使用它,例如,在一个窗格中显示一列数字,在另一个窗格中显示一个图形

对于像您这样的情况,您希望能够拥有窗口,然后拆分它并拥有两个基本相同的视图,您至少通常希望使用动态拆分器

至少在正常情况下,在创建视图时创建拆分器。这将创建一个窗口,该窗口的右上角有一个控制柄,用户可以向下拉以拆分视图:

要拆分窗口,用户向下拉动手柄:

当拆分到他们想要的位置时,他们释放鼠标按钮,视图将拆分为两个单独的可滚动部分:

因为您没有指定是要垂直拆分还是水平拆分,所以我将此设置为允许其中一个或两个:

此操作的代码如下所示:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
    return my_splitter.Create(this,
        2, 2,               // 2 rows, 2 columns
        CSize(20, 20),      // minimum pane size
        pContext);
}
CSplitterWnd my_splitter;
我的_拆分器定义如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
    return my_splitter.Create(this,
        2, 2,               // 2 rows, 2 columns
        CSize(20, 20),      // minimum pane size
        pContext);
}
CSplitterWnd my_splitter;

静态拆分器用于静态拆分,即始终拆分的窗口。当您希望在拆分的每个窗格中显示不同的视图时,通常会使用它,例如,在一个窗格中显示一列数字,在另一个窗格中显示一个图形

对于像您这样的情况,您希望能够拥有窗口,然后拆分它并拥有两个基本相同的视图,您至少通常希望使用动态拆分器

至少在正常情况下,在创建视图时创建拆分器。这将创建一个窗口,该窗口的右上角有一个控制柄,用户可以向下拉以拆分视图:

要拆分窗口,用户向下拉动手柄:

当拆分到他们想要的位置时,他们释放鼠标按钮,视图将拆分为两个单独的可滚动部分:

因为您没有指定是要垂直拆分还是水平拆分,所以我将此设置为允许其中一个或两个:

此操作的代码如下所示:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
    return my_splitter.Create(this,
        2, 2,               // 2 rows, 2 columns
        CSize(20, 20),      // minimum pane size
        pContext);
}
CSplitterWnd my_splitter;
我的_拆分器定义如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
    return my_splitter.Create(this,
        2, 2,               // 2 rows, 2 columns
        CSize(20, 20),      // minimum pane size
        pContext);
}
CSplitterWnd my_splitter;

如果要按需使用拆分器窗口,则需要更改当前视图的父视图。 因此,这些步骤是:

创建一个简单的SDI应用程序 按需创建拆分器窗口 对当前视图使用SetParent,并在拆分器窗口中将其设置为父视图。 在第二个拆分器中创建另一个窗口。 还有回去的路

使用SetParent并将法线视图附着回主框架。 摧毁拆分器
存在如何在当前文档中切换视图的活动示例。它可以帮助您如何替换和更改ID。

如果您想按需使用拆分器窗口,则需要更改当前视图的父视图。 因此,这些步骤是:

创建一个简单的SDI应用程序 按需创建拆分器窗口 对当前视图使用SetParent,并在拆分器窗口中将其设置为父视图。 在第二个拆分器中创建另一个窗口。 还有回去的路

使用SetParent并将法线视图附着回主框架。 摧毁拆分器
存在如何在当前文档中切换视图的活动示例。它可以帮助您如何更换和更改ID。

感谢您提供的详细信息,这正是我想要的!澄清一下,当你说在第二个拆分器中创建另一个窗口时,你的意思是在第二个窗口中哪个是拆分器,还是我应该创建两个拆分器?不!我的答案是关于一个具有两个不同ki的拆分器
视野的尽头。因此,创建意味着创建第二个视图,该视图应显示在splitter.Ok中。我已经按照您的步骤创建了一个拆分器,并在我的问题中发布了我的更新代码,但它似乎仍然不起作用。也许你可以看看,看看能不能找到我做错了什么?谢谢。你没有听从我的建议。拆分器将主帧作为其父帧。视图将拆分器作为父视图。。。您将拆分器设置为视图的子级,这是错误的。感谢您的分解,这正是我要查找的!澄清一下,当你说在第二个拆分器中创建另一个窗口时,你的意思是在第二个窗口中哪个是拆分器,还是我应该创建两个拆分器?不!我的回答是关于一个有两种不同观点的分裂者。因此,创建意味着创建第二个视图,该视图应显示在splitter.Ok中。我已经按照您的步骤创建了一个拆分器,并在我的问题中发布了我的更新代码,但它似乎仍然不起作用。也许你可以看看,看看能不能找到我做错了什么?谢谢。你没有听从我的建议。拆分器将主帧作为其父帧。视图将拆分器作为父视图。。。您将拆分器设置为视图的子级,这是错误的。谢谢。我想创建一个静态拆分,我可以通过切换父母来打开和关闭它,基本上就像xMRi在他的回答中描述的那样。不过我遇到了另一个问题,请查看我的问题编辑。谢谢。我想创建一个静态拆分,我可以通过切换父母来打开和关闭它,基本上就像xMRi在他的回答中描述的那样。我遇到了另一个问题,请查看我的问题。