Windows SDK(四)鼠标和键盘消息处理

鼠标基础知识

鼠标一般分为三种状态,三个按钮

三种状态:单击,双击,拖动

三个按钮:左键(LBUTTON),右键(RBUTTON),中键(MBUTTON)

左键具有的消息

WM_LBUTTONDOWM 点击鼠标

WM_LBUTTONUP 抬起鼠标

WM_LBUTTONDBLCLK 双击鼠标,有时窗的不支持

右键具有的消息

WM_RBUTTONDOWM

WM_RBUTTONUP

WM_RBUTTONDBLCLK(双击,有时窗口不支持)

中键具有的消息

WM_MBUTTONDOWM

WM_MBUTTONUP

WM_MBUTTONDBLCLK(双击,有时窗口不支持)

直接通过messsage进行分发的消息一般是WM开头,也叫顶层消息,如上消息都是顶层消息

lParam,32位大小,低16位存储x坐标,高16位存储y坐标,用于存储鼠标目前的坐标信息

wParam,32位大小,用于存储系统键盘或鼠标输入的消息

键盘基础知识

顶级窗口:存在多个窗口时,在最上面的窗口

焦点:鼠标点击窗口后,只有该窗口可以被执行各种操作,如键盘发送的消息只会发送到有焦点的

窗口,鼠标点击处叫做焦点

键盘消息的发送:点击键盘时,系统将对应的硬件扫描码格式化成消息,发送到操作系统的消息队

列中,由操作系统进行消息的初步存储,当应用完成上一次消息的处理后,系统将会从消息队列中

抽取消息分发到应用程序进行翻译处理

我们可以自行操作的键盘消息有四种,可以分为以下两种类型:

非系统按键:

WM_KEYDOWN:按键按下去的消息

WM_KEYUP:按键抬起来的消息

当按键按下去不放时,系统认为有很多个按下去的消息发送给操作系统,但此时抬起来时,只会有

一次抬起来的消息发送给操作系统

GetMessageTime:获取上次消息时间

系统按键:

WM_SYSKEYDOWN

WM_SYSKEYUP

如ALT+TAB:页面切换,ALT+F4:关闭窗口,诸如此类ALT按键+,都属于系统按键

如果使用系统按键,应用程序会跳过安全消息,直接把该消息交给默认处理程序:

DefWindowProc进行转发,由Windows进行默认处理,应用程序不对该消息进行处理

每个按键都有相应的虚拟键码对应,用于表示按键动作

wParam 可以与鼠标或键盘的输入的状态作为参数结合,用于判断是否同时多种行为同时进行,这

些参数如下显示,都是以MK_ 前缀:

MK_LBUTTON : 左键按下

MK_MBUTTON : 中键按下

MK_RBUTTON: 右键按下

MK_SHIFT : Shift键按下

MK_CONTROL : Ctrl键按下

应用如下:在点击鼠标左键时

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN 用于接收系统鼠标消息,此处左键按下

    {

       if(wParam & MK_SHIFT) 指在左键点击的前提下,shift键按下

       {

           MessageBox(NULL, L"MK_SHIFT + LBUTTON", L"Msg", MB_OK);

       }

       break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

获取窗口句柄的两种方式:

方式一,用类名寻找窗口:

HWND hMyHWnd = FindWindow(L"rkvir", NULL);  参数依次 窗口类名 标题名,

返回值是窗口句柄

方式二,用标题名寻找窗口:

HWND hMyHWnd = FindWindow(NULL, L"GrkDemo");

鼠标点击画点

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN: 用于接收系统鼠标消息,此处左键按下

    {

        int nPosX = LOWORD(lParam);

       int nPosY = HIWORD(lParam); 获取鼠标点击处的xy坐标

       HWND hMyHWnd = FindWindow(NULL, L"GrkDemo");访问一个外部的窗口

       HDC hDC = GetDC(hMyHWnd); 获取窗口句柄

       HPEN hPen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0)); 创建一个画笔

       SelectObject(hDC, hPen); 选择画笔

       POINT pi = { 0 };画笔位置初始化

       MoveToEx(hDC, nPosX, nPosY, &pi);

       LineTo(hDC, nPosX, nPosY); 原地画一个点

       ReleaseDC(hMyHWnd, hDC); 释放设备上下文

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

鼠标点击划线

鼠标点击某处,再移动到其他处,松开鼠标,出现一条线

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN: 用于接收系统鼠标消息,此处左键按下

    {

       Pos[0].x = LOWORD(lParam);

       Pos[0].y = HIWORD(lParam); 保存第一个点xy坐标

        break;

    }

case WM_LBUTTONUP: 鼠标抬起时绘制

    {

       Pos[1].x = LOWORD(lParam);

       Pos[1].y = HIWORD(lParam); 保存第二个点

       HWND hMyHWnd = FindWindow(NULL, L"GrkDemo"); 此处是在一起其他的窗口处

       HDC hDC = GetDC(hMyHWnd);

       HPEN hPen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));

       SelectObject(hDC, hPen);

       POINT pi = { 0 };

       MoveToEx(hDC, Pos[0].x, Pos[0].y, &pi); 画笔移至起始位置

       LineTo(hDC, Pos[1].x, Pos[1].y); 画笔移至结束位置

        break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

鼠标点击画矩形

鼠标点击某处,再移动到其他点,松开鼠标,出现一个矩形

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM

lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN: 用于接收系统鼠标消息,此处左键按下

    {

       Pos[0].x = LOWORD(lParam);

       Pos[0].y = HIWORD(lParam); 保存第一个点xy坐标

        break;

    }

case WM_LBUTTONUP: 鼠标抬起时绘制

    {

        Pos[1].x = LOWORD(lParam);

       Pos[1].y = HIWORD(lParam); 保存第二个点

       HWND hMyHWnd = FindWindow(NULL, L"GrkDemo");

       HDC hDC = GetDC(hMyHWnd);

       HPEN hPen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));

       SelectObject(hDC, hPen);

       Rectangle(hDC, Pos[0].x, Pos[0].y, Pos[1].x, Pos[1].y);

        break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

鼠标点击画圆

鼠标点击某处,再移动到其他点,松开鼠标,出现一个圆

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM

lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN: 用于接收系统鼠标消息,此处左键按下

    {

       Pos[0].x = LOWORD(lParam);

       Pos[0].y = HIWORD(lParam); 保存第一个点xy坐标

        break;

    }

case WM_LBUTTONUP: 鼠标抬起时绘制

    {

        Pos[1].x = LOWORD(lParam);

       Pos[1].y = HIWORD(lParam); 保存第二个点

       HWND hMyHWnd = FindWindow(NULL, L"GrkDemo");

       HDC hDC = GetDC(hMyHWnd);

       HPEN hPen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));

       SelectObject(hDC, hPen);

       Arc(hDC, Pos[0].x, Pos[0].y, Pos[1].x, Pos[1].y, 350, 350, 350, 350);

       ReleaseDC(hMyHWnd, hDC);

       break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

鼠标点击移动画圆

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM

lParam)

{

    switch (message)

    {

    case WM_LBUTTONDOWN: 用于接收系统鼠标消息,此处左键按下

    {

       Pos[0].x = LOWORD(lParam);

       Pos[0].y = HIWORD(lParam); 保存第一个点xy坐标

        break;

    }

case WM_MOUSEMOVE: 鼠标滑动

    {

       if (wParam & WM_LBUTTONDOWN) 滑动的同时按住左键

       {

           int nPosX = LOWORD(lParam);

           int nPosY = HIWORD(lParam);

           HWND hMyHWnd = FindWindow(NULL, L"GrkDemo");

           HDC hDC = GetDC(hMyHWnd);

           HPEN hPen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));

           SelectObject(hDC, hPen);

           POINT pi = { 0 };

           MoveToEx(hDC, nPosX, nPosY, &pi);

           LineTo(hDC, nPosX, nPosY);

           ReleaseDC(hMyHWnd, hDC);

       }      

       break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

键盘的应用

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_KEYDOWN 用于接收系统键盘消息

    {

       switch (wParam) 传入按键信息

       {组合键

       case VK_F1: 按下按键F1

       {       

           SHORT bFlag = (getKeyState(VK_SHIFT) & 0x8000); 判断是否同时按下shift键,此处加上&0x8000,可以屏蔽其他无关状态

           if(bFlag < 0) 如果获取短整数小于0,说明shift键被按到

           {

                MessageBox(NULL, L"F1 + SHIFT", L"Msg", MB_OK); 生成一个窗口

           }

           else

           {

                 ​​​​​​​MessageBox(NULL, L"F1", L"Msg", MB_OK); 生成一个窗口

           }  

           break;

       }

       case VK_F2: 按下F2,如果想要触发按下F1的消息:

       {

           SendMessage(hWnd, WM_KEYDOWN, VK_F1, NULL); 发送消息到某窗口 参数依次 要发

送到的窗口的句柄 发送的消息 两个附加消息,如主消息的内部各种选择,一般写NULL。该函数不

仅可以发送给自己的窗口,也可以是别的窗口,此处是发送给别的窗口。此时窗口按下F2,会触

发按下F1的指令

            SendMessage(hWnd, 0x12138, 9999, NULL); 按下F2,触发0x12138的指令

            break;

       }

       case 'B':

       case 'b': 该方式可以设置按到两种不同按键时,都可以同一种操作

       {

           MessageBox(NULL, L"B/b", L"Msg", MB_OK); 生成一个窗口

           break;

       }

    case 0x12138: 接收一个自定义消息

    {

       switch (wParam)

       {

       case 9999:

       {

           MessageBox(NULL, L"MyMsg", L"Msg", MB_OK);

           break;

       }

       }

       break;

    }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

按钮绘制

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_PAINT:

        {

            PAINTSTRUCT ps; 创建一个包含窗口信息的结构体

            HDC hdc = BeginPaint(hWnd, &ps);

           HFONT hFont = CreateFont(20, 10, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, L"宋体"); 创建一个字体

           SelectObject(hdc, hFont); 选择应用该字体

           SetBkMode(hdc, TRANSPARENT); 设置背景色

           RECT rect; 获取位置

           SetRect(&rect, 30, 50, 400, 200);设置x30y50位置

           SetTextColor(hdc, RGB(0, 0, 255)); 设置字体颜色

           DrawText(hdc, L"蓝色", -1, &rect, DT_NOCLIP); 输出字体

           SetRect(&rect, 30, 100, 400, 200);

           SetTextColor(hdc, RGB(255, 0, 0));

           DrawText(hdc, L"红色", -1, &rect, DT_NOCLIP);

           HBRUSH hSolidBrushBlue = CreateSolidBrush(RGB(0, 0, 255));创建实心画刷

           SelectObject(hdc, hSolidBrushBlue); 选择画刷

           Rectangle(hdc, 90, 50, 120, 80); 绘制矩形

           HBRUSH hSolidBrushRed = CreateSolidBrush(RGB(255, 0, 0));

           SelectObject(hdc, hSolidBrushRed);

           Rectangle(hdc, 90, 100, 120, 130);

           EndPaint(hWnd, &ps);

           break;

      }

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665767.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机视觉】目标检测 |滑动窗口算法、YOLO、RCNN系列算法

一、概述 首先通过前面对计算机视觉领域中的卷积神经网络进行了解和学习&#xff0c;我们知道&#xff0c;可以通过卷积神经网络对图像进行分类。 如果还想继续深入&#xff0c;会涉及到目标定位(object location)的问题。在图像分类的基础上(Image classification)的基础上…

JAVA中的多态参数

1.方法定义的参数类型为父类类型&#xff0c;实参类型允许为子类类型 public class Ploy_parameter {public static void main(String[] args) {Manage jack new Manage("jack",12000,3000);Staff tom new Staff("tom",10000);Ploy_parameter ploy_para…

【Linux系统化学习】进程等待

目录 进程等待 进程等待的必要性 进程等待的方法 wait方法 等待一个进程(阻塞等待&#xff09; waitpid方法 任意等待多个进程&#xff08;阻塞等待&#xff09; 父进程获取子进程的退出信息 非阻塞轮询等待 进程等待 进程等待的必要性 之前讲过&#xff0c;子进程退…

javascript设计模式之建造者

工厂模式不关心过程&#xff0c;只关心结果&#xff0c;这与建造者相反&#xff0c;建造者更关心的是过程&#xff0c; 这里我们创建一个基类&#xff0c;其拥有技能跟爱好两个属性&#xff0c;还有两个实例方法用来获取技能跟爱好 // 基类 let Human function (param {}) …

【深入浅出Java性能调优】「底层技术原理体系」详细分析探索Java服务器性能监控Metrics框架的实现原理分析(Dropwizard度量基础案例指南)

深入探索Java服务器性能监控Metrics框架的实现原理分析 前提介绍Dropwizard MetricsDropwizard的特点Dropwizard的开发案例需要引入Maven依赖常用度量类型Meter(每秒请求数为单位测量请求率)定义度量核心MetricRegistry构建对应的Meter指标对象请求标记采样业务方法控制报告器…

chisel 语法

// TODO: find out the new way to have a reset signal class KnightRider(resetSignal: Bool null, frequ: Int)//extends Module(_reset resetSignal) {extends Module {val io IO(new Bundle {val led Output(Bits(6.W))})//定义了一个枚举类型&#xff0c;包含两个状态…

使用Python将Excel数据导入Word并设置字体样式(成功)

在日常办公和数据处理中&#xff0c;我们经常需要将Excel中的数据导入到Word文档中。手动完成这个过程可能既费时又容易出错。本文将介绍如何使用Python自动化这一任务&#xff0c;同时根据数据的不同设置不同的字体样式和大小。 所需工具 Python&#xff1a;一种广泛使用的高…

kafka自定义分区策略详解

文章目录 前言一、kafka是什么&#xff1f;二、kafka的分区策略三、自定义的 Kafka 分区器实现总结 前言 在分布式消息系统中&#xff0c;正确地将消息发送到合适的分区是至关重要的。Kafka 作为一种高性能、可扩展的消息队列系统&#xff0c;在处理海量数据和高并发场景下表现…

三、05 ansible基础命令ansible 常用命令

这里写目录标题 命令介绍ansible 的基础语法实力 使用一个copy 模块 Ansible 模块功能查看工具ansible-doc的全部用法&#xff1a;mysql 实例 命令介绍 /usr/bin/ansible  (常用) Ansibe AD-Hoc 临时命令执行工具&#xff0c;常用于临时命令的执行 /usr/bin/ansible-playbo…

【Linux Day15 TCP网络通讯】

TCP网络通讯 TCP编程流程 接口介绍 socket()方法是用来创建一个套接字&#xff0c;有了套接字就可以通过网络进行数据的收发。创建套接字时要指定使用的服务类型&#xff0c;使用 TCP 协议选择流式服务&#xff08;SOCK_STREAM&#xff09;。 **bind()方法是用来指定套接字使…

Quppy wise 注册教程,轻松通过欧洲银行同名转账绑定个人IBAN账号

Quppy 注册教程,轻松通过欧洲银行同名转账绑定个人IBAN账号 官网下载APP或者去香港区下载APP使用, 按照官方APP里的邮箱注册就行&#xff0c;成功后添加电话和个人信息&#xff1b;需要说明的是&#xff1a;网站所填内容请全部用真实身份填写&#xff1b;名在前&#xff0c;姓…

蓝桥杯每日一题-----数位dp

前言 今天浅谈一下数位dp的板子&#xff0c;我最初接触到数位dp的时候&#xff0c;感觉数位dp老难了&#xff0c;一直不敢写&#xff0c;最近重新看了一些数位dp&#xff0c;发现没有想象中那么难&#xff0c;把板子搞会了&#xff0c;变通也会变的灵活的多&#xff01; 引入…

六、java函数

文章目录 java函数1.1 什么是函数1.2 进一步理解函数1.2.1 参数传递1.2.2 理解返回 java函数 本文为书籍《Java编程的逻辑》1和《剑指Java&#xff1a;核心原理与应用实践》2阅读笔记 在编写代码过程中&#xff0c;如果需要经常做某一种操作&#xff0c;则类似的代码需要重复…

列式数据库、行式数据库简介

列式数据库、行式数据库简介 1、数据准备2、行式数据库3、列式数据库4、行式、列式存储对比 常见的行式数据库有Mysql&#xff0c;DB2&#xff0c;Oracle&#xff0c;Sql-server等&#xff1b;列数据库&#xff08;Column-Based&#xff09;数据存储方式按列存储&#xff0c;常…

2024/1/30 dfs与bfs

想要了解dfs与bfs&#xff0c;就得了解队列和栈。 一、栈与队列 1.栈 栈说白了就是先入后出。把栈类比为一个容器。只有一个口&#xff0c;所以如果我们想要取出最底层也就是最先放入的元素&#xff0c;只能最后取出它。 栈基础操作有如下几种&#xff1a; push 放入pop 拿…

python 爬虫安装http请求库

我的是window环境&#xff0c;安装的python3&#xff0c;如果再linux环境&#xff1a;pip install requests 开始&#xff1a; 上面我们成功发送请求并获取到响应&#xff0c;现在需要解析html或xml获取数据&#xff0c;因此我使用现成的工具库Beautiful Soup

leetcode刷题(剑指offer) 297.二叉树的序列化和反序列化

297.二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。 请设计一个算法来实现…

图论练习3

内容&#xff1a;过程中视条件改变边权&#xff0c;利用树状数组区间加处理 卯酉东海道 题目链接 题目大意 个点&#xff0c;条有向边&#xff0c;每条边有颜色和费用总共有种颜色若当前颜色与要走的边颜色相同&#xff0c;则花费为若当前颜色与要走的边颜色不同&#xff0c;…

shell脚本中的变量,运算符

1.脚本格式 我们一般将shell脚本写在xxx.sh文件中&#xff0c;执行的时候bash/sh xxx.sh 注意文件路径 xxx.sh文件中的第一行为 #!/usr/bin/bash 注代表我们使用的是bin文件夹下的bash解释器(此条为注释语句&#xff0c;不写也可以) 2.echo用法 相当与print 示例1&…

ASP.NET Core 自定义解压缩提供程序

写在前面 在了解ASP.NET Core 自定义请求解压缩中间件的应用时&#xff0c;依据官方文档操作下来碰到了几个问题&#xff0c;这边做个记录。 关键点就是配置 Content-Encoding&#xff0c;参数需要和代码中添加的提供程序的Key保持一致&#xff1b; builder.Services.AddRequ…