WinForm中MouseEnter和MouseLeave混乱的问题

  MouseEnter+MouseLeave不行,我用了MouseMove+MouseLeave,效果一样

  最近做个聊天的系统,仿照qq的界面设计,像qq聊天界面中字体、表情、截图等图片,鼠标放上去显示边框,所以很自然用到了enter和leave这两个事件,因为是picturebox控件没有over和out事件,但调了两个小时就是不行,mouseleave事件不灵,经常不触发,也不是速度太快造成的,因为有时快也能触发,我慢慢经过反倒经常不触发,头疼,因为我这些图片外面套的有两层panel,网上查了些资料看了,说鼠标在控件上也算不在panel上,但和我的情况不符合呀,整了一下午不行,放弃(最后终于知道是因为Leave是在离开控件边缘的一瞬间触发,但我进入控件后加了边框,所以鼠标离开控件边缘时,是在后加上的边框上,依然认为在控件里,导致慢慢经过边缘不触发,但Enter事件不能控制,所以还得用下面的);

  没办法开始尝试用判断鼠标是否在控件上这个方法,这里用到的是mousemove事件,这里也有坑,什么相对于屏幕的坐标和相对于窗口的,也是整的有点云里雾里的。先看下最终实现的效果,:

  private void picBoxLog_MouseMove(object sender, MouseEventArgs e)
        {
            Point p = flowLayoutPanel2.PointToClient(Control.MousePosition);//flowLayoutPanel2是picBoxLog的父容器
            int side = 1;//决定于边框的宽度
            if (p.X > picBoxLog.Location.X + side && p.X < picBoxLog.Location.X + picBoxLog.Width - side && p.Y > picBoxLog.Location.Y + side && p.Y < picBoxLog.Location.Y + picBoxLog.Height - side)
            {
                picBoxLog.BorderStyle = BorderStyle.FixedSingle;
            }
            //else
            //    picBoxLog.BorderStyle = BorderStyle.None;
        }

开始只用move,但移出控件上就不触发该事件,所以不会去掉边框,尝试鼠标进入控件过一段距离后加边框,四周留一些边距,触发去掉边框(看上面的代码我加了side就知道了,所以大家就不用加side了),但如果移动过快也会造成去不掉的情况,虽然不容易发生,而且控件本来就30高度没多大,我两边都留了8,还是会发生,再多点就没了,灵光一闪,把去掉边框的方法,又放到了Leave事件中,日了狗了,这两个事件竟完美配合,想砸键盘的心都有了,所以记录下来,献给正在为此砸键盘或将来可能砸键盘的猿猿们。

贴一下用这个方法过程中查看的知识点:

1)PointToClient 将指定屏幕点的位置计算成工作区坐标。坐标原点为黄色区域左上角,X轴方向从左到右;Y轴方向从上到下;坐标单位为像素;

2)PointToScreen 将指定工作区点的位置计算成屏幕坐标。坐标原点在屏幕左上角,X轴方向从左到右;Y轴方向从上到下;坐标单位为像素;

获取鼠标的位置的:

  很多时候我们需要用到鼠标在相对于窗体上的坐标,或者相对于屏幕的坐标,这里就把我的经验记录下。

  用Control.MousePosition获得当前鼠标的坐标CurrentPoint,使用Control.PointToClient方法,前面获得的CurrentPoint作为其参数,返回的Point类型的对象即为鼠标相对于某个控件的坐标。

现在以鼠标相对于窗体的坐标做为例子,如下:   

          Point screenPoint = Control.MousePosition;//鼠标相对于屏幕左上角的坐标           

   Point formPoint = this.PointToClient(Control.MousePosition);//鼠标相对于窗体左上角的坐标

同理:

            Point button1Point= button1Point.PointToClient(Control.MousePosition); //鼠标相对于button1左上角的坐标

还有Control.PointToScreen方法,返回的是相对于屏幕的坐标。

    大概就这些吧,中间还试了Rectangle相关的,没成功,不知道是不是哪写错了,哪位大神知道了,可以指点下

    //Rectangle rec = picBoxLog.RectangleToClient(this.ClientRectangle);
            //Point p = flowLayoutPanel2.PointToClient(Control.MousePosition);  flowLayoutPanel2是picBoxLog的父容器,改成this也试了不行
            //if (rec.Contains(p))
            //{
            //    picBoxLog.BorderStyle = BorderStyle.FixedSingle;
            //}
            //else
            //    picBoxLog.BorderStyle = BorderStyle.None; 

原文地址:https://www.cnblogs.com/dachuang/p/5717525.html