【问题标题】:How can a component at designtime determine the project directory设计时组件如何确定项目目录
【发布时间】:2011-01-26 21:01:06
【问题描述】:

我编写了一个组件,它应该存储一些与项目目录相关的信息。每次更改我的组件的属性时,它都应该写入一个文件。那么组件如何在设计时确定当前项目目录。

提前致谢

编辑:
每次更改组件的属性时,我都想生成一个 delphi 源文件,以便在编译代码时始终获得最新版本。将其视为一种代码生成器。

目前我设置了应该存储源的完整路径和文件名,但我更喜欢项目的相对路径(或包含我的组件的表单/数据模块),以便更容易在不同的开发人员机器上复制项目.

【问题讨论】:

    标签: delphi delphi-2010 components design-time


    【解决方案1】:

    感谢您的提示。 Open Tools API 是一种可行的方法,并且可以在设计时从表单上的组件中使用 Open Tools API。

    所以这是我的解决方案:

    我需要两个单元,一个用于组件,一个用于注册组件和使用 Open Tools API 的代码。

    组件单元来了:

    
    unit TestLabels;
    
    interface
    
    uses
      SysUtils, Classes, Windows, Controls, StdCtrls;
    
    type
      TTestLabel = class(TLabel)
      private
        FTestProperty: Boolean;
        procedure SetTestProperty(const Value: Boolean);
        procedure Changed;
      published
        property TestProperty: Boolean read FTestProperty write SetTestProperty;
      end;
    
    var
      OnGetUnitPath: TFunc;
    
    implementation
    
    { TTestLabel }
    
    procedure TTestLabel.Changed;
    begin
      if not (csDesigning in ComponentState) then
         Exit; // I only need the path at designtime
    
      if csLoading in ComponentState then
         Exit; // at this moment you retrieve the unit path which was current before
    
      if not Assigned(OnGetUnitPath) then
        Exit;
    
      // only for demonstration
      Caption := OnGetUnitPath;
      MessageBox(0, PChar(ExtractFilePath(OnGetUnitPath)), 'Path of current unit', 0);
    end;
    
    procedure TTestLabel.SetTestProperty(const Value: Boolean);
    begin
      if FTestProperty  Value then
      begin
        FTestProperty := Value;
        Changed;
      end;
    end;
    
    end.
    

    这里是注册组件和调用 Open Tools API 的单元:

    
    unit TestLabelsReg;
    
    interface
    
    uses
      SysUtils, Classes, Controls, StdCtrls, TestLabels;
    
    procedure register;
    
    implementation
    
    uses
      ToolsAPI;
    
    function GetCurrentUnitPath: String;
    var
      ModuleServices: IOTAModuleServices;
      Module: IOTAModule;
      SourceEditor: IOTASourceEditor;
      idx: integer;
    
    begin
      Result := '';
      SourceEditor := nil;
    
      if SysUtils.Supports(BorlandIDEServices, IOTAModuleServices,
        ModuleServices) then
      begin
        Module := ModuleServices.CurrentModule;
    
        if System.Assigned(Module) then
        begin
          idx := Module.GetModuleFileCount - 1;
    
          // Iterate over modules till we find a source editor or list exhausted
          while (idx >= 0) and not SysUtils.Supports(Module.GetModuleFileEditor(idx), IOTASourceEditor, SourceEditor) do
            System.Dec(idx);
    
          // Success if list wasn't ehausted.
          if idx >= 0 then
            Result := ExtractFilePath(SourceEditor.FileName);
        end;
    
      end;
    
    end;
    
    procedure register;
    begin
      RegisterComponents('Samples', [TTestLabel]);
      TestLabels.OnGetUnitPath := GetCurrentUnitPath;
    end;
    
    end.
    

    【讨论】:

    • 我很确定您的 GetCurrentUnitPath 不会编译(至少 while 循环的布尔表达式不会)并且 while 循环永远不会结束。但是这个想法很有趣,所以我确实赞成你的回答。
    • @Jeroen:感谢您指出这一点。 stackoverflow.com 编辑器裁剪了“while not ((idx
    【解决方案2】:

    从 delphi 7 开始,ToolsAPI 单元定义了一个 getActiveProject 函数,该函数返回当前项目的 IOTAProject 接口。

    IOTAProject 的 fileName 属性返回项目主源文件(通常为 .dpr 文件)的完整路径。

    因此,在许多情况下,可以使用简单的指令,例如:

    if csDesigning in componentState then
        appFolderPath := extractFilePath( getActiveProject.fileName ) 
    else
        appFolderPath := extractFilePath( application.exeName );
    

    (并且不需要像上面 Heinz 的示例那样使用两个单位)

    【讨论】:

      【解决方案3】:

      组件无法访问您的源路径,因为组件放置在您的应用程序中,并作为应用程序的一部分在 Delphi IDE 之外运行。

      如果您想访问项目路径,或自动化 IDE 中的任何流程;您必须使用 OpenTools API 而不是组件来编写 IDE 专家。

      【讨论】:

        【解决方案4】:

        我不认为它可以。您可以很容易地确定您的 EXE 运行所在的目录,但您的组件在设计时作为 IDE 的一部分运行。我怀疑组件是否可以通过 IDE 访问项目信息。

        【讨论】:

        • 这不是我想听到的。 :-) 我希望我可以从我的组件中访问 IDE 的设计 API。
        • 看看 OTAPI,它可以访问 IDE 的设计 API,但我认为您不能将 OTAPI 功能与表单上的组件混合。
        • @Heinz:正如 Mason 所说,不是来自您的组件。您可以通过 IDE 专家使用 Open Tools API (OTAPI)。
        • 可以将 OTAPI 与组件混合(参见我的解决方案)
        【解决方案5】:

        http://www.gexperts.org/otafaq.html#project

        然后

        www.href.com/pub/sw/ProjectOptions.html

        可能有帮助

        【讨论】:

        • gexperts otafaq 的链接非常有用。
        猜你喜欢
        • 2014-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-06
        • 2019-02-22
        • 2013-04-03
        • 2010-10-06
        • 2021-10-10
        相关资源
        最近更新 更多