1、背景
在Windows系统中,有3种获取鼠标位移信息的方法:WM_MOUSEMOVE, WM_INPUT 和DirectInput。这3种方法中,WM_MOUSEMOVE获取的是鼠标当前在窗口上的绝对位置,通过它可以获取鼠标的屏幕位移;WM_INPUT和DirectInput获取的则是鼠标相对于上一个位置的相对位移,它们就是鼠标实际上的物理位移。事实上,WM_INPUT与DirectInput在获取鼠标位移信息上是等价的,这与他们的实现有关,本文不作讨论。下面的讨论中,我只会提及WM_INPUT。

物理位移与屏幕位移之间有一个转换公式,但是这个公式微软没有公开(或者是我没有找到)。本文第二、三节分别讨论物理位移和屏幕位移的一些细节,第四节要讨论这两者之间的转换关系以及我的一些研究结果。第五节是结论。

2、物理位移
物理位移就是鼠标实际上移动了多少个点,这里首先要介绍一下鼠标的一些概念。首先是鼠标的分辨率,鼠标分辨率单位是dpi,即每个英寸可以分辨多少个点。以400dpi的鼠标为例(以下都会使用这个参数的鼠标),理想情况下,用户每移动鼠标1/400英寸,鼠标硬件就可以检测到一个点的位移。第二是鼠标的扫描率,这个参数会影响鼠标的跳帧问题,不过这与我的讨论没有太大关系。在下面讨论中,我假设不存在跳帧问题。最后一个参数是数据更新频率,这是与鼠标接口和鼠标本身都有关的一个参数。例如USB1.1鼠标,数据更新频率是125Hz,PS/2的鼠标为100Hz,而USB2.0的鼠标频率更高。

鼠标数据每一次更新时包含一个数据包,这个包中包含了此次更新间隔中鼠标的每一个轴的位移,这个位移值为一个8bit整数,即每一个轴位移可以在-128到+127之间。

根据以上数据,我们可以计算出鼠标某个轴向的速度。

数据更新频率   
鼠标某个轴向速度Vmouse(单位 inch per second)=  ---------------------× 此轴位移    (1)
                                                                                                鼠标分辨率

对于400dpi的USB1.1鼠标,如果某一帧鼠标x轴变化3的话,则Vmouse=0.9375,大约是1英寸每秒

3、屏幕位移
我们实际看到屏幕上的鼠标指针移动为屏幕位移。对于一个在1280*1024显示模式下的19英寸4:3显示器,其长边约为15.2英寸,其分辨率(这里指的是dpi)大约为84dpi。此时我们可以计算屏幕指针在某个轴向的速度。

屏幕刷新率
屏幕指针某个轴向速度Vpointer(单位inch per second)=------------------------ ×此轴位移  (2)
                                                                                                        屏幕分辨率

如果在上面的屏幕上,屏幕刷新频率为75Hz,则某一帧鼠标指针在x轴移动3的话,Vpointer= 2.67,大约2.67英寸每秒。从这个数据和上面物理鼠标位移速度比较可以看出,如果屏幕位移与物理位移比率是1:1的话,指针在屏幕上移动的速度大约是鼠标实际移动速度的3倍。此处写屏幕刷新率是因为windows设计者将屏幕指针刷新频率与屏幕刷新频率挂钩了。

4、鼠标加速度
实际上,由于以上谈到的参数都不是固定的,因此不同情况下这些Vpointer和Vmouse都不一样。如果只有一个固定的物理位移到屏幕位移的比率会给用户带来不适。因而Windows系统要设计一个鼠标加速度函数。

Windows XP设计鼠标加速度函数的目的有以下几点:

为了在不同分辨率的屏幕上能够有效的移动鼠标的同时,保证鼠标能够移动到每个像素上。
平滑鼠标移动
保证加速是基于鼠标整体移动而不是基于单独的轴的移动。
减少选择对象时的鼠标移动,并且可以一个个像素的选择(?这不是和1一个意思吗)
移除鼠标设置中的“高级”按钮。这是由于原来大多数用户不知道如何使用这些设置。
在这种情况下,Windows需要建立起一个物理位移与屏幕位移的转换函数,而且这个函数必须不是纯线性的,为了降低计算复杂度,使用一个基于查表的分段函数比较合适。假设F(Vmouse)=Vpointer / Vmouse。则在鼠标速度比较小的情况下,F(x)<1,这样可以做到使鼠标能够移动到屏幕上的每个像素上。而在鼠标速度比较大的情况下,F(x)>1,这样保证在高分辨率屏幕上鼠标仍然能够高速移动,否则如果如第三节中分析,屏幕位移与物理位移比率是1:1的话,在高分辨率屏幕上人会感觉到鼠标移动的特别慢。

微软的研究人员经过可用性研究后得出了一个用户最希望的Vmouse-Vpointer曲线,见下图

可以看出这个曲线是分段的,在Vmouse较小的时候,曲线斜率较小。在Vmouse较大的时候,曲线斜率较大。由于屏幕坐标为整数,因此每次计算的小数部分都会使用一个变量记录下来,以累积到下一次的计算中。Windows会根据当前的屏幕参数和鼠标参数来调整F(x),设得到的新曲线为F1(x)

总的计算公式如下:
Vpointer=interger(F1(Vmouse)×(Vmouse+Rn-1)×M)                         (3)
Rn=remainder(F1(Vmouse)×(Vmouse+Rn-1)×M)                             (4)
这里的interger表示取整数部分,remainder表示取小数部分,M为windows中固定的放大倍数,为控制面板-〉鼠标-〉指针选项中的鼠标移动速度设定。在这个计算公式中,有一个原则就是在M可取得范围中,如果Vmouse<1,则F1(Vmouse)×M<=1

在实际的Windows系统中,F1(x)是通过查表和插值的到的,如果控制面板-〉鼠标-〉指针选项中的“提高指针精确度”被关闭,则上述计算是通过会被跳过,此时的计算公式是将公式(3)(4)中的F1(Vmouse)去掉而成。

而F(x)中几个分段点为(0,0.43,1.25,3.86,40),这几个分段点在Windows XP Sp2以及Windows 2003 Sp1中都是正确的。下面是控制面板-〉鼠标-〉指针选项中的鼠标移动速度设定中拖动条从左到右各个值所对应的M

公式中M实际大小 拖动条值 1            2          3      4    5      6    7    8    9    10    11
MouseSensitivity           1             2          4      6    8     10  12   14  16   18   20
M值大小                          0.03125 0.0625 0.25 0.5 0.75 1   1.5   2    2.5  3     3.5

5、结论
虽然我没有将微软将F(x)转换到F1(x)的实际公式推导出来,也没有得到F(x)的每一段的具体斜率,但是通过以上的说明,我相信耐心的读者可以通过实验将这些具体数据得到的。

参考材料:
[1] "Pointer Ballistics for Windows XP" http://www.microsoft.com/whdc/device/input/pointer-bal.mspx
[2] MSDN Library April 2005

未经作者同意,请勿将此文用于商业用途。转载本文时,请保留作者信息以及原始链接。

本文来自CSDN博客,转载自:http://blog.csdn.net/liuweili_lwl/archive/2006/04/12/660868.aspx

windows鼠标,物理位移与屏幕位移的计算方法(鼠标加速度)相关推荐

  1. windows屏幕捕捉BitBlt函数鼠标闪烁问题

    转自:http://liufan5005.blog.163.com/blog/static/26710173200911291739569/ 我们在用BitBlt函数进行屏幕捕捉时,若传递了CAPTU ...

  2. 【鼠标无限移动】鼠标超出浏览器边界,怎么捕捉鼠标移动的方向和位移?

    鼠标无限移动 朋友问了一个问题,没有鼠标的时候,鼠标超出浏览器边界,怎么捕捉鼠标移动的方向和位移? 这~ 不好说 但是朋友让看了一个demo是cesim+XbsjEarth 实现了. 那就研究一下吧 ...

  3. 使用Windows XP 的放大镜、屏幕和键盘(转)

    使用Windows XP 的放大镜.屏幕和键盘(转)[@more@] 放大镜是针对那些有轻度视觉障碍的用户而设计的,使用放大镜可以使这些用户更容易地阅读屏幕上的内容,下面就来介绍如何使用放大镜. 使用 ...

  4. VLC 屏幕录像时录制鼠标的方法:

    目前屏幕录像如果录制鼠标需要: 1,VLC的config.h中 加入宏定义:#define SCREEN_MOUSE 重新编译 2,传参时须传入:"screen-mouse-image&qu ...

  5. C#屏幕录制图像处理:(包含鼠标图像录制)

    C#屏幕录制图像处理:(包含鼠标图像录制) using System; using System.Collections.Generic; using System.ComponentModel; u ...

  6. 【语言-c#】显示设置-设置了缩放比列后,如何处理鼠标光标位置和屏幕大小

    问题描述 C#获取屏幕尺寸与位置与实际屏幕尺寸位置不一致 使用System.Windows.Forms.Screen.PrimaryScreen.Bounds获取的边界是 1536*864 而使用微信 ...

  7. linux和windows共享鼠标,synergy-两台电脑Linuxwindows共享一套鼠标键盘

    synergy-两台电脑共享一套鼠标键盘-Linux&windows详细教程 前些天,我把自己的台式电脑搬到实验室,与实验室里分配给我的电脑一起用.为了方便使用,我尝试了下用软件的方法实现两台 ...

  8. 如何在Windows 8中更改登录屏幕的颜色

    Nearly every component of Windows 8 can be customized to suit your needs, some settings however are ...

  9. 标准配置的Windows平台上潜在可用屏幕区域

    经常在windows开发网站的朋友,在开始设计网站时,最需要知道的就是一个图片的大小和尺寸.我本人也是在windows上玩弄了几年的,虽然没有什么正规的证书之类的,但是自己对windows的东西,一些 ...

最新文章

  1. Python3.6.4 安装
  2. PDF 补丁丁 0.5.0.2078 测试版发布:不用打字,也能加书签
  3. vbs禁用任务管理器
  4. 天使投资家李镇樟:如何培养世界级企业家
  5. Swoole的think-swoole的安装
  6. linux下c语言按q退出_在linux下C语言写了一个while循环,怎么实现按任意键退出。如何编写程序?...
  7. 开头th_是什么文件_Python文件读写最详细的讲解
  8. 【Python】Numpy处理.csv数据
  9. CVPR 2020 | 3D目标检测泛化问题研究
  10. java编译运行_如何编译运行一个简单的java程序
  11. keras 基础入门整理
  12. python调用matlab绘图_python调用matlab绘图
  13. 互联网广告定价策略与算法
  14. java如何重命名class_java – 如何重命名XStream列表元素?
  15. MATLAB求解微分方程
  16. 量化分析(6)——K线图、交易量图、动量图、rsi强度图
  17. 机器学习之数据挖掘算法(一)OneR算法
  18. python绘制分形图形_Python绘制L-System的分形图
  19. Cesium模拟雷达追踪卫星
  20. 线性规划-概念与公式总结

热门文章

  1. mapinfo常用功能系列讲解——(3)统计线段长度(SQL统计法)
  2. OPEN-VOCABULARY OBJECT DETECTION VIAVISION AND LANGUAGE KNOWLEDGE DISTILLATION
  3. 微软官方WinPE的制作流程
  4. 字符编码笔记:ASCII,Unicode 和 UTF-8(转帖、留着自己学习)
  5. 五种全面质量管理工具
  6. 基于RFID的停车场收费系统c语言,基于RFID的停车场收费系统.DOC
  7. 两轮市场红海,利尔达芯智行如何乘风破浪?
  8. linux 配置阿里云ddns 定时任务定时更新
  9. Java、JSP物流仓储调度系统
  10. 平安金融壹账通正筹备赴美上市,已将区块链落地到5个行业