导航:
论坛 -> 论坛精华贴
斑竹:liumazi,iamdream
作者:
2003/5/2 20:20:47
标题:
请问在delphi中如果判断鼠标的指针已离开了一个控件或是离开了窗体??
浏览:6364
加入我的收藏
楼主:
如题,我想在鼠标离开时激活一个事件
----------------------------------------------
-
作者:
123 (猪猪)
★☆☆☆☆
-
盒子活跃会员
2003/5/2 22:00:17
1楼:
用 GetCursorPos() 函数.
----------------------------------------------
-
作者:
2003/5/2 23:06:25
2楼:
能否给出一个例子呢?
----------------------------------------------
-
作者:
2003/5/3 17:55:52
3楼:
加入一TTimer控件,然后在Timer事件中判断当前的鼠标是否在窗体之内即可。
----------------------------------------------
-
作者:
2004/9/19 12:03:51
4楼:
c++ builder里四种处理“鼠标离开窗体”事件的方法 hhdsq(原作) 关键字 鼠标,窗体,消息 在处理窗体消息的时候,我想不少人都会碰到鼠标离开窗体的消息(下面称之为 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环境中编译成功。
----------------------------------------------
好好学习,天天上网。
作者:
2004/11/25 22:26:06
5楼:
我试验的结果是,在98也支持TrackMouseEvent的.我好几个程序都用了这个方法. 另外,有时我也在计时器中使用GetCursorPos来判断当前鼠标所在窗体,代码为: var ItemPoint: TPoint; hwCursor: LongWord; begin GetCursorPos(ItemPoint); hwCursor := WindowFromPoint(ItemPoint); if (hwCursor = 句柄) then .....; end;
----------------------------------------------
好好学习,天天上网。
作者:
2006/11/23 19:41:04
6楼:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; procedure FormCreate(Sender: TObject); procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); private { Private declarations } bMouseTrack:Boolean; procedure WndProc(var Msg:TMessage);override; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin bMouseTrack:=false; end; procedure TForm1.WndProc(var Msg: TMessage); begin if (Msg.Msg=WM_MOUSELEAVE) then //在这里捕获WM_MOUSELEAVE消息 begin Label1.Caption:='out'; bMouseTrack:=false; //鼠标Track已经完成 end; inherited; end; procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var tt:TagTRACKMOUSEEVENT; begin Label1.Caption:='in'; if not bMouseTrack then begin tt.cbSize:=sizeof(tt); tt.dwFlags:=TME_LEAVE; tt.hwndTrack:=Handle; TrackMouseEvent(tt); bMouseTrack:=true; //开始鼠标Track end; end; end.
----------------------------------------------
我是个俗人