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

基于 MFC 对话框应用程序中的分隔条

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (5投票s)

2011年7月15日

CPOL

2分钟阅读

viewsIcon

63074

downloadIcon

4347

在基于 MFC 对话框的应用程序中使用按钮作为分隔条。

Screen Shot 1

引言

这是我第一次在 CodeProject 上发表文章。 CodeProject 对我非常有帮助。我想通过提交自己的文章来回馈作者提供的帮助。

在 MFC 中,CSplitterWnd 通常用于 MDI 或 SDI。我只是认为分隔条控件就是可拖动的按钮。所以我决定实现一个名为 CControlSplitter 的类,它派生自 CButton,以便像 CSplitterWnd 一样用于基于对话框的 MFC 应用程序。

背景

实现非常简单。只要你了解如何对 MFC 控件进行子类化,你就能理解它的工作原理并改进它。

使用代码

在您的项目中,包含以下文件

  • ControlSplitter.h
  • ControlSplitter.cpp

在你的对话框头文件中包含 ControlSplitter.h

#include "ControlSplitter.h"

使用普通的按钮控件在你的对话框中添加分隔条按钮,它将作为分隔条使用,并设置其控件 ID,例如 IDC_SPLITTER1

使用 MFC 类向导,在你的对话框中为添加的分隔条按钮添加控件成员变量,类型为 CControlSplitter

添加成员控件变量后,必须实现以下内容

  1. 在你的对话框头文件中声明控件分隔条
    //{{AFX_DATA(CSplitterDlg)
    ...
    CControlSplitter m_splitter;
    ...
    //}}AFX_DATA
  2. 使用对话框的 DoDataExchange 中的 DDX_Control 对控件进行子类化。
    void CSplitterDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CSplitterDlg)
        ...
        DDX_Control(pDX, IDC_SPLITTER, m_splitter);
        ...
        //}}AFX_DATA_MAP
    }

在你的对话框的 OnInitDialog() 方法中设置你的分隔条

  1. [必需] 设置控件分隔条的类型
    m_splitter.SetType(CControlSplitter::CS_VERT);

    可用的类型有 CS_NONE(默认值)、CS_VERTCS_HORZ

    public:
    typedef enum {
        CS_VERT = 1,
        CS_HORZ = 2,
        CS_NONE = 0
    };
  2. 将同级控件添加到分隔条的控件列表中。

    控件分隔条有两个控件列表

    • 顶部控件列表(对于 CS_VERT 类型)或左侧控件列表(对于 CS_HORZ 类型)
    • 底部控件列表(对于 CS_VERT 类型)或右侧控件列表(对于 CS_HORZ 类型)

    要添加控件的顶部控件列表或左侧控件列表,请使用 AddToTopOrLeftCtrls 方法。

    m_splitter.AddToTopOrLeftCtrls(IDOK);

    要添加控件的底部控件列表或右侧控件列表,请使用 AddToBottomOrRightCtrls 方法。

    m_splitter.AddToBottomOrRightCtrls(IDC_EDIT1);

    这是 AddToTopOrLeftCtrlsAddToBottomOrRightCtrls 的声明

    void AddToBottomOrRightCtrls(UINT nCtrlId, WORD nFlags = 
                                 SPF_TOP|SPF_LEFT|SPF_RIGHT|SPF_BOTTOM);
    void AddToTopOrLeftCtrls(UINT nCtrlId, WORD nFlags = 
                             SPF_TOP|SPF_LEFT|SPF_BOTTOM|SPF_RIGHT);

    [注意:] 这两种方法都有额外的标志参数,可用于指定当控件分隔条被拖动时同级控件的行为。可能的值可以是以下各项的组合

    /* distance of the control to the top of the window will be constant */
    #define SPF_TOP     0x0010
    /* distance of the control to the bottom of the window will be constant */
    #define SPF_BOTTOM  0x0020
    /* distance of the control to the left of the window will be constant */
    #define SPF_LEFT    0x0040
    /* distance of the control to the right of the window will be constant */
    #define SPF_RIGHT   0x0080

类工作方法

CControlSplitter();

这是构造函数。

void SetType(UINT nType);

这设置了控件分隔条的类型,可以是 CS_VERTCS_HORZ

void AddToTopOrLeftCtrls(UINT nCtrlId, WORD nFlags);

这用于将控件添加到顶部或左侧控件列表中。

void AddToBottomOrRightCtrls(UINT nCtrlId, WORD nFlags);

这用于将控件添加到底部或右侧控件列表中。

void OnLButtonDown(UINT nFlags, CPoint point);

当用户在控件上按下鼠标左键时,将触发此事件。

void OnLButtonUp(UINT nFlags, CPoint point);

当用户在控件上释放鼠标左键时,将触发此事件。

void OnMouseMove(UINT nFlags, CPoint point);

当用户在控件上移动鼠标时,将触发此事件。

void OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

当系统请求光标时,将触发此事件。光标使用 SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)m_hCursor); 设置。

类工作成员变量

//Holds the Type of the control splitter
unsigned int m_nType;
//Holds the Top or Left Control Listing
std::vector<DWORD> m_vtTopLeftControls;
//Holds the Bottom or Right Control Listing
std::vector<DWORD> m_vtBottomRightControls;
//Holds the POINT position used to calculate the movement changes
CPoint m_ptStartDrag,m_ptStartPos;
//Used to determine if user Starts to Drag, Dragging, and Ends Draging
bool m_bDragging;
//Used to hold the loaded HCURSOR 
HCURSOR m_hCursor;
//Holds the bounds the splitter is allowed to be moved.
CRect m_rectMax;
//Holds the old control that is previously holdes cursor capture.
CWnd * m_pOldDragCapture;

历史

  • 2011 年 7 月 15 日:首次发布。
  • 2011 年 7 月 25 日:翻译了演示下载中的 Readme.txt
© . All rights reserved.