RT.
前提 class CMyEdit : public CEdit {};
测试CEdit接收的WM_KEYDOWN消息。
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)这个函数要注意。
调用CMyEdit::PreTranslateMessage,如果未处理(也就是CMyEdit::PreTranslateMessage返回FALSE),那么会调用CMyEdit的父窗口的PreTranslateMessage,由于我这里设定父窗口为CDialog,那么调用的是CDialog::PreTranslateMessage,在CDialog::PreTranslateMessage的最后有return CDialog::PreTranslateInput(pMsg);,在CDialog::PreTranslateInput(pMsg)的最后又有return IsDialogMessage(lpMsg);,继续进入CDialog::PreTranslateInput里面发现最后调用return ::IsDialogMessage(m_hWnd, lpMsg);这是个API函数,直接给CEdit显示了'a '这个字符。
然后才会调用到CMyEdit::WndProc,代码如下
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // OnWndMsg does most of the work, except for DefWindowProc call LRESULT lResult = 0; if (!OnWndMsg(message, wParam, lParam, &lResult)) lResult = DefWindowProc(message, wParam, lParam); return lResult; }
下面继续调用CWnd::WindowProc这个函数,它首先OnWndMsg(message, wParam, lParam, &lResult);返回FALSE,那么继续调用
lResult = DefWindowProc(message, wParam, lParam);这里,然后进入
LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { if (m_pfnSuper != NULL) return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); .... }因为m_pfnSuper不空,注意这里调用的是CMyEdit的窗口过程。也就是说m_hWnd就是m_myEdit.m_hWnd。
最终发现是
::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
这个 API函数来设定CEdit显示字符'a'的。
但是CEdit::OnChar确实可以使WM_KEYDOWN消息不显示字符’a',为什么呢?
因为OnChar是在OnWndMsg里面调用的,其实不论OnChar掉不调用,OnWndMsg都会返回TRUE的。只是因为
void CMyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == 97) { //MessageBox(L"CMyEdit::OnChar\n"); //return; } CEdit::OnChar(nChar, nRepCnt, nFlags); }
_AFXWIN_INLINE void CWnd::OnChar(UINT, UINT, UINT) { Default(); }
LRESULT CWnd::Default() { // call DefWindowProc with the last message _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); return DefWindowProc(pThreadState->m_lastSentMsg.message, pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam); }
LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { if (m_pfnSuper != NULL) return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); WNDPROC pfnWndProc; if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL) return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam); else return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam); }在这个OnChar的默认处理里面调用了
::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);这个API,使字符'a'显示在CEdit上面。
哦,谜团解开了。。