用回车键实现MFC对话框中TAB键控件输入焦点在控件中跳转的效果(转)
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://hcq11.blogbus.com/logs/54217707.html
必须重载WM_GETDEFID,因为当用户按下回车键时,Windows发送WM_GETDEFID消息来获得缺省的命令ID,Windows再将它作为WM_COMMAND发送,所以重载这个消息必须在高位字中返回DC_HASDEFID。 如下所例:
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_MESSAGE(DM_GETDEFID, OnGetDefID)
...
END_MESSAGE_MAP()
LRESULT CMyDlg::OnGetDefID(WPARAM wp, LPARAM lp)
{
return MAKELONG(0,DC_HASDEFID);
}
这是一种方法,另外一种方法是在消息循环处着手处理。重载PreTranslateMessage这个虚函数,将消息队列中有关键盘按下的消息给拦载下来,在框架之前处理WM_KEYDOWN消息。判断是按下回车键后,我们可以用GetNextDlgTabItem 函数获得TAB键序中下一个或上一个接受TAB键的控件句柄。示例代码如下:
BOOL CKeydownDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
CWnd *mwnd = GetNextDlgTabItem (GetFocus()); //取得当前焦点控件的下一个控件的句柄
if (mwnd)
{
mwnd->SetFocus(); //设置下一件控件得到输入焦点
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
但是,各位有没有注意到。这样处理之后,虽然可以在各个控件之进行输入焦点的转移。可是当一个按钮控件获得了焦点之后,也是按下回车键。以前我们习惯中或者说预料中按下该按钮的后应该执行的功能没有被执行,而焦点又跑到按钮之后的控件上去了。这就是上面代码的不足之处,虽然实现了焦点由回车键控件转移,但是按钮却不能用回车键来操作了。只以用鼠标,这和大家习惯不合。而且,在快速的数据输入中不能用回车键来按下这个按钮却要用鼠标来点击也有违当初我们要快速这样一个目的。所以,还得对以上代码做适当的修改。代码如下。
在这里增加了对当前焦点控件类的判断,即如果当前控件是按钮(Button)那么就不执行焦点跳转而是构造一条WM_COMMAND消息发送给程序,让程序以为是鼠标点击了该按钮。从而执行了这个按钮具有的功能而不是什么也不做的焦点转移。
BOOL CKeydownDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
CWnd *wnd = GetFocus ();
if (wnd != NULL)
{
char str[256];
CString ClassName = _T("Button");
GetClassName (wnd->m_hWnd, str, 256);
if (ClassName == str)
{
UINT i = wnd->GetDlgCtrlID ();
SendMessage (WM_COMMAND, i, (LPARAM)wnd->m_hWnd);
return TRUE;
}
}
CWnd *mwnd = GetNextDlgTabItem (wnd);
if (mwnd)
{
mwnd->SetFocus();
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
TAB ORDER按回车键使下个控件自动获得焦点
1.选中主对话框:Layout菜单=>Tab Order(或者直接按Ctrl+D):按你需要的TAB顺序依次单击控件.
2.按Ctrl+W打开MFC ClassWizard=>Message Maps选项卡:给你的主DLG映射PreTranslateMessage消息处理函数:
BOOL CYourDlg::PreTranslateMessage(MSG* pMsg)
{
// 顺次传递焦点,除非当前焦点在确定按钮上时才响应触发消息
if((pMsg->message == WM_KEYDOWN) && (VK_RETURN == (int) pMsg->wParam))
{
if(GetFocus()->GetDlgCtrlID() != IDOK)
{
pMsg->wParam = VK_TAB;
}
}
return CDialog::PreTranslateMessage(pMsg);
}