第5单基本输入一键盘和标 第二篇 VC常用类、控件、资源篇 第4章基本输入——一键盘和鼠标消息 Windows采用的是事件驱动机制,因此要让程序完成一定功能,很多情况下用户必须进行干预, 告诉程序要干什么,这就要求用户通过某种手段与计算机进行交互。鼠标和键盘是用户与 Windows应 用程序交换的最主要的交换设备。 Windows预先定义了大量的鼠标消息和键盘消息,而MFC也对其中 的常用消息进行了封装。本章主要介绍在MFC应用程序中,键盘和鼠标消息的响应与处理 4.1键盘消息及其处理 在 Windows中,键盘输入以消息的形式传递给程序的视窗消息处理程序。按下或释放一个键均会 产生一条消息,系统将其放到与键盘输入窗口相对应的线程消息队列中 4.1.1键盘消息 键盘消息有三种:键盘被按下、键盘被松开(弹起)、输入字符。其中,输入字符相当于直接得 到用户输入的字符,这在不需要处理按键细节时使用:而键盘被按下、松开在按键状态改变时发送。 MFC对键盘的这三种键盘消息进行了封装,如 表4.1MFC中封装的键盘消息 表4.1所示 键盘消息 按键和释放键消息通常是成对出现的,但如果用 WM KEYDOWN 键盘按下 户按住键到一定的时间就启动了键盘的自动重复特 WM KEYUP 键盘抬起 性,系统就会产生一系列的 WM KEYDOWN消息, WM CHAR 可打印字符键按下并抬 在用户释放一个键时,才产生一条 WM KEYUP消息 起,输入了一个字符 4.1.2键盘消息的处理 般来讲,用户输入消息,如菜单选择、鼠标、键盘等,多在文档/视图结构的应用程序中使用 在MFC应用程序开发中,可以使用 Classwizard为键盘消息和鼠标消息添加消息映射和消息处理函数, 在MFC文档/视图结构的应用程序中,视图窗口和框架窗口均能处理键盘和鼠标消息。当有键盘 或鼠标消息产生时,系统会先将消息发往视图窗口,如果视图类中没有发现相应的消息映射和处理函 数,就将该消息再发往框架窗口。所以在使用 Class wizard为键盘消息定义消息映射时,定义在视图 励志照亮人生编程改变命运
第二篇 VC常用类、控件、资源篇 第4 章 基本输入—键盘和鼠标消息 Windows采用的是事件驱动机制,因此要让程序完成一定功能,很多情况下用户必须进行干预, 告诉程序要干什么,这就要求用户通过某种手段与计算机进行交互。鼠标和键盘是用户与Windows应 用程序交换的最主要的交换设备。Windows预先定义了大量的鼠标消息和键盘消息,而MFC也对其中 的常用消息进行了封装。本章主要介绍在MFC应用程序中,键盘和鼠标消息的响应与处理。 4.1 键盘消息及其处理 在Windows中,键盘输入以消息的形式传递给程序的视窗消息处理程序。按下或释放一个键均会 产生一条消息,系统将其放到与键盘输入窗口相对应的线程消息队列中。 4.1.1 键盘消息 键盘消息有三种:键盘被按下、键盘被松开(弹起)、输入字符。其中,输入字符相当于直接得 到用户输入的字符,这在不需要处理按键细节时使用;而键盘被按下、松开在按键状态改变时发送。 MFC对键盘的这三种键盘消息进行了封装,如 表4.1所示。 按键和释放键消息通常是成对出现的,但如果用 户按住键到一定的时间就启动了键盘的自动重复特 性,系统就会产生一系列的WM_KEYDOWN消息, 在用户释放一个键时,才产生一条WM_KEYUP消息。 4.1.2 键盘消息的处理 一般来讲,用户输入消息,如菜单选择、鼠标、键盘等,多在文档/视图结构的应用程序中使用。 在MFC应用程序开发中,可以使用ClassWizard为键盘消息和鼠标消息添加消息映射和消息处理函数。 在MFC文档/视图结构的应用程序中,视图窗口和框架窗口均能处理键盘和鼠标消息。当有键盘 或鼠标消息产生时,系统会先将消息发往视图窗口,如果视图类中没有发现相应的消息映射和处理函 数,就将该消息再发往框架窗口。所以在使用ClassWizard为键盘消息定义消息映射时,定义在视图 71 励志照亮人生 编程改变命运 第 5 章 基本输入—键盘和鼠标消息 表4.1 MFC中封装的键盘消息 键盘消息 描 述 WM_KEYDOWN 键盘按下 WM_KEYUP 键盘抬起 WM_CHAR 可打印字符键按下并抬 起,输入了一个字符
Visual c++ 类中就可以了。如果一个应用同时拥有多个视图,而当前活动没有对消息进行处理,则消息会发往框 架窗口。 下面通过具体的实例讲解键盘消息的映射及处理。 4.1.3按键消息的处理 当按下一个键或松开一个键时,将产生一个按键消息。在MFC中,WM_ KEYDOWN和 WM KEYUP消息分别在按下一个键和松开一个键时被激发 本节将创建一个单文档应用程序,当用户按下任意一个键时,弹出对话框显示相应的提示信息 具体实现过程如下 1.使用 MFC AppWizard创建SD程 ,启动wuaC+60,执行“Fle”→“New”菜单命令,在“ Projects”选项卡中,创建一个MFC App wizardlexe]工程,工程名为“Ch5 Demo1”,如图4.1所示。 单击“OK”按钮,在“ MFC App Wizard Step1”对话框中,选中“ Single document”,即基于单 文档的MFC工程,其余的几步向导对话框均采用默认设置。 2.添加 WM KEYDOWN消息映射和响应函数 执行“view”→“ Class wizard”菜单命令,或者使用【Ctrl+W】快捷键,打开“MFC Class wizard”对话框。在“ Message Maps”选项卡的“ Class name”列表框中选择要响应键盘消息 的类“ CCh5 Demo l view”,在“ Object IDs”列表框中选择“ CCh5 Demol view",在“ Messages”列 表框中选择“ WM KEYDOWN”按键消息 单击“ Add Function”按钮, Class wizard自动为 WM KEYDOWN添加了 ON WM KEYDOWN 消息映射宏和 OnKey Down(消息处理函数,如图42所示。 ActiveXEvents Cleas Into I D ChsDemolich5DemaIView, D:Ch5Demalch5Demal Viewtpp 4 Create new workspace Console Application Hlatlormsc 图41“New”对话框 图4.2“ MFC Class wizard”对话框 此时,在“ Ch5Demol Viewcpp”资源文件的开始部分会发现自动添加的消息映射代码: BEGIN MESSAGE MAP(CCh5Demo lview, cview) //((AEX MSG MAP (CCh5Demolview) ON WM KEY DOWN //消息映射代码 //1JAEX MSG MAP 励志照亮人生编程改变命运
类中就可以了。如果一个应用同时拥有多个视图,而当前活动没有对消息进行处理,则消息会发往框 架窗口。 下面通过具体的实例讲解键盘消息的映射及处理。 4.1.3 按键消息的处理 当按下一个键或松开一个键时,将产生一个按键消息。在MFC中,WM_KEYDOWN和 WM_KEYUP消息分别在按下一个键和松开一个键时被激发。 本节将创建一个单文档应用程序,当用户按下任意一个键时,弹出对话框显示相应的提示信息。 具体实现过程如下。 1. 使用MFC AppWizard创建SDI工程 启动Visual C++6.0,执行“File”→“New”菜单命令,在“Projects”选项卡中,创建一个MFC AppWizard[exe]工程,工程名为“Ch5Demo1”,如图4.1所示。 单击“OK”按钮,在“MFC AppWizard Step 1”对话框中,选中“Single document”,即基于单 文档的MFC工程,其余的几步向导对话框均采用默认设置。 2. 添加WM_KEYDOWN消息映射和响应函数 执行“View”→“ClassWizard”菜单命令,或者使用【Ctrl+W】快捷键,打开“MFC ClassWizard”对话框。在“Message Maps”选项卡的“Class name”列表框中选择要响应键盘消息 的类“CCh5Demo1View”,在“Object IDs”列表框中选择“CCh5Demo1View”,在“Messages”列 表框中选择“WM_KEYDOWN”按键消息。 单击“Add Function”按钮,ClassWizard自动为WM_KEYDOWN添加了ON_ WM_KEYDOWN 消息映射宏和OnKeyDown()消息处理函数,如图4.2所示。 此时,在“Ch5Demo1View.cpp”资源文件的开始部分会发现自动添加的消息映射代码: BEGIN_MESSAGE_MAP(CCh5Demo1View, CView) //{{AFX_MSG_MAP(CCh5Demo1View) ON_WM_KEYDOWN() //消息映射代码 //}}AFX_MSG_MAP 72 励志照亮人生 编程改变命运 零基础学 Visual C++ 图4.1 “New”对话框 图4.2 “MFC ClassWizard”对话框
第5单基本输入一键盘和标 END MESSAGE MAP ( 在“Ch5 Demol view. h”头文件,自动添加了消息处理函数 OnKey Down()的声明代码如下: protected //((AEX MSG(CCh5Demolview) afx msg void onKey Down(UINT nchar, UINT nRepCnt, UINT nFlags) //AEX MSG 3.手工添加函数的实现代码 在 Class wizard对话框(图42)中,单击“ Edit Code”按钮,在工作区中,即跳转至新增函数代 码的定义处。这时,需要手工添加 On Drawcircleo函数的实现代码,如下: void cch DemolView:: OnKey Down(UINT nchar, UINT nRepcnt, UINT nFlags) // TODO: Add your message handler code here and/or call default AfxMessageBox("用户按下了键!") //弹出提示对话框 cview:: OnKeyDown(nchar, nRepcnt, nFlags) 这里只添加了一行代码,实现弹出提示对话框。 编译运行程序后,若用户按下键盘的任意键,就会弹 SOREST 出提示对话框,如图4.3所示。 WM KEYUP消息的消息映射和处理过程与 按下了继 WM KEYDOWN的完全相同。 4.14按键消息处理函数 从上一节实例可见,MFC会将 WM KEYDOWN消息 映射为 ON WM KEYDOWN,而对应的处理函数为 图4.3程序运行结果 OnKey Down(。同样, WM KEYUP消息对应的处理函数 为 OnKeyUpo。它们具有完全相同的参数,声明如下: void onkey Down (UINT nchar, UINT nRepCnt, UINT nFlags); void OnkeyUp(UINT nchar, UINT nRepcnt, UINT nFlags) 口参数 n char表示按键的虚拟键码。如“ VK ALT”,表示按下的键为【Alt】键, “ VK CONTROL”表示按下的键为【 Ctrl】键。 Windows中常用的虚拟键码及其对应的按键如 表4.2所示。 表4.2 Windows常用的虚拟键码及其对应的按键 虚拟键码 对应的键 虚拟键码 对应的键 K LBUTTON 鼠标左键 VK BACK 退格键 K RBUTTON 鼠标右键 VK TAB 制表键 VK MBUTTON 鼠标中键 VK RETURN 回车键 K SHIFT 16 Shift键 VK CONTROL Ctrl键 励志照亮人生编程改变命
// Standard printing commands …… END_MESSAGE_MAP() 在“Ch5Demo1View.h”头文件,自动添加了消息处理函数OnKeyDown()的声明代码如下: protected: //{{AFX_MSG(CCh5Demo1View) afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); //}}AFX_MSG 3. 手工添加函数的实现代码 在ClassWizard对话框(图4.2)中,单击“Edit Code”按钮,在工作区中,即跳转至新增函数代 码的定义处。这时,需要手工添加OnDrawcircle()函数的实现代码,如下: void CCh5Demo1View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default AfxMessageBox("用户按下了键!"); //弹出提示对话框 CView::OnKeyDown(nChar, nRepCnt, nFlags); } 这里只添加了一行代码,实现弹出提示对话框。 编译运行程序后,若用户按下键盘的任意键,就会弹 出提示对话框,如图4.3所示。 WM_KEYUP 消息的消息映射和处理过程与 WM_KEYDOWN的完全相同。 4.1.4 按键消息处理函数 从上一节实例可见,MFC会将WM_KEYDOWN消息 映射为 ON_WM_KEYDOWN,而对应的处理函数为 OnKeyDown()。同样,WM_KEYUP消息对应的处理函数 为OnKeyUp()。它们具有完全相同的参数,声明如下: void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); ❑ 参 数 nChar 表示按键的虚拟键码。如“ VK_ALT ”,表示按下的键为【 Alt 】键, “VK_CONTROL”表示按下的键为【Ctrl】键。Windows中常用的虚拟键码及其对应的按键如 表4.2所示。 表4.2 Windows常用的虚拟键码及其对应的按键 虚拟键码 数 值 对应的键 虚拟键码 数 值 对应的键 VK_LBUTTON 1 鼠标左键 VK_BACK 8 退格键 VK_RBUTTON 2 鼠标右键 VK_TAB 9 制表键 VK_MBUTTON 4 鼠标中键 VK_RETURN 13 回车键 VK_SHIFT 16 Shift键 VK_CONTROL 17 Ctrl键 73 励志照亮人生 编程改变命运 第 5 章 基本输入—键盘和鼠标消息 图4.3 程序运行结果
Visual c++ (续) 虚拟键码 虚拟键码 对应的键 VK MENU VK PAUSE Pause键 VK CAPTIAL 803 Caplock键 VK ESCAPE VK PRIOR VK NEXT age down键 VK END VK HOME Home键 VK LEFT VK RIGHT 右箭头键 VK UP 上箭头键 VK DOWN 974690046 下箭头键 0~9键 空格键 VK SNAPSHOT Print screen键 VK INSERT Insert键 VK DELETE Delete键 112~135 功能键F~F24 VK NUMLOCK 144 NumLock键 使用虚拟键码时,可以使用键码也可以直接使用其数值。如判断按键是否为回车键时,可以采用 “if( n Char== VK RETURN)”语句,也可采用“i( nChar==13)”语句 说明 虚拟键码是 Windows内部建立的设备无关的键盘代码。在 Windows中不论使用什么类型的键盘 都将扫描代码翻译成同一的虚拟键码,这样应用程序就不用直接同硬盘硬件打交道 口参数 nRepCnt表示按键的重复次数,即长时间按住一个键时,相当于按键的次数。 口参数 nFlags中的不同位代表不同的含义,包括键盘扫描码、扩展键盘标志、描述码、键的先前 状态和转换状态标志等,一般很少用到 根据按键消息响应函数各参数的值,可以判断按键的相关信息,便于进行灵活的程序开发。下面 给出一个具体应用实例。 实例功能:当用户同时按住【Ctrl】键和【F8】键时,激发某一操作,即弹出提示对话框。实现 过程如下。 1.使用 MFC AppWizard创建SD|工程 按照4.1.3节介绍的“Ch5Demo1”工程的创建过程,创建 MFC SDI工程“Ch5Demo2”。 2.添加 WM KEYDOWN和WMUP消息映射和响应函数 同样,利用 Class wizard,分别为视图类CCh5Demo2view添加 WM KEYDOWN、WMUP消息映 射和消息处理函数 3.手工添加实现代码 (1)在视图类CCh5Demo2view的头文件“Ch5Demo2 View. h”中,定义两个布尔变量,分别用于 记录【Ctl】键和【F8】键的状态:按下时为“true”,释放后为“ false"。代码如下: public BOOL b ctrldown,b F8down (2)在CCh5Demo2view类的构造函数中,初始化变量为“ false”。代码如下: cch5Demo2view:: CCh5Demo 2view() 励志照亮人生编程改变命运
(续) 虚拟键码 数 值 对应的键 虚拟键码 数 值 对应的键 VK_MENU 18 Alt键 VK_PAUSE 19 Pause键 VK_CAPTIAL 20 Caplock键 VK_ESCAPE 27 Esc键 VK_PRIOR 33 Page Up键 VK_NEXT 34 Page Down键 VK_END 35 End键 VK_HOME 36 Home键 VK_LEFT 37 左箭头键 VK_RIGHT 39 右箭头键 VK_UP 38 上箭头键 VK_DOWN 40 下箭头键 48~57 0~9键 65~90 A~Z键 VK_SPACE 32 空格键 VK_SNAPSHOT 44 Print Screen键 VK_INSERT 45 Insert键 VK_DELETE 46 Delete键 112~135 功能键F1~ F24 VK_NUMLOCK 144 NumLock键 使用虚拟键码时,可以使用键码也可以直接使用其数值。如判断按键是否为回车键时,可以采用 “if(nChar == VK_RETURN)”语句,也可采用“if(nChar == 13)”语句。 说明 虚拟键码是Windows内部建立的设备无关的键盘代码。在Windows中不论使用什么类型的键盘, 都将扫描代码翻译成同一的虚拟键码,这样应用程序就不用直接同硬盘硬件打交道。 ❑ 参数nRepCnt表示按键的重复次数,即长时间按住一个键时,相当于按键的次数。 ❑ 参数nFlags中的不同位代表不同的含义,包括键盘扫描码、扩展键盘标志、描述码、键的先前 状态和转换状态标志等,一般很少用到。 根据按键消息响应函数各参数的值,可以判断按键的相关信息,便于进行灵活的程序开发。下面 给出一个具体应用实例。 实例功能:当用户同时按住【Ctrl】键和【F8】键时,激发某一操作,即弹出提示对话框。实现 过程如下。 1. 使用MFC AppWizard创建SDI工程 按照4.1.3节介绍的“Ch5Demo1”工程的创建过程,创建MFC SDI工程“Ch5Demo2”。 2. 添加WM_KEYDOWN和WM_UP消息映射和响应函数 同样,利用ClassWizard,分别为视图类CCh5Demo2View添加WM_KEYDOWN、WM_UP消息映 射和消息处理函数。 3. 手工添加实现代码 (1)在视图类CCh5Demo2View的头文件“Ch5Demo2View.h”中,定义两个布尔变量,分别用于 记录【Ctrl】键和【F8】键的状态:按下时为“true”,释放后为“false”。代码如下: public: BOOL b_Ctrldown,b_F8down; (2)在CCh5Demo2View类的构造函数中,初始化变量为“false”。代码如下: CCh5Demo2View::CCh5Demo2View() 74 励志照亮人生 编程改变命运 零基础学 Visual C++
第5单基本输入一键盘和标 / TODO: add construction code here b ctrldown=fals //初始化 b F8down=false //初始化 (3)在 WM KEYDOWN消息响应函数 onkey Downo中,实现按键状态的赋值,并在满足条件的 情况下,弹出提示对话框。代码如下 void cch5Demo2View:: Onkey Down(UINT nchar, UINT nRepcnt, UINT nFlags) / TODO: Add your message handler code here and/or call default if(nchar==VK CONTROL) //如果按下了【ctr1】键 b ctrldown=true if(nchar==VK F8) //如果按下了【E8】键 b Adown=true if(b ctrldown&&b F8down) //同时按下了【ctr1】键和【F8】键 b ctrldown=false AfxMessageBox("同时按下了ctr1键和F8键”);//弹出提示框 Cview:: OnKeyDown(nchar, nRepcnt, nFlags (4)在 WM KEYUP消息响应函数 Onkeyup(O中,实现按键状态的赋值。代码如下 void cch5 Demo 2View:: OnkeyUp(UINT nchar, UINT nRepCnt, UINT nElags) / TODO: Add your message handler code here and/or call default (nchar==vK CON //如果释放了【ctr1】键 if(nchar==VK E8) //如果释放了【F8】键 F Cview: OnkeyUp(nchar, nRepCnt, nFlags) 编译运行程序后,若用户同时按下了【Ctrl】键和【F8】键,就会弹出提示对话框,如图4.4 所 励志照亮人生编程改变命
{ // TODO: add construction code here b_Ctrldown=false; //初始化 b_F8down=false; //初始化 } (3)在WM_KEYDOWN消息响应函数onkeyDown()中,实现按键状态的赋值,并在满足条件的 情况下,弹出提示对话框。代码如下: void CCh5Demo2View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if(nChar==VK_CONTROL) //如果按下了【Ctrl】键 { b_Ctrldown=true; } if(nChar==VK_F8) //如果按下了【F8】键 { b_F8down=true; } if(b_Ctrldown&&b_F8down) //同时按下了【Ctrl】键和【F8】键 { b_Ctrldown=false; b_F8down=false; AfxMessageBox("同时按下了Ctrl键和F8键"); //弹出提示框 } CView::OnKeyDown(nChar, nRepCnt, nFlags); } (4)在WM_KEYUP消息响应函数Onkeyup()中,实现按键状态的赋值。代码如下: void CCh5Demo2View::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if(nChar==VK_CONTROL) //如果释放了【Ctrl】键 { b_Ctrldown=false; } if(nChar==VK_F8) //如果释放了【F8】键 { b_F8down=false; } CView::OnKeyUp(nChar, nRepCnt, nFlags); } 编译运行程序后,若用户同时按下了【Ctrl】键和【F8】键,就会弹出提示对话框,如图4.4 所示。 75 励志照亮人生 编程改变命运 第 5 章 基本输入—键盘和鼠标消息