1

我正在尝试使用 ToolsApi 实现 IDE 向导,并使用 GExperts 常见问题解答(http://www.gexperts.org/examples/GXModuleCreator.pas)作为参考。

尽管 bpl 可以编译,但该单元并未显示在 IDE 上。我正在使用 Delphi 10.3.2 Rio。

unit ModuleCreator;

interface

uses
  SysUtils, Windows, Dialogs, ToolsAPI;

type
  TJIdeWizardSourceFile = class(TInterfacedObject, IOTAFile)
  private
    FSource: string;
  public
    function GetSource: string;
    function GetAge: TDateTime;
    constructor Create(const Source: string);
  end;

  TJIdeWizardModuleCreator = class(TInterfacedObject, IOTACreator, IOTAModuleCreator)
  public
    // IOTACreator
    function GetCreatorType: string;
    function GetExisting: Boolean;
    function GetFileSystem: string;
    function GetOwner: IOTAModule;
    function GetUnnamed: Boolean;
    // IOTAModuleCreator
    function GetAncestorName: string;
    function GetImplFileName: string;
    function GetIntfFileName: string;
    function GetFormName: string;
    function GetMainForm: Boolean;
    function GetShowForm: Boolean;
    function GetShowSource: Boolean;
    function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
    function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
    function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
    procedure FormCreated(const FormEditor: IOTAFormEditor);
  end;

implementation

{ TJIdeWizardModuleCreator }

procedure TJIdeWizardModuleCreator.FormCreated(const FormEditor: IOTAFormEditor);
begin
  //
end;

function TJIdeWizardModuleCreator.GetAncestorName: string;
begin
  Result := 'Form';
end;

function TJIdeWizardModuleCreator.GetCreatorType: string;
begin
  Result := sUnit;
end;

function TJIdeWizardModuleCreator.GetExisting: Boolean;
begin
  Result := False;
end;

function TJIdeWizardModuleCreator.GetFileSystem: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetFormName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetImplFileName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetIntfFileName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetMainForm: Boolean;
begin
  Result := False;
end;

function TJIdeWizardModuleCreator.GetOwner: IOTAModule;
var
  ModuleServices: IOTAModuleServices;
  Module: IOTAModule;
  NewModule: IOTAModule;
begin
  // You may prefer to return the project group's ActiveProject instead
  Result := nil;
  ModuleServices := (BorlandIDEServices as IOTAModuleServices);
  Module := ModuleServices.CurrentModule;

  if Module <> nil then
  begin
    if Module.QueryInterface(IOTAProject, NewModule) = S_OK then
      Result := NewModule

    else if Module.OwnerModuleCount > 0 then
    begin
      NewModule := Module.OwnerModules[0];
      if NewModule <> nil then
        if NewModule.QueryInterface(IOTAProject, Result) <> S_OK then
          Result := nil;
    end;
  end;
end;

function TJIdeWizardModuleCreator.GetShowForm: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.GetShowSource: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.GetUnnamed: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

function TJIdeWizardModuleCreator.NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
begin
  // or Result := nil; for the default unit
  Result := nil;
end;

function TJIdeWizardModuleCreator.NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

{ TJIdeWizardSourceFile }

constructor TJIdeWizardSourceFile.Create(const Source: string);
begin
  FSource := Source;
end;

function TJIdeWizardSourceFile.GetAge: TDateTime;
begin
  Result := -1;
end;

function TJIdeWizardSourceFile.GetSource: string;
begin
  result := FSource;
end;

end.

这是我如何从 IOTAModuleCreator 调用方法“NewImplSource”的示例

  procedure TfrmMapearObjetoRelacional.btnSimpleORMDaoClick(Sender: TObject);
  var
    _Mod: TJIdeWizardModuleCreator;
    _Str: string;
  begin
    _Mod := TJIdeWizardModuleCreator.Create;
    try
      _Str := _Mod.NewImplSource('unit1','','');
      ShowMessage(_Str);
    finally
      FreeAndNil(_Mod);
    end;
  end;
4

2 回答 2

1

这个问题的答案是肯定的。

问题是不应该直接调用“NewImplSource”。

为了使其工作,应根据“IOTAModuleCreator”构造函数中“GetCreatorType”的结果调用它。

例如:

  procedure TJModuleCreatorWizard.Execute;
  begin
    (BorlandIDEServices as IOTAModuleServices).CreateModule(TJModuleCreator.Create);
  end;

其中“TJModuleCreator”实现了 IOTAModuleCreator 接口。

马丁,非常感谢您的帮助,事实上,我可以通过简化您在回答中建议的场景来解决这个问题。

于 2020-07-04T15:01:50.560 回答
1

如果您没有任何运气像我在项目中建议的那样在 IDE 的第二个实例中调试它,我认为您应该考虑更改您的代码,并按照我实现类似这样的方式进行。

  1. 我在一个小窗体上实现了感兴趣的 OTA 接口。尽管表单原则上是不必要的,但它非常有用,它可以直观地显示事物正在运行,并且实际上您可以进行大量调试,而无需求助于第二个 IDE 实例业务。您可以通过在表单上放置一个小的 TMemo 并将其用作日志记录工具来记录它所做的事情,从而在表单中构建相当多的调试工具。而且,当然,表单可以有一个 MainMenu 或其他任何东西来调用各种 OTA 接口的方法来检查它们是否做了他们应该做的事情。

  2. 不应自动创建表单。相反,在表单单元的“初始化”部分中创建并调用 .Show 并在其完成部分中释放它。

  3. 编译包含表单的 .Dpk 后,使用 .Dpk 将其安装在 IDE 中Install Packages

我总是以这样的形式编写 OTA 的东西,并且很少遇到任何需要第二个 IDE 实例来调查和解决的重大问题。

祝你好运!

于 2020-07-02T21:38:34.470 回答