重载PreTranslateMessage响应CTreeCtrl控件的回车键后运行程序出现中断ASSERT(::IsWindow(m_hWnd));

场景:

在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));的情况记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值