MFC中按钮对于键盘回车和空格响应,引发的问题

在调试写的代码的时候,碰到一个“很奇怪的"现象。因为进度的原因,当时就是当成一个异常输入进行了处理。现在空闲下来,重现了问题现象。现象是:在一个弹出窗口中,按键”enter“和”space“关闭对话框,对话框已经按照我以前的博客文章(https://blog.csdn.net/yishang44/article/details/99680673)描述的处理过了。在一个很偶然的启发下才发现问题。弹出框大概是这个样子的,两个按钮会选择性显示和隐藏。

MFC中按钮对于键盘回车和空格响应,引发的问题_第1张图片

当按钮都隐藏的时候,就会重现现象。为了便于显示,两个按钮的响应函数对了对应的标记。

MFC中按钮对于键盘回车和空格响应,引发的问题_第2张图片          MFC中按钮对于键盘回车和空格响应,引发的问题_第3张图片

在两个按钮都显示的时候,按键”enter“和”space“输入实际上响应的是按钮的单击消息,因为我在响应函数中调用了关闭对话框函数,就关闭了对话框。

void CDlgTestPath::OnBnClickedButton1()
{
	AfxMessageBox("按钮1");
	CDialogEx::OnCancel();
}

MFC中按钮对于键盘回车和空格响应,引发的问题_第4张图片

但是,这里就出现了一个新的疑惑,按钮是被隐藏了的,难道不应该屏蔽掉点击响应?!

实际上,当你隐藏按钮时候,鼠标的点击或者其他的(非”enter“和”space“)输入都是不响应的。在查看MSDN中按钮样式的说明,而一般情况,常规意义上说的按钮基本都会具有下面的属性。

而在默认的配置里面,VS2010会把对话框的输入焦点默认设置在按钮上,相关的属性如下:

MFC中按钮对于键盘回车和空格响应,引发的问题_第5张图片

对话框获取输入焦点的时候,基本的都是指定在按钮上的,特别如下面的情况的时候。这个时候,即便你把按钮隐藏,输入焦点也是在按钮上的,因为静态框默认是不接受输入焦点的。

MFC中按钮对于键盘回车和空格响应,引发的问题_第6张图片

所以,这个时候,”enter“和”space“的按键实际响应的是焦点状态的输入。现象虽类似,但原因却不同。解决方法就有很直观的两种的方法了。

第一种,将对话框的焦点修改到静态框上,如下图修改静态框属性。

MFC中按钮对于键盘回车和空格响应,引发的问题_第7张图片

第二种,就是修改按钮类对于”enter“和”space“按键响应。这个可以参考对话框的处理方式,或者直接参考CMFCButton类的方式,即创建你自己的按钮基类。创建控件基类可以参考我以前的文章https://blog.csdn.net/yishang44/article/details/99680673。CMFCButton中处理方式如下:

BOOL CMFCButton::PreTranslateMessage(MSG* pMsg)
{
	if (m_pToolTip->GetSafeHwnd() != NULL)
	{
		if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP || pMsg->message == WM_MOUSEMOVE)
		{
			m_pToolTip->RelayEvent(pMsg);
		}
	}

	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN && CMFCPopupMenu::GetActiveMenu() == NULL)
	{
		CWnd* pParent = GetParent();
		if (pParent != NULL)
		{
			pParent->SendMessage( WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM) m_hWnd);
			return TRUE;
		}
	}

	if (pMsg->message == WM_KEYDOWN && m_bAutoCheck && GetParent() != NULL)
	{
		switch (pMsg->wParam)
		{
		case VK_SPACE:
			if (m_bCheckButton)
			{
				m_bChecked = !m_bChecked;

				RedrawWindow();

				CWnd* pWndParent = GetParent();
				ASSERT_VALID(pWndParent);

				::SendMessage(pWndParent->GetSafeHwnd(), WM_COMMAND, MAKELONG(::GetWindowLong(m_hWnd, GWL_ID), BN_CLICKED), (LPARAM) m_hWnd);

				return TRUE ;
			}
			break;

		case VK_UP:
		case VK_LEFT:
			if (CheckNextPrevRadioButton(FALSE))
			{
				return TRUE;
			}
			break;

		case VK_DOWN:
		case VK_RIGHT:
			if (CheckNextPrevRadioButton(TRUE))
			{
				return TRUE;
			}
			break ;
		}
	}

	return CButton::PreTranslateMessage(pMsg);
}

 

你可能感兴趣的:(MFC框架相关)