另类的CDialogBar——可停靠对话框的实现方法

来源:互联网 发布:侯景之乱 知乎 编辑:程序博客网 时间:2024/05/17 16:56

         本文大部分思路来自于《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"// CDialogBarExtclass 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"// CDialogBarExtIMPLEMENT_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"// CDlgContainerclass 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"// CDlgContainerIMPLEMENT_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 DIALOGSetWindowPos(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()}

    如此一来,我们在MainFrame中声明如下变量

      

    CDialogBarExt m_dialogbar;

    并在OnCreate中创建该控制条即可!