【问题标题】:Delphi Custom TImage Component - MouseEnter, MouseLeave in componentDelphi 自定义 TImage 组件 - 组件中的 MouseEnter、MouseLeave
【发布时间】:2021-12-23 04:48:21
【问题描述】:

我正在尝试基于FMX.Objects.TImage 构建一个组件。我希望MultiResBitmap.Items 永久分配的图像可以更改,而不必在应用程序中使用OnMouseEnterOnMouseLeave。当然,我会使用构造函数和析构函数。

我是一个初学者,也许我不明白一些东西。我已经尝试了一周,但我无法检测到鼠标悬停在组件上并将事件正确分配给它。我暂时使用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.

【问题讨论】:

    标签: delphi components controls mouseevent timage


    【解决方案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 中进行显示更改,例如颜色更改等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-10
      • 2016-04-03
      • 2018-03-22
      相关资源
      最近更新 更多