参考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 }

上面只提供了基类代码,有需要的,可以自己派生相关的类。

自实现模态对话框-DoModal函数的更多相关文章

  1. 模态对话框 DoModal的用法 (vs2008)与非模态对话框

    Windows对话框分为两类:模态对话框和非模态对话框. 模态对话框,当它弹出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作退出后,其他窗口才能继续与用户交互. ...

  2. vc创建模态和非模态对话框

    模态对话框的创建 创建模态对话框需要调用CDialog类的成员函数:DoModal,该函数的功能就是创建并显示一个模 态对话框,关闭模态对话框的函数是EndDialog,该函数需要一个参数,这个参数就 ...

  3. Qt按ESC关闭模态对话框不触发closeEvent()问题解析(ESC默认调用的是reject()函数,所以必须覆盖这个函数才会有效果)good

    事情是这样的:今天调试窗体,突然发现按ESC键居然跳过closeEvent()关闭了对话框!我的关闭判断都在closeEvent()里,这直接导致非正常关闭了正在进行的工作.先重建下场景: 调用处: ...

  4. MFC编程入门之十一(对话框:模态对话框及其弹出过程)

    加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有了些解了,有个好的开始对于以后的学习大有裨益.趁热打铁,这一节讲讲什么是对话框和非模态对话框,以及模态对话框怎样弹出. 一.模态对话框和非 ...

  5. MFC学习笔记(一)向模态对话框传递数据

    声明构造函数为2个参数,具有默认参数的参数须放在后面. CDialogDimmer::CDialogDimmer(CString name,CWnd* pParent /*=NULL*/) : CDi ...

  6. VC++模态对话框和非模态对话框

    MFC中有两种类型的对话框:模态对话框和非模态对话框.  模态对话框是指当其显示时,程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中其他任务.非模态对话框是指当其显示时,允许转而执行程序中 ...

  7. mfc模态对话框

    Mfc模态对话框: 创建模态对话框: [模态对话框:具有独占行为,必须由用户完成对当前对话框的响应,才能对本对话框所属的进程进行其他操作] 例如: 我们创建一个加法计算器.点击计算之后,弹出一个对话框 ...

  8. VS2010/MFC对话框:非模态对话框的创建及显示

    非模态对话框的创建及显示 上一节讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切 ...

  9. VS2010/MFC:模态对话框及其弹出过程

    模态对话框及其弹出过程 加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有些了解了,有个好的开始对于以后的学习大有裨益.趁热打铁,这一节讲讲什么是模态对话框和非模态对话框,以及模态对话框怎 ...

  10. MFC模态和非模态对话框编程

    MFC中对话框有两种形式,一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box). 一.模态对话框(model dialog box) 在程 ...

随机推荐

  1. 安川机器人HW1171766-A本体线缆维修详解

    随着工业自动化程度的不断提高,安川机器人在生产线上的应用越来越广泛.然而,在长期运行过程中,安川机器人本体线缆可能会出现磨损.老化.断裂问题,这些问题不仅会影响机器人的正常运行,还可能导致生产线的停滞 ...

  2. OpenCvSharp 打开rtsp视频并录制mp4文件

    public class OpenCvSharpUtils { private VideoCapture Capture; private VideoWriter VideoWriter; priva ...

  3. Java 实现 Excel(XLS/ XLSX)和 HTML 格式之间的转换

    Excel 是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言.虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,以便更好地利用和展示数据.本文 ...

  4. MT Photos——一个比群晖Moments更好用的AI相册管理神器

    MT Photos是一款为NAS用户量身打造的照片管理系统. 通过AI技术,自动将您的照片整理.分类,包括但不限于时间.地点.人物.照片类型. 您可以在任何支持Docker的系统中运行它. 如果您的操 ...

  5. flutter - [02] 基本语法

    题记部分 一.注释 ///这是一个注释 //这也是个注释 /* 这还是个注释 */ void main(List<String> args) { print ('你好 dart'); } ...

  6. P4688 [Ynoi Easy Round 2016] 掉进兔子洞

    莫队可以维护种类数 但是无法维护出现次数 考虑离散化以后我们后面腾出了一些空位 那么我们就可以填进那些坑里面 这样做我们就可以用 bitset 直接做与运算 那么 莫队 + bitset 即可

  7. 【资源分享】Latex mathematical symbol

    https://files.cnblogs.com/files/blogs/705982/symbols.zip?t=1660463874 上面这个是pdf版,把这个压缩包下载之后,后缀改为pdf即可 ...

  8. [tldr]通过指令获取github仓库的单个文件的内容

    针对一个公开的github仓库,有些时候不需要clone整个仓库的内容,只需要对应的几个文件.但是直接通过网页点击下载文件很麻烦,在服务器上也不好这样操作. 因此,如何使用curl或者wget指令快速 ...

  9. Caddy web服务器

    caddy 中文文档:https://caddy2.dengxiaolong.com/docs/ 常用命令 命令 描述 caddy run 启动Caddy服务器 caddy reload 重载Cadd ...

  10. 如何避免VMware平台ESXi主机CPU使用率的“坑”?

    https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650636818&idx=1&sn=c43f3a3146092f ...