一、创建DialogBar的派生类
首先,创建对话框资源:在对话框资源编辑器内生成一个Dialog资源,并将其风格(Style)属性必须设置为Child,不能设置为Overlapped或Popup,否则运行肯定出错;至于边界属性则随用户自己喜欢,一般都是选择None。其余属性也随用户选择,一般没有特殊要求还是选择默认的好。
其次,创建基于CDialog的派生类:打开ClassWizard,为以上创建的资源添加一个以CDialog为基类的派生类(因为ClassWizard没有将CDialogBar列在基类目录清单中,所以用户只能先以CDialog类派生)。
然后重写OnInitDialog();//注意这里一定先重写,如果先将基类改成CDialogBar,则编译器就没有这个重写的函数了
重新初始化函数相当重要,如果不这么做的话,DDX函数形同虚设,当然用户的工具条如果没有用到DDX的话当然可以不加这段代码)
将编译器自动生成的OnInitDialog声明和定义分别改成
afx_msg LONG OnInitDialog(UINT wParam,LONG lParam);//头文件中的声明
LONG CMyDialogBar::OnInitDialog(UINT wParam,LONG lParam)
{
// TODO: Add extra initialization here
BOOL bRet = HandleInitDialog(wParam,lParam);
if (!UpdateData(FALSE))
{
TRACE("InitCMyDialogBar Failed!");
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
在消息映射中添加以下红色的部分
BEGIN_MESSAGE_MAP(CMyDialogBar, CDialogBar)
ON_MESSAGE(WM_INITDIALOG,OnInitDialog)
END_MESSAGE_MAP()
再次,修改派生类以CDialogBar为基类:通常需要手工修改几处代码,在本例中派生类以CMyDialogBar命名。(注:以后讲解中凡是手工改动都是以灰背景显示)
1、 在头文件中修改继承关系
将class CMyDialogBar: public CDialog 改为IMPLEMENT_DYNAMIC(CMyDialogBar, CDialogBar)
2、 在代码文件中修该构造函数继承关系
将CMyDialogBar::CMyDialogBar(CWnd* pParent /*=NULL*/)
: CDialog(CMyDialogBar::IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDialogBar)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
改为
CMyDialogBar::CMyDialogBar(CWnd* pParent /*=NULL*/)
{
//{{AFX_DATA_INIT(CMyDialogBar)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
3、 将DDX绑定函数中的继承关系去掉
即将void CMyDialogBar::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);//删去
//{{AFX_DATA_MAP(CCurrentCheckDlg)
………..
//}}AFX_DATA_MAP
}
改为
void CMyDialogBar::DoDataExchange(CDataExchange* pDX)
{
//{{AFX_DATA_MAP(CCurrentCheckDlg)
………….
//}}AFX_DATA_MAP
}
二、在框架类中实现该派生类的对象化
首先,在框架类的头文件内声明实例对象,本例实例化:CMyDialogBar m_wndDataStatus;当然头文件中不可避免要包含新派生类的头文件。
其次,在框架类的OnCreate函数内创建对象并将对象绑定对话框资源。形式与创建ToolBar原理一样,本例实例如下:
if (!m_wndDataStatus.Create(this,IDD_DATASTATUS,WS_VISIBLE|WS_CHILD
|CBRS_SIZE_DYNAMIC|CBRS_BOTTOM,IDD_DATASTATUS))
{
TRACE0("Failed to create CMyDialogBar bar!");
return -1;
}
再次,最为关键的一点就是重写框架类的OnCmdMsg虚函数。如果不重写该函数,那么不光DDX功能无法实现,连最基本的OnCommand事件都无法实现。而且还得手工添加代码,形式如下:
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
改为:
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
if (m_wndDataStatus.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))
return TRUE;
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
在添加CDialogBar上添加控件
在你创建的Dialog上面放一个按钮,运行程序试一试,怎么按钮是灰色的,即使在Dialog中添加了响应事件,也没有用。这个问题困扰了我好长时间,最后在CSDN上找到答案。按钮消息不是发到Dialog上,而是直接发给CMainFrame上,也就是说cdialogbar上面的按钮消息只有映射到CMainframe上面才好使。这回你在CMainframe上面处理消息看看,满意了吧。
在CSDN上有人是这么做的:
----------------------------------------------------
这个问题我也遇到过,dialogbar上的控件消息可以直接由Mainframe类处理,如果通过派生CDialogBar类来处理消息的话有时确实会出现明明映射了消息处理函数,但控件就是灰色。
我是这么解决的,在MainFrame里为控件再做一次消息映射,但处理函数里什么都不做,这样控件一定是已经enable了,这时候如果在DialogBar派生类里也做了消息映射那么你的处理函数就已经起作用了。
也就是说在dialogbar派生类处理控件消息比在mainframe中处理优先级高,但在mainframe中有处理函数一定会将控件enable。
本文参考了http://blog.csdn.net/franksunny/archive/2006/01/06/572357.aspx