(转)!注意:PreTranslateMessage弹出框出错
生活随笔
收集整理的這篇文章主要介紹了
(转)!注意:PreTranslateMessage弹出框出错
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
dlg.DoModal()截住了界面消息,所以返回時原來的pMsg的內容已經更改了,消息,窗口句柄都不在是if以前的值了,而且窗口句柄應該是對話框里的子窗口的句柄,所以調用CFrameWnd::PreTranslateMessage(pMsg);? 時pMsg的窗口句柄是個無效值(窗口已銷毀)? BOOL CViewUP::PreTranslateMessage(MSG* pMsg)? { if (pMsg->message == WM_KEYDOWN) { if(pMsg->wParam =='M' || pMsg->wParam == 'm')//暫時為按“M”鍵退出系統 { AfxGetApp()->m_pMainWnd->SendMessage(WM_CLOSE,0L,0L); return TRUE; } else if(pMsg->wParam=='Z' || pMsg->wParam == 'z')//暫時為按“Z”鍵啟動就地系統 { //激活上一個窗口還是退出??因須要而定 CWnd* pWnd = FindWindow(NULL,_T("就地站_JD")); if (pWnd) { pWnd->ShowWindow(SW_SHOWNA );//SW_SHOWMAXIMIZED); pWnd->SetForegroundWindow(); return TRUE; } // ???CAONumValueDlg ?aoDlg; ? // ???aoDlg. DoModal(); } } return CView::PreTranslateMessage(pMsg); } 注意事項? 模態窗口極大地簡化了一些需要和用戶交互的操作,好處顯而易見。但這里還是要指出一些需要注意的地方,否則使用的時候很可能會出問題。 影響PreTranslateMessage機制? 在使用MFC,WTL等進行開發的時候,經常用到PreTranslateMessage機制,這個機制可以讓我們在消息被派發之前先做一些事情。很多人以為PreTranslateMessage是Windows本身支持的,其實不然。PreTranslateMessage是MFC和WTL自己引入的一個概念,完全是和Windows無關的。在MFC和WTL的消息循環中,這兩個庫的設計者在消息分發之前,人為的加了一些代碼,使得整個架構支持這一套機制。 正是如此,如果在正常的流程中彈出了模態窗口,就會使正常的PreTranslateMessage機制失效。因為模態窗口中已經包含了一個消息循環,接管了線程中缺省的消息循環。而這個消息循環是在DialogBox這個API函數中執行的,顯然不可能再有PreTranalateMessage機制了。 為了解決這一問題,只有讓模態窗口也使用和UI線程相同的消息循環,MFC正是這么做的。在MFC中,對話框類的DoModal函數,并不是調用DialogBox函數,而是直接使用CreateWindows創建一個非模態窗口,在窗口創建成功之后再調用MFC自己的消息循環,這樣就可以讓PreTranslateMessage繼續生效。同時在窗口創建出來之后,必須再做一些別的操作,使這個模態窗口的父窗口失效(一般直接把窗口Disable掉)。同時消息循環里有合適的退出條件,并有恢復現場的一些操作,具體可以查看MFC的DoModal函數。 WTL到目前為止,貌似暫時還沒有一個合適的方案來解決這個問題。事實上WTL的PreTranslateMessage機制實現的其實是有點問題的,或許以后會在這方面做一定的增強。 可能導致崩潰? 這是一個嚴重問題,在條件合適的情況下,這個崩潰是必然的。 因為模態窗口彈出來之后,模態窗口后面的代碼在窗口關閉之前將不會得到執行。然而此時整個窗口是在正常運行的,對于一些極端的情況,是極有可能造成崩潰的。下面看一個例子: void CTestDlg::OnOK() { CInputDialog dlg; If(dlg.DoModal() == IDOK) { m_nValue = dlg.GetValue(); UpdateData(FALSE); } } 這是一段典型的MFC代碼,在絕大多數情況下,不會有任何問題。但是由于模態窗口彈出的時候,只是父窗口不能操作,但別的窗口完全還能正常運行,這時候就非常有可能由于某種原因,CTestDlg類已經銷毀了,而CInputDialog卻不知道,還在繼續執行,結果到了IDOK之后,對CTestDialog類的成員變量m_nValue賦值,就會出現崩潰了。 這個問題,如果在多線程的情況下,將會更加嚴重。因為在多線程的情況下,將會有更加多的不可預料的因素,所以使用的時候要更加小心。 改成這樣就OK了,? if ??(pMsg-> message ??== ??WM_CHAR)? {? MSG ??msg ??= ??*pMsg;//后來發現這樣還是有點問題,模態對話框回車后,鼠標不見了? CMyDlg ??dlg;? dlg.DoModal();? *pMsg ??= ??msg; //后來發現這樣還是有點問題,模態對話框回車后,鼠標不見了 return ??TRUE;//最終方法還是在這里直接返回吧,破壞消息循環總是不好的。 }? 我估計是MFC保存了一個當前消息的結構來跟蹤消息路由,dlg.DoModal();時這個結構的值都更新好多遍了 /注意///下面是自己實踐的代碼 BOOL CDoctorAdd::PreTranslateMessage(MSG* pMsg)? { if(pMsg->hwnd==((CButton*)GetDlgItem(IDOK))->m_hWnd && pMsg->message==WM_MOUSEMOVE) UpdateData(); if(m_number.IsEmpty()) { CMyDlg ??dlg;? dlg.DoModal();? //return CDialog::PreTranslateMessage(pMsg); return true; } } //呵呵這樣就不報錯啦 轉自:http://blog.sina.com.cn/s/blog_9e2e84050101fnjk.html
轉載于:https://www.cnblogs.com/lydit/p/6815683.html
總結
以上是生活随笔為你收集整理的(转)!注意:PreTranslateMessage弹出框出错的全部內容,希望文章能夠幫你解決所遇到的問題。