为什么此资源指令显示在可用表单列表中?

时间:2013-05-22 14:04:03

标签: delphi delphi-xe2

我偶然发现了一件非常奇怪的事情。请参阅此屏幕截图:

Project Options > Forms

为什么在可用表单列表中显示$R *.res?这个项目只有两个表单和一个附加单元,这是项目的主文件源:

program MyProgram;

uses
  Forms,
  uMain in 'uMain.pas' {fMain},
  uEmail in 'uEmail.pas' {frmEmail},
  Vcl.Themes,
  Vcl.Styles,
  Other.Unit in 'Other.Unit.pas';

{$R *.res}

begin
  Application.Initialize;
  TStyleManager.TrySetStyle('Iceberg Classico');
  Application.Title := 'My Program Title';
  Application.CreateForm(TfMain, fMain);
  Application.Run;
end.

PS - 这是稍微修改过的代码,唯一改变的是程序名称,程序标题和其中一个单位(Other.Unit.pas)的名称,我知道这是一个不好的例子,因为{{1是一个保留字。但原始单元名称具有名称空间前缀,例如此名称。

更新

我按照建议将此RES引用移到uses子句之前。在此之后(并清除所有临时文件,重新启动IDE等),它仍然显示在列表中。但令我惊讶的是,IDE实际上已经添加了这个RES参考!

所以现在IDE已经把它变成了:

Unit

(UpdateUnit是我给它的新名称所以我不会提供内部信息)

所以,我打开了DPROJ文件并搜索了UpdateUnit in 'UpdateUnit.pas' {$R *.res}; ,确实找到了这个:

*.res

2 个答案:

答案 0 :(得分:10)

如上所述,我无法重现这一点......但是,如果我在'Other.unit.pas'“行中的”Other.Unit“之后删除了尾随的分号(”;“),则”$ R * .res “显示在项目选项中。

据我所知,这不是一个错误。由于您的评论表明所呈现的代码与您使用的代码不同,因此很难诊断。我会尝试解释发生的事情;如果您查看uMain和uEmail单元,则每个单元旁边都会有一个注释,即表单的名称。由于这些单元实际上可能未在IDE中打开,因此无法知道是否存在与该单元关联的表单。 uMain.dfm的存在并不能保证uMain.pas实际上有一个形式(它可能是遗留下来的)。 IDE将此简单注释放在该单元的uses子句中,以告诉项目经理该单元具有表单。

通过删除“;”,解析器将下一个注释标记视为{$ R * .res}。然后得出结论,Other.Unit.pas必须包含名为“$ R * .res”的表单。它没有验证名称,甚至没有尝试打开单位。它只需要该注释的原始内容并假定它是一个表单名称。

您可以安全地在uses子句之前移动{$ R * .res},以便项目解析器不会将该指令注释混淆为表单。

编辑:从上面的评论:

可能发生的是这个;在某些时候,您可能已经编辑了.dpr文件,使得解析器认为“$ R * .res”是表单名称。然后,您在该状态下保存它,该状态也将该信息注入.dproj文件。 IDE会尝试将这两个内容保持同步,有时会将.dproj文件作为“主”并更新.dpr文件以进行匹配。您应该能够安全地从dproj文件中删除$ R * .res。

答案 1 :(得分:4)

这不能用Delphi XE2 Update 4重现(见下文) 更准确地说:您发布的代码无法重现。

但是您在评论中描述的方案确实如果:.dproj被清除,IDE会将不正确的信息重新添加到.dpr。请参阅下文以获得进一步说明。

在这个答案的最后一个编辑,显示你在客户端发生的事情:Delphi XE2可能会以某种方式混淆内部状态出错,并且它回写错误的.dproj和{{1}文件。

如果您发布的代码与失败的代码不同,请使用失败的代码更正您的问题(并在我的回答中发表评论,以便我收到通知并更新QC条目;在当前表单中您的QC条目将被标记为“无法重现”,然后关闭)。

我看到IDE在AV之后在各个地方(包括项目选项)混淆,或者.pas或.dpr文件中的行结尾不是CRLF,或者手动编辑.DPR文件时。

重新启动IDE时,这些问题通常会消失。有时您甚至需要清理一些文件(扩展名为.DCU,.local等)。

最糟糕的情况是,IDE非常混乱,以至于.DPR和.DPROJ都包含错误信息(因此我的评论),在您的情况下似乎是这种情况(感谢您编辑过的问题)。您可以手动编辑.DPROJ和.DPR文件来解决此问题。确保备份,因为很容易破坏.DPROJ文件的XML格式

如果我在分号之前移动RES声明,我可以重现它:这是IDE期望的格式,因此它可以解析Forms,DataModule和Frames(以及可能的其他设计表面)的.DPR:

.dpr

基本上,您不应该编辑.DPR文件:IDE拥有它并将重写它,例如当您向项目添加新单元,更改程序图标,更改应用程序标题等时。

不重现的主程序:

  Unit1 in 'Unit1.pas' {DataModule1: TDataModule},
  Unit2 in 'Unit2.pas' {Frame2: TFrame};
  Unit3 in 'Unit3.pas' {Form3};

选项对话框:

enter image description here

重现的主程序(注意RES所在的位置):

program MyProgram;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {fMain},
  uEMail in 'uEMail.pas' {frmEmail},
  Vcl.Themes,
  Vcl.Styles,
  Other.Module in 'Other.Module.pas';

{$R *.res}

begin
  Application.Initialize;
  TStyleManager.TrySetStyle('Iceberg Classico');
  Application.Title := 'My Program Title';
  Application.CreateForm(TfMain, fMain);
  Application.Run;
end.

编辑20130616

在下面的客户端进入此区域是program MyProgram; uses Vcl.Forms, uMain in 'uMain.pas' {fMain}, uEMail in 'uEMail.pas' {frmEmail}, Vcl.Themes, Vcl.Styles, Other.Module in 'Other.Module.pas' {$R *.res}; begin Application.Initialize; TStyleManager.TrySetStyle('Iceberg Classico'); Application.Title := 'My Program Title'; Application.CreateForm(TfMain, fMain); Application.Run; end. .dpr之前/之后的差异(某些名称已被匿名化)。

Delphi XE2以某种方式感到困惑:它不是.dpr中的编辑导致了这个问题。

我怀疑有两件事:

  • 某处的访问冲突覆盖了一些内部状态,导致内部项目结构被破坏(项目依赖于许多第三方软件包的安装,所有这些都在同一个BDS过程中)。
  • .dpr中有很多代码可能混淆了内部项目结构

我已将所有.dpr代码重构为一个单独的模块。希望这是原因,这不会再发生。

旧的.dpr片段:

.dproj

新的.dpr片段:

program Server;

uses
  ShareMem,
  SysUtils,
  Forms,
  SvcMgr,
  WebReq,
  uMain in 'uMain.pas' {fMain},
//...
  uDBOrm in 'uDBOrm.pas',
  uWinProxySettings in '..\..\..\Server\trunk\Server\uWinProxySettings.pas',
  GpStuff in 'GpStuff.pas',
  DSiWin32 in 'DSiWin32.pas';

{$R *.res}

function IsServiceApp: Boolean;
begin
//...
end;

begin
  if IsServiceApp = True then
  begin
//...
  end else
  begin // GUI Interface
    if Assigned(Application) then
       FreeAndNil(Application);
    Forms.Application.Initialize;
    Forms.Application.MainFormOnTaskbar := True;
    ReportMemoryLeaksOnShutdown := True;
    Forms.Application.CreateForm(TfMain, fMain);
    Forms.Application.Run;
  end;
end.

旧的.dproj片段:

program Server;

uses
  ShareMem,
  SysUtils,
  Forms,
  SvcMgr,
  WebReq,
  uMain in 'uMain.pas' {fMain},
//...
  uDBOrm in 'uDBOrm.pas' {$R *.res},
  uWinProxySettings in '..\..\..\Server\trunk\Server\uWinProxySettings.pas',
  GpStuff in 'GpStuff.pas',
  DSiWin32 in 'DSiWin32.pas';

{$R *.res}

function IsServiceApp: Boolean;
begin
//...
end;

begin
  if IsServiceApp = True then
  begin
//...
  end else
  begin // GUI Interface
    if Assigned(Application) then
       FreeAndNil(Application);
    Forms.Application.Initialize;
    Forms.Application.MainFormOnTaskbar := True;
    ReportMemoryLeaksOnShutdown := True;
    Forms.Application.CreateForm(TfMain, fMain);
    Forms.Application.Run;
  end;
end.

新的.dproj片段:

        <DCCReference Include="uDBOrm.pas"/>
        <DCCReference Include="..\..\..\Server\trunk\Server\uWinProxySettings.pas"/>