为什么CEdit::WndProc无法拦截WM_KEYDOWN使,CEdit不显示字符

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上面。


哦,谜团解开了。。





你可能感兴趣的:(thread,api,测试,null,Class,pascal)