在CTreeCtrl控件中编辑完节点名称后按下回车键控件、节点都没有反应,只有鼠标光标点击非该节点编辑框编辑才会生效,所以希望按下回车键也能使编辑生效(即按下回车键后CTreeCtrl控件可以响应 OnTvnEndlabeledit 函数事件。
在网上查了资料发现重载 PreTranslateMessage 函数可以实现,需要添加回车键消息响应:
case VK_RETURN:
::TranslateMessage(pMsg);
::DispatchMessage(pMsg); //执行完这一行后会响应 ***OnTvnEndlabeledit*** 函数事件
break;
这样确实会响应 OnTvnEndlabeledit 函数事件,但是程序在执行完 OnTvnEndlabeledit 函数事件之后继续往下执行到重载函数PreTranslateMessage 返回指令后会触发中断:
return CDialogEx::PreTranslateMessage(pMsg);
中段代码最终会指示到如下所示的地方:
//wincore.cpp
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{
ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
ASSERT(pMsg != NULL);
// walk from the target window up to the hWndStop window checking
// if any window wants to translate this message
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{
// target window is a C++ window
if (pWnd->PreTranslateMessage(pMsg))
return TRUE; // trapped by target window (eg: accelerators)
}
// got to hWndStop window without interest
if (hWnd == hWndStop)
break; 这里最终会中断退出循环
}
return FALSE; // no special processing
}
//thrdcore.cpp
BOOL AfxInternalPreTranslateMessage(MSG* pMsg)
{
// ASSERT_VALID(this);
CWinThread *pThread = AfxGetThread();
if( pThread )
{
// if this is a thread-message, short-circuit this function
if (pMsg->hwnd == NULL && pThread->DispatchThreadMessageEx(pMsg))
return TRUE;
}
// walk from target to main window
CWnd* pMainWnd = AfxGetMainWnd();
if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
return TRUE;
// in case of modeless dialogs, last chance route through main
// window's accelerator table
if (pMainWnd != NULL)
{
CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
if (pWnd->GetTopLevelParent() != pMainWnd) //继续进入GetTopLevelParent
return pMainWnd->PreTranslateMessage(pMsg);
}
return FALSE; // no special processing
}
//wincore.cpp
CWnd* CWnd::GetTopLevelParent() const
{
if (GetSafeHwnd() == NULL) // no Window attached
return NULL;
ASSERT_VALID(this); //继续进入ASSERT_VALID
//objcore
void AFXAPI AfxAssertValidObject(const CObject* pOb,
LPCSTR lpszFileName, int nLine)
{
if (pOb == NULL)
{
TRACE(traceAppMsg, 0, "ASSERT_VALID fails with NULL pointer.\n");
if (AfxAssertFailedLine(lpszFileName, nLine))
AfxDebugBreak();
return; // quick escape
}
if (!AfxIsValidAddress(pOb, sizeof(CObject)))
{
TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");
if (AfxAssertFailedLine(lpszFileName, nLine))
AfxDebugBreak();
return; // quick escape
}
// check to make sure the VTable pointer is valid
ASSERT(sizeof(CObject) == sizeof(void*));
if (!AfxIsValidAddress(*(void**)pOb, sizeof(void*), FALSE))
{
TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal vtable pointer.\n");
if (AfxAssertFailedLine(lpszFileName, nLine))
AfxDebugBreak();
return; // quick escape
}
if (!AfxIsValidAddress(pOb, pOb->GetRuntimeClass()->m_nObjectSize, FALSE))
{
TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");
if (AfxAssertFailedLine(lpszFileName, nLine))
AfxDebugBreak();
return; // quick escape
}
pOb->AssertValid(); //这里进入AssertValid
}
//wincore.cpp
void CWnd::AssertValid() const
{
if (m_hWnd == NULL)
return; // null (unattached) windows are valid
// check for special wnd??? values
ASSERT(HWND_TOP == NULL); // same as desktop
if (m_hWnd == HWND_BOTTOM)
ASSERT(this == &CWnd::wndBottom);
else if (m_hWnd == HWND_TOPMOST)
ASSERT(this == &CWnd::wndTopMost);
else if (m_hWnd == HWND_NOTOPMOST)
ASSERT(this == &CWnd::wndNoTopMost);
else
{
// should be a normal window
ASSERT(::IsWindow(m_hWnd)); //最终会中断在这里
网上了解了资料发现PreTranslateMessage可以立即返回,所以修改如下代码:
case VK_RETURN:
::TranslateMessage(pMsg);
::DispatchMessage(pMsg); //执行完这一行后会响应 ***OnTvnEndlabeledit*** 函数事件
return(TRUE); //立即终止消息
break;
如上的解决办法虽然可行,但导致该问题的原因仍旧不知,待探寻;
其中响应OnTvnEndlabeledit 函数事件除了使用下面的代码还有另一种办法:
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
之前说到编辑完节点后鼠标光标点击非该节点编辑框节点编辑也会生效,所以可以将这两行代码改为修改鼠标焦点的指令
m_treeCtrl.SetFocus(); //其中m_treeCtrl也可以是其他控件
参考链接:
MFC中的PreTranslateMessage
解决GetDlgItem 使用时出现ASSERT(::IsWindow(m_hWnd))断言
MFC下拉框中断出错,中断在ASSERT(::IsWindow(m_hWnd));的情况记录