用独立线程解决弹出模态对话框后执行自定义函数问题模态对话框在执行DoModal()时,当前线程处于阻塞状态。
因此,只有当退出该对话框时,当前线程才能继续执行。 你的要求很另类,既要模态对话框,又要执行另一个函数,可以用新建线程的方法来解决 单独创建一个线程,在该线程中创建模态对话框,当对话框创建完成时置位主线程的某事件句柄,使得阻塞的线程可以继续执行某函数。 例程: 设CDlgModal为模态对话框类,设CViewMain为创建CDlgModal的主线程对象(此时要求CViewMain类的必须是CWnd类的子孙类) 在CViewMain的头文件ViewMain.h 中加入自定义消息的定义 1. 在CViewMain类的声明中加入一个线程指针,并在CViewMain类构造函数中为其赋值NULL CWinThread* pThrdModalDlg; // 模态对话框线程指针(此线程为工作者线程就足够了,生成方法见下文) 2. 在ViewMain.h 中加入全局回调函数声明及友元声明 2.1 在ViewMain.h末尾(CViewMain类的声明的体外)加入回调函数声明 UINT AFX_CDECL CallbackModalDlg(LPVOID pParam); // 接收并解析报文线程用的回调函数 2.2 在CViewMain类的声明的体内加入事件句柄变量,加入对回调函数、CDlgModal类的友元声明(视情况可忽略) friend UINT AFX_CDECL CallbackModalDlg(LPVOID pParam); // 声明回调函数为友元函数,在该线程内部任意访问CViewMain对象的各个成员变量或函数;假如你不需要访问的话,可以忽略此句。 friend class CDlgModal; // 声明CDlgModal为友元类,这样模块对话框对象可任意访问CViewMain对象的各个成员变量或函数;假如你不需要访问的话,可以忽略此句。 public: HANDLE m_hEventModelDlgCreated; // 事件句柄,标识模态对话框是否创建。此变量最好设为公有类型,否则如果没有上句的友元声明的话,CDlgModal对象将无法置位此事件句柄 3. 在ViewMain.cpp中实现回调函数体 /************************************************************************/ /* 创建模态对话框用专用的线程pThrdModalDlg用的回调函数 */ /************************************************************************/ UINT AFX_CDECL CallbackModalDlg(LPVOID pParam) { CViewMain* pViewMain=NULL; pViewMain=(CViewMain*)pParam; // 通过线程构造时的LPVOID pParam变量来传递指向CViewMain的指针。如果前面声明了此回调函数为CViewMain类的友元的话,以后可以通过这个指针来任意调用CViewMain对象的成员变量和函数 CDlgModal dlg(pViewMain); // 创建模态对话框,将CViewMain对象指针作为参数传递给CDlgModal dlg.DoModal(); // 执行CDlgModal对话框 // 对话框退出时,本线程退出 pViewMain->pThrdModalDlg=NULL; // 将CViewMain对象的pThrdModalDlg置空,这样下次可以再次产生本线程来创建模态对话框 pViewMain=NULL; ::AfxEndThread(0); return 0; } 4. 在ViewMain.cpp中实现线程创建与句柄关闭 4.1 CViewMain类的合适位置(某函数内,某按钮处理函数,自己任意指定)加入创建模态对话框线程的代码 if (pThrdModalDlg==NULL) // 判断线程是否已经创建,没创建时新建一个,如果已创建线程(模态对话框未关闭),就忽略 { pThrdModalDlg=::AfxBeginThread(::CallbackModalDlg,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL); // 创建线程,并处于休眠状态 ASSERT(pThrdModalDlg); m_hEventModelDlgCreated=CreateEvent(NULL,TRUE,FALSE,_T("ModalDlgCreated")); // 此事件初始状态为FALSE,必须手动复位 ::ResetEvent(m_hEventModelDlgCreated); // 复位此标识 pThrdModalDlg->ResumeThread(); // 唤醒该线程 if (WAIT_OBJECT_0==WaitForSingleObject(m_hEventModelDlgCreated, 2000)) // 阻塞当前线程,等待m_hEventModelDlgCreated标识在CDlgModal::On { DoSomething(); // 模态对话框已创建,执行自定义的函数 } } 4.2 在CViewMain类析构函数中关闭事件句柄 CViewMain::~CViewMain() { CloseHandle(m_hEventModelDlgCreated); } 5. 在CDlgModal类的头文件中加入对ViewMain.h 文件的包含,并添加一个指向CViewMain的指针成员变量 #include "ViewMain.h" 在CDlgModal类声明中加入: CViewMain* m_pViewMain; 6. 修改CDlgModal类的构造函数和On CDlgModal:CDlgModal(CWnd* pParent /*=NULL*/) : CDialog(CDlgModal::IDD, pParent) , m_pViewMain(NULL) { m_pViewMain=(CViewMain*)pParent; // m_pViewMain是指向CViewMain的指针 } BOOL CDlgModal::On { CDialog::On // TODO: 在此添加额外的初始化 // 执行你自定义的另一个函数,此函数执行起来后模态对话框就显示了 ::SetEvent(m_hEventModelDlgCreated); // 指示标识模态对话框已经创建,此时在CViewMain中用WaitForSingleObject阻塞的线程可以继续执行自定义函数 return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } 小结: 此方法的本质就是先创建一个工作者线程,在该线程中创建模态对话框。当模态对话框创建完成后,通过置位主线程的事件句柄来通知主线程继续执行自定义的函数。 此方法的缺点是主线程的退出和模态对话框的退出产生异步,此时需要自己保证程序的可靠性。否则主线程关闭了,模态对话框还活着可能会产生错误。 使用者可以依本文思想,另外加一个事件标识来在主线程退出时通知模态对话框提前关闭,篇幅关系,在此不再赘述。 Google站点地图 - 百度站点地图 - 联系我们 - 关于我们 - TOP 引文来源 用独立线程解决弹出模态对话框后执行自定义函数问题 - VC/MFC - 提供最全面实用的Java面试题,JAVA自测题,Java代码,Java项目,Java学习资料,Java论坛,Java教程,Java下载 - JAVA世纪网 |
|
来自: chensirDSP > 《我的图书馆》