我正在使用OnMouseMove事件来检测鼠标指针是否悬停在我的TPanel上,有没有办法知道鼠标指针何时移开了它?
当鼠标指针悬停在面板上时,我需要将面板的颜色更改,并在移开后返回到原始颜色。
顺便说一下,我正在使用Delphi 6。
请帮忙解决。
最好的问候。
procedure TForm1.Panel1MouseEnter(Sender: TObject);
begin
Panel1.Caption:= 'IN';
Panel1.Color:= clBlue;
end;
procedure TForm1.Panel1MouseLeave(Sender: TObject);
begin
Panel1.Caption:= 'OUT';
Panel1.Color:= clWhite;
end;
我无法在Delphi 6中测试以下代码,但希望一切顺利。
感谢Sertac Akyuz提供的答案,已添加TrackMouseEvent代码。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
FOldWndProc: TWndMethod;
FMouseInPanel: Boolean;
procedure PanelWndProc(var Message: TMessage);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FOldWndProc:= Panel1.WindowProc;
Panel1.WindowProc:= PanelWndProc;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Panel1.WindowProc:= FOldWndProc;
end;
procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mEvnt: TTrackMouseEvent;
begin
if not FMouseInPanel then begin
mEvnt.cbSize := SizeOf(mEvnt);
mEvnt.dwFlags := TME_LEAVE;
mEvnt.hwndTrack := Panel1.Handle;
TrackMouseEvent(mEvnt);
Panel1.Caption:= 'IN';
FMouseInPanel:= True;
end;
end;
// if not defined in Delphi 6, WM_MOUSELEAVE = $02A3
procedure TForm1.PanelWndProc(var Message: TMessage);
begin
if Message.Msg = WM_MOUSELEAVE then begin
Panel1.Caption:= 'OUT';
FMouseInPanel:= False;
end;
FOldWndProc(Message);
end;
end.
TrackMouseEvent
接收WM_MOUSELEAVE
事件;type
TMyPanel = class(TPanel)
private
FMouseTracking: Boolean;
FOnMouseLeave: TNotifyEvent;
procedure WMMouseLeave(var Msg: TMessage); message WM_MOUSELEAVE;
protected
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
published
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
procedure TMyPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
var
mEvnt: TTrackMouseEvent;
begin
inherited;
if not FMouseTracking then begin
mEvnt.cbSize := SizeOf(mEvnt);
mEvnt.dwFlags := TME_LEAVE;
mEvnt.hwndTrack := Handle;
TrackMouseEvent(mEvnt);
FMouseTracking := True;
end;
end;
procedure TMyPanel.WMMouseLeave(var Msg: TMessage);
begin
Msg.Result := 0;
FMouseTracking := False;
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self);
end;
如果您没有OnMouseEnter和OnMouseLeave,则可以使用OnMouseMove并将鼠标捕获到面板上。 捕获鼠标需要稍微多做一些工作,但效果更好。
procedure Form1.Panel1MouseMove(Sender:TObject; Shift:TShiftState; X,Y:Integer);
begin
if (X >= 0) and (Y >= 0) and (X < Panel1.Width) and (Y < Panel1.Height) then
begin
// Movement within the panel
if GetCapture <> Panel1.Handle then
begin
// The mouse just moved over the panel. Do your "on enter" stuff
// over here.
SetCapture(Panel1.Handle); // Capture the mouse so we'll receive
// mouse move messages even if the cursor
// is no longer over our panel.
end;
end
else
begin
// Movement outside the panel! This is possible because I've previously
// captured the mouse.
// Do your "move out" stuff over here.
ReleaseCapture; // release mouse capture
end;
end;
OnMouseLeave。请注意,您还需要查看鼠标是否离开了整个应用程序,因为当面板位于表单边缘且我离开表单时,OnMouseLeave可能不会触发。
TCustomPanel
(或 TPanel
) 派生,因为 Delphi 6 默认不包含 MouseEnter 和 MouseLeave 事件,可以自行添加。将以下内容添加到声明部分中的私有部分:procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
接下来就是处理mouseenter和mouseleave事件的事情了:
procedure TMyPanel.CMMouseEnter(var msg: TMessage);
begin
inherited;
Color := clBlue;
{ Do Whatever }
end;
procedure TMyPanel.CMMouseLeave(var msg: TMessage);
begin
inherited;
Color := clRed;
{ Do Whatever }
end;
希望这可以帮到你。如果颜色没有显示出来,请将以下内容添加到您的组件构造函数中:
ControlStyle := ControlStyle - [csParentBackground] + [csOpaque];
感谢您的帮助。对我来说非常有效,我从原始的bitbtn派生出一个新的bitbtn控件,并使用Delphi 7实现了mouseenter和mouseleave事件。以下是我的代码:
TBitBtnPanel = class(TBitBtn) private { 私有声明 } FOnMouseLeave: TNotifyEvent; FOnMouseEnter: TNotifyEvent; FActivateMouseLeave: boolean; procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE; protected { 受保护的声明 } public { 公共声明 } constructor Create(AOwner: TComponent); override; published { 发布声明 } property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; end;雨果·巴罗斯 - 巴西
TrackMouseEvent
中没有指定窗口,则不会发布WM_MOUSELEAVE
。 - Sertac Akyuz