Как определить, когда мышь отходит от TPanel в Delphi 6?

Я использую событие OnMouseMove, чтобы определить, когда указатель мыши находится над моим TPanel, есть ли способ узнать, когда указатель мыши отошел от него?

Мне нужно, чтобы панель меняла цвет, когда указатель мыши находится над ней, и возвращался к исходному цвету, как только он отошел от нее?

Я использую Delphi 6, кстати.

Пожалуйста помоги.

С уважением.

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;

Вы можете использовать пару событий 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 - благодаря ответу Сертака Акьюза

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.

Если у вас нет 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 и реализующий mouseenter и отпуск мыши, с Delphi 7. Следуйте моему коду:

TBitBtnPanel = class (TBitBtn)
  частный
    {Частные объявления}
    FOnMouseLeave: TNotifyEvent;
    FOnMouseEnter: TNotifyEvent;
    FActivateMouseLeave: логическое значение;
    процедура CMMouseEnter(var Msg: TMessage); сообщение CM_MOUSEENTER;
    процедура CMMouseLeave(var Msg: TMessage); сообщение CM_MOUSELEAVE;
  защищенный
    {Защищенные декларации}
  общественности
    {Публичные декларации}
    конструктор Create(AOwner: TComponent); переопределить;
  опубликованный
    {Опубликованные объявления}
    свойство OnMouseLeave: TNotifyEvent читать FOnMouseLeave писать FOnMouseLeave;
    свойство OnMouseEnter: TNotifyEvent читать FOnMouseEnter писать FOnMouseEnter;
  конец;

{ TBitBtnPanel }

процедура TBitBtnPanel.CMMouseEnter(var Msg: TMessage);
начать
  Msg.Result:= WM_CANCELMODE;
  FActivateMouseLeave:=True;
  если назначено (FOnMouseEnter), то FOnMouseEnter(Self);
конец;

процедура TBitBtnPanel.CMMouseLeave(var Msg: TMessage);
начать
  if (FActivateMouseLeave) тогда
  начать
    Msg.Result:= WM_CANCELMODE;
    FActivateMouseLeave:=False;
    если назначено (FOnMouseLeave), то FOnMouseLeave(Self);
  конец;
конец;

конструктор TBitBtnPanel.Create(AOwner: TComponent);
начать
  FActivateMouseLeave: = True;
  наследуется;
конец;

Уго Баррос - Бразилия

Другие вопросы по тегам