当前位置:C++技术网 > 精选软件 > win32鼠标移动实时提示框漂离主窗口的问题分析和解决办法

win32鼠标移动实时提示框漂离主窗口的问题分析和解决办法

更新时间:2015-12-24 16:47:49浏览次数:1+次

    在文章《win32鼠标移动实时提示信息框的自动消失功能实现》中,我们已经分析实现了鼠标移动实时提示框的显示和自动消失的功能。然而却发现,主窗口移动离开左上角之后,提示框竟然没有跟着光标跑。效果图如下:

主窗口移动之后,提示框没有跟着光标跑

【主窗口移动之后,提示框没有跟着光标跑】
    问题出在哪呢?我们移动窗口的函数为MoveWindow,所以MSDN中寻求解释。然而MSDN确实解释MoveWindow函数的坐标为窗口客户区坐 标,所以,我们传入的坐标并没有问题。但是MSDN提到,MoveWindow函数会想将要被移动的窗口发送WM_MOVE消息,然而在WM_MOVE消 息中,我们看到一个解释。如果窗口有WM_POPUP或者WS_OVERLAPPED风格的窗口,则此消息传入的就是基于屏幕的坐标,其他风格的窗口,如 果是子窗口,则是父窗口的客户区坐标。而我们的提示框窗口,刚好有WM_POPUP风格,这样我们是传入的父窗口的客户区坐标,结果被当做了屏幕坐标,所 以主窗口移动之后,提示框移动的位置并不是屏幕的。这样就产生了问题。

    那么我们如果将提示框的WM_POPUP风格去掉,则会导致提示框贴在客户区,移动后就出现大量的痕迹,如下图所示:

提示框在主窗口客户区乱窜,留下很多的影子

【提示框在主窗口客户区乱窜,留下很多的影子】
    如果要解决这个问题呢,可以给主窗口客户区发送一个WM_PAINT消息,这样就可以导致客户区重画,同时要指定让背景擦除。在鼠标移动消息处理后,执行一句让客户区失效的代码:
InvalidateRect(hwnd,NULL,TRUE);
    然而这样会导致客户区非常的闪烁,效果不尽如人意。所以,我们还是找到问题的根本。那就是将传入的坐标转换一下。将要传入的主窗口的客户区转换为屏幕坐 标。这样,经这个屏幕坐标传给提示框,提示框依然可以定位到光标附近的位置。将客户区坐标转换为屏幕坐标的意思就是,在你当前看到的主窗口的这个光标位 置,当前是用主窗口坐标来定位光标位置的,转换后就是用整个屏幕的位置来定位当前你看到的光标的这个位置。实际上,你看到的光标位置,都是同一个位置。转 换坐标只是换了一个定位的参考坐标系而已,并没有改变改变的位置。代码如下:
POINT ptScreen;
ptScreen.x = GET_X_LPARAM(lParam);
ptScreen.y = GET_Y_LPARAM(lParam);
ClientToScreen(hwnd,&ptScreen);

    这样转换之后,就可以正确的定位了,提示框也就可以正确的移动位置了。

PS:本来写了非常详细的,中途Win10蓝屏,没了。所以,迅速将思路简洁的写了出来。对于详细分析找问题的经验的丢失,很抱歉。如果有问题,可以提问哈。