How can I trigger an event when the mouse leaves my control?
Asked Answered
C

2

6

How do I create an OnMouseLeave event?

Corticosteroid answered 27/4, 2011 at 14:40 Comment(11)
In which component do you want create (or assign) this event?Blameless
TCustomControl, im creating my own unicode button. :)Corticosteroid
Creating your own Unicode button sounds rather a painful task considering Delphi already has one. Not Delphi 7 of course, but you are crippling yourself if you stick with out of date tools.Hindrance
I have buttons in .dcu files but i need my own unicode button since im from latvia. Remember not TButton, but my own.Corticosteroid
Yes I appreciate that you are from Latvia and that Unicode is important. That's why you should seriously consider a Unicode Delphi and then these problems disappear and you can get on with the coding.Hindrance
I am using WideStrings in Delphi. It works fine.Corticosteroid
I don`t need help with unicodECorticosteroid
And what about the fact that Delphi's message loop is ANSI? Are you painting the button yourself?Hindrance
I don't see the reason why you don't use a Unicode Delphi, Robrok.Debar
@TheBlastOne: I think that Delphi 7 was the last version of Delphi that had a free edition aimed at hobbyists. I also think that is why Delphi 7 is still so widely used.Clevelandclevenger
I need some help, because canvas can only draw ANSI letters. I need unicode support.Corticosteroid
B
9

Another alternative to the Andreas solution, is use the CM_MOUSELEAVE VCL Message which is already defined in delphi 7.

check this sample using a interposer class for the TButton

type
  TButton = class(StdCtrls.TButton)
  private
    FOnMouseLeave: TNotifyEvent;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  end;


  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
  private
     procedure ButtonMouseLeave(Sender: TObject);
  public
  end;

//handle the message and call the event handler
procedure TButton.CMMouseLeave(var Message: TMessage);
begin
  if (Message.LParam = 0) and Assigned(FOnMouseLeave) then
      FOnMouseLeave(Self);
end;


procedure TForm1.ButtonMouseLeave(Sender: TObject);
begin
   //your code goes here   
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //assign the event
  Button1.OnMouseLeave:=ButtonMouseLeave;
end;
Blameless answered 27/4, 2011 at 15:10 Comment(3)
Will this work if the custom control is at the very edge of the form, and the mouse is leaving the control and form without being above the form at all?Clevelandclevenger
@Andreas I think , this will work in that situation, in fact this way is very similar as how the modern versions of Delphi implement this event.Blameless
@RRUZ: I tried essentially this on Delphi 4 on Windows 95, with a TImage (a graphic control), and it doesn't work 'at the form's edge'.Clevelandclevenger
C
6

You can tell Windows to post you a message, more specifically a WM_MOUSELEAVE message, when the mouse leaves the control. To do this, call the TrackMouseEvent function. In the TRACKMOUSEEVENT structure, specify the TME_LEAVE flag.

On request, some code:

When the control has been created, and the mouse is inside the client area of the control, tell Windows that you want to be notified about the mouse leaving the control:

procedure TMyControl.SetMouseEvent;
var
  tme: TTrackMouseEvent;
begin
  tme.cbSize := sizeof(tme);
  tme.dwFlags := TME_LEAVE;
  tme.hwndTrack := Self.Handle;
  TrackMouseEvent(tme);
end;

Call this procedure when the control has been created and the mouse is inside the control. Now you just have to listen to the WM_MOUSELEAVE mesage. In your WndProc procedure (a protected member of the class), add a WM_MOUSELEAVE case.

procedure TMyControl.WndProc(var Message: TMessage);
begin
  inherited;
  case Message.Msg of
    WM_MOUSELEAVE:
      beep;
  end;
end;

I think that Windows removes the notification request when a message has been created, so you have to rerequest the notification when you have recieved a message. You cannot call SetMouseEvent in the WndProc, because the mouse needs to be inside the client area of the control when you call TrackMouseEvent. I think you could place your SetMouseEvent inside the OnMouseMove of the control:

procedure TMyControl.WndProc(var Message: TMessage);
begin
  inherited;
  case Message.Msg of
    WM_MOUSELEAVE:
      beep;
    WM_MOUSEMOVE:
      SetMouseEvent;
  end;
end;

I haven't tested the code above myself, because I use a newer version of Delphi, Delphi 2009, which does things like this behind the scenes (I think, because there is now a OnMouseLeave event in controls), and I think that will interfere.

Clevelandclevenger answered 27/4, 2011 at 14:45 Comment(2)
Please, help! How to create events in Delphi 7? Example or source code plsCorticosteroid
@Robrok: How to create an event, asked yesterday.Shevat

© 2022 - 2024 — McMap. All rights reserved.