Przypisanie procedury dynamicznie do zdarzenia wewnątrz kodu komponentu

Przypisanie procedury dynamicznie do zdarzenia wewnątrz kodu komponentu
srobert1000
  • Rejestracja: dni
  • Ostatnio: dni
0

Mam komponent bazujący na TCustomListView:

Kopiuj
unit DRListView;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ComCtrls, Messages, UxTheme, LCLType, Windows;

type
  TDRListView = class(TCustomListView)
  private
    FColumn: TListColumn;
    FItemHeight: Integer;
    procedure DROnDrawItem(Sender: TCustomListView; AItem: TListItem; ARect: TRect; AState: TOwnerDrawState);
  protected
    FPreviewLight: Integer;
    procedure WMMeasureItem(var AMsg: TWMMeasureItem); message CN_MEASUREITEM;
    procedure CreateWnd; override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseLeave; override;
    procedure Resize; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Action;
    property AllocBy;
    property Align;
    property Anchors;
    property BorderStyle;
    property BorderWidth;
    property Color;
    property Constraints;
    property Enabled;
    property Font;
    property FlatScrollBars;
    property ItemHeight: Integer read FItemHeight write FItemHeight default 50;
    property Items;
    property MultiSelect;
    property ParentBiDiMode;
    property ParentColor default False;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property SortType;
    property TabOrder;
    property TabStop default True;
    property Visible;
    property OnChange;
    property OnClick;
    property OnDblClick;
    property OnDeletion;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnSelectItem;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Common Controls',[TDRListView]);
end;

constructor TDRListView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ViewStyle := vsReport;
  OwnerDraw := True;
  FItemHeight := 50;
  ShowColumnHeaders := False;
  ReadOnly := True;
  FColumn := Columns.Add;
  FColumn.Width := Width;
  FPreviewLight := -1;
  OnDrawItem := @DROnDrawItem; // Tutaj występuje błąd
end;

{deklaracja pozostałych procedur}

initialization
  UxTheme.InitThemeLibrary;


end.

Kiedy próbuję przypisać procedurę DROnDrawItem do zdarzenia OnDrawItem kompilator pokazuje błąd:

Kopiuj
Error: Incompatible types: got "<procedure variable type of procedure(TCustomListView;TListItem;TRect;TOwnerDrawState) of object;Register>" 
expected "COMCTRLS.<procedure variable type of procedure(TCustomListView;TListItem;TRect;TOwnerDrawState) of object;Register>"

O co tu chodzi?

GS
  • Rejestracja: dni
  • Ostatnio: dni
0

Nie jestem ekspertem od Lazaura i Free Pascala, ale spróbował bym jak poniżej

Kopiuj
 OnDrawItem := DROnDrawItem
flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
1

Musisz użyć operatora adresu:

Kopiuj
OnDrawItem := @DROnDrawItem;

Taki jest wymóg Free Pascala, zarówno w przypadku zdarzeń, jak i zwykłych funkcji. I jest to lepsza składnia od tej Delphi, dlatego że operator adresu jasno informuje, że chodzi o przypisanie adresu do zmiennej, a nie wyniku wywołanej subrutyny. Dzięki temu czytelność jest lepsza.

MI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 50
5

Problemem jest niezgodność typów bo użyłeś modułu "Windows" jako ostatni. Moduł ten definiuje zarówno typ TRect jak i TOwnerDrawState, jednak TCustomListView używa typów TRect z modułu Classes i TOwnerDrawState z modułu LCLType.
Rozwiązaniem jest użycie nazwy modułu jako przedrostka:

Kopiuj
procedure DROnDrawItem(Sender: TCustomListView; AItem: TListItem; ARect: Classes.TRect; AState: LCLType.TOwnerDrawState);

typu lub przesunięcie modułu Windows na początek listy używanych modułów:

Kopiuj
uses
  Windows, Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ComCtrls, Messages, UxTheme, LCLType;

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.