二、模态对话框的消息处理
由上面我们看到,Windows是一个巨大的消息驱动结构,由用户发出消息,系统响应处理。非模态对话框是响应一个消息,系统处理一个消息,处理完毕后返回控制权给Windows。文档/视图框架结构与其类似。模态对话框在对话框创建后,挂起外部的消息,只是响应对话框内部的消息,而外部消息则全部"过滤"掉了,直到系统接收到WM_DESTROY或WM_CLOSE后,系统返回控制权给模态对话框创建前的线程,继续模态对话框创建前的线程将执行下面的代码。
让我们看看下面的对话框DoModal实现代码:
{ … … // Disable 父窗口 (在创建对话框前) HWND hWndParent = PreModal(); AfxUnhookWindowCreate(); BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)) { ::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; } TRY { // 创建模态对话框 AfxHookWindowCreate(this); if (CreateDlgIndirect(lpDialogTemplate,CWnd::FromHandle(hWndParent), hInst)) { if (m_nFlags & WF_CONTINUEMODAL) { // 进入模式循环 DWORD dwFlags = MLF_SHOWONIDLE; if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); } } } CATCH_ALL(e) { DELETE_EXCEPTION(e); m_nModalResult = -1; } END_CATCH_ALL file://Enable 父窗口 if (bEnableParent) ::EnableWindow(hWndParent, TRUE); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); // 删除对话框 DestroyWindow(); PostModal(); … … } |
可以看到,在此实现代码中,并没有开辟新的线程。系统是在RunModalLoop()中进行消息循环。当 m_nFlags 为 WF_CONTINUEMODAL时,系统继续模式状态。RunModalLoop()函数实际上也是一for(;;)循环,控制重新分派Windows消息。直到ContinueModal()返回FALSE,而当调用EndModalLoop()时,ContinueModal()返回FALSE。此时,标志着模态显示的结束。因此,实现模态对话框消息处理的核心部分为RunModalLoop()和EndModalLoop()函数。
三、以模态的形式显示应用到文档/视图框架结构实例
(1)新建一工程文件:ModeFrame,选取MFC AppWizard(exe)。
(2)第二步选取Single document(单文档)。
(3)其余几步均为缺省值。
(4)用ClassWizard添加一新类CSubModeFrame,以CFrameWnd为基类。
(5)添加CsubModeFrame的实现函数DoMode();
int CsubModeFrame::DoModal() { HWND hWndParent = m_hWndPrt; CRect rc(0,0,400,400); CWnd *pParent = CWnd::FromHandle(hWndParent); DWORD dwStyle=WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_THICKFRAME | WS_VISIBLE | WS_SYSMENU | WS_CAPTION; if(!Create(NULL,"模态文档/试图框架 ",dwStyle,rc,pParent,NULL)) return FALSE; BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)) { ::EnableWindow(hWndParent,FALSE); ::EnableWindow(m_hWnd,TRUE); bEnableParent = TRUE; } CenterWindow(); TRY { // enter modal loop DWORD dwFlags = MLF_SHOWONIDLE; if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); } CATCH_ALL(e) { DELETE_EXCEPTION(e); m_nModalResult = -1; } END_CATCH_ALL if (bEnableParent) ::EnableWindow(hWndParent, TRUE); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); // destroy modal window DestroyWindow(); return m_nModalResult; } |
(6)添加CsubModeFrame的实现函数EndMode()
void CSubFrame::EndModal(){ ASSERT(::IsWindow(m_hWnd)); if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL)) { EndModalLoop(1); } } |
(7)添加CModeFrameView的实现函数OnLButtonDblClk()
在此函数的消息处理中:可以象显示对话框一样处理CsubModeFrame类。
CSubModeFrame SubModeFrame; If(SubModeFrame.DoMode()){ MessageBox("Mode Ok");} |
(8)编译运行工程,双击视图,就会弹出模态的子文档/视图框架结构
结论: 通过上面的分析和实例可以看出,深入研究了解Windows的消息处理机制,可利用消息对Windows的事件进行任意的定制和处理,不用拘泥于系统原有的模式。对进行深入Windows编程是很有必要的。 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |