一个关于Windows下SetCursorPos和GetCursorPos的小坑

时间:2022-05-09 06:54:02

这两天在做一个编辑特定格式Mesh的小工具,需要检查鼠标的移动,一般来说可以用WM_MOUSEMOVE事件解决的,但是我为了省事用了定时查询+设置的方式,也就是:

1 void Frame(void) 2 { 3 //do something else... 4 5 POINT cursorPos; 6 GetCursorPos(&cursorPos); 7 curMoveX = cursorPos.x - cursorBaseX; 8 curMoveY = cursorPos.y - cursorBaseY; 9 cursorPos.x = cursorBaseX, cursorPos.y = cursorBaseY; 10 SetCursorPos(&cursorPos); 11 12 //do something else 13 }

很简单的逻辑,就是定期把Cursor设置到指定位置,然后过一会儿来检查Cursor跑到哪里了,看看这一段时间里Cursor移动了多少,不断重复这个过程就能得知鼠标怎么移动的(只是个小工具所以就这样实现了)。但是跑起来的时候遇到一个诡异的问题:在我没有移动鼠标的情况下,得到的Cursor位置变化量居然不是0(拔掉鼠标还是有这个现象,不是鼠标的问题),网上没有查到这个问题,我对Windows编程本来就不熟悉也不可能去仔细看文档(至少GetCursorPos和SetCursorPos的条目里没提这种现象),所以就搁下了。

后来想了想,问题可能出在我SetCursorPos的时候。于是我在Set过后立刻Get一次,然后比对Set和Get得到的值,然后发现有的时候这两个值竟然不一样(在未移动鼠标的情况下),差异也不大,但是足以干扰程序运行。知道了这一点,立刻就得出几种解决方法:一种是老老实实在窗口事件函数里用WM_MOUSEMOVE,相当于避开了这个问题;一种是当检测到的Cursor移动速度过慢的时候忽略这一移动,,这样虽然能工作但不怎么漂亮;然后就是把Get和Set的量分开存储,每次Set之后立刻Get一次,下一次计算偏移量的时候就用这一次Get的值。最后我用了第三种方法,算是解决了问题。

问题本身不困难,但是算是个小坑,所以记录一下。关于导致问题的原因,我现在暂不清楚,以后学习的过程中会留意。初步猜测是在我SetCursorPos的时候系统并没有严格地把Cursor移动到我指定的位置,而是由于单位不同或者精度问题把Cursor设置到了离我指定的位置很近的另一个位置(比方说,偏移了一个像素),结果就是我没动鼠标,却发现Get和Set的值有时不一样了。

一个关于Windows下SetCursorPos和GetCursorPos的小坑