MFC中按鈕對於鍵盤迴車和空格響應,引發的問題

在調試寫的代碼的時候,碰到一個“很奇怪的"現象。因爲進度的原因,當時就是當成一個異常輸入進行了處理。現在空閒下來,重現了問題現象。現象是:在一個彈出窗口中,按鍵”enter“和”space“關閉對話框,對話框已經按照我以前的博客文章(https://blog.csdn.net/yishang44/article/details/99680673)描述的處理過了。在一個很偶然的啓發下才發現問題。彈出框大概是這個樣子的,兩個按鈕會選擇性顯示和隱藏。

當按鈕都隱藏的時候,就會重現現象。爲了便於顯示,兩個按鈕的響應函數對了對應的標記。

          

在兩個按鈕都顯示的時候,按鍵”enter“和”space“輸入實際上響應的是按鈕的單擊消息,因爲我在響應函數中調用了關閉對話框函數,就關閉了對話框。

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

但是,這裏就出現了一個新的疑惑,按鈕是被隱藏了的,難道不應該屏蔽掉點擊響應?!

實際上,當你隱藏按鈕時候,鼠標的點擊或者其他的(非”enter“和”space“)輸入都是不響應的。在查看MSDN中按鈕樣式的說明,而一般情況,常規意義上說的按鈕基本都會具有下面的屬性。

而在默認的配置裏面,VS2010會把對話框的輸入焦點默認設置在按鈕上,相關的屬性如下:

對話框獲取輸入焦點的時候,基本的都是指定在按鈕上的,特別如下面的情況的時候。這個時候,即便你把按鈕隱藏,輸入焦點也是在按鈕上的,因爲靜態框默認是不接受輸入焦點的。

所以,這個時候,”enter“和”space“的按鍵實際響應的是焦點狀態的輸入。現象雖類似,但原因卻不同。解決方法就有很直觀的兩種的方法了。

第一種,將對話框的焦點修改到靜態框上,如下圖修改靜態框屬性。

第二種,就是修改按鈕類對於”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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章