Delphi 自定义 TImage 组件 - 组件中的 MouseEnter、MouseLeave
Posted
技术标签:
【中文标题】Delphi 自定义 TImage 组件 - 组件中的 MouseEnter、MouseLeave【英文标题】:Delphi Custom TImage Component - MouseEnter, MouseLeave in component 【发布时间】:2021-12-23 04:48:21 【问题描述】:我正在尝试基于FMX.Objects.TImage
构建一个组件。我希望MultiResBitmap.Items
永久分配的图像可以更改,而不必在应用程序中使用OnMouseEnter
和OnMouseLeave
。当然,我会使用构造函数和析构函数。
我是一个初学者,也许我不明白一些东西。我已经尝试了一周,但我无法检测到鼠标悬停在组件上并将事件正确分配给它。我暂时使用ShowMessage()
进行测试。
理论上,这段代码应该可以工作,但不能工作。告诉我我做错了什么。
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 OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: 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.
【问题讨论】:
【参考方案1】:谢谢你,它帮助了我,我正在努力上坡。事实上,在 FMX 中它很简单并且一切正常。非常感谢。我为程序编写了虚拟键盘支持,整个只是一个稍微改变焦点的透明按钮。再次感谢。对于后人,现在看起来像这样,我将尝试添加来自全局 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.```
【讨论】:
如果您想在某个 ImageList 中包含所有这些图像,那么为什么不直接使用 TSpeedButton 连接到 AnyImage 列表,然后简单地更改图像索引以显示所需图片。或者也许只是使用只有一张图像和附加效果的 SpeedButton 来达到您所说的这种轻微的焦点效果。通过这种方式,您可以减少应用程序所需的图像数量,并在聚焦状态和非聚焦状态之间逐渐过渡。这值得一试。【参考方案2】:首先,不要在自己的设备中混合使用 VCL 和 FMX 设备。 VCL 和 FMX 不能一起使用。而且由于 FMX 是跨平台的,因此不要在代码中使用 Winapi
单位,除非您正在编写 Windows 特定 代码(在这种情况下您不是)。
您不需要直接处理CM_MOUSE(ENTER|LEAVE)
消息,框架已经在内部为您完成了这项工作。而且您不需要重新声明 OnMouse(Enter|Leave)
事件,它们已经存在并且在 TImage
中是 published
。
您真正需要做的只是override
(而不是重新声明)来自Timage
的现有虚拟DoMouse(Enter|Leave)
方法,例如:
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.
不要使用ShowMessage()
调试组件代码,尤其是在对键盘/鼠标焦点更改做出反应的事件中。如果要查看调试消息,请改用OutputDebugString()
或等效项,然后在 IDE 的“输出”窗口中查找消息。或者,只需在 UI 中进行显示更改,例如颜色更改等。
【讨论】:
以上是关于Delphi 自定义 TImage 组件 - 组件中的 MouseEnter、MouseLeave的主要内容,如果未能解决你的问题,请参考以下文章
Delphi7Personal EAccessViolation 同时创建从 TImage 派生的组件
Delphi自定义组件如何在属性面板中实现打开文件的对话框?