深入了解鼠标光标的设置过程
有一位读者问了这样一个问题:
“为什么鼠标光标的设定绑定在窗口类,而不是窗口上?”
这个问题隐含地假设了光标与窗口类相关联。虽然每个窗口类都有一个关联的光标,但决定使用哪个光标的是窗口。
光标设置过程在 WM_SETCURSOR 消息的文档中进行了描述,请看如下:
===================================
DefWindowProc 函数在处理 WM_SETCURSOR 消息之前,会将其传递到父窗口。如果父窗口返回 TRUE,则停止进一步处理。将消息传递到窗口的父窗口可使父窗口控制子窗口中光标的设置。DefWindowProc 函数还使用此消息将光标设置为箭头(如果它不在工作区中)或已注册的窗口类的光标(如果它位于工作区中)。
===================================
以上文档几乎涵盖了整个光标的设置过程。从现在开始,我所写的只是重述这几句话。
WM_SETCURSOR 会传递到光标下方的子窗口。(显然,它转到子窗口而不是父窗口,因为文档说 DefWindowProc 将消息转发到其父窗口。 如果消息最初发送给父窗口,则没有人可以将消息转发到!) 此时,窗口过程可以捕获 WM_SETCURSOR 消息,设置光标并返回 TRUE。因此,窗口在决定光标是什么时具有第一优先级。
如果窗口不处理 WM_SETCURSOR 消息,则 DefWindowProc 会将消息转发给父级,父级又可以决定是处理该消息还是依次转发到其父级。一种可能性是,其中一个祖先窗口将处理消息、设置光标并返回 TRUE。在这种情况下,TRUE 返回值告诉 DefWindowProc 光标已设置,无需再执行任何工作。
另一种更有可能的可能性是,没有一个祖先窗口关心设置光标。每次返回到 DefWindowProc 时,光标将设置为窗口类中关联的光标。
下图描述了整个过程。
假设我们有三个窗口,A、B 和 C,其中 A 是顶层窗口,B 是子窗口,C 是孙窗口,它们在 WM_SETCURSOR 中都没有做任何特别的事情。进一步假设鼠标位于窗口 C 上:
>> 请移步至 topomel.com 以查看图片 <<
请注意观察,WM_SETCURSOR 从底部(窗口 C)开始,向上冒泡到顶部(窗口 A),然后向下移动到窗口 C。在向上时,它会询问每个窗口是否要设置光标,如果它一直到顶部,没有人发表意见,那么在向下时,每个窗口都会将光标设置为 C 类光标。
现在,当然,沿途的任何窗口都可以决定“我正在设置光标!”并返回 TRUE,在这种情况下,消息处理将立即停止。
所以你看,窗口确实决定了光标是什么。是的,有一个与该类关联的游标,但仅当窗口决定使用它时才使用它。如果要将光标与窗口关联,可以通过显式处理WM_SETCURSOR 消息来实现,而不是让 DefWindowProc 默认为类光标。
这位读者提出了另外一个问题:”许多程序在每个 WM_MOUSEMOVE 调用 SetCursor。这合理吗?”
虽然没有规则禁止在 WM_MOUSEMOVE 消息中设置光标,但这会导致一些问题。
首先,不那么严重的后果是,你将无法参与 WM_SETCURSOR 谈判,因为你没有在那里进行光标设置。
但真正的问题是,你会得到一个光标闪烁。WM_SETCURSOR 将被发送到你的窗口以确定光标。由于你没有执行任何操作,因此它可能会变成窗口类光标。然后你得到你的WM_MOUSEMOVE 并再次设置光标。
结果:每次用户移动鼠标时,光标都会变为类光标,然后变为默认光标。
让我们看看实际的效果,从我们的例子程序开始,并进行以下更改:
>> 请移步至 topomel.com 以查看图片 <<
运行程序并将鼠标移到工作区上。请注意,它在箭头(类光标,在 WM_SETCURSOR 期间设置)和十字光标(在 WM_MOUSEMOVE 期间设置)之间闪烁。
总结
新技能 GET: 在正确的位置设置你的鼠标光标,这个正确的位置是:WM_SETCURSOR 消息的处理函数中。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《What is the process by which the cursor gets set?》

相关文章:
深入了解鼠标光标的设置过程
有一位读者问了这样一个问题: “为什么鼠标光标的设定绑定在窗口类,而不是窗口上?” 这个问题隐含地假设了光标与窗口类相关联。虽然每个窗口类都有一个关联的光标,但决定使用哪个光标的是窗口。 光标设置过程在 WM_SETCURSOR 消…...
数据结构-散列表
列表(Hash Table),又称哈希表,是一种数据结构,特点是:数据元素的关键字与其存储地址直接相关 例:有一堆数据元素,关键字分别为{19,14,23ÿ…...
一款IT团队都在用的私有化知识库,技术开放,还开源了!
IT和软件开发团队需要处理大量的技术文档和知识,通过建立内部知识库,可以将技术文档、代码示例、最佳实践等知识整理和归档起来,方便团队成员查找和参考。 IT和软件开发团队为什么要建立内部知识库? 提高知识管理效率:…...
解决 docker compose 官方 MySQL 镜像在容器中不能输入中文的问题
该问题可以通过添加环境变量解决,途径如下: 一、如果容器没条件或不允许重启,可通过命令行方式临时解决。 docker compose exec SERVICE-NAME env LANGC.UTF-8 mysql -u username -p 二、修改 docker-compose.yml 配置文件一劳永逸 envir…...
基于连续Hopfield神经网络优化——旅行商问题优化计算
大家好,我是带我去滑雪! 利用神经网络解决组合优化问题是神经网络应用的一个重要方面。所谓组合优化问题,就是在给定约束条件下,使目标函数极小(或极大)的变量组合问题。将Hopfield网络应用于求解组合优化问…...
SpringBoot整合Activiti7——定时器事件(九)
文章目录 定时器事件时间定义时间固定时间段时间周期 1.开始事件2.中间事件3.边界事件代码实现xml文件自定义服务任务监听器自定义用户任务监听器测试流程流程执行步骤 定时器事件 可以用在开始事件、中间事件、边界事件上,边界事件可以是中断和非中断边界事件 需要…...
轻量封装WebGPU渲染系统示例<29>- 深度模糊DepthBlur(源码)
实现方式: step1. 通过mrt机制,输出颜色和深度相关数据的两张rtt纹理。 step2. 基于上述颜色纹理,生成一张模糊之后的新rtt纹理。 setp3. 基于深度(也就是距离摄像机的远近)数据,合成颜色和模糊纹理数据,并最终输出。 当前示例…...
LeetCode226. Invert Binary Tree
文章目录 一、题目二、题解2.1 前序遍历版本2.2 中序遍历版本2.3 后序遍历版本 一、题目 Given the root of a binary tree, invert the tree, and return its root. Example 1: Input: root [4,2,7,1,3,6,9] Output: [4,7,2,9,6,3,1] Example 2: Input: root [2,1,3] Ou…...
Java设计模式-创建型模式-建造者模式
建造者模式 建造者模式案例与工厂模式的区别:Builder 注解 建造者模式 建造者模式是将一个复杂对象的构件与表示分离,使得同样的构件过程可以创建不同的表示。 建造者模式将内部构件的创建和组装分割开,一般使用链式编程,代码整洁…...
PyQt中QFrame窗口中的组件不显示的原因
文章目录 问题代码(例)原因和解决方法 问题代码(例) from PyQt5.QtWidgets import * from PyQt5.QtGui import QFont, QIcon, QCursor, QPixmap import sysclass FrameToplevel(QFrame):def __init__(self, parentNone):super().…...
git 命令行回退版本
git 命令行回退版本 git 命令行回退版本命令: 1.切换到需要回退的分支 git checkout branch-v2.0.02.更新远程分支 git fetch3.找到需要回退版本的版本号git revert a6914da55ff40a09e67ac2426b86f1212e6580eb4.清除工作区缓存git clean -df5.强制提交git push -f...
IntelliJ IDEA 安装 GitHub Copilot插件 (最新)
注意: GitHub Copilot 插件对IDEA最低版本要求是2021.2,建议直接用2023.3,一次到位反正后续要升级的。 各个版本的依赖关系,请参照: ##在线安装: 打开 IntelliJ IDEA扩展商店,输入 "Git…...
viewpage选择器
GitHub - hackware1993/MagicIndicator: A powerful, customizable and extensible ViewPager indicator framework. As the best alternative of ViewPagerIndicator, TabLayout and PagerSlidingTabStrip —— 强大、可定制、易扩展的 ViewPager 指示器框架。是ViewPagerIndi…...
vue中如何将json数组指定的key赋值给el-form-item并均匀的分成2列
在Vue中,你可以使用v-for指令来遍历JSON数组,并将指定的key赋值给el-form-item。下面是一个示例: <template><el-form><el-row><el-col :span"6" v-for"item in jsonArray" :key"item.key&qu…...
笔记本分屏怎么操作?3个方法提高工作效率!
“有朋友知道笔记本怎么才能实现分屏吗?我在工作时,经常需要来回切换屏幕,效率真的太低了,有什么方法可以实现两个屏幕同时使用吗?” 在现代生活中,多任务处理已成为常态,而笔记本分屏技术为用户…...
Android 使用poi生成Excel ,word并保存在指定路径内
一添加依赖(一定要用新版依赖防止一些bug) minSdk 26 //注意最小支持SDK26 dependencies {implementation org.apache.poi:poi:5.2.4implementation org.apache.poi:poi-ooxml:5.2.4implementation javax.xml.stream:stax-api:1.0-2 }二,创…...
嵌入式杂记 -- MCU的大小端模式
MCU的大小端模式 大端模式小端模式大小端模式测试联合体概念MCU大小端模式测试大端模式测试小端模式测试 大小端模式转换 在进行MCU开发的时候,我们需要注意MCU的数据存储模式,在嵌入式中有两种不同的存储模式,分别是 大端模式和小端模式。 …...
对这套BI零售数据分析方案心动,是零售人天性
零售数据分析做了这么多年,难道真的没累积点经验,摸索出一条又快又能满足绝大多数需求的数据分析捷径?别人不知道,奥威BI还真就有这么一套标准化的BI零售数据分析方案,不管是服装零售、医药连锁、商超都能利用这套方案…...
vuekeyclock 集成
前端集成keycloak鉴权的主要写法, 在main.js里面写 import VueKeycloakJs from dsb-norge/vue-keycloak-js import { KeycloakInstance } from "keycloak-js";// 回调地址 const pageIndex process.env.NODE_ENV production ? http://xxxx/#/ : http:…...
ARM Linux 基础学习 / 配置交叉编译工具链 / 编译 Linux 应用和驱动 / 编译内核
编辑整理 by Staok。 本文部分内容摘自 “100ask imx6ull” 开发板的配套资料(如 百问网的《嵌入式Linux应用开发完全手册》,在 百问网 imx6ull pro 开发板 页面 中的《2.1 100ASK_IMX6ULL_PRO:开发板资料》或《2.2 全系列Linux教程…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
