关于动态监测鼠标移入移出窗体问题的分析

文章移至这里

最近项目中用到需要动态监测鼠标是否移入或者移出窗体,用来控制窗体的显示和隐藏,常规思路:使用系统的消息WM_MOUSELEAVE(鼠标离开)和WM_MOUSEHOVER(鼠标进入)来检测,具体做法就是在鼠标移动消息中增加如下代码:

 //打开鼠标进入与离开的消息监听
TRACKMOUSEEVENT tme; 
tme.cbSize = sizeof(tme); 
tme.hwndTrack = m_hWnd; 
tme.dwFlags = TME_LEAVE | TME_HOVER; 
tme.dwHoverTime = 1; 
m_bTracking = _TrackMouseEvent(&tme); 
具体代码请参考这里:http://blog.csdn.net/rankun1/article/details/51659679

但是,这样做有一个问题,就是当窗体上面有子窗体的时候,鼠标移动到子窗体上,监听消息就会认为鼠标已经离开主窗体(这是正确的),但并不是我想要的效果,我想要的是只要鼠标在窗体上,不管是子窗体还是父窗体,只要在父窗体区域内,都认为鼠标还在窗体上,没有离开,于是就在WM_MOUSELEAVE和WM_MOUSEHOVER消息中增加判断鼠标位置代码,以此判断鼠标是否离开窗体:

CPoint point;
	CRect rectWindow;
	BOOL bIn = FALSE;
	GetWindowRect(rectWindow);
	GetCursorPos(&point);
	if (rectWindow.PtInRect(point))
	{
		bIn = TRUE;
	}

这样貌似可以了,但是,当我快速把鼠标从窗体子控件上移出窗体的时候,有时候会捕获不到鼠标离开的消息,猜测原因可能是鼠标移动消息没有触发或者鼠标消息触发是周期性的,带着这样的疑问继续查找鼠标移动消息的资料,查资料发现:WINDOWS系统并不是在鼠标每移动一个像素时都产生WM_MOUSEMOVE消息,但奇怪的是,我鼠标移动的距离已经超出了N个像素了,为什么还没有触发那,或者触发了没有检测到鼠标离开消息,还是鼠标移动消息也是周期性的,有自己的时钟周期,不得而知,总之,上面的方案没有能解决我想要的效果。

在查检测鼠标移入移出窗体的时候,也有人提到用鼠标钩子的,处于安全考虑,没敢用,进程你的钩子钩不到鼠标移出的消息,全局的钩子还容易被杀毒软件拦截,认为是病毒误报。

后来实在没办法,就选择了一个笨方法:定时器,定时执行检查鼠标是否在窗体上,代码如下:

static int nLastStatue = -1;
	CPoint point;
	CRect rectWindow;
	BOOL bIn = FALSE;

	GetWindowRect(rectWindow);
	GetCursorPos(&point);

	if (rectWindow.PtInRect(point))
	{
		bIn = TRUE;
	}

	if (bIn && nLastStatue != 1)
	{
		nLastStatue = 1;
		//显示窗体
	}else if (!bIn && nLastStatue != 0)
	{
		nLastStatue = 0;
		//隐藏窗体
	}

当窗体失去焦点的适合也要处理一下隐藏窗体代码,这样基本就能实现自己想要的效果了

也不知道自己分析的对不对,如果有问题,请留言指正,谢谢!!!

你可能感兴趣的:(C/C++)