在調試寫的代碼的時候,碰到一個“很奇怪的"現象。因爲進度的原因,當時就是當成一個異常輸入進行了處理。現在空閒下來,重現了問題現象。現象是:在一個彈出窗口中,按鍵”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);
}