参考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. Linux服务器部署SpringBoot项目教程

    1. 服务器配置1.1 购买服务器1.2 配置安全组1.3 登录实例1.4 安装宝塔面板2. 配置宝塔2.1 创建数据库3. 打包部署项目3.1 修改项目配置3.2 打包3.3 部署3.4 放行端口3 ...

  2. 数字先锋 | 天翼云xDeepSeek,赋能东莞开启智慧政务新篇章!

    人工智能浪潮奔涌 DeepSeek堪称"全能战士" 在各行各业疯狂"上分" 特别是在政务领域 其以强大的智能问答 公文写作.数据分析等能力 为政务服务按下了&q ...

  3. zabbix - [03] 安装部署

    参考:https://www.yuque.com/fenghuo-tbnd9/ffmkvs zabbix6要求操作系统为Centos8,所以一开始安装部署的时候发现少了zabbix-server-my ...

  4. 【忍者算法】从快慢指针到倒数查找:优雅解决链表倒数问题|LeetCode第19题"删除链表的倒数第N个结点"

    从快慢指针到倒数查找:优雅解决链表倒数问题 从生活场景说起 想象你在一个漫长的队伍中,想知道自己距离队尾还有多少人.一个巧妙的方法是:让你的朋友从你所在位置往后数N步,然后你和朋友一起向后走.当朋友走 ...

  5. 读论文-基于序列模式的电子商务推荐系统综述(A Survey of Sequential Pattern Based E-Commerce Recommendation Systems)

    前言 今天读的论文为一篇于2023年10月3日发表在<算法>(Algorithms)的论文,这篇文章综述了基于序列模式的电子商务推荐系统,强调了通过整合用户购买和点击行为的序列模式来提高推 ...

  6. BUGKU_PWN_OVERFLOW2_WP

    WP_OVERFLOW2 拿到程序,首先放到我们的kali里面看看是多少位的程序,然后在看看有没有什么安全属性 64位程序,并且开启了RELRO,NX 也就是说,这道题我们需要使用ROP绕过 使用id ...

  7. 【面试题】实现 queryParse 函数,完成解析 URL 参数的功能

    问题:实现 queryParse 函数,完成解析 URL 参数的功能 /** * 问题:实现 queryParse 函数,完成解析 URL 参数的功能 * * 用法: * ```js * const ...

  8. windows 稀疏文件 (sparse file) 的一个实用场景——解决 SetEndOfFile 占据磁盘空间引入的性能问题

    前言 之前写过一篇文章说明文件空洞:<[apue] 文件中的空洞>,其中提到了 windows 稀疏文件是制造空洞的一种方式,但似乎没什么用处,如果仅仅处理占用磁盘空间的场景,使用SetE ...

  9. oracle的各版本的名称

    我最早接触的是oracle的版本8那个时候是8i i是internet后来是9i然后到10,就是版本10g g是grid的意思然后是11g然后12就变成了C,就是12c c是cloud的意思然后后面的 ...

  10. SSH远程神器—Termius

    简介 Termius是一款非常好用而且漂亮的SSH客户端,能快速远程控制服务器,可以定制自己喜欢的主题.Termius不仅涵盖了PC端的Windows.Linux.Mac,还支持手机端的Android ...