从CDialogBar派生自己的类进行控件的初始化

来源:互联网 发布:mac不显示电池 编辑:程序博客网 时间:2024/05/18 03:30
当创建一些简单的形如只包含了一些BUTTON的DialogBar的时候,是不需要从CDialogBar派生,因为CDialogBar本身就是从CControlBar派生而来,它可以接收任何的通告消息。
然而,在一下的诸多较为复杂的情形下,我们就需要利用CDialogBar派生出自己的类了(子控件是指用作子窗口的控件------个人理解)。
·           dialogbar包含了具有drop-down属性的COMBOBOX;
·           dialogbar包含了treeview或者tree控件,listview, list控件;
·           dialogbar包含了ActiveX控件;
诸如上面所说的任何较为复杂的情形下,我们都应该对Dialogbar进行派生,以便在派生的类中对其他的控件进行初始化。因为在ClassWizard并没有支持以CDialogBar为基类的派生。所以我们必须自己手动完成该派生过程。这篇文章就是要阐述如何将CDialog的派生类转换为CDialogBar的派生类。
在开始正题之前,有必要说明一点:CDialogBar类是从CControlBar类派生而来的,而CControlBar类则是从CWnd类派生而来,所以CDialogBar并非CDialog的派生类。
首先打开VS2008,创建一个DialogBar类型的dialog资源(在创建对话框资源的时候,单击Dialog选项前面的"+"号进行选择)。并以CDialog类为基类生成派生类,然后按照下面的步骤对所产生的类进行修改。
1.              在类的声明中,将基类CDialog改为CDialogBar,同时将.cpp文件中,BEGIN_MESSAGE_MAP中的基类也改为CDialogBar.
2.              修改.h文件和.cpp文件中的析构函数,同时修改DoDataExchange()函数,具体修改后的效果如下图:
 //修改前的代码:
 1 CMyDlgBar (CWnd* pParent = NULL);   // standard constructor
 2  
 3 CMyDlgBar:: CMyDlgBar (CWnd* pParent /*=NULL*/)
 4    : CDialog(CMyDlgBar::IDD, pParent)
 5 {
 6    ...
 7
 8  void CMyDlgBar::DoDataExchange(CDataExchange* pDX)
 9 {
10     CDialog::DoDataExchange(pDX);
11     ...
12               
 
 //修改后的代码
 1 CMyDlgBar ();   // standard constructor
 2  
 3 CMyDlgBar:: CMyDlgBar (CWnd* pParent)
 4 {
 5     ...
 6
 7  void CMyDlgBar::DoDataExchange(CDataExchange* pDX)
 8 {
 9     CDialogBar::DoDataExchange(pDX);
10     ...
 
3.从文章开始所谈到的继承关系可以看出,在CDialogBar中并没有用来响应WM_INITDIALOG消息的虚函数。我们需要将.h文件中用来响应WM_INITDIALOG消息的虚函数OnInitDialog变化成为一个消息响应函数。首先将.h文件中的“virtual BOOL OnInitDialog();”从文件中删掉,然后在相同的位置上添加“afx_msg LONG OnInitDialog ( UINT, LONG );”函数。然后在.cpp文件中做相应的改动,并将.cpp文件中消息映射ON_WM_INITDIALOG()改为OM_MESSAGE(WM_INITDIALOG, OnInitDialog),例如:
 //在头文件中
 1 class CMyDlgBar : public CDialogBar
 2 {
 3    ...
 4  // Implementation
 5  protected:
 6
 7    // Generated message map functions
 8    //{{AFX_MSG(CMyDlgBar)
 9     virtual BOOL OnInitDialog();                // <-删除这一行.
10    //}}AFX_MSG
11  
12    afx_msg LONG OnInitDialog ( UINT, LONG );   // <-添加这一行.
13     DECLARE_MESSAGE_MAP()
14 };
 
1   //在源文件中
2  BEGIN_MESSAGE_MAP(CMyDlgBar, CDialogBar)// 把原来的CDialog改为CDialogBar
3  ...
4  ON_MESSAGE(WM_INITDIALOG, OnInitDialog ) // <-- 添加这一行.
5  END_MESSAGE_MAP()
 
//将函数实现从:

BOOL CMyDlgBar::OnInitDialog()
{
      CDialog::OnInitDialog();   // <-- 这行被替代掉:
       ...

//改为:
LONG CMyDlgBar::OnInitDialog ( UINT wParam, LONG lParam)
{
    // <-- 用以下的代码替代上面需要替代的部分. -->
    BOOL bRet = HandleInitDialog(wParam, lParam);

    if (!UpdateData(FALSE))
    {
         TRACE0("Warning: UpdateData failed during dialog init./n");
    }
        ...
     return bRet;
 
到此为止所有需要修改的地方都已经完成,剩下的就是使用了。在CMainFrame中定义变量,并在CMainFrame::OnCreate()函数中添加代码:
 1 if (!m_wndDlgBar.Create(this, IDD_DIALOGBAR, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM
 2         | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC, IDD_DIALOGBAR))
 3 {
 4     TRACE0("Failed to create Dialog bar/n");
 5     return -1;      // fail to create
 6 }
 7
 8 //如果需要实现可停靠的功能,则添加如下代码:
 9 m_wndDlgBar.EnableDocking(CBRS_ALIGN_BOTTOM );
10 EnableDocking(CBRS_ALIGN_ANY); //这句很重要
11 DockControlBar(&m_wndDlgBar, AFX_IDW_DOCKBAR_BOTTOM);
9 10 11这三行可以注释掉
 
接下来在mainframe.h中添加
 
virtual BOOL OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo);
.cpp中添加
BOOL CMainFrame::OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
{
     if(m_DlgToolBar.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))
         return TRUE;
     return CFrameWnd::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);
}
 
这个消息函数处理button发到mainframe的消息,所以必须添加
 
然后在oninitdialog函数中初始化,使位图贴到按钮上
HBITMAP hBmp=::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));
     button = (CButton*)GetDlgItem(IDC_BUTTON1);
     button ->SetBitmap(HBITMAP(hBmp));
button是在头文件中定义 Cbutton* button;
这里因为不能添加control类型的button变量,不知道为什么,所以只能通过获取ID的方法来控制,不知道为啥。这样就能把位图贴到按钮上了。(注意:得把按钮的第一个属性设为bitmap)