自实现模态对话框-DoModal函数
参考CDialog::DoModal函数的实现方式,自己实现了模态框相关功能。
ModalBase.h头文件
1 #include <afxwin.h> 2 3 #define ID_NULL 0 4 #define ID_OK 1 5 #define ID_CANCEL 2 6 #define ID_ABORT 3 7 #define ID_RETRY 4 8 #define ID_IGNORE 5 9 #define ID_YES 6 10 #define ID_NO 7 11 #define ID_CLOSE 8 12 13 14 //模态窗基类 15 class ModalBase : public CWnd 16 { 17 public: 18 ModalBase(); 19 ~ModalBase(); 20 21 virtual int DoModal(HWND hParent = NULL); 22 23 void SetWindowSize(int nWidth, int nHeight); 24 25 protected: 26 virtual void EndDialog(int nExitCode); 27 28 virtual void UpdateLayout(); 29 30 virtual CRect GetTitleRect(); //获取标题栏矩形 31 32 virtual CRect GetWndRect(); //获取整个窗口的矩形【忽略了边框】 33 34 BOOL Create(CWnd* pParent); 35 36 //消息循环 37 protected: 38 DECLARE_MESSAGE_MAP() 39 afx_msg void OnMouseMove(UINT nFlags, CPoint point); 40 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 41 afx_msg void OnLButtonUp(UINT nFlags, CPoint point); 42 43 private: 44 bool m_bMouseMove = false; 45 CPoint m_ptOrigin; 46 int m_nRetCode = ID_NULL; //模态窗退出码 47 int m_nWidth = 0; //窗口的宽度 48 int m_nHeight = 0; //窗口的高度 49 };
ModalBase.cpp源文件
1 #include "stdafx.h" 2 #include <afxpriv.h> 3 #include "ModalBase.h" 4 5 BEGIN_MESSAGE_MAP(ModalBase, CWnd) 6 ON_WM_SIZE() 7 ON_WM_PAINT() 8 ON_WM_LBUTTONDOWN() 9 ON_WM_MOUSEMOVE() 10 ON_WM_LBUTTONUP() 11 END_MESSAGE_MAP() 12 13 ModalBase::ModalBase(){ } 14 15 16 ModalBase::~ModalBase(){ } 17 18 int ModalBase::DoModal(HWND hParent /*= NULL*/) 19 { 20 CWinApp* pApp = AfxGetApp(); 21 if (pApp) pApp->EnableModeless(FALSE); //禁用所有非模态窗 22 23 if (!hParent) 24 hParent = ::GetActiveWindow(); //获取当前焦点窗口 25 26 BOOL bEnableParent = FALSE; 27 BOOL bEnableMainWnd = FALSE; 28 CWnd* pMainWnd = NULL; 29 if (hParent && hParent != ::GetDesktopWindow() && ::IsWindowEnabled(hParent)) //判断窗口是否禁用 30 { 31 ::EnableWindow(hParent, FALSE); //禁用父窗口 32 bEnableParent = TRUE; 33 34 pMainWnd = AfxGetMainWnd(); 35 if (pMainWnd && pMainWnd->IsFrameWnd() && pMainWnd->IsWindowEnabled()) //禁用框架窗口 36 { 37 pMainWnd->EnableWindow(FALSE); 38 bEnableMainWnd = TRUE; 39 } 40 } 41 42 BOOL bRet = Create(CWnd::FromHandle(hParent)); //创建窗口 43 if (!bRet) 44 { 45 if (bEnableParent) ::EnableWindow(hParent, TRUE); 46 47 if (bEnableMainWnd) pMainWnd->EnableWindow(TRUE); 48 49 return 0; 50 } 51 52 HWND hWndLastActive = ::SetActiveWindow(m_hWnd); //激活当前窗口 53 54 //显示当前窗口 55 SetWindowPos(CWnd::FromHandle(HWND_TOPMOST), 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); 56 CenterWindow(CWnd::FromHandle(hParent)); 57 58 DWORD dwFlags = MLF_SHOWONIDLE; 59 if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; 60 61 int nResult = RunModalLoop(dwFlags); //进入消息循环 62 63 ASSERT(m_nRetCode != ID_NULL); //从消息循环退出,应该已经设置了其他值 64 65 if (IsWindow(m_hWnd)) 66 SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); 67 68 if (bEnableMainWnd) pMainWnd->EnableWindow(TRUE); //激活框架窗口 69 if (bEnableParent) ::EnableWindow(hParent, TRUE); //激活父窗口 70 71 ::SetActiveWindow(hWndLastActive); //还原 72 ::DestroyWindow(m_hWnd); //销毁当前窗口 73 74 if (pApp) pApp->EnableModeless(TRUE); //启用所有非模态窗 75 } 76 77 void ModalBase::SetWindowSize(int nWidth, int nHeight) 78 { 79 m_nWidth = nWidth; 80 m_nHeight = nHeight; 81 } 82 83 BOOL ModalBase::Create(CWnd* pParent) 84 { 85 CString strWndClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), NULL, NULL); 86 BOOL bResult = CreateEx(NULL, strWndClass, _T(""), WS_POPUP, CRect(0, 0, m_nWidth, m_nHeight), pParent, NULL); 87 return bResult; 88 } 89 90 void ModalBase::OnMouseMove(UINT nFlags, CPoint point) 91 { 92 if (m_bMouseMove) 93 { 94 CRect rcWindow; 95 GetWindowRect(rcWindow); 96 CPoint pt = point - m_ptOrigin + rcWindow.TopLeft(); 97 SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW); 98 } 99 __super::OnMouseMove(nFlags, point); 100 } 101 102 void ModalBase::OnLButtonDown(UINT nFlags, CPoint point) 103 { 104 SetFocus(); 105 if (nFlags == MK_LBUTTON && GetTitleRect().PtInRect(point)) 106 { 107 SetCapture(); 108 m_bMouseMove = true; 109 m_ptOrigin = point; 110 } 111 __super::OnLButtonDown(nFlags, point); 112 } 113 114 void ModalBase::OnLButtonUp(UINT nFlags, CPoint point) 115 { 116 if (m_bMouseMove) 117 { 118 ReleaseCapture(); 119 m_bMouseMove = false; 120 } 121 } 122 123 void ModalBase::EndDialog(int nExitCode) 124 { 125 ASSERT(nExitCode != ID_NULL); 126 if (m_nRetCode == ID_NULL) 127 { 128 m_nRetCode = nExitCode; 129 if (m_nFlags & (WF_MODALLOOP | WF_CONTINUEMODAL)) 130 EndModalLoop(m_nRetCode); 131 132 ::EndDialog(m_hWnd, m_nRetCode); 133 } 134 } 135 136 void ModalBase::UpdateLayout() 137 { 138 139 } 140 141 CRect ModalBase::GetTitleRect() 142 { 143 CRect rcTitle = GetWndRect(); 144 rcTitle.bottom = rcTitle.top + 28; 145 return rcTitle; 146 } 147 148 CRect ModalBase::GetWndRect() 149 { 150 CRect rcClient; 151 GetClientRect(rcClient); 152 rcClient.DeflateRect(2, 2, 2, 2); 153 return rcClient; 154 }
上面只提供了基类代码,有需要的,可以自己派生相关的类。