c++ builder 鼠标移开窗体时的事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ builder 鼠标移开窗体时的事件相关的知识,希望对你有一定的参考价值。

如题,还有当鼠标放到窗体上时的事件。请指教。

在处理窗体消息的时候,我想不少人都会碰到鼠标离开窗体的消息(下面称之为MouseLeave)。在C++ Builder里,并没有直接提供处理这种消息的方法,需要我们自己动手来做。通过参考一些资料,我发现在C++ Builder里面处理MouseLeave,不外乎以下四种方法,现写出来供大家参考。如果有什么不对之处,请指正。

(一)、笨拙的Timer

每每提到捕捉鼠标离开窗体的消息的时候,也许有人就会马上想到用Timer来处理。不错,这种方法很简单,也确实有效。只须在Timer的OnTimer事件中判断鼠标所处位置的坐标是否在窗体内就可以了,详细代码如下:

void __fastcall TForm1::Timer1Timer(TObject *Sender)

POINT pt;
GetCursorPos(&pt); //得到鼠标的坐标
RECT rect;
GetWindowRect(Handle,&rect); //得到窗体的矩形范围
if(!PtInRect(rect,pt)) //判断鼠标的坐标是否在窗体的矩形范围内

Caption="out";
else
Caption="in";


为什么我要说是笨拙的Timer呢?原因有二:其一、OnTimer是优先级别比较低的消息,从严格意义上讲,上面这种做法并不精准。如果系统正在处理一大堆级别比较高的消息,那我们就无法及时获得MouseLeave消息。其二、Timer是比较宝贵的系统资源,用在MouseLeave上面似乎有些浪费了,因为我们还有更好的方法来做同样的事情。

(二)、霸道的SetCapture()

SetCapture()可以让指定的窗体捕获所有鼠标消息,当然也包括MouseLeave了:

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)

Caption="in";
SetCapture(Handle);
TPoint pt(X,Y);
TRect rect;
rect=GetClientRect();
if (!PtInRect(rect,pt))

ReleaseCapture();
Caption="out";



不过这种方法太过于霸道了,因为SetCapture()将所有的鼠标消息据为己有。虽然在捕获了MouseLeave以后已经ReleaseCapture了,但是在捕获过程中,你却无法对其他的鼠标消息做出反应。不信?你不妨在窗体在多放一个Button控件,再运行点点看?:)

(三)、受限的TrackMouseEvent()

MSDN上面说,TrackMouseEvent()可以让指定的窗体接受WM_MOUSELEAVE消息。但是在接受消息以后如果还要继续接受WM_MOUSELEAVE消息,必须重新调用TrackMouseEvent():

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)

MouseTrack=false; //TForm1的私有变量,检测鼠标是否已经被Track

//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(TMessage& Message) //重载WndProc

if (Message.Msg==WM_MOUSELEAVE) //在这里捕获WM_MOUSELEAVE消息

Caption="out";
MouseTrack=false; //鼠标Track已经完成

TForm::WndProc(Message);

//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)

Caption="in";
if (!MouseTrack)

TRACKMOUSEEVENT tt;
tt.cbSize=sizeof(tt);
tt.dwFlags=TME_LEAVE;
tt.hwndTrack=Handle;
TrackMouseEvent(&tt);
MouseTrack=true; //开始鼠标Track


//---------------------------------------------------------------------------

这种方法很好用,唯一的缺点是可能不支持Win98(具体支不支持我也没有做过实验,哪位兄弟有Win98的帮我测试一下)。在Win2000的环境下,我推荐用这种方法,:)

(四)、未知的CM_MOUSELEAVE

在CSDN论坛里经常看到有人说可以通过捕获CM_MOUSELEAVE消息来达到同样的效果。不过根据我的测试,CM_MOUSELEAVE在控件上面工作得很好,可以用来捕获鼠标离开控件的消息。但用在窗体上似乎就不灵验了,可能我自己没有做对吧。如果有哪位大虾知道该怎么用,请告知小弟一声,我将感激不尽。

以上代码均在Win2k Professional+bcb6.0环境中编译成功。
参考技术A 教你个简单的,使用窗口消息处理函数指针来实现吧
修改窗体的消息处理函数,输入this->。。。,应该可以看到的一个形如
windowproc的函数指针。仿照它的样子再定义一个窗口消息处理函数,要保证参数返回值一模一样的。NewWndProc
同时定义一个函数指针,指向上面所说的函数类型。m_pfnOldWndProc;

然后将此函数指针赋值,指向默认的消息处理函数
m_pfnOldWndProc = this->DefWindowProc;
this->DefWindowProc = NewWndProc;
定义NewWndProc(message .....)

....if ( message == WM_KILLFOCUS)
.... // 此处做鼠标移开的处理
....
....if ( message == WM_SETFOCUS)
.... // 此处做鼠标移出的消息处理
....
....return m_pfnOldWndProc(message...);


不好意思,好久没玩BCB了,具体的名称都忘记了,不过上面应该是可行的。

另外,我记得好象,在窗口的函数声明里面可以写消息处理函数(默认未列在窗口属性里面的消息事件处理页面里面的)的,你看看BCB的源代码,我记得以前写过的。

鼠标移入移出事件

鼠标移入移出事件:

mouseover:鼠标移入到目标元素的上方,在其子元素上时也会触发,。所以说也就是说会产生冒泡。

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
    <style>
        .parent{height: 400px;  width: 400px;border: 1px solid red;}
        .children{height: 200px;  width: 200px;border: 1px solid green;}
    </style>
</head>
<body>
<div class="parent">
    <div class="children"></div>
</div>
</body>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
$(".parent").mouseover(function () {
  console.log(123)
})
</script>
</html>

  鼠标依次从外往里,以下是结果

可以看出打印出了两次,可见确实冒泡执行了两次。

mouseenter:鼠标移入元素范围内触发,该事件不冒泡,即鼠标移到其后代元素上时不会触发。

同样的代码用mouseenter输出的是一次123

mousemove:鼠标在元素内部移到时不断触发,

同样的HTML,效果见下图,鼠标移动一次下,打出了140多次。

mouseenter:鼠标移出目标元素上方,这是会产生冒泡的。从父元素移到子元素也是算移出去的。我从父元素移到子元素得到下面结果:

mouseleave:鼠标移出元素范围时触发,该事件不冒泡,即鼠标移到其后代元素时不会触发.

从父元素移到子元素不会触发,直到鼠标移出。


以上是关于c++ builder 鼠标移开窗体时的事件的主要内容,如果未能解决你的问题,请参考以下文章

jQuery链式调用、鼠标移入移出、轮播、键盘事件

actionscript 3-按钮操作[侦听多个事件。[鼠标移过,鼠标移出,鼠标向上]

jquery中鼠标移上和移开的动作是啥?

认清鼠标移入移出事件

WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件

jquery 鼠标移除 清除所有的事件