65.9K
CodeProject 正在变化。 阅读更多。
Home

分割窗口教程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (68投票s)

2003年1月14日

4分钟阅读

viewsIcon

358378

downloadIcon

12547

在 MFC SDI 应用程序中实现 CSplitterWnd 控件

Sample Image - SplitterWindowTutorial.gif

引言

本文旨在涵盖使用默认 MFC CSplitterWnd 对象的基础知识。我花了很长时间寻找关于使用这些对象的入门介绍,但只找到了子类或经过改编的 CSplitterWnd 教程。我希望这篇文章能帮助那些和我一样,只是想对这个基本对象有一个初步了解的人。

背景

CSplitterWnd 或分割器窗口是一种将屏幕分割成两个或多个不同窗格的方法(请参阅截图或 3D 编辑器等应用程序)。窗格本身通常填充有 CViewCWnd 派生对象,以提供文档的不同视图(或用户界面功能)。

分割器窗口有两种形式:静态和动态。本教程仅涵盖静态分割器,因为动态分割器稍微复杂一些。两者的主要区别在于,动态分割器可以由用户分割和折叠,而静态分割器则不能。

Using the Code

步骤 1 - 声明数据

使用 AppWizard 创建一个支持文档/视图的新单文档应用程序。在主框架的头文件中添加一个 CSplitterWnd 对象和一个用于分割器管理的布尔标志。

CSplitterWnd m_mainSplitter;
BOOL m_bInitSplitter;

m_mainSplitter 将用于将窗口分割成两个窗格,如上图所示。该布尔标志将用于在管理大小调整之前检查分割器是否已设置。确保在主框架类的构造函数中,将布尔值初始化为 FALSE

步骤 2 - 创建分割器

分割器窗口应在主框架窗口客户区的初始化期间创建。在主框架类中为 OnCreateClient 消息添加一个函数,并插入以下分割器创建代码:

//calculate client size 
CRect cr; 
GetClientRect( &cr);

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

CreateStatic() 的参数是父窗口(this)以及行数和列数。获取客户区矩形的大小以便后续进行尺寸调整。

步骤 3 - 创建视图

分割器中的每个窗格,除非嵌套有另一个分割器,否则在显示之前必须附加一个视图。调用 CreateStatic 后,使用以下代码为窗格创建默认视图。请注意,分割器中的每一列都必须有一个视图,因为它没有嵌套的分割器。这给我带来了很多问题(对视图的要求的理解),所以花一些时间查看各种代码示例以获得更深入的理解。然后将布尔标志更新为 TRUE,以指示分割器已创建。

if ( !m_mainSplitter.CreateView( 0, 0, 
       RUNTIME_CLASS(CSplitterWindowTutorialView), 
       CSize(cr.Width()/2, cr.Height()), pContext ) ) 
{ 
    MessageBox( "Error setting up splitter frames!", 
                "Init Error!", MB_OK | MB_ICONERROR );
    return FALSE; 
}

if ( !m_mainSplitter.CreateView( 0, 1, 
        RUNTIME_CLASS(CSplitterWindowTutorialView), 
        CSize(cr.Width()/2, cr.Height()), pContext ) ) 
{ 
    MessageBox( "Error setting up splitter frames!", 
        "Init Error!", MB_OK | MB_ICONERROR );
    return FALSE; 
}

m_bInitSplitter = TRUE;

要使用 RUNTIME_CLASS(CSplitterWindowTutorialView),您必须在 MainFrm.cpp 中包含您的视图类头文件,并在视图类头文件中包含您的文档类,就在

#endif // _MSC_VER > 1000.

这将允许您在主框架类中使用您的视图类。如果您不在视图类头文件中包含您的文档类,则会遇到很多问题 - 这是另一个需要注意的地方!

步骤 4 - 替换返回值

替换

return CFrameWnd::OnCreateClient(lpcs, pContext);

return TRUE;

现有代码的默认返回值将不会显示我们的工作,因为它将默认方法返回给框架窗口。

步骤 5 - 管理大小调整

SetRowInfoSetColumnInfo 负责管理分割器的大小。添加一个 WM_ONSIZE 消息的处理程序,并添加以下代码:

void CMainFrame::OnSize(UINT nType, int cx, int cy) 
{
    CFrameWnd::OnSize(nType, cx, cy);
    CRect cr;
    GetWindowRect(&cr);

    if (  m_bInitSplitter && nType != SIZE_MINIMIZED )
    {
        m_mainSplitter.SetRowInfo( 0, cy, 0 );
        m_mainSplitter.SetColumnInfo( 0, cr.Width() / 2, 50);
        m_mainSplitter.SetColumnInfo( 1, cr.Width() / 2, 50);

        m_mainSplitter.RecalcLayout();
    }
}

在上面的代码中,我们首先通过检查布尔值来确保分割器已初始化。此检查是必需的,因为我认为在创建方法运行之前,WM_SIZE 消息会传递给框架 - 因此,代码首次运行时对象将不存在,如果您不检查它的存在,就会崩溃。

现在应用程序应该可以运行了,并且会显示一些类似于文章开头截图的内容!我可能会在系列文章中添加第二篇,介绍如何添加更深入的嵌套分割器和其他基于表单的视图!敬请期待...

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.