现在的位置: 首页 > 综合 > 正文

使用非模态对话框的小技巧

2013年04月08日 ⁄ 综合 ⁄ 共 2056字 ⁄ 字号 评论关闭

使用非模态对话框的小技巧

作者:刘胤

工作上有用到非模态对话框,但是使用上有如下麻烦,
所有者拥有一个非模态对话框指针,非模态对话框在关闭的时候要设置这个指针为空,这样一来,非模态对话框就必须"知道"所有者并且实现

了这样的非模态对话框,就不能让它在栈上创建(因为是 delete this),也不能一次创建多个非模态对话框(当然,这种情况很少)。如果把非

模态对话框声明为 CNonModalDialg m_dlg;,那用户点击 OK 的时候,你就得 ShowWindow(SW_HIDE),这和对话框的本意还是有点不一致。

class CNonModalDialg;

class COwner
{
private:
     CNonModalDialg *m_pDlg;
};

class CNonModalDialg
{
...
 void OnOK()
 {
  ...
  delete this;
 }
 void OnCancel()
 {
  ...
  delete this;
 }

 void OnDestory()
 {
  m_pOwner->m_pDlg = NULL;
 }
private:
 COwner *m_pOwner;
};

通过 C++ 的模板,实现了一个 NonModal 类可以解决以上问题。代码如下。
#ifndef NonModal_H
#define NonModal_H

template <typename DialogImpl, typename OwnerType>
class NonModal : public DialogImpl
{
public:
 NonModal(OwnerType *pOwner)
  : m_pOwner(pOwner)
 {
 }

 void SetOwner(OwnerType *pOwner) { m_pOwner = pOwner; }

 virtual BOOL DestroyWindow()
 {
  DialogImpl::DestroyWindow();

  return DestroySelf();
 }

protected:
 virtual void OnOK()
 {
  DialogImpl::OnOK();

  DestroySelf();
 }

 virtual void OnCancel()
 {
  DialogImpl::OnCancel();

  DestroySelf();
 }

private:
 virtual ~NonModal() {}

 BOOL DestroySelf()
 {
  BOOL bRet = FALSE;
  if (m_pOwner) {
   m_pOwner->OnDestroyNonModal(this);
  }

  bRet = DialogImpl::DestroyWindow();
  delete this;
  return bRet;
 }

 OwnerType *m_pOwner;
};

#define DECLARE_NonModalDialog(DialogImpl, OwnerImpl, VariableName) /
private:/
 typedef NonModal<DialogImpl, OwnerImpl> DialogImpl##NonModal; /
 friend DialogImpl##NonModal; /
 /
 DialogImpl##NonModal *VariableName; /
 void OnDestroyNonModal(DialogImpl##NonModal *pDlg) /
 { /
  if (pDlg == VariableName) { /
   VariableName = NULL; /
  } /
 }

#endif

使用方法如下:
class COwnerDlg
{
 ...
 DECLARE_NonModalDialog(CAboutDlg, COwnerDlg, m_pNonModalAboutDlg)
};

void COwnerDlg::ShowNonModal()
{
 if (m_pNonModalAboutDlg == NULL) { // 记得初始化 m_pNonModalAboutDlg = NULL;
  m_pNonModalAboutDlg = new CAboutDlgNonModal(this);
  m_pNonModalAboutDlg->Create(CAboutDlg::IDD);
 }

 m_pNonModalAboutDlg->ShowWindow(SW_SHOW);
 m_pNonModalAboutDlg->UpdateWindow();
}

void CCOwnerDlg::OnDestroy()
{
 CDialog::OnDestroy();

 if (m_pNonModalAboutDlg) {
  m_pNonModalAboutDlg->DestroyWindow();
 }
 m_pNonModalAboutDlg = NULL;
}

这样对话框要成为非模态对话框就加在所有者里面加上 DECLARE_NonModalDialog,如果不用非模态对话框,也不用修改对话框的代码了。

抱歉!评论已关闭.