MFC中热键操作
2016-01-06 14:57
531 查看
MFC添加快捷键、热键和修改的问题 /article/2447656.html
在写MFC程序时,如果想自定义热键比如ALT+S可以采用下面两种方法:
方法一:定义热键的消息响应函数:OnHotKey
定义系统全局热键:(不管光标在视图上还是在对话框上,都能响应事件)
1、首先在.h文件中添加消息响应函数声明
2、关联消息及响应函数
3、在初始化函数里注册热键
RegisterHotKey(m_hWnd,ID_HOTKEY,MOD_ALT,‘s’);
//ID_HOTKEY是自己定义的一个ID宏,‘s'可以写成ASCII码
4、在消息响应函数里添加操作
释放热键。因为此资源绑定到了对话框上了.
但是热键的问题是全系统的,如果你设了热键,其他软件相同的热键就被这个软件占用了。
方法二:
Accelerator(加速键)方法只在本应用程序内有效 http://support.microsoft.com/?kbid=222829
1、插入一个新的Accelerator到资源里,把加速键和对应的响应控件(如一个按钮)关联
2、在对话框头文件中声明: HACCEL m_hAccel;
3、在对话框的构造函数里初始化m_hAccel
//去掉确定按钮(IDOK)的默认按钮
CButton *pokbutton = (CButton *)GetDlgItem(IDOK);
Pokbutton->ModifyStyle(BS_DEFPUSHBUTTON,0);
//添加IDCANCEL的默认按钮风格
CButton *pcancelbutton = (CButton *)GetDlgItem(IDCANCEL);
pcancelbutton->SetButtonStyle(BS_DEFPUSHBUTTON);
我这个对话框界面主要输入的是数字,因此如果使用TAB键作编辑框之间的跳转会在使用数字键盘时不方便。因此,就考虑了用回车键来实现TAB键的功能。因为MFC对话框的特点,基于MFC对话框的对话框按下回车键会调用框架内的的OnOk成员函数导至退出。即使你去掉IDC_OK按键的BS_DEFPUSHBUTTON 属性也是不行的。 必须重载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键的控件句柄。示例代码如下:
如果热键已经占用了Ctrl+Z,则下面的操作无效,需要把热键中注册的资源删除。
[csharp] view plaincopy
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 (); //获得指定控件的ID号
SendMessage (WM_COMMAND, i, (LPARAM)wnd->m_hWnd);
CWnd *mwnd = GetNextDlgTabItem (wnd);
if (mwnd)
{
mwnd->SetFocus();
return TRUE;
}
return TRUE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
AfxGetMainWnd()-> m_hWnd是主窗口的句柄
FindWindow API ,用标题获取或者是 窗口注册类名
FindWindowEx - 或者你知道那个窗口的第几个子窗口(HWND句柄)
MSG结构表示Windows中的一个消息
窗口的焦点自动切换
在对话框中按下回车键时,会选择对话框中默认按钮的消息响应函数来处理这件事
在写MFC程序时,如果想自定义热键比如ALT+S可以采用下面两种方法:
方法一:定义热键的消息响应函数:OnHotKey
定义系统全局热键:(不管光标在视图上还是在对话框上,都能响应事件)
1、首先在.h文件中添加消息响应函数声明
<span style="font-size:12px;"> afx_msg LRESULT OnHotKey(WPARAM wParam,LPARAM lParam);</span>
2、关联消息及响应函数
<span style="font-size:12px;"> BEGIN_MESSAGE_MAP() ON_MESSAGE(WM_HOTKEY,OnHotKey) END_MESSAGE_MAP()</span>
3、在初始化函数里注册热键
RegisterHotKey(m_hWnd,ID_HOTKEY,MOD_ALT,‘s’);
//ID_HOTKEY是自己定义的一个ID宏,‘s'可以写成ASCII码
4、在消息响应函数里添加操作
<span style="font-size:12px;">LRESULT CMyTest::OnHotKey(WPARAM wParam,LPARAM lParam) { UINT Mod = (UINT) LOWORD(lParam); // key-modifier flags UINT uVirtKey = (UINT) HIWORD(lParam); // virtual-key code //判断响应了什么热键 if( MOD_CONTROL == Mod && ‘s’ == uVirtKey ) { AfxMessageBox(_T("你按下了组合键 ALT+ S")); } else AfxMessageBox(_T("你按下了未知热键")); return 0; }</span>一定要释放,最后在
<span style="font-size:12px;">OnDestroy() { UnregisterHotKey(m_hWnd,1001) } </span>
释放热键。因为此资源绑定到了对话框上了.
但是热键的问题是全系统的,如果你设了热键,其他软件相同的热键就被这个软件占用了。
方法二:
Accelerator(加速键)方法只在本应用程序内有效 http://support.microsoft.com/?kbid=222829
1、插入一个新的Accelerator到资源里,把加速键和对应的响应控件(如一个按钮)关联
2、在对话框头文件中声明: HACCEL m_hAccel;
3、在对话框的构造函数里初始化m_hAccel
m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_ACCELERATOR1)); //将加速键表加载到内存并获取其句柄4、然后重载对话框的PreTranslateMessage函数,在
BOOL CAboutDlg::PreTranslateMessage(MSG* pMsg) { if (m_hAccel) { if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg)) { return(TRUE); } } return CDialog::PreTranslateMessage(pMsg); } if(pMsg->hwnd == Object.GetSafeHwnd() && pMsg->message == WM_KEYDOWN && pMsg->wParam==VK_C&& (GetKeyState(VK_CONTROL)&0x8000)) { AfxMessageBox("截到了Ctrl+C键"); }Accelerator资源中类型——用来指定键的定义方式,可以是VIRTKEY和ASCII,分别用来表示“键名”字段定义的是虚拟键还是ASCII码。
//去掉确定按钮(IDOK)的默认按钮
CButton *pokbutton = (CButton *)GetDlgItem(IDOK);
Pokbutton->ModifyStyle(BS_DEFPUSHBUTTON,0);
//添加IDCANCEL的默认按钮风格
CButton *pcancelbutton = (CButton *)GetDlgItem(IDCANCEL);
pcancelbutton->SetButtonStyle(BS_DEFPUSHBUTTON);
我这个对话框界面主要输入的是数字,因此如果使用TAB键作编辑框之间的跳转会在使用数字键盘时不方便。因此,就考虑了用回车键来实现TAB键的功能。因为MFC对话框的特点,基于MFC对话框的对话框按下回车键会调用框架内的的OnOk成员函数导至退出。即使你去掉IDC_OK按键的BS_DEFPUSHBUTTON 属性也是不行的。 必须重载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键的控件句柄。示例代码如下:
如果热键已经占用了Ctrl+Z,则下面的操作无效,需要把热键中注册的资源删除。
BOOL CMyRichEditCtrl::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 if(pMsg->message == WM_KEYDOWN && pMsg->wParam == 'Z' && GetAsyncKeyState(VK_CONTROL)&0X8000) { //AfxMessageBox(_T("Ctrl + V 被按下")); int i = 0; i++; } return CRichEditCtrl::PreTranslateMessage(pMsg); }但是,各位有没有注意到。这样处理之后,虽然可以在各个控件之进行输入焦点的转移。可是当一个按钮控件获得了焦点之后,也是按下回车键。以前我们习惯中或者说预料中按下该按钮的后应该执行的功能没有被执行,而焦点又跑到按钮之后的控件上去了。这就是上面代码的不足之处,虽然实现了焦点由回车键控件转移,但是按钮却不能用回车键来操作了。只以用鼠标,这和大家习惯不合。而且,在快速的数据输入中不能用回车键来按下这个按钮却要用鼠标来点击也有违当初我们要快速这样一个目的。所以,还得对以上代码做适当的修改。代码如下。在这里增加了对当前焦点控件类的判断,即如果当前控件是按钮(Button)那么就不执行焦点跳转而是构造一条WM_COMMAND消息发送给程序,让程序以为是鼠标点击了该按钮。从而执行了这个按钮具有的功能而不是什么也不做的焦点转移。
[csharp] view plaincopy
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 (); //获得指定控件的ID号
SendMessage (WM_COMMAND, i, (LPARAM)wnd->m_hWnd);
CWnd *mwnd = GetNextDlgTabItem (wnd);
if (mwnd)
{
mwnd->SetFocus();
return TRUE;
}
return TRUE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
AfxGetMainWnd()-> m_hWnd是主窗口的句柄
FindWindow API ,用标题获取或者是 窗口注册类名
FindWindowEx - 或者你知道那个窗口的第几个子窗口(HWND句柄)
MSG结构表示Windows中的一个消息
窗口的焦点自动切换
在对话框中按下回车键时,会选择对话框中默认按钮的消息响应函数来处理这件事
相关文章推荐
- Android开发中的屏幕适配问题
- java24.线程------实现
- JAVA线程池中的Callable和Future
- How can a database be in-memory and durable at the same time?
- 当方法的返回类型是数组或集合时,不要返回null,尽量返回容量为0的数组或集合
- U-BOOT的两个阶段启动过程与第二阶段的board_init_f和board_init_r
- 快捷键收集
- Bootstrap输入框组
- 第六章
- It选择
- 快速算法
- 张正友标定法
- Swift语法之 ---- ?和!区别
- 开博第一天,留贴纪念.
- 【虫师--系列18】性能测试知多少--系统计数器与硬件分析
- 在ALV列表中添加下拉框
- MySQL开启binlog
- Download 文件下载
- Android应用开发中的风格和主题(style,themes)
- git之版本回退