求TFDQuery原生TComponentEditor的类名与所在单元
自定义TFDQuery右键菜单保留原生编辑器功能的解决方法
我给自定义TFDQuery的右键菜单添加新选项时,按照常规方法实现自定义TComponentEditor后,发现原有Fields Editor、Query Editor等功能都无法访问了——因为自定义编辑器完全替换了TFDQuery的原生编辑器。我推测应该从FireDAC的原生TComponentEditor继承来扩展,但找不到原生编辑器的类和所在单元。后来通过代码获取到原生编辑器是FireDAC.dcl.Reg单元的TFDQueryEditor,但既没有这个单元的源码,也找不到FireDAC源码里的相关引用。
获取编辑器信息的代码
constructor TKpQuery.Create(AOwner: TComponent); begin inherited Create(AOwner); ShowMessage( (GetComponentEditor(Self, NIL) as TObject).ClassName ); ShowMessage( (GetComponentEditor(Self, NIL) as TObject).UnitName ); end;
原自定义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}
解决方法
不需要直接继承FireDAC的私有编辑器类,而是通过委托原生编辑器的方式来扩展功能:
- 在自定义编辑器中保存原生编辑器的实例
- 重写
GetVerbCount时,将自定义选项数量加上原生编辑器的动词数量 - 重写
GetVerb时,索引小于自定义数量返回自定义动词,否则返回原生编辑器对应索引的动词 - 重写
ExecuteVerb时,同理处理执行逻辑 - 重写
Edit方法,调用原生编辑器的Edit方法以保留原有的编辑窗口
修改后的自定义编辑器代码示例:
interface uses System.Classes, DesignIntf, DesignEditors, FireDAC.Comp.Client; type TKpQueryEditor=class(TComponentEditor) private FOriginalEditor: TComponentEditor; public constructor Create(AComponent: TComponent; ADesigner: IDesigner); override; destructor Destroy; override; function GetVerbCount: Integer; override; function GetVerb(Index: Integer): string; override; procedure ExecuteVerb(Index: Integer); override; procedure Edit; override; end; implementation uses Data.DB, System.Types, System.SysUtils; constructor TKpQueryEditor.Create(AComponent: TComponent; ADesigner: IDesigner); begin inherited; // 创建原生编辑器实例 FOriginalEditor := GetComponentEditor(AComponent, ADesigner) as TComponentEditor; if FOriginalEditor = nil then FOriginalEditor := inherited Create(AComponent, ADesigner); end; destructor TKpQueryEditor.Destroy; begin FOriginalEditor.Free; inherited; end; function TKpQueryEditor.GetVerbCount: Integer; begin // 自定义动词数 + 原生编辑器动词数 Result := 1 + FOriginalEditor.GetVerbCount; end; function TKpQueryEditor.GetVerb(Index: Integer): string; begin if Index = 0 then Result := 'Set DisplayLabels' else // 索引偏移,调用原生编辑器的GetVerb Result := FOriginalEditor.GetVerb(Index - 1); end; procedure TKpQueryEditor.ExecuteVerb(Index: Integer); begin if Index = 0 then (Component as TKpQuery).SetDisplayLabels else // 索引偏移,调用原生编辑器的ExecuteVerb FOriginalEditor.ExecuteVerb(Index - 1); end; procedure TKpQueryEditor.Edit; begin // 调用原生编辑器的Edit方法,保留原有的编辑功能 FOriginalEditor.Edit; end;
内容的提问来源于stack exchange,提问作者Marc Guillot
相关产品推荐
相关产品推荐

