如何检测鼠标何时离开Delphi 6中的TPanel?

时间:2010-07-05 02:29:54

标签: delphi vcl

我正在使用OnMouseMove事件来检测鼠标指针何时在我的TPanel上,是否有办法知道鼠标指针何时离开它?

当鼠标指针悬停在面板上时,我需要面板改变颜色,一旦它离开它就会恢复原来的颜色吗?

我顺便使用Delphi 6。

请帮忙。

最诚挚的问候。

6 个答案:

答案 0 :(得分:8)

您可以使用OnMouseEnter / OnMouseLeave事件对来检测鼠标

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中测试以下代码,但我希望它没问题

更新

添加了TrackMouseEvent代码 - 感谢Sertac Akyuz的回答

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.

答案 1 :(得分:6)

另一种解决方案,使用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;

答案 2 :(得分:4)

如果您没有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;

答案 3 :(得分:2)

OnMouseLeave在。请注意,您还需要查看鼠标是否已离开整个应用程序,因为当面板位于表单边缘并且我离开表单时,OnMouseLeave不会触发。

答案 4 :(得分:1)

创建自己的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];

答案 5 :(得分:1)

感谢您的帮助。为了让我工作得很好,我使用Delphi 7创建了一个新的bitbtn控件,该控件源自原始bitbtn并实现了mouseenter和mouse leave。遵循我的代码:

TBitBtnPanel = class(TBitBtn)
  private
    { Private declarations }
    FOnMouseLeave: TNotifyEvent;
    FOnMouseEnter: TNotifyEvent;
    FActivateMouseLeave: boolean;
    procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  published
    { Published declarations }
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
    property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
  end;

{ TBitBtnPanel }

procedure TBitBtnPanel.CMMouseEnter(var Msg: TMessage);
begin
  Msg.Result := WM_CANCELMODE;
  FActivateMouseLeave:=True;
  if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;

procedure TBitBtnPanel.CMMouseLeave(var Msg: TMessage);
begin
  if (FActivateMouseLeave) then
  begin
    Msg.Result := WM_CANCELMODE;
    FActivateMouseLeave:=False;
    if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
  end;
end;

constructor TBitBtnPanel.Create(AOwner: TComponent);
begin
  FActivateMouseLeave:=True;
  inherited;
end;

Hugo Barros - 巴西