delphifiredacdelphi-11-alexandria

Which is the TComponentEditor for TFDQuery?


I needed to add a new option on the contextual menu of our custom TFDQuery, so I followed this guide and it works nicely. How to add context-menu actions in Delphi Form Designer for a custom component?

The problem is that it replaces the current TComponentEditor for the TFDQuery, so I can no longer access to its Fields Editor, Query Editor, ...

I guess what I need is to derive my TComponentEditor from the FireDAC base TComponentEditor, but I haven't been able to identify it. Can you, please, address me to the Unit and class that declares the regular TComponentEditor for a TFDQuery ?.

Update: I have added this code to my custom Query to get the current ComponentEditor for TFDQuery, it says TFDQueryEditor in the FireDAC.dcl.Reg unit. But my system doesn't have any FireDAC.Dcl.Reg.pas, nor I can find any reference to TFDQueryEditor to the FireDAC source code.

constructor TKpQuery.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  ShowMessage(  (GetComponentEditor(Self, NIL) as TObject).ClassName  );
  ShowMessage(  (GetComponentEditor(Self, NIL) as TObject).UnitName  );
end;

This is my custom ComponentEditor:

interface

uses System.Classes, DesignIntf, DesignEditors, FireDAC.Comp.Client;

type
{$REGION 'TKpQuery Editor Declaration'}
  TKpQueryEditor=class(TComponentEditor)
    function GetVerbCount: Integer; override;
    function GetVerb(Index: Integer): string; override;
    procedure ExecuteVerb(Index: Integer); override;
  end;
{$ENDREGION}

{$REGION 'TKpQuery Declaration'}
  ...
  ...
{$ENDREGION}

procedure Register;

implementation

uses
  Data.DB,
  System.Types,
  System.SysUtils,
  System.StrUtils,
  System.RegularExpressions;

procedure Register;
begin
  {$IFDEF WIN32}
  RegisterComponents('My Custom Data Access', [TKpQuery]);
  RegisterComponentEditor(TKpQuery, TKpQueryEditor);
  {$ENDIF}
end;

{$REGION 'TKpQuery Editor Implementation'}
procedure TKpQueryEditor.ExecuteVerb(Index: Integer);
begin
  inherited;
  case Index of
    0: (Component as TKpQuery).SetDisplayLabels;  
  end;
end;

function TKpQueryEditor.GetVerb(Index: Integer): string;
begin
  case Index of
    0: Result := 'Set DisplayLabels';  
  end;
end;

function TKpQueryEditor.GetVerbCount: Integer;
begin
  Result := 1;   
end;
{$ENDREGION}

Solution

  • As Uwe Raabe has confirmed that the unit needed to derive the FDQuery Component Editor is not available, I've replicated the solution that Blurry Sterk suggested.

    This seems to work fine:

    unit MyCustom.Query.Editor;
    
    interface
    
    uses
      Windows, SysUtils, Classes, DesignIntf, DesignEditors;
    
      type
      TgkQueryEditor = class(TComponentEditor)
      private
        FOldEditor: IComponentEditor;
      protected
      public
        constructor Create(AComponent: TComponent; ADesigner: IDesigner); override;
        procedure ExecuteVerb(Index: Integer); override;
        function GetVerb(Index: Integer): string; override;
        function GetVerbCount: Integer; override;
        procedure Edit; override;
        procedure Copy; override;
      end;
    
    procedure Register;
    
    implementation
    
    uses
      MyCustom.Query;
    
    var
      PrevEditorClass: TComponentEditorClass = nil;
    
    constructor TgkQueryEditor.Create(AComponent: TComponent; ADesigner: IDesigner);
    begin
      inherited Create(AComponent, ADesigner);
    
      if Assigned(PrevEditorClass) then
        FOldEditor := TComponentEditor(PrevEditorClass.Create(AComponent, ADesigner));
    end;
    
    procedure TgkQueryEditor.ExecuteVerb(Index: Integer);
    var
      i: Integer;
    begin
      i := Index - FOldEditor.GetVerbCount;
      case i of
        0: (Component as TKpQuery).SetDisplayLabels;  // This is my new custom action
      else
        if Assigned(FOldEditor) then
          FOldEditor.ExecuteVerb(Index)
      end;
    end;
    
    function TgkQueryEditor.GetVerb(Index: Integer): string;
    var
      i: Integer;
    begin
      i := Index - FOldEditor.GetVerbCount;
      case i of
        0: Result := 'Set Display Label';
      else
        if Assigned(FOldEditor) then
          Result := FOldEditor.GetVerb(Index)
      end;
    end;
    
    function TgkQueryEditor.GetVerbCount: Integer;
    begin
      Result := 1;
      if Assigned(FOldEditor) then
        Inc(Result, FOldEditor.GetVerbCount);
    end;
    
    procedure TgkQueryEditor.Edit;
    begin
      if Assigned(FOldEditor) then
        FOldEditor.Edit;
    end;
    
    procedure TgkQueryEditor.Copy;
    begin
      if Assigned(FOldEditor) then
        FOldEditor.Copy;
    end;
    
    procedure Register;
    var
      Query: TKpQuery;
      Editor: IComponentEditor;
    begin
      Query := TKpQuery.Create(nil);
      try
        Editor := GetComponentEditor(Query, nil);
        if Assigned(Editor) then
          PrevEditorClass := TComponentEditorClass((Editor as TObject).ClassType);
      finally
        Editor := nil;
        FreeAndNIL(Query);
      end;
      RegisterComponentEditor(TKpQuery, TgkQueryEditor);
    end;
    
    end.