科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件MFC程序员的WTL指南之对话框与控件

MFC程序员的WTL指南之对话框与控件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

MFC 的对话框和控件的封装真得可以节省你很多时间和功夫

作者:lithe 来源:BLOG 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

·ATL 方式 3 - 子类化(Subclassing)

  第三种方法创建一个CWindowImpl派生类并用它子类化一个控件。这和第二种方法有些相似,只是消息处理放在CWindowImpl类内部而不是对话框类中。

  ControlMania1使用这种方法子类化主对话框的About按钮。下面是CButtonImpl类,他从CWindowImpl类派生,处理WM_SETCURSOR消息:

class CButtonImpl : public CWindowImpl<CButtonImpl, CButton>
{
 BEGIN_MSG_MAP_EX(CButtonImpl)
  MSG_WM_SETCURSOR(OnSetCursor)
 END_MSG_MAP()

 LRESULT OnSetCursor(HWND hwndCtrl, UINT uHitTest, UINT uMouseMsg)
 {
  static HCURSOR hcur = LoadCursor ( NULL, IDC_SIZEALL );

  if ( NULL != hcur )
  {
   SetCursor ( hcur );
   return TRUE;
  }
  else
  {
   SetMsgHandled(false);
   return FALSE;
  }
 }
};

  接着在主对话框声明一个CButtonImpl成员变量:

class CMainDlg : public CDialogImpl<CMainDlg>
{
 // ...
 protected:
  CContainedWindow m_wndOKBtn, m_wndExitBtn;
  CButtonImpl m_wndAboutBtn;
};

  最后,在OnInitDialog()种子类化About按钮。

LRESULT CMainDlg::OnInitDialog(...)
{
 // ...
 // Attach CContainedWindows to OK and Exit buttons
 m_wndOKBtn.SubclassWindow ( GetDlgItem(IDOK) );
 m_wndExitBtn.SubclassWindow ( GetDlgItem(IDCANCEL) );

 // CButtonImpl: subclass the About button
 m_wndAboutBtn.SubclassWindow ( GetDlgItem(ID_APP_ABOUT) );

 return TRUE;
}

  ·WTL 方式 - 对话框数据交换(DDX)

  WTL的DDX(对话框数据交换)很像MFC,可以使用很简单的方法将变量和控件关联起来。首先,和前面的例子一样你需要从CWindowImpl派生一个新类,这次我们使用一个新类CEditImpl,因为这次我们使用得是Edit控件。你还需要将#include atlddx.h 添加到stdafx.h中,这样就可以使用DDX代码。

  要使主对话框支持DDX,需要将CWinDataExchange添加到继承列表中:

class CMainDlg : public CDialogImpl<CMainDlg>,
public CWinDataExchange<CMainDlg>
{
//...
};

  接着在对话框类中添加DDX链,这和MFC的类向导使用的DoDataExchange()函数功能相似。对于不同类型的数据可以使用不同的DDX宏,我们使用DDX_CONTROL用来连接变量和控件,这次我们使用CEditImpl处理WM_CONTEXTMENU消息,使它能够在你右键单控件时做一些事情。

class CEditImpl : public CWindowImpl<CEditImpl, CEdit>
{
 BEGIN_MSG_MAP_EX(CEditImpl)
  MSG_WM_CONTEXTMENU(OnContextMenu)
 END_MSG_MAP()

 void OnContextMenu ( HWND hwndCtrl, CPoint ptClick )
 {
  MessageBox("Edit control handled WM_CONTEXTMENU");
 }
};

class CMainDlg : public CDialogImpl<CMainDlg>,
public CWinDataExchange<CMainDlg>
{
 //...

 BEGIN_DDX_MAP(CMainDlg)
  DDX_CONTROL(IDC_EDIT, m_wndEdit)
 END_DDX_MAP()


 protected:
  CContainedWindow m_wndOKBtn, m_wndExitBtn;
  CButtonImpl m_wndAboutBtn;
  CEditImpl m_wndEdit;
};

  最后,在OnInitDialog()中调用DoDataExchange()函数,这个函数是继承自CWinDataExchange。DoDataExchange()第一次被调用时完成相关控件的子类化工作,所以在这个例子中,DoDataExchange()子类化ID为IDC_EDIT的控件,将其与m_wndEdit建立关联。

LRESULT CMainDlg::OnInitDialog(...)
{
 // ...
 // Attach CContainedWindows to OK and Exit buttons
 m_wndOKBtn.SubclassWindow ( GetDlgItem(IDOK) );
 m_wndExitBtn.SubclassWindow ( GetDlgItem(IDCANCEL) );

 // CButtonImpl: subclass the About button
 m_wndAboutBtn.SubclassWindow ( GetDlgItem(ID_APP_ABOUT) );

 // First DDX call, hooks up variables to controls.
 DoDataExchange(false);


 return TRUE;
}

  DoDataExchange()的参数与MFC的UpdateData()函数的参数意义相同,我会在下一节详细介绍。

  现在运行ControlMania1程序,可以看到子类化的效果。鼠标右键单击编辑框将弹出消息框,当鼠标通过按钮上时鼠标形状会改变。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章