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

文章移至这里

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

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

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

<span style="font-size:18px;">CPoint point;
	CRect rectWindow;
	BOOL bIn = FALSE;
	GetWindowRect(rectWindow);
	GetCursorPos(&point);
	if (rectWindow.PtInRect(point))
	{
		bIn = TRUE;
	}</span>

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

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

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

<span style="font-size:18px;">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;
		//隐藏窗体
	}
</span>

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 你可以在Label的Leave事件中添加代码,使控件消失。例如: private void label1_Leave(object sender, EventArgs e) { label1.Visible = false; } 这样当Label移出窗体时,Label就会消失。 ### 回答2: 在微软的Windows操作系统中,如果想要在label移出窗体时让控件消失,可以遵循以下步骤: 1. 在窗体中添加一个label控件,并设置好相关的属性和位置。 2. 在窗体的代码文件中,找到该label控件的MouseMove事件处理程序。该事件在鼠标指针移动到label控件上方时触发。 3. 在MouseMove事件处理程序中,首先判断鼠标指针是否超出了窗口的边界。可以通过获取鼠标位置和窗口的大小来实现。如果鼠标超出了窗口边界,表示鼠标离开了窗口,此时可以让label控件消失。 4. 要让label控件消失,可以将其Visible属性设置为false,表示控件不可见。 下面是一个示例代码片段,演示如何实现在label移出窗体时让控件消失的效果: ```csharp private void label1_MouseMove(object sender, MouseEventArgs e) { // 获取鼠标在窗口中的位置 Point mousePos = this.PointToClient(Cursor.Position); // 判断鼠标是否超出了窗口边界 if (mousePos.X < 0 || mousePos.X > this.Width || mousePos.Y < 0 || mousePos.Y > this.Height) { // 如果鼠标超出了窗口边界,将label控件设为不可见 label1.Visible = false; } } ``` 通过以上的步骤和示例代码,当label控件移出窗体边界时,控件将会消失,以达到题目要求。 ### 回答3: 当一个控件被移出窗体时,我们可以通过以下方法让它消失: 1. 在控件移出窗体的事件中,添加代码来隐藏控件。可以使用控件的Visible属性将其设置为False,这将使控件在窗体上不可见。 例如: ``` private void label1_MouseLeave(object sender, EventArgs e) { label1.Visible = false; } ``` 2. 使用Dispose方法。Dispose方法用于释放控件所占用的资源,并将其从内存中删除。可以在控件移出窗体的事件中调用Dispose方法来删除控件。 例如: ``` private void label1_MouseLeave(object sender, EventArgs e) { label1.Dispose(); } ``` 需要注意的是,使用Dispose方法后,控件将完全被删除,可能无法再次使用。因此,如果需要再次在窗体中显示该控件,建议使用Visible属性来控制其可见性,而不是使用Dispose方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daiafei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值