本文大部分思路来自于《VISUAL C++ 6.0 MFC 类库参考手册》一书!
CDialogBar在MFC中就是提供控制条形式的非模态对话框。
其使用过程很简单:
1.在MainFrame框架中声明变量
CDialogBar m_dialogbar;
2.在MainFrame的OnCreate函数中创建
EnableDocking(CBRS_ALIGN_ANY); if (!m_dialogbar.Create(this,IDD_PREV,WS_CHILD|WS_VISIBLE|CBRS_TOOLTIPS|CBRS_LEFT|CBRS_SIZE_DYNAMIC|CBRS_FLYBY,IDD_PREV)) { TRACE0("控制栏创建失败!"); return -1; } m_dialogbar.EnableDocking(CBRS_ALIGN_LEFT); DockControlBar(&m_dialogbar);其中IDD_PREV为在资源中加入的对话框ID
这样确实可以创建一个可以停靠的对话框条,但是同时这个对话框条有很多问题:
1.在该对话框上添加的按钮都会呈灰色,无论你是否给该按钮添加消息响应函数。
2.你为该对话框重载了OnInitDialog()后发现仍然无法初始化对话框
1的原因是因为CDialogBar对话框的消息响应是由MainFrame处理,所以你在当前对话框下给按钮绑定消息响应是不会响应的!
2的原因是因为CDialogBar是CContorlBar的子类,而非CDialog的子类,无法重载OnInitDialog()。(网上有解决办法可以让其初始化,点击打开链接)
为了让创建的对话框条能够像一般对话框那样响应消息,本文给的思路是采用多级嵌套,将一个可以响应消息的对话框覆盖在对话框条上。
为此我们需要创建如下几个类
1.CDialogBarExt 继承于CDialogBar
2.CDlgContainer 对话框容器类,
3.CInnerDlg 要嵌套的对话框类(相应的对话框资源)
下面分别是这三个类的代码
DialogBar.h
#pragma once #include "DlgContainer.h" // CDialogBarExt class CDialogBarExt : public CDialogBar { DECLARE_DYNAMIC(CDialogBarExt) public: CDlgContainer m_Container; CDialogBarExt(); virtual ~CDialogBarExt(); protected: DECLARE_MESSAGE_MAP() public: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); };DialogBar.cpp
// DialogBarExt.cpp : 实现文件 // #include "stdafx.h" #include "MagicHouse.h" #include "DialogBarExt.h" // CDialogBarExt IMPLEMENT_DYNAMIC(CDialogBarExt, CDialogBar) CDialogBarExt::CDialogBarExt() { } CDialogBarExt::~CDialogBarExt() { } BEGIN_MESSAGE_MAP(CDialogBarExt, CDialogBar) ON_WM_CREATE() END_MESSAGE_MAP() // CDialogBarExt 消息处理程序 int CDialogBarExt::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialogBar::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 m_Container.Create (NULL,(LPCTSTR)"",WS_CHILD|WS_VISIBLE|WS_BORDER,CRect (0,10,203,500),this,0,NULL); return 0; }DlgContainer.h
#pragma once #include "InnerDlg.h" // CDlgContainer class CDlgContainer : public CWnd { DECLARE_DYNAMIC(CDlgContainer) public: CDlgContainer(); CInnerDlg m_InnerDlg; virtual ~CDlgContainer(); protected: DECLARE_MESSAGE_MAP() public: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnPaint(); };DlgContainer.cpp
// DlgContainer.cpp : 实现文件 // #include "stdafx.h" #include "MagicHouse.h" #include "DlgContainer.h" // CDlgContainer IMPLEMENT_DYNAMIC(CDlgContainer, CWnd) CDlgContainer::CDlgContainer() { } CDlgContainer::~CDlgContainer() { } BEGIN_MESSAGE_MAP(CDlgContainer, CWnd) ON_WM_CREATE() ON_WM_PAINT() END_MESSAGE_MAP() // CDlgContainer 消息处理程序 int CDlgContainer::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 m_InnerDlg.Create(IDD_INNERDLG,this); m_InnerDlg.ShowWindow(SW_NORMAL); return 0; } void CDlgContainer::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 CRect rect; CBrush brush; brush.CreateSolidBrush (RGB (128,128,128)); GetClientRect (rect); dc.FillRect (rect,&brush); // 不为绘图消息调用 CWnd::OnPaint() }InnerDlg.h
#pragma once // CInnerDlg 对话框 class CInnerDlg : public CDialog { DECLARE_DYNAMIC(CInnerDlg) public: CInnerDlg(CWnd* pParent = NULL); // 标准构造函数 virtual ~CInnerDlg(); // 对话框数据 enum { IDD = IDD_INNERDLG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() public: virtual BOOL OnInitDialog(); afx_msg void OnPaint(); };InnerDlg.cpp
// InnerDlg.cpp : 实现文件 // #include "stdafx.h" #include "MagicHouse.h" #include "InnerDlg.h" #include "afxdialogex.h" // CInnerDlg 对话框 IMPLEMENT_DYNAMIC(CInnerDlg, CDialog) CInnerDlg::CInnerDlg(CWnd* pParent /*=NULL*/) : CDialog(CInnerDlg::IDD, pParent) , posY(0) { } CInnerDlg::~CInnerDlg() { } void CInnerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CInnerDlg, CDialog) ON_WM_PAINT() END_MESSAGE_MAP() // CInnerDlg 消息处理程序 BOOL CInnerDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: 在此添加额外的初始化 CWnd *pParent=GetParent(); CRect rc_parent; pParent->GetClientRect(&rc_parent); // SET INITIAL POSITION OF THE DIALOG SetWindowPos(NULL, 0, 0, rc_parent.right, rc_parent.bottom, SWP_SHOWWINDOW); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CInnerDlg::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CDialog::OnPaint() }
CDialogBarExt m_dialogbar;