Windows 程序设计--- 鼠标(1)

这篇具有很好参考价值的文章主要介绍了Windows 程序设计--- 鼠标(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近学习了一下Windows 程序设计这本书中的鼠标章节,现在总结一下学习的内容。大家可以一起参考。我将分为两个部分进行介绍。有关鼠标更具体的学习可以参考微软官方文档鼠标输入

1.鼠标的基础知识

1.0 定义:鼠标带有一个或者多个按钮的定位设备。区别于键盘:输入和管理文本功能。鼠标主要用来绘制和处理图形对象。我们常用的鼠标是两个按钮+一个滚轮,其实滚轮中间也有一个按钮。
1.1 操作系统中与鼠标有关的API函数:
①获取电脑是否连接鼠标:

fMouse = GetSystemMetrics(SM_MOUSEPRESENT)
// fMouse:连接了鼠标时为TRUE,否则为0。

②确定鼠标按钮数

cButtons = GetSystemMetrics(SM_CMOUSEBUTTONS)
// 如果没有鼠标则cButtons 为0。

③设置鼠标的其他信息

BOOL
WINAPI
SystemParametersInfoW(
    _In_ UINT uiAction,
    _In_ UINT uiParam,
    _Pre_maybenull_ _Post_valid_ PVOID pvParam,
    _In_ UINT fWinIni);

例如获取鼠标滚轮信息:

SystemParametersInfo(SPI_GETWHEELSCROLLLINES,0,&uScrollLine,0);

1.2 一些和鼠标有关的术语:
①鼠标指针:位图格式的小图标。具有一个单像素精度的"热点"(hot spot),它在显示设备上指示了一个精确位置。我们平时知道的鼠标位置,说的就是热点的位置了。
Windows 在Winuser.h中为我们提供了几种常用的指针。最常用的是斜向箭头,称为IDC_ARROW。然后还有IDC_CROSS(➕ 状)、IDC_WAIT(⌛状,表示等待)等,具体查看Winuser.h头文件。我们的创建窗口类时,默认指定为IDC_ARROW。

ws.hCursor = LoadCursor(NULL, IDC_ARROW);

②单击:按下鼠标按钮,然后松开。
③双击:连续两次快速按下按钮并且松开。
④拖动:保持按下按钮,并且移动鼠标。

2.客户区鼠标消息

2.0 介绍:与键盘不同的是键盘只会把消息发送到具有指定焦点的窗口上。但是鼠标不同,当鼠标被单击或者经过窗口时,即使该窗口是非活动窗口或不带输入焦点,窗口过程依然会处理鼠标消息。
Windows 定义了21种鼠标消息。但是其中11种消息与客户区无关,称为"非客户区消息"。Windows应用程序经常忽略这类消息。
2.1 客户区鼠标消息:

按钮 按下 释放 第二次按下按钮
左键 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK
中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK
右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK

注意:只有当窗口定义成了接受鼠标消息时,窗口过程才能处理DBLICK。
对于所有的客户区消息来说:
参数LParam:包含了鼠标的位置信息。LOWORD(LParam):低位字表示x坐标,HIWORD(LParam)表示y坐标。
参数wParam:表示鼠标按钮、SHIFT键和CTRL键的状态。在WinUser.h头文件中定义了位掩码来测试参数wParam。前缀MK_代表"鼠标键"(Mouse Key).

/*
 * Key State Masks for Mouse Messages
 */
#define MK_LBUTTON          0x0001
#define MK_RBUTTON          0x0002
#define MK_SHIFT            0x0004
#define MK_CONTROL          0x0008
#define MK_MBUTTON          0x0010
#if(_WIN32_WINNT >= 0x0500)
#define MK_XBUTTON1         0x0020
#define MK_XBUTTON2         0x0040
#endif /* _WIN32_WINNT >= 0x0500 */

例如可以这样使用判断当出现WM_LBUTTONDOWN消息时,是否同时按下SHIFT键:

case WM_LBUTTONDOWN:
	{
	if(wParam & MK_SHIFT)
			// Do Something...
		    MessageBox(hWnd, TEXT("鼠标左键 + SHIFT键 "), TEXT("提示"), MB_OK);
		break;
	}

Windows规定:如果在非活动窗口内按下鼠标左键,Windows会将这个窗口变成活动窗口。并且向该窗口发送WM_LBUTTONDOWN消息。窗口过程再收到WM_LBUTTONDOWN消息时,就能保证安全的保证该窗口是活动窗口。另外即使窗口没有WM_LBUTTONDOWN消息时,也能够处理WM_LBUTTONUP消息。
下面是一个简单例子:

#include <windows.h>

#define MAXPOINTS 1000

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("Connect") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Connect-the-Points Mouse Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT pt[MAXPOINTS] ;
     static int   iCount ;
     HDC          hdc ;
     int          i, j ;
     PAINTSTRUCT  ps ;

     switch (message)
     {
     case WM_LBUTTONDOWN:
          iCount = 0 ;
          InvalidateRect (hwnd, NULL, TRUE) ;
          return 0 ;
          
     case WM_MOUSEMOVE:
          if (wParam & MK_LBUTTON && iCount < 1000)
          {
               pt[iCount  ].x = LOWORD (lParam) ;
               pt[iCount++].y = HIWORD (lParam) ;
               
               hdc = GetDC (hwnd) ;
               SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0) ;
               ReleaseDC (hwnd, hdc) ;
          }
          return 0 ;
          
     case WM_LBUTTONUP:
          InvalidateRect (hwnd, NULL, FALSE) ;
          return 0 ;
          
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          
          SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          ShowCursor (TRUE) ;
          
          for (i = 0 ; i < iCount - 1 ; i++)
               for (j = i + 1 ; j < iCount ; j++)
               {
                    MoveToEx (hdc, pt[i].x, pt[i].y, NULL) ;
                    LineTo   (hdc, pt[j].x, pt[j].y) ;
               }
               
          ShowCursor (FALSE) ;
          SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
               
          EndPaint (hwnd, &ps) ;
          return 0 ;
               
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

2.2 处理Shift键:
在上面的程序中在处理WM_MOUSEMOVE消息时有如下处理: if (wParam & MK_LBUTTON && iCount < 1000)判断是否按下鼠标左键。如果在处理鼠标消息时,需要用判断Shift键和Ctrl键的状态时,可以这样处理:

	if(wParam & MK_SHIFT)
	{
		if (wParam & MK_CONTROL)
		{
			 // 按下Shift + Ctrl 键
			MessageBeep(0);
			MessageBox(hWnd,TEXT("Ctrl+Shift 键被按下"),TEXT("提示"),MB_OK);
		}
		else if (wParam & MK_SHIFT)
		{
			 // 按下Shift键
			MessageBeep(0);
			MessageBox(hWnd, TEXT("Shift 键被按下"), TEXT("提示"), MB_OK);
		}
	}
	else 
	{
		if (wParam & MK_CONTROL)
		{
			MessageBox(hWnd, TEXT("Ctrl 键被按下"), TEXT("提示"), MB_OK);
		}
		else
		{
			MessageBox(hWnd, TEXT("Ctrl 和 shift键都没有被按下"), TEXT("提示"), MB_OK);
	    }
	}

利用虚拟键VK_LBUTTON、VK_RBUTTON、VK_MBUTTON、VK_SHIFT、VK_CONTROL和GetKeyState()函数也能够返回鼠标按钮的状态。

2.3 鼠标双击:
要做到鼠标双击需要达到两个条件:
①物理位置上十分靠近。
②必须发生在特定的时间间隔内。(双击速度)
前面提到窗口过程要处理鼠标双击消息时,窗口类需要包含CS_DBLCLKS风格:

ws.style = CS_HREDRAW | CS_VREDRAW| CS_DBLCLKS;

如果窗口过程没有包含CS_DBLCLKS风格,则窗口过程处理鼠标双击消息顺序如下:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP
可以使用GetMessageTime函数来获取WM_LBUTTONDOWN消息之间的时间间隔。

包含CS_DBLCLKS风格时,处理顺序如下:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP

3.非客户区鼠标消息

到目前为止我们说的10种鼠标消息都是发生在窗口客户区内的移动或者单击。如果鼠标位于窗口客户区以外的区域,鼠标就会产生非客户区消息。窗口的非封闭区域包括其边框、菜单栏、标题栏、滚动条、窗口菜单、最小化按钮和最大化按钮。具体可以参考微软官方文档鼠标输入

系统一般不需要用户处理非客户区消息。只需要将消息发送给DefWindowProc函数,由系统来处理。这与键盘中的WM_SYSKEYDOWN、WM_SYSKEYUP、WM_CHAR等消息相似。非客户区消息与客户区消息基本上是对应的。表识符包含了"NC"字样,表示"非客户"(NonClient).
非客户区消息如下:

按钮 按下 释放 第二次按下按钮
左键 WM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
中键 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
右键 WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

非客户区消息的wParam参数与客户区的有一些不同。wParam参数表示非客户区鼠标移动或者单击的位置。它的值被设定成表示一个HT为首的标识符,其中HT表示"击中测试"。
LParam则相同都是表示坐标。

3.1 击中测试消息
我们来学习最后一个鼠标消息叫做WM_NCHITTEST。这个消息的优先级高于其他所有的客户区和非客户区消息。Windows 应用程序通常会把这个消息发送给DefWindowProc函数,然后系统利用WM_NCHITTEST产生其他所有和鼠标位置有关的消息。DefWindowProc函数返回一个可用于鼠标参数的wParam值。这个值可以是任何非客户区消息的wParam值。也可以是如下的值。
HTBORDER
18
在没有大小调整边框的窗口的边框中。
HTBOTTOM
15
在可调整大小的窗口的下水平边框 (用户可以单击鼠标以垂直调整窗口大小) 。
HTBOTTOMLEFT
16
在可调整大小的窗口边框的左下角, (用户可以单击鼠标以) 对角线调整窗口大小。
HTBOTTOMRIGHT
17
在可调整大小的窗口边框的右下角 (用户可以单击鼠标以) 对角线调整窗口大小。
HTCAPTION
2
在标题栏中。
HTCLIENT
1
在工作区中。
HTCLOSE
20
在 “关闭 ”按钮中。
HTERROR
-2
在屏幕背景或窗口之间的分隔线上, (与 HTNOWHERE 相同,只不过 DefWindowProc 函数会发出系统蜂鸣声以指示) 错误。
HTGROWBOX
4
在大小框中, (与 HTSIZE) 相同。
HTHELP
21
在 “帮助 ”按钮中。
HTHSCROLL
6
在水平滚动条中。
HTLEFT
10
在可调整大小的窗口的左边框 (用户可以单击鼠标以水平调整窗口大小) 。
HTMENU
5
在菜单中。
HTMAXBUTTON
9
在 “最大化 ”按钮中。
HTMINBUTTON
8
在 “最小化 ”按钮中。
HTNOWHERE
0
在屏幕背景上或窗口之间的分隔线上。
HTREDUCE
8
在 “最小化 ”按钮中。
HTRIGHT
11
在可调整大小的窗口的右边框 (用户可以单击鼠标以水平调整窗口大小) 。
HTSIZE
4
在大小框中 (与 HTGROWBOX) 相同。
HTSYSMENU
3
在窗口菜单或子窗口的 “关闭 ”按钮中。
HTTOP
12
在窗口的上水平边框中。
HTTOPLEFT
13
在窗口边框的左上角。
HTTOPRIGHT
14
在窗口边框的右上角。
HTTRANSPARENT
-1
在同一线程 (当前由另一个窗口覆盖的窗口中,消息将发送到同一线程中的基础窗口,直到其中一个窗口返回不是 HTTRANSPARENT) 的代码。
HTVSCROLL
7
在垂直滚动条中。
HTZOOM
9
在 “最大化 ”按钮中。

欢迎大家一起学习和交流。文章来源地址https://www.toymoban.com/news/detail-834205.html

到了这里,关于Windows 程序设计--- 鼠标(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何设计WIndows系统下的单例进程程序?

    为了设计一个Windows系统下的单例进程程序,你可以遵循以下步骤: 首先,确定你的应用程序只能运行一个实例。这可以通过使用互斥量(Mutex)来实现。互斥量是一种同步对象,用于控制对共享资源的独占访问。 在应用程序的启动代码中,创建一个命名的互斥量对象。命名

    2024年01月22日
    浏览(48)
  • 【windows程序设计作业】用c#语言实现记事本

    使用Visual C# 2015设计一个Windows应用程序——记事本,通过本章的学习,可以进一步掌握MenuStrip(菜单)、ToolStrip(工具栏)、RichTextBox(高级文本框)和StatusStrip(状态栏控件)等控件的使用,以及如何使用CommonDialog(公共对话框)实现对文本的存取、格式设置等操作。 实现

    2024年02月05日
    浏览(63)
  • [渝粤教育] 中国地质大学 Windows程序设计 复习题

    《Windows程序设计》模拟题 一单选题 1.所有的Windows应用程序都是由()驱动的. A.事件 B.消息 C.命令 D.菜单 2.一般应用程序不会派生自己的()类. A.主框架 B.视图 C.菜单 D.文档 3.MessageBox不能完成()功能. A.接收用户输入 B.显示消息 C.改变对话框标题 D.显示问号图标 4.Windows系统中的消

    2024年02月05日
    浏览(41)
  • MFC Windows 程序设计[332]之十进制转十六进制编辑框(附源码)

    MFC是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。 有很多初学MFC的小伙伴们都觉得MFC比较难学,看书吧,看

    2024年02月08日
    浏览(59)
  • 操作系统原理及安全 3-并发程序设计(综合型)

    实验目的 1、熟悉并发程序实验工具BACI。 2、掌握BACC和BAINTERP的使用。 3、熟悉信号量的同步控制机制。 二、实验软硬件要求    1、CPU:P4 1.6GHz   内存:4G   2、Windows平台上的Linux虚拟机 实验内容 (1)完成Linux系统的登录,启动进入终端。 编程步骤:   cd baci/balnxxe  

    2024年02月06日
    浏览(59)
  • Java程序设计——鼠标监视器

     

    2024年02月12日
    浏览(43)
  • 全量知识系统 程序详细设计之“ AI操作系统” (百度搜索的Q&A)

    Q1. 今天讨论的题目是:全量知识系统 程序详细设计之“ AI操作系统”..本篇是基于前面的文章给出的系统核心(一个恰当的组织)之上的一个扩展,并在此基础上给出整个全量知识系统 (以下简称“全知系统”)程序详细设计大纲 全量知识系统(全知系统)程序详细设计大

    2024年04月09日
    浏览(75)
  • C#Windows窗体设计之ContextMenuStrip(鼠标右击菜单)的用法

    摘要:Winform开发进阶之ContextMenuStrip,以自身开发经验讲解ContextMenuStrip的具体用法。 编程语言:C# 编程环境:Visual Studio 2019         有没有人跟小编一样,想给控件加入鼠标右击菜单,但点到属性框发现......         Oh我的天,这居然是无,那到底要怎样添加鼠标右击

    2024年02月09日
    浏览(43)
  • 关于Windows 7操作系统进行磁盘碎片整理时提示“已使用其他程序计划了磁盘碎片整理程序”的解决办法

    一位网友的Windows 7电脑近期启动缓慢,估计是系统盘磁盘碎片太多引起的,于是想对系统盘进行磁盘碎片整理,但在操作时却得到提示: 已使用其他程序计划了磁盘碎片整理程序 磁盘碎片整理程序当前正在使用由其它程序创建的自定义设置。您必须先删除这些自定义设置,

    2024年02月05日
    浏览(41)
  • 微软操作系统中,windows server 系列和windows 的区别

    Windows Server和Windows Desktop(即我们常说的Windows系统)是Microsoft公司的两种操作系统产品,它们都基于Windows NT内核。两者在设计目标、功能和价格等方面存在显著的区别。 设计目标与功能 Windows Desktop系统主要针对个人用户和企业的端点用户,以满足日常办公、娱乐、浏览网页

    2024年02月13日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包