当前位置:编程学习 > 网站相关 >>

基于面向对象封装的模态对话框类

头文件

class CBlxDialog
 {
 public:
  CBlxDialog();
  virtual ~CBlxDialog();

  BOOL Create(HINSTANCE hInstance, UINT uDialogID, UINT uIconId = NULL);
  BOOL Destroy();
  HWND m_hWnd;
  HICON m_hIcon;

 protected:
  virtual BOOL CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  virtual void OnCommand(WORD wID, WORD wCmdCode);
  virtual BOOL OnInitDialog();
  virtual void OnClose();
  virtual void OnDestroy();
  virtual void OnOK();
  virtual void OnCancel();

 private:
  friend BOOL CALLBACK _DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 };

 

 

 

CPP文件

CBlxDialog::CBlxDialog()
 {
  m_hWnd = NULL;
  m_hIcon = NULL;
 }

 CBlxDialog::~CBlxDialog()
 {

 }

 BOOL CALLBACK _DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
  CBlxDialog *pDlg;
  if(uMsg == WM_INITDIALOG)
  {
   CBlxDialog *pDlg = (CBlxDialog*)lParam;
   SetWindowLong(hWnd, GWL_USERDATA, lParam);//<-------------

//在WM_INITDIALOG中取得this指针,将该指针设置到GWL_USERDATA

//这样就完成了对象与窗口过程的关联了,只需要每次获取GetWindowLong一下,即可获得this指针。

//实测双核机器,1秒时间内可以执行1000w+次 pDlg = (CBlxDialog *)GetWindowLong(hWnd, GWL_USERDATA); 所以在效率上的影响是微乎其微的。
   pDlg->m_hWnd = hWnd;
   return pDlg->OnInitDialog();
  }
  else
  {
   pDlg = (CBlxDialog *)GetWindowLong(hWnd, GWL_USERDATA);
  }

  return pDlg ? pDlg->DlgProc(hWnd, uMsg, wParam, lParam) : FALSE;
 }

 BOOL CALLBACK CBlxDialog::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
  switch(uMsg)
  {
  case WM_COMMAND:
   OnCommand(LOWORD(wParam), HIWORD(wParam));
   return TRUE;
  case WM_CLOSE:
   OnClose();
   return TRUE;
  case WM_DESTROY:
   OnDestroy();
   break;
  default:
   break;
  }
  return FALSE;
 }

BOOL CBlxDialog::Create(HINSTANCE hInstance, UINT uDialogID, UINT uIconId)
 {

//该例子基于资源创建对话框,毕竟对于对话框程序来说,有资源的可视化编辑拖拖拉拉,要比纯靠代码实现的要方便

//uIconId是传入的图标ID,该参数默认为NULL,也就是无图标。
  if(uDialogID)
  {
   if(uIconId)
    m_hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(uIconId));
   return DialogBoxParamA(hInstance, MAKEINTRESOURCE(uDialogID), NULL, _DlgProc, (LPARAM)this);//<---传入this指针到WM_INITDIALOG中的lParam参数
  }
  return -1;
 }

 BOOL CBlxDialog::Destroy()
 {
  return EndDialog(m_hWnd, 0);
 }

 BOOL CBlxDialog::OnInitDialog()
 {
  if(m_hIcon)
  {
   SendMessage(m_hWnd, WM_SETICON, TRUE, (LPARAM)m_hIcon);
   SendMessage(m_hWnd, WM_SETICON, FALSE, (LPARAM)m_hIcon);
  }
  return TRUE;
 }

 void CBlxDialog::OnClose()
 {
  EndDialog(m_hWnd, 0);
 }

 void CBlxDialog::OnDestroy()
 {

 }

 void CBlxDialog::OnCommand(WORD wID, WORD wCmdCode)
 {
  if(wID == IDOK)
   OnOK();
  else if(wID == IDCANCEL)
   OnCancel();
 }

 void CBlxDialog::OnOK()
 {
  EndDialog(m_hWnd, IDOK);
 }

 void CBlxDialog::OnCancel()
 {
  EndDialog(m_hWnd, IDCANCEL);
 }

 

 这个类只是基本的封装,只是为了说明可以依靠SetWindowLong和GetWindowLong来进行窗口与类的关联。

另外,该类中声明的友元函数,只是为了让原始对话框消息函数能够访问到类中的protected函数。在该函数中,我并没有依靠参数来传递this指针(废话,消息函数也传不了),所以,可见面向对象的public  protected private这几个概念,只是在针对编译器的设定。而除了友元函数,还可以使用静态函数来实现访问,但是静态会被显示到类成员中,所以在这里我选择了友元函数。

 

最后,对于这个方式,不得不说存在瑕疵,因为存在安全隐患,因为SetWindowLong本身是没有什么权限要求的。

 

 

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,