第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 章 基本输入—键盘和鼠标消息
Visual c++ 99a BeAr 同时按下了Ctr1和P键 匚醍 图44程序运行结果 4.1.5字符消息的处理 当按下一个可显示的字符(数字、字母、标点等)的键时,除了产生按下键消息 WM KEYDOWN外,还将产生一个字符消息 WM CHAR。当然,如果释放该键,还将产生 WM KEYUP消息。用户敲击一个一个字符键后,其产生的消息及处理函数的执行顺序如图45所示。 用户敲击字符按键 键盘消息 WM_ KEY DOWN WM CHAR WM KEYUP 处理函数 OnKey Dowr0 On Char O OnKeyUpO 图45键盘消息的处理过程 MFC将 WM CHAR消息映射为 ON WM CHAR,其对应的处理函数为 On Char(。函数 On Char( 的定义如下: void (UINT nchar, UINT nRepcnt, UINT nFlags) 其中参数 nRep Cnt和 nFlags的含义与41.3节介绍的 OnKey Down函数的完全相同。而参数 n Char存 放的不再是按键的虚拟键码,而是 Windows字符集的字符代码,默认为ASCI码。键盘上常见的字符 及其ASCI码值如表4.3所示 表4.3常见的字符及其ASc码值 字符符号 ASC码值 字符符号 ASC码值 字符符号 AScl码值 35 励志照亮人生编程改变命运
图4.4 程序运行结果 4.1.5 字符消息的处理 当按下一个可显示的字符(数字、字母、标点等)的键时,除了产生按下键消息 WM_KEYDOWN外,还将产生一个字符消息WM_CHAR。当然,如果释放该键,还将产生 WM_KEYUP消息。用户敲击一个一个字符键后,其产生的消息及处理函数的执行顺序如图4.5所示。 图4.5 键盘消息的处理过程 MFC将WM_CHAR消息映射为ON_WM_CHAR,其对应的处理函数为OnChar()。函数OnChar() 的定义如下: void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 其中参数nRepCnt和nFlags的含义与4.1.3节介绍的OnKeyDown函数的完全相同。而参数nChar存 放的不再是按键的虚拟键码,而是Windows字符集的字符代码,默认为ASCII码。键盘上常见的字符 及其ASCII码值如表4.3所示。 表4.3 常见的字符及其ASCII码值 字符符号 ASCII码值 字符符号 ASCII码值 字符符号 ASCII码值 ! 33 " 34 # 35 $ 36 % 37 & 38 ' 39 ( 40 ) 41 * 42 + 43 , 44 - 45 . 46 / 47 76 励志照亮人生 编程改变命运 零基础学 Visual C++ E 用户敲击字符按键 处理函数 键盘消息
第5单基本输入一键盘和标 (续) 符符号 AScl码值 字符符号 ASC码值 符符号 ASC码值 0~9 48-57 65-90 97~122 126 如果 n char取值为64,则表示按键字符为“@”。下面给出一个在视图窗口中,显示键盘输入字符 的实例。 该实例实现的功能是在单文档应用程序界面中,当用户通过键盘键入字符时,在视图窗口依次显 示键入的字符。当用户按下【 Enter】键时,进行换行输出。具体实现过程如下。 1.使用 MFC AppWizard创建SD|工程 按照41.3节介绍的“Ch5Demo1”工程的创建过程,创建 MFC SDI工程“Ch5Demo3 2.添加 WM CHAR消息映射和响应函数 执行“view”→“ Class wizard”菜单命令,或者使用【Ctrl+W】快捷键,打开“MFC Class wizard”对话框。在“ Message Maps”选项卡的“ Class name”列表框中选择要响应键盘消息 的类“ CChsDemo3view”,在“ Object IDs”列表框中选择“ CChs Demo3view”,在“ Messages”列 表框中选择“ WM CHAR”字符按键消息 单击“ Add function”按钮, Class wizard自动为 WM CHAR添加了 ON WM CHAR消息映射宏 On Char(消息处理函数,如图46所示。 Message Maps Member Variables Automation ActiveX Events class Info Class name CCh5Demo3view D: \Ch5Demo3\Ch Demo 3View.h, D: Ch5Demo 3\Ch Delete Function WMCAPTURECHANGED Edit Code A CONTEXTMENU v WM_DROPFILES v OnBeginPrinting v OnPreparePrintir asses keyboard events to focus window 图46“ MFC Class Wizard”对话框 励志照亮人生编程改变命
(续) 字符符号 ASCII码值 字符符号 ASCII码值 字符符号 ASCII码值 0~9 48~57 : 58 ; 59 62 ? 63 @ 64 A~Z 65~90 [ 91 \ 92 ] 93 ^ 94 _ 95 ` 96 a~z 97~122 { 123 | 124 } 125 ~ 126 如果nChar取值为64,则表示按键字符为“@”。下面给出一个在视图窗口中,显示键盘输入字符 的实例。 该实例实现的功能是在单文档应用程序界面中,当用户通过键盘键入字符时,在视图窗口依次显 示键入的字符。当用户按下【Enter】键时,进行换行输出。具体实现过程如下。 1. 使用MFC AppWizard创建SDI工程 按照4.1.3节介绍的“Ch5Demo1”工程的创建过程,创建MFC SDI工程“Ch5Demo3”。 2. 添加WM_CHAR消息映射和响应函数 执行“View”→“ClassWizard”菜单命令,或者使用【Ctrl+W】快捷键,打开“MFC ClassWizard”对话框。在“Message Maps”选项卡的“Class name”列表框中选择要响应键盘消息 的类“CCh5Demo3View”,在“Object IDs”列表框中选择“CCh5Demo3View”,在“Messages”列 表框中选择“WM_CHAR”字符按键消息。 单击“Add Function”按钮,ClassWizard自动为WM_CHAR添加了ON_ WM_CHAR消息映射宏 和OnChar()消息处理函数,如图4.6所示。 图4.6 “MFC ClassWizard”对话框 77 励志照亮人生 编程改变命运 第 5 章 基本输入—键盘和鼠标消息
Visual c++ 3.手工添加实现代码 (1)在视图类CCh5Demo3view的头文件“Ch5Demo3 View. h”中,定义 CPoint型变量,用于记录 字符在视图窗口中的输出位置。代码如下 public //记录字符位置 (2)在CCh5Demo3view类的构造函数中,初始化 chAracter位置为(0,0)。代码如下: cCh5Demo3view:: cCh5Demo 3view() / TODO: add construction code here //初始位置设置在(0,0) character. x=0; character. y=O (3)在 WM CHAR消息响应函数 On Char(中,实现字符的显示以及换行。代码如下: void cch5 Demo 3view:: Onchar (UINT nchar, UINT nRepCnt, UINT nFlags) // TODO: Add your message handler code here and/or call default if (nchar==13) //按下了回车键 //换行 chAracter. x=0 ptcharacter. y=ptcharacter. y+25 cclientDc dc(this) dc. Textout(ptcharacter x, ptcharacter y,(LPCTSTR)&nchar) //输出显示字符 CSize textsize textsize=dc. GetTextExtent((LPCTSTR)&nchar //获取当前字符大小 //前进到下一个字符位置 ptcharacter. x=ptcharacter. x+textsizecx cview:: Onchar (nchar, nRepcnt, nFlags) 编译运行程序后,当用户通过键盘键入字符时,即色无标= 会在视图窗口输出显示。如果按下了【Ene】键,将换|s 行输出,如图4.7所示。 23456789asdlghjk 本程序只是简单演示了 WM CHAR消息响应和按 说明键字符的显示操作,并没有实现窗口的重绘。另 外,实际程序如果涉及文本输入、编辑操作,则 是通过Edit控件和 CEdit View视图来实现的。 图47程序运行结果 励志照亮人生编程改变命运
3. 手工添加实现代码 (1)在视图类CCh5Demo3View的头文件“Ch5Demo3View.h”中,定义CPoint型变量,用于记录 字符在视图窗口中的输出位置。代码如下: public: CPoint ptCharacter; //记录字符位置 (2)在CCh5Demo3View类的构造函数中,初始化ptCharacter位置为(0,0)。代码如下: CCh5Demo3View::CCh5Demo3View() { // TODO: add construction code here //初始位置设置在(0,0) ptCharacter.x=0; ptCharacter.y=0; } (3)在WM_CHAR消息响应函数OnChar()中,实现字符的显示以及换行。代码如下: void CCh5Demo3View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if(nChar==13) //按下了回车键 { //换行 ptCharacter.x=0; ptCharacter.y=ptCharacter.y+25; } else { CClientDC dc(this); dc.TextOut(ptCharacter.x,ptCharacter.y,(LPCTSTR)&nChar); //输出显示字符 CSize textsize; textsize=dc.GetTextExtent((LPCTSTR)&nChar); //获取当前字符大小 //前进到下一个字符位置 ptCharacter.x=ptCharacter.x+textsize.cx; } CView::OnChar(nChar, nRepCnt, nFlags); } 编译运行程序后,当用户通过键盘键入字符时,即 会在视图窗口输出显示。如果按下了【Ente】键,将换 行输出,如图4.7所示。 说明 本程序只是简单演示了WM_CHAR消息响应和按 键字符的显示操作,并没有实现窗口的重绘。另 外,实际程序如果涉及文本输入、编辑操作,则 是通过Edit控件和CEditView视图来实现的。 78 励志照亮人生 编程改变命运 零基础学 Visual C++ 图4.7 程序运行结果
第5单基本输入一键盘和标 4.1.6创建键盘插入符 键盘插入符( Caret)是一个闪烁的位图(通常是一个细的垂直杠),它可使用户知道在窗口何处 可进行有效的键盘输入 表44创建和管理键盘插入符的CWnd成员函数 Cwnd类提供了8个创建和管理键盘插入符的 成员函数,如表44所示 CreateCaret 使用用户提供的位图创建插入符 Windows总是把键盘消息送到拥有输入焦点的 Create Gray caret 创建用户定义大小的实心灰色插入符 窗口。一般情况下,一个应用程序有多个窗口,而 Create SolidCaret创建用户定义大小的实心黑色插入符 键盘消息只能被一个窗口接收,接收键盘消息的窗Dscd销插入符 口称为有“输入焦点”的窗口,具有输入焦点的窗 显示插入符 口称为活动窗口。当某一个窗口成为活动窗口时, Hidec 隐藏插入符 Windows会加亮显示其标题栏或窗口边框 GetCaretPos 返回插入符的位置 Windows用 WM SETFOCUS和 WM Set Caret 移动插入符到窗口的某一位置 KILLFOCUS消息通知即将通知接收或失去输入 焦点的窗口。MFC分别对这两个消息进行了封装 在窗口获得键盘焦点时,就可以创建插入符了,若窗口没有焦点,就不能进行键盘输入。另外, 插入符一旦创建起来,还要在窗口中对其进行定位和显示。下面通过具体的实例讲解插入符的使用。 下面在4.1.5节创建的“CCh5Demo3”实例的基础上,在字符将要显示的位置显示插入符。其具 体实现过程如下 1.打开工程 启动 Visual c++6.0,打开4.1.5节创建的“Ch5Demo3”工程文件“Ch5Demo3.dsw”。 2.添加 WM SETFOCUS消息映射和响应函数 执行“vew"-“ Class wizard”菜单命令,am 或者使用【Ctrl+W】快捷键,打开“ MFC Message Maps. ember Vatiables Automation Activex Events Class Into I Class wizard”对话框。在“ Message Maps”选 dch5Demo3Ch5Demo3vicw. h, D-Ch5Demnric 项卡中的“ Class name”列表框中选择要响应捕| 获窗口消息的类“ CCh5demo3view”,在區m “ Object IDs”列表框中选择“ CCh5Demo3view”, 在“ Messages”列表框中选择“WM-|、 SETFOCUS”捕获窗口消息。 单击“ Add Function”按钮, Class Wizard自/e 动为 WM SETFOCUS添加了ON iw has gained inputt WM SETFOCUS消息映射宏和 OnSet Focus消息 处理函数,如图48所示。 图48“ MFC Class wizard”对话框 3.手工添加实现代码 (1)在 WM SETFOCUS消息响应函数 OnSetFocus(中,实现插入符的创建与显示。代码如下 void cch5 Demo 3view:: OnsetFocus (cWnd* poldwnd) 励志照亮人生编程改变命
4.1.6 创建键盘插入符 键盘插入符(Caret)是一个闪烁的位图(通常是一个细的垂直杠),它可使用户知道在窗口何处 可进行有效的键盘输入。 CWnd类提供了8个创建和管理键盘插入符的 成员函数,如表4.4所示。 Windows总是把键盘消息送到拥有输入焦点的 窗口。一般情况下,一个应用程序有多个窗口,而 键盘消息只能被一个窗口接收,接收键盘消息的窗 口称为有“输入焦点”的窗口,具有输入焦点的窗 口称为活动窗口。当某一个窗口成为活动窗口时, Windows会加亮显示其标题栏或窗口边框。 Windows 用 WM_SETFOCUS 和 WM_ KILLFOCUS消息通知即将通知接收或失去输入 焦点的窗口。MFC分别对这两个消息进行了封装。 在窗口获得键盘焦点时,就可以创建插入符了,若窗口没有焦点,就不能进行键盘输入。另外, 插入符一旦创建起来,还要在窗口中对其进行定位和显示。下面通过具体的实例讲解插入符的使用。 下面在4.1.5节创建的“CCh5Demo3”实例的基础上,在字符将要显示的位置显示插入符。其具 体实现过程如下。 1. 打开工程 启动Visual C++ 6.0,打开4.1.5节创建的“Ch5Demo3”工程文件“Ch5Demo3.dsw”。 2. 添加WM_SETFOCUS消息映射和响应函数 执行“View”→“ClassWizard”菜单命令, 或者使用【 Ctrl+W 】快捷键,打开“ MFC ClassWizard”对话框。在“Message Maps”选 项卡中的“Class name”列表框中选择要响应捕 获窗口消息的类“ CCh5Demo3View ”, 在 “Object IDs”列表框中选择“CCh5Demo3View”, 在 “ Messages ”列表框中选择“ WM_ SETFOCUS”捕获窗口消息。 单击“Add Function”按钮,ClassWizard自 动 为 WM_SETFOCUS 添加了 ON_ WM_SETFOCUS消息映射宏和OnSetFocus()消息 处理函数,如图4.8所示。 3. 手工添加实现代码 (1)在WM_SETFOCUS消息响应函数OnSetFocus()中,实现插入符的创建与显示。代码如下: void CCh5Demo3View::OnSetFocus(CWnd* pOldWnd) 79 励志照亮人生 编程改变命运 第 5 章 基本输入—键盘和鼠标消息 表4.4 创建和管理键盘插入符的CWnd成员函数 函数 功能 CreateCaret 使用用户提供的位图创建插入符 CreateGrayCaret 创建用户定义大小的实心灰色插入符 CreateSolidCaret 创建用户定义大小的实心黑色插入符 DestoryCaret 销毁插入符 ShowCaret 显示插入符 HideCaret 隐藏插入符 GetCaretPos 返回插入符的位置 SetCaretPos 移动插入符到窗口的某一位置 图4.8 “MFC ClassWizard”对话框
Visual c++ cview:: OnsetFocus(poldWnd) // TODO Add your message handler code here Createsolidcaret(4, 20) //创建插入符 setcaretPos (ptcharacter)i //将插入符移到当前字符输入点 sh。 cAret() //显示插入符 (2)修改 On Char(函数,在适当的时机显示、隐藏插入符。代码如下: void cch5 Demo 3view:: Onchar (UINT nchar, UINT nRepcnt, UINT nFlags) / TODO: Add your message handler code here and/or call default if(nchar==13) //按下了回车键 //换行 character. x=O pt character. y=ptcharacter. y+25 Showcard.s (ptcharacter //将插入符移到键入点 //显示插入符 cclientDc dc(this Hidecaret //隐藏插入符 dc. Textout( character,x, character.y,( LPCTSTR)& nchar);//显示字符 csize textsize textsize=dc. GetTextExtent((LPCTSTR)&nchar //获取当前字符大小 //前进到下一个字符位置 ptcharacter. x=ptcharacter. x+textsizecx SetcaretPos (ptcharacter): //将插入符移到键入点 //显示插入符 cview:: Onchar(nchar, nRepcnt, nFlags) 编译运行程序后,会发现与原程序相比,在字符的输入位置增加了插入符,如图4.9所示 无标题-Ch5De3 文件)②)查看Q0帮助0 回ee? 图49程序运行结果 励志照亮人生编程改变命运
{ CView::OnSetFocus(pOldWnd); // TODO: Add your message handler code here CreateSolidCaret(4, 20); //创建插入符 SetCaretPos (ptCharacter); //将插入符移到当前字符输入点 ShowCaret (); //显示插入符 } (2)修改OnChar()函数,在适当的时机显示、隐藏插入符。代码如下: void CCh5Demo3View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if(nChar==13) //按下了回车键 { //换行 ptCharacter.x=0; ptCharacter.y=ptCharacter.y+25; SetCaretPos (ptCharacter); //将插入符移到键入点 ShowCaret (); //显示插入符 } else { CClientDC dc(this); HideCaret (); //隐藏插入符 dc.TextOut(ptCharacter.x,ptCharacter.y,(LPCTSTR)&nChar);//显示字符 CSize textsize; textsize=dc.GetTextExtent((LPCTSTR)&nChar); //获取当前字符大小 //前进到下一个字符位置 ptCharacter.x=ptCharacter.x+textsize.cx; SetCaretPos (ptCharacter); //将插入符移到键入点 ShowCaret (); //显示插入符 } CView::OnChar(nChar, nRepCnt, nFlags); } 编译运行程序后,会发现与原程序相比,在字符的输入位置增加了插入符,如图4.9所示。 图4.9 程序运行结果 80 励志照亮人生 编程改变命运 零基础学 Visual C++