2

I have put images (TImage) as buttons in my program. I want to add some extra effects, so in OnMouseMove (whenever the user moves his mouse over the image) the image is replaced by another image in order to give the extra effect:

procedure TForm1.Image4MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var 
  Path, Destination: String;
begin
  Path := ParamStr(0);
  Destination := Extractfilepath(Path) + 'Images\Image2.bmp';
  Image4.Picture.LoadFromFile(Destination);
end;

But whenever the user moves his mouse away (when he leaves the image), it doesn't undo the things done (change back to Image1). How am I going to do that? There isn't a OnMouseLeave event. I am using delphi 7.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
user2242090
  • 37
  • 1
  • 2
  • 6

2 Answers2

8

First, the code in your question is horrible! It will (re-) load the bitmap every time the cursor moves a pixel inside the image control! That's such a waste of CPU time!

Anyhow, in modern versions of Delphi, you'd simply use the OnMouseEnter and OnMouseLeave events. I don't think these exist in Delphi 7, so you have to do something like this:

TImage = class(ExtCtrls.TImage)
protected
  procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
end;

where

{ TImage }

procedure TImage.CMMouseEnter(var Message: TMessage);
begin
  // Do something
end;

procedure TImage.CMMouseLeave(var Message: TMessage);
begin
  // Do something else 
end;

This example takes the form of an interposer class, but of course you might be better of making a properly subclassed control.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • If you don't want to derive a new class, you can alternatively subclass the `TImage.WindowProc` property to catch the same messages. – Remy Lebeau Apr 10 '13 at 19:43
0

If you load another picture in the image control, then the previous loaded one is gone: you have to load it again. You could do that when the mouse moves over the container of the image, presumably the form itself.

But loading pictures in a mouse move event handler is terrible as Andreas already explained.

May I present an alternative? Create two image controls and place them at the same place. Then add the following handlers:

procedure TForm1.Image4AMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Image4B.BringToFront;
  Image4B.Tag := 1;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Image4B.Tag = 1 then
  begin
    Image4B.Tag := 0;
    Image4A.BringToFront;
  end;
end;
Community
  • 1
  • 1
NGLN
  • 43,011
  • 8
  • 105
  • 200
  • 1
    What if there is no free space (or very narrow regions) surrounding the pictures? Still, I'd even be a bit concerned about my own implementation, because if the image is aligned to some border of the form, then the cursor can leave the entire form without the picture being 'reset'. – Andreas Rejbrand Apr 10 '13 at 19:52
  • @AndreasRejbrand but what would be the alternatzives except InstallLLMouseHook – bummi Apr 10 '13 at 20:26
  • @Andreas `OnMouseLeave` wíll fire, even when the control is aligned against a form border or other control. – NGLN Apr 10 '13 at 20:35
  • @NGLN: But the old-Delphi version doesn't do that. I tried it on Delphi 4 with Windows 95. – Andreas Rejbrand Apr 10 '13 at 21:38