MFC中如何创建一个非模态对话框

对话框是编程中常用的一个控件,非模态对话框与用户交互更加友好,用户不必关闭对话框就能进行其他操作,比如拷贝黏贴,对比数据,执行其他命令。

由于无模态对话经常使用,且用法类似,因此我把它写成了一个类,每次只要继承即可使用非模态对话框,不再重复做哪些繁琐的操作。

下面以具体实例讲解,如何使用这个类。
首先使用VS2022创建一个MFC的工程。
在这里插入图片描述
因为只是演示对话框的使用,因此我们直接用向导的默认值直接生成工程
在这里插入图片描述
运行效果是这样:
在这里插入图片描述
将非模态对话框类的两个文件拷贝到工程中,并加入到解决方案。在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
继承自CModelessDlg
修改包含的头文件
在这里插入图片描述
添加一个对话框资源,名称改为:IDD_CModelessDlg
这个对话框就是以后你需要给用户展示用的。在这里插入图片描述
找一个可以调用此对话的地方演示效果,就在菜单中吧,加一个菜单项

在这里插入图片描述
添加事件处理程序:
在这里插入图片描述
增加实际调用代码:

#include "CTestM.h"
void CMFCApplication8App::On32771()
{
	BOOL bResult = FALSE;
	CTestM *pDlg = new CTestM;
	ASSERT_VALID(pDlg);
	bResult = pDlg->Create(CTestM::IDD);
	pDlg->ShowWindow(SW_SHOW);
}

最后效果如下:
在这里插入图片描述
不需要考虑指针释放,不需要考虑多次调用,这些都已经在非模态对话框已经都做好了。

源代码件见绑定的资源

<think>嗯,用户想在MFC创建一个非模态对话框,并添加进度条功能供其他模块调用。首先,我需要回忆一下非模态对话框和模态对话框的区别。非模态对话框不会阻塞主窗口,用户可以同时与主窗口和对话框交互,这对于显示进度条来说很合适,因为用户可能需要在任务进行时继续操作其他部分。 接下来,进度条的实现。根据引用[2]和[4],MFC中使用CProgressCtrl控件,并通过SetRange、SetPos等方法控制进度。同时,引用[3]提到了一个第三方组件SegeX Progress,但用户可能更倾向于原生控件,所以暂时不考虑第三方库。 非模态对话框创建需要注意生命周期管理。模态对话框通常用DoModal创建,而非模态的需要用Create,并且要确保对话框对象在关闭时不被立即销毁,否则可能导致内存访问错误。通常做法是在堆上分配,并在关闭时调用DestroyWindow,然后在PostNcDestroy中删除自身,如引用[2]中的线程处理可能相关。 然后,如何让其他模块调用这个对话框。可能需要设计接口函数,比如StartProgress、UpdateProgress、CloseProgress,这样外部模块可以调用这些方法来控制进度条。同时,考虑到线程安全,如果进度更新是在工作线程中进行的,需要使用PostMessage来跨线程更新UI,避免直接操作控件导致的崩溃。 另外,引用[4]提到了使用WM_TIMER消息,但如果是多线程的话,可能不需要定时器,而是由工作线程发送消息来更新进度。不过需要确保消息传递的正确性,比如使用自定义消息和PostMessage。 还需要考虑对话框资源的创建,在资源编辑器中添加进度条控件,并为其关联变量,比如CProgressCtrl类型的成员变量,或者如引用[2]中的CProgressCtrl m_hThread1这样的变量。 可能的步骤:设计非模态对话框类,重写PostNcDestroy以便正确释放内存;在对话框类中添加进度条控件变量和更新方法;提供公共接口供外部调用;处理线程间的消息传递,确保安全更新UI。 用户可能遇到的问题包括对话框不显示,可能是因为没有调用ShowWindow;或者进度条不更新,可能因为未在主线程中更新控件,或者未正确使用消息机制。需要提醒用户注意线程安全和资源管理。</think>在MFC中实现非模态对话框进度条需要分步骤完成,以下是具体实现方法: ### 一、非模态对话框进度条实现步骤 1. **创建对话框资源** - 添加Progress Control控件,设置ID(如`IDC_PROGRESS`) - 添加CStatic控件用于显示进度文本(可选) 2. **创建对话框类**(如`CProgressDlg`) ```cpp // ProgressDlg.h class CProgressDlg : public CDialogEx { DECLARE_DYNAMIC(CProgressDlg) public: CProgressDlg(CWnd* pParent = nullptr); virtual ~CProgressDlg(); void SetProgress(int nPercent); void SetMessage(LPCTSTR lpszMsg); protected: virtual void DoDataExchange(CDataExchange* pDX); virtual void PostNcDestroy(); CProgressCtrl m_Progress; CStatic m_StatusText; public: afx_msg void OnTimer(UINT_PTR nIDEvent); DECLARE_MESSAGE_MAP() }; ``` 3. **初始化与销毁处理** ```cpp // ProgressDlg.cpp void CProgressDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_PROGRESS, m_Progress); DDX_Control(pDX, IDC_STATUS_TEXT, m_StatusText); } void CProgressDlg::PostNcDestroy() { delete this; // 确保对象销毁 } ``` ### 二、进度控制接口实现 ```cpp void CProgressDlg::SetProgress(int nPercent) { m_Progress.SetPos(nPercent); CString str; str.Format(_T("%d%%"), nPercent); m_StatusText.SetWindowText(str); } void CProgressDlg::SetMessage(LPCTSTR lpszMsg) { m_StatusText.SetWindowText(lpszMsg); } ``` ### 三、调用方法 1. **创建对话框实例** ```cpp // 在调用类中声明成员变量 CProgressDlg* m_pProgressDlg = nullptr; // 创建非模态对话框 void CYourClass::ShowProgress() { if (!m_pProgressDlg) { m_pProgressDlg = new CProgressDlg(); m_pProgressDlg->Create(IDD_PROGRESS_DLG, GetDesktopWindow()); m_pProgressDlg->ShowWindow(SW_SHOW); m_pProgressDlg->m_Progress.SetRange(0, 100); } } ``` 2. **更新进度** ```cpp // 线程安全更新方法 void CYourClass::UpdateProgress(int nPercent) { if (m_pProgressDlg && ::IsWindow(m_pProgressDlg->m_hWnd)) { m_pProgressDlg->PostMessage(WM_USER+100, nPercent); // 自定义消息 } } // 在CProgressDlg中添加消息处理 BEGIN_MESSAGE_MAP(CProgressDlg, CDialogEx) ON_MESSAGE(WM_USER+100, OnUpdateProgress) END_MESSAGE_MAP() LRESULT CProgressDlg::OnUpdateProgress(WPARAM wParam, LPARAM lParam) { SetProgress(static_cast<int>(wParam)); return 0; } ``` 3. **关闭对话框** ```cpp void CYourClass::CloseProgress() { if (m_pProgressDlg) { m_pProgressDlg->DestroyWindow(); m_pProgressDlg = nullptr; } } ``` ### 四、注意事项 1. **线程安全**:工作线程中必须使用`PostMessage`更新界面[^2] 2. **生命周期管理**:必须通过`PostNcDestroy`释放对象内存[^4] 3. **进度范围设置**:初始化时应调用`SetRange(0,100)`设置范围[^4] 4. **资源释放**:关闭父窗口时需要确保销毁进度对话框
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值