第4章  鼠标与键盘消息的处理

第4章 鼠标与键盘消息的处理

  • 最近更新2018年09月27日

特殊说明:版权归个人所有,请勿转载,谢谢合作。

鼠标及键盘作为Windows系统最重要的输入设置,要深入理解消息的类型以及消息的捕获方法。本章节重点介绍鼠标及键盘消息的基本概念与应用。

4.1 鼠标消息的应用

根据MSDN的描述,Windows系统有24种不同的消息,用来报告与鼠标有关的事件。这些消息分为两大类:客户区域鼠标消息与非客户区域鼠标消息。客户区域鼠标消息,用来报告当前窗口客户区域里发生的事件。非客户区域鼠标消息,则用来报告除当前窗口以外的窗口区域发生的事件。

在鼠标消息处理过程中,非客户区域并不常用,在过程处理函数中不去捕获这部分消息即可,系统会通过DefWindowProc函数交给系统处理。表4.1列出了鼠标的消息,并对响应区域进行了区分。

 

  • 表4.1 鼠标消息事件
区域 消息 事件描述
客户区域 WM_LBUTTONDOWN 客户区左键按下事件
WM_LBUTTONUP 客户区左键抬起事件
WM_LBUTTONDBLCLK 客户区左键双击事件
WM_MBUTTONDOWN 客户区中键按下事件
WM_MBUTTONUP 客户区中键抬起事件
WM_MBUTTONDBLCLK 客户区中键双击事件
WM_RBUTTONDOWN 客户区右键按下事件
WM_RBUTTONUP 客户区右键抬起事件
WM_RBUTTONDBLCLK 客户区右键双击事件
WM_MOUSEMOVE 客户区鼠标移动事件
WM_MOUSEWHEEL 客户区滚轮滚动事件
WM_MOUSEACTIVATE 非活动窗口,鼠标操作事件
WM_CAPTURECHANGED 失去鼠标捕获窗口的事件
非客户区域 WM_NCHITTEST 移动窗口标题栏发生的事件
WM_NCLBUTTONDBLCLK 非客户区左键双击事件
WM_NCLBUTTONDOWN 非客户区左键按下事件
WM_NCLBUTTONUP 非客户区左键抬起事件
WM_NCMBUTTONDBLCLK 非客户区中键双击事件
WM_NCMBUTTONDOWN 非客户区中键按下事件
WM_NCMBUTTONUP 非客户区中键抬起事件
WM_NCMOUSEMOVE 非客户区鼠标移动事件
WM_NCRBUTTONDBLCLK 非客户区右键双击事件
WM_NCRBUTTONDOWN 非客户区右键按下事件
WM_NCRBUTTONUP 非客户区右键抬起事件

 

鼠标消息的记忆,有一定的规则,“WM_”为消息的标识,“L”为left,代表左键,“M”为middle,代表中键, “R”为right,代表右键,NC表示为非客户区域。例如,鼠标右键抬起事件,可以写为:“WM_  R  BUTTON  UP”,当然正确的写法是“WM_RBUTTONUP”,只是用空格将规则进行区分。部分鼠标消息是有连贯性的,其中包括左键、中键与右键。如果做了一次鼠标左键的点击事件,系统则先触发左键接下(WM_LBUTTONDOWN)事件,再触发左键抬起(WM_LBUTTONUP)事件。

接下来以鼠标左键按下事件为例,讲解鼠标消息在过程处理函数中的处理方法以及各参数的含义。下例是鼠标左键按下时,弹出一个提示框:

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message) 
  {
    // 鼠标左键按下实例
  case WM_LBUTTONDOWN:
    MessageBox(hWnd, "鼠标左键被接下。", "提示", MB_OK);
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    // 调用系统默认消息处理,即交给系统处理。
    return DefWindowProc(hWnd, message, wParam, lParam);
  }//end switch
  
  return 0;
}

 

从事例中不难看出,捕获鼠标消息非常简单。对于此时的过程处理函数,其参数是有一定含义的:

参数hWnd,当前窗口的句柄;

参数message,消息的类型,此处值为WM_LBUTTONDOWN;

参数wParam,存放一个标志,该标志注明了当鼠标左键按下的时,还有什么键同时被按下。如果判断鼠标左键按下的同时按了什么键,可以通过如下方法来验证:

 

              // 鼠标左键按下实例
case WM_LBUTTONDOWN:
  if(wParam & MK_CONTROL)
  {
    MessageBox(hWnd, "Ctrl键同时被按下。", "提示", MB_OK);	
  }
  break;

 

其中MK_CONTROL为虚拟键值,系统还提供如表4.2所示的虚拟键值。

  • 表4.2 鼠标消息中wParam的值
含义
MK_CONTROL 按下了Ctrl键
MK_LBUTTON 按下了鼠标左键
MK_MBUTTON 按下了鼠标中键
MK_RBUTTON 按下了鼠标右键
MK_SHIFT 按下了Shift键

 

参数lParam,存放当前光标在窗口中的位置。在获得光标位置时,需要将lParam进行拆分,lParam为四个字节的数值,高位两位代表着鼠标的Y坐标,低两位代表着鼠标的X坐标,如图所示。

  • 图4.1 lParam中的坐标

可以通过LOWORD函数与HIWORD函数,分别获得鼠标的X坐标值与Y坐标值,具体写法如下:

 

xPos = LOWORD(lParam); 
yPos = HIWORD(lParam);

 

已经学会了鼠标左键按下消息的捕获与处理,针对于鼠标的其他事件,处理方法相同,所以,这里不过多介绍。接下来,做一个关于鼠标的示例。【例4-1】介绍了如何响应鼠标消息。鼠标移动时,窗口标题显示当前光标在客户区的位置。

 

//-----------------------------------------------------------------------------
//	FUNC	:	回调函数
//-----------------------------------------------------------------------------
//	IN	:	hWnd,窗口句柄;
//			message,要处理的消息ID,以此来区分消息;
//			wParam,消息参数,根据消息的不同内容也有所不同;
//			lParam,消息参数,根据消息的不同内容也有所不同。
//	OUT	:	void
//	RETURN	:	void
//	AUTHOR	:	2012-2-6 11:36 Create by lixinghua for functions.
//	NOTE	:	此函数用于系统消息的处理。
//-----------------------------------------------------------------------------
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  char szBuffer[64] = { 0 };				// 用于存放鼠标位置的缓冲区
  int  nX, nY;						// 存放鼠标的X,Y值

  // 消息处理
  //
  switch (message) 
  {
    // 鼠标移动事件
  case WM_MOUSEMOVE:
    // 获取X,Y值
    nX = LOWORD(lParam); 
    nY = HIWORD(lParam);
    // 格式化到缓冲区
    sprintf(szBuffer, "X:%d, Y:%d", nX, nY);
    // 设置窗口标题
    SetWindowText(hWnd, szBuffer);
    break;
    // 窗口销毁消息,关闭窗口时响应。
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    // 调用系统默认消息处理,即交给系统处理。
    return DefWindowProc(hWnd, message, wParam, lParam);
  }//end switch

  return 0;
}

 

首先,需要捕获鼠标的移动事件(捕获WM_MOUSEMOVE消息);其次,得到鼠标的坐标位置。可以使用LOWORD、HIWORD函数,分别获得X、Y坐标。坐标已经有了,但需要将X、Y的值格式化到字符串中,可以使用sprintf函数。sprintf函数的用法与printf函数的用法相似,printf函数是打印相关的内容到屏幕上,而sprintf函数是结果格式化到它的第一个参数中。sprintf函数的第一个参数是字符串,它要有足够大的空间来存放X、Y坐标值;最后,将存放坐标位置的字符串显示在窗口的标题栏中。SetWindowText函数的功能是设置窗口标题的内容,它的第一个参数是窗口的句柄(将设置窗口的句柄),第二个参数是设置的内容。最终实现结果如图4.2所示。

  • 图4.2 鼠标移动实例
分享到 :
相关推荐

发表回复

登录... 后才能评论