I'm trying to build a component based on FMX.Objects.TImage
. I want the permanently assigned images by MultiResBitmap.Items
to change without having to use OnMouseEnter
and OnMouseLeave
in the application. Of course, I will use the constructor and the destructor.
I'm a beginner, and maybe I don't understand something. I've been trying for a week now, and I can't detect the mouse over the component and assign events correctly to it. I temporarily used ShowMessage()
for the test.
Theoretically, this code should probably work and not work. Tell me what I'm doing wrong.
unit ImageCustoms;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, FMX.Types, vcl.Controls, FMX.Objects, FMX.ImgList, vcl.Dialogs, vcl.Graphics, FMX.ExtCtrls;
type
TImageCostoms = class(TImage)
private
{ Private declarations }
FOnMouseLeave: TNotifyEvent;
FOnMouseEnter: TNotifyEvent;
procedure CMMouseEnter(var msg: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;
protected
{ Protected declarations }
procedure DoMouseEnter; virtual;
procedure DoMouseLeave; virtual;
public
{ Public declarations }
//constructor Create(AOwner: TComponent); override;
//destructor Destroy; override;
published
{ Published declarations }
property onm ouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property onm ouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TImageCostoms]);
end;
procedure TImageCostoms.CMMouseEnter(var msg: TMessage);
begin
ShowMessage('Enter');
DoMouseEnter;
end;
procedure TImageCostoms.CMMouseLeave(var msg: TMessage);
begin
ShowMessage('Leave');
DoMouseLeave;
end;
procedure TImageCostoms.DoMouseEnter;
begin
if Assigned(FOnMouseEnter) then
ShowMessage('Enter');
FOnMouseEnter(Self);
end;
procedure TImageCostoms.DoMouseLeave;
begin
if Assigned(FOnMouseLeave) then
ShowMessage('Leave');
FOnMouseLeave(Self);
end;
{constructor TImageCostoms.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
MultiResBitmap.Items[0].Bitmap.LoadFromFile('focus0.png'); // .\img\i.png
end;
destructor TImageCostoms.Destroy;
begin
inherited Destroy;
end; }
end.
CodePudding user response:
First off, don't mix VCL and FMX units together in your own units. VCL and FMX are not designed to be used together. And since FMX is cross-platform, don't use Winapi
units in your code unless you are writing Windows-specific code (which you are not, in this situation).
You don't need to handle the CM_MOUSE(ENTER|LEAVE)
messages directly, the framework already does that internally for you. And you don't need to redeclare the OnMouse(Enter|Leave)
events, they already exist and are published
in TImage
.
All you really need to do is override
(not redeclare) the existing virtual DoMouse(Enter|Leave)
methods from Timage
, eg:
unit ImageCustoms;
interface
uses
System.SysUtils, System.Classes, FMX.Types, FMX.Objects, FMX.ImgList, FMX.ExtCtrls;
type
TImageCostoms = class(TImage)
private
{ Private declarations }
protected
{ Protected declarations }
procedure DoMouseEnter; override;
procedure DoMouseLeave; override;
public
{ Public declarations }
//constructor Create(AOwner: TComponent); override;
//destructor Destroy; override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TImageCostoms]);
end;
procedure TImageCostoms.DoMouseEnter;
begin
...
inherited;
end;
procedure TImageCostoms.DoMouseLeave;
begin
...
inherited;
end;
{constructor TImageCostoms.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
MultiResBitmap.Items[0].Bitmap.LoadFromFile('focus0.png'); // .\img\i.png
end;
destructor TImageCostoms.Destroy;
begin
inherited Destroy;
end; }
end.
Don't use ShowMessage()
to debug component code, especially in events that react to keyboard/mouse focus changes. If you want to see debug messages, use OutputDebugString()
or equivilent instead, and then look for the messages in the IDE's Output window. Or, just make display changes in your UI, like color changes, etc.
CodePudding user response:
Thank you, it helped me, I was trying very uphill. In fact, in FMX it is simple and everything works. Thank you very much. I write the virtual keyboard support for the program, the whole is just a transparent button changing the focus slightly. Thanks again. For posterity, for now, it looks like this, I will try to add support from the global ImageList.
interface
uses
System.SysUtils, System.Classes, FMX.Types, FMX.Objects, FMX.ImgList, vcl.Dialogs, System.UITypes;
type
TImageCostoms = class(TImage)
private
{ Private declarations }
procedure DoMouseEnter; override;
procedure DoMouseLeave; override;
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TImageCostoms]);
end;
procedure TImageCostoms.DoMouseEnter;
begin
inherited ;
MultiResBitmap.Items[1].Bitmap.LoadFromFile('focus1.png');
end;
procedure TImageCostoms.DoMouseLeave;
begin
inherited;
MultiResBitmap.Items[0].Bitmap.LoadFromFile('focus0.png');
end;
constructor TImageCostoms.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
width:=45;
height:=45;
MultiResBitmap.Items[0].Bitmap.LoadFromFile('focus0.png');
end;
end.```