MFC onmousemove不停排查

Published

1.tracetool看鼠标消息

2.spy++

 

一、Windows对鼠标键按下的响应流程

Windows对鼠标键按下的响应流程:

1. 确定鼠标键点击的是哪个窗口。Windows会用表记录当前屏幕上各个窗口的区域坐标,当鼠标驱动程序通知Windows鼠标键按下了,Windows根据鼠标的坐标确定它点击的是哪个窗口。

2. 确定鼠标键点击的是窗口的哪个部位。Windows会向鼠标键点击的窗口发送WM_NCHITTEST消息,来询问鼠标键点击的是窗口的哪个部位。(WM_NCHITTEST的消息响应函数的返回值会通知Windows)。通常来说,WM_NCHITTEST消息是系统来处理的,用户一般不会主动去处理它(也就是说,WM_NCHITTEST的消息响应函数通常采用的是Windows默认的处理函数)。

3. 根据鼠标键点击的部位给窗口发送相应的消息。例如:如果WM_NCHITTEST的消息响应函数的返回值是HTCLIENT,表示鼠标点击的是客户区,则Windows会向窗口发送WM_LBUTTONDOWN消息;如果WM_NCHITTEST的消息响应函数的返回值不是HTCLIENT(可能是HTCAPTION、HTCLOSE、HTMAXBUTTON等),即鼠标点击的是非客户区,Windows就会向窗口发送WM_NCLBUTTONDOWN消息。

 

如果WM_NCHITTEST的消息响应函数的返回值是HTCAPTION,即指示了鼠标点击了标题栏,接下去Windows的处理是怎样的?

上面已经提到,接下来,Windows会向窗口发送WM_NCLBUTTONDOWN消息。

MSDN对WM_NCLBUTTONDOWN消息描述如下:

WM_NCLBUTTONDOWN

nHittest = (INT) wParam; // hit-test value

pts = MAKEPOINTS(lParam); // position of cursor

WM_NCLBUTTONDOWN的wParam指示了鼠标点击的窗口部位,lParam指示了当前鼠标的坐标。

如果应用程序没有对该消息响应,则由系统默认处理。

系统默认处理又是怎样的呢?系统发现wParam指示了鼠标点击的是标题栏,就会标识当前窗口处于“拖拽状态”(Windows内部记录了每个窗口的状态信息)。由于标识了“拖拽状态”,则从此刻起到鼠标键放开之前,你的鼠标移动状况完全由Windows跟踪。它根据鼠标的移动,使得窗口作“同步”移动。

注意,这个过程中,窗口不会收到WM_NCMOUSEMOVE消息,因为窗口和鼠标是“同步”移动的,你的鼠标相对于窗口是静止的。

 

初步排查是不停的发送了WM_SETCURSOR消息。

使用spy++捕获到的消息详解

主要是今天正好自己用到。

 

原来也有用过SPY++查看消息,然后自己SendMessage或者PostMessage 直接发送消息给目标程序。但是原来一用就有效果,今天要发的窗口是QT写的,所以就想着把消息尽量弄得和SPY++里捕获到的一样,看看是否能行。

 

嗯,最终依然还是不行。不过也明白了SPY++捕获到的消息字串具体对应的是哪个参数了,特在此记录,方便以后查找,也方便需要的朋友。

 

1.jpg

 

因为是重复的,我就只讲顶上的三条就行。

 

第一条:<00001> 00130042 S WM_SETCURSOR hwnd:00130042 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE

 

<00001>:是SPY++捕获到的消息序号,主要是它记录顺序用。

 

00130042:这是目标窗口句柄的16进制。

 

S:这里第一行是S,第二行是R,第三行是P。一起说了。S 是指使用 SendMessage 发送的消息,R 是使用SendMessage发送消息后得到的返回值。P 是使用PostMessage 发送的消息。

 

WM_SETCURSOR:发送的消息值,也就是 SendMessage 的第二个参数(PostMessage 参数与SendMessage的一样)。

 

从这里往后,就分别是 SendMessage 的第三个参数和第四个参数的值了,但是它们不是固定对应的,是根据具体消息值不同而不同的。

 

第一条在消息值 WM_SETCURSOR 之后,是 hwnd:00130042,可以看出这是一个句柄,也就是目标窗口的句柄。同时这里是 SendMessage 的第三个参数。

 

然后在 hwnd:00130042 的后面有两个数据,而我们的SendMessage只剩最后一个参数了,所以后面的两个数据都是SendMessage的最后一个参数。一个低位,一个高位。

 

SPY++捕获的第一条消息,要使用代码发送实现一样的数据的话,就应该是:

 

SendMessage(00130042,WM_SETCURSOR,00130042,HTCLIENT+WM_MOUSEMOVE*65536)

 

注意,上面的代码我并没有使用任何一种编程语言来表示,这样大家都能看懂,如果要用的话,你只需要把上面的代码换成你所使用的编程语言就行了。

 

然后下面来说SPY++的第二条。

 

<00002>00130042 R WM_SETCURSOR fHaltProcessing:False

 

这条不需要我们操作,我们使用SendMessage发送了之后,就会有类似的返回值回来。

 

第三条:<00003> 00130042 P WM_MOUSEMOVE fwKeys:0000 xPos:1088 yPos:27

 

我们直接说 WM_MOUSEMOVE 之后的东西就行了,WM_MOUSEMOVE包含之前的看上面的第一条。

 

WM_MOUSEMOVE 之后是 fwKeys:0000 ,因为WM_MOUSEMOVE是PostMessage的第二个参数(为什么是PostMessage而不是SendMessage?上面有说到)

 

所以这个fwKeys:0000就是PostMessage的第三个参数了,而且值是 0 ,我们不用看前面的 fwKeys ,只需要看 : 后面,它的值就行了。

 

fwKeys:0000 是第三个参数了,那它之后的就是第四个参数。

 

同样,还有两个数据,低位和高低。

 

最后,这条捕获的消息用代码实现就是:

 

PostMessage(00130042,WM_MOUSEMOVE,0,1088 + 27 × 65536)

 

Using Cursors

https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors?redirectedfrom=MSDN#_win32_Displaying_a_Cursor