首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么自由度要移除线?

为什么自由度要移除线?
EN

Stack Overflow用户
提问于 2019-11-25 19:38:24
回答 1查看 176关注 0票数 0

我试图为Delphi 5编写一个插件,它将把我们测试的路径存储在自由度中,这样项目和该项目的测试之间就有了直接的关联。当我将自己的模块添加到自由度文件中时,如下所示

代码语言:javascript
复制
[DUint Plugin]
IntegrationTestExe=Somepath
UnitTestExeList=Some;Path;

每当我手动或通过代码添加这一点时,当我保存该项目时,我添加的行将被删除。我认为这可能是因为IDE只是不允许在自由度中定制模块。

然而,我们使用一个名为EurekaLog的第三方插件。EurekaLog将自己的vars注入到自由度中,当您保存时,这些vars不会被移除。我复制了大部分代码,这样我就可以测试EurekaLog代码是否能正常工作(通过一些魔法),但是他们的代码只是将他们的模块写到了自由度上,并没有做什么特别的事情。

有谁知道这是如何在EurekaLog中完成的吗?我是否需要在某个地方注册我的模块,以便IDE知道不删除它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-26 16:25:48

更新经过一些实验,似乎保存设置到自由度实际上比保存到DSK文件明显更可靠。

向表单中添加另一个TEdit,并创建类似于现有LoadSettings和SaveSettings的LoadDOFSettings和SaveDOFSettings,并在收到DesktopLoad和DesktoSave通知时调用它们。不需要通过SaveDOFSettings事件调用Timer1,因为重命名似乎不会发生在自由度上。

原始答案--我建议在阅读这个答案之前,先在IDE中做一个文件,关闭所有的文件,创建一个新的包,将下面的单元添加到这个包中,然后将它安装在IDE中。

该包的用途有两个方面,一是演示如何在DSK文件中保存自定义设置,二是让您了解通过ToolsAPI单元中的服务可以从IDE获得哪些项目文件的事件信息。

一旦您安装了包,请注意它的表单,它显示您在打开、处理和关闭项目时在上面备忘录中的文件通知。有几件事需要注意:

当您打开一个项目时,您收到的最后一个通知是关于它的DSK文件已被打开。

  • 并不是每个文件类型都是通知的主题。特别是,你没有收到任何关于自由度文件的具体通知,所以如果你想写它,然后从它读,你必须假设什么时候这样做是安全的(或不安全的),这也可能是为什么你遇到了你要问的问题。
  • 当你对这个项目做了一个结束,你收到的最后一个文件更改通知就是正在写的DSK。问题是,它最初被写入一个同名的文件,但扩展名为.$$$。不久之后,但是你无法确切地知道何时,这个.$$$文件被重命名为.DSK.

下面的代码创建的表单有一个编辑框,DSK文件的edMyValue' which can be used to set a value in a section of the DSK file calledMySettingsand which is reloaded the next time the project is opened. The writing of theMySettings`部分被TTimer触发,延迟2秒,以便像我所描述的那样让TTimer有时间编写和重命名DSK文件。这显然为比赛条件提供了机会。

你可以参考一下

http://www.gexperts.org/open-tools-api-faq/#dsk

(GExperts是从德尔菲早期就出现的IDE外接程序工具)

本文的部分讨论的是当前项目的.DSK文件。就像自由度一样,这是INI文件格式,部分如下

代码语言:javascript
复制
[Closed Files]
[Modules]
[EditWindow0]
[View0]

正如你所看到的,上面写着

检查ofnProjectDesktopLoad和ofnProjectDesktopSave NotifyCode值。当您看到其中之一时,可以使用类(如FileName )从TIniFile参数指示的文件中保存/加载值。

也许这比这篇文章所建议的要复杂一些,因为重命名业务。

玩得开心!

代码语言:javascript
复制
unit IDEEventsu;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ToolsAPI, Grids, IniFiles;

type
  TFileEventsForm = class(TForm)
    Panel1: TPanel;
    Memo1: TMemo;
    edMyValue: TEdit;
    btnClear: TButton;
    Timer1: TTimer;
    Memo2: TMemo;
    procedure btnClearClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    function GetCurrentProject: IOTAProject;
  public
    //  The following are using interfaces accessible via the ToolsAPI
    Services: IOTAServices;
    ProjectGroup : IOTAProjectGroup;
    Project: IOTAProject;
    Options : IOTAProjectOptions;
    ModServices: IOTAModuleServices;
    Module: IOTAModule;

    NotifierIndex: Integer;  // This is used to disconnect our notifier from the IDE
    IsSetUp : Boolean;
    SetUpCount : Integer;
    DskFileName : String;
    procedure SetUp;
    procedure SaveSettings;
    procedure LoadSettings;
  end;

var
  FileEventsForm: TFileEventsForm;

procedure Register;

[...]
uses
 typinfo;

type
  TIdeNotifier = class(TNotifierObject, IOTANotifier, IOTAIDENotifier)
  //  This is the class we use to receive file notication events from the IDE via the
  //  interfaces in ToolsAPI.Pas
  //
  //  It needs to implement the IOTANotifier and IOTAIDENotifier interfaces and,
  //  once registered with the IDE, the IDE calls its methods as a kind of call-back
  //  mechanism so that it gets notified of file events
  //
  //  Note that this file also provides a form for displaying the received event
  //  notifications and that the IOTANotifier and IOTAIDENotifier interfaces could
  //  just as easily be implemented by the form itself
  protected
    procedure AfterCompile(Succeeded: Boolean);
    procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
    procedure FileNotification(NotifyCode: TOTAFileNotification;
      const FileName: string; var Cancel: Boolean);
  end;

procedure Register;
//  This is necessary to register the package in the IDE
var
  Notifier : TIdeNotifier;
begin
  FileEventsForm:= TFileEventsForm.Create(Nil);
  FileEventsForm.Services := BorlandIDEServices as IOTAServices;
  Notifier := TIdeNotifier.Create;
  Notifier.Form := FileEventsForm;
  FileEventsForm.NotifierIndex := FileEventsForm.Services.AddNotifier(TIdeNotifier.Create);
end;

procedure CloseDown;
begin
  FileEventsForm.Services.RemoveNotifier(FileEventsForm.NotifierIndex);
  FileEventsForm.Close;
  FileEventsForm.Free;
end;

function NotifyCodeString(NotifyCode : TOTAFileNotification) : String;
begin
  Result := Copy(GetEnumName(TypeInfo(TOTAFileNotification), Ord(NotifyCode)), 4, MaxInt);
end;

procedure TIdeNotifier.AfterCompile(Succeeded: Boolean);
begin
end;

procedure TIdeNotifier.BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
begin
end;

procedure TIdeNotifier.FileNotification(NotifyCode: TOTAFileNotification;
  const FileName: string; var Cancel: Boolean);
begin
  if True {NotifyCode in [ofnProjectDesktopLoad, ofnActiveProjectChanged]}  then begin
    FileEventsForm.Show;
    FileEventsForm.Memo1.Lines.Add(Format('%s file: %s', [NotifyCodeString(NotifyCode), FileName]));
    case NotifyCode of
      ofnProjectDesktopLoad,
      ofnDefaultDesktopLoad : begin
        FileEventsForm.DskFileName := FileName;
        FileEventsForm.LoadSettings;
      end;
      ofnProjectDesktopSave,
      ofnDefaultDesktopSave : begin
        if True{CompareText(ExtractFileExt(FileName), '.DSK') = 0} then begin
          FileEventsForm.Caption := FileName;
          FileEventsForm.Timer1.Enabled := True;  //  causes DSK file to be updated after Timer1.Interval (=2000ms)
        end;
      end;
    end; { case }
  end;
end;

procedure TFileEventsForm.btnClearClick(Sender: TObject);
begin
  Memo1.Lines.Clear;
end;

function TFileEventsForm.GetCurrentProject: IOTAProject;
var
  i: Integer;
begin
  Result := nil;
  ModServices := BorlandIDEServices as IOTAModuleServices;
  for i := 0 to ModServices.ModuleCount - 1 do
  begin
    Module := ModServices.Modules[i];
    if Supports(Module, IOTAProjectGroup, ProjectGroup) then begin
      Result := ProjectGroup.ActiveProject;
      Options := Result.ProjectOptions;
      Exit;
    end
    else if Supports(Module, IOTAProject, Project) then
    begin // In the case of unbound packages, return the 1st
      if Result = nil then begin
        Result := Project;
        Options := Result.ProjectOptions;
      end;
    end;
  end;
end;

procedure TFileEventsForm.SetUp;
begin
  Project := GetCurrentProject;
  Inc(SetUpCount);
  Caption := 'Setup done ' + IntToStr(SetUpCount);
  IsSetUp := True;
end;

procedure TFileEventsForm.LoadSettings;
var
  Ini : TMemIniFile;
  S : String;
begin
  Ini := TMemIniFile.Create(DSKFileName);
  try
    S := Ini.ReadString('MySettings', 'Name', 'no value');
    edMyValue.Text := S;
  finally
    Ini.Free;
  end;
end;

procedure TFileEventsForm.SaveSettings;
var
  Ini : TMemIniFile;
  S : String;
begin
  S := DSKFileName;
  Caption := 'Saving: ' + S;
  Ini := TMemIniFile.Create(S);
  try
    Ini.WriteString('MySettings', 'Name', edMyValue.Text);
    Ini.UpdateFile;
    Ini.ReadSections(Memo2.Lines);
    Memo2.Lines.Add('This file : ' + DSKFileName);
    edMyValue.Text := '?';
  finally
    Ini.Free;
  end;
end;

procedure TFileEventsForm.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  SaveSettings;
end;

initialization

finalization
  CloseDown;
end.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59038963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档