You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi自定义FMX TImage组件实现MouseEnter、MouseLeave事件问题求助

FMX自定义图片组件鼠标悬停无响应问题修复

代码核心错误点

  • 框架单元混引:同时引入了VCL和FMX两类框架的单元,两类框架控件体系、消息逻辑完全独立,混引会导致逻辑冲突,vcl.Controls、vcl.Dialogs等VCL单元不应该出现在FMX组件代码中。
  • 消息机制误用:CM_MOUSEENTER、CM_MOUSELEAVE是VCL框架的私有Windows消息,FMX控件不依赖Windows消息体系,用消息绑定的方式检测鼠标状态完全不生效。
  • 事件逻辑错误:已有的DoMouseEnter、DoMouseLeave方法中,将外部事件调用代码放在了非空判断外,未给组件赋值OnMouseEnter/OnMouseLeave时会触发空指针异常;且内部逻辑依赖外部事件赋值,不满足你无需调用外部事件就自动切换图片的需求。
  • 资源访问越界:注释掉的构造函数中直接访问MultiResBitmap.Items[0],未预先添加图片项时访问索引0会直接抛出数组越界异常。

修正后完整代码

unit ImageCustoms;

interface

uses
  System.SysUtils, System.Classes, FMX.Types, FMX.Objects, FMX.Dialogs;

type
  TImageCustoms = class(TImage)
  private
    { Private declarations }
    FOnMouseLeave: TNotifyEvent;
    FOnMouseEnter: TNotifyEvent;
  protected
    { Protected declarations }
    procedure DoMouseEnter; override;
    procedure DoMouseLeave; override;
  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', [TImageCustoms]);
end;

constructor TImageCustoms.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  // 预加载图片前先判断数量,避免越界
  if MultiResBitmap.Count = 0 then
    MultiResBitmap.Add;
  // 这里可以换成你的资源加载逻辑,建议用资源文件而不是本地路径
  // MultiResBitmap.Items[0].Bitmap.LoadFromFile('focus0.png');
end;

destructor TImageCustoms.Destroy;
begin
  inherited Destroy;
end;

procedure TImageCustoms.DoMouseEnter;
begin
  inherited;
  // 内部逻辑直接写这里,不需要依赖外部事件赋值
  ShowMessage('Enter');
  // 切换悬停图片的逻辑可以写在这里
  
  // 执行外部绑定的事件(如果有赋值)
  if Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TImageCustoms.DoMouseLeave;
begin
  inherited;
  // 内部逻辑直接写这里
  ShowMessage('Leave');
  // 切换默认图片的逻辑可以写在这里
  
  // 执行外部绑定的事件(如果有赋值)
  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;

end.

功能说明

  • 修正后的代码完全基于FMX原生框架逻辑,通过重写父类已有的DoMouseEnter、DoMouseLeave虚方法实现鼠标状态检测,不需要绑定外部事件就能执行内部的图片切换逻辑。
  • 保留了OnMouseEnter、OnMouseLeave发布属性,不影响组件在使用时额外绑定自定义事件。
  • 预加载图片逻辑建议使用资源文件嵌入,避免发布后本地路径不存在的问题。

内容的提问来源于stack exchange,提问作者Max_Poland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:36:03