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

Delphi 为什么此资源指令显示在可用表单列表中?,delphi,delphi-xe2,Delphi,Delphi Xe2,我只是偶然发现了一件非常奇怪的事。请参阅此屏幕截图: 表格“> 为什么在可用表格列表中显示$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
?此项目只有两个表格和一个附加单元,以下是项目的主要文件源:

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
),我知道这是一个很糟糕的示例,因为
Unit
是一个保留字。但是原始单元名有一个名称空间前缀,比如这个

更新

我按照建议将此RES引用移到uses子句之前。在此之后(以及清理所有临时文件、重新启动IDE等),它仍然显示在列表中。但令我惊讶的是,IDE实际上又将此RES引用添加了回来

现在IDE将其自身变成:

UpdateUnit in 'UpdateUnit.pas' {$R *.res};
(UpdateUnit是我给它起的新名字,所以我不会泄露内部信息)

因此,我打开了DPROJ文件并搜索了
*.res
,果然找到了:

<ItemGroup>
        ....
        <DCCReference Include="UpdateUnit.pas">
            <Form>$R *.res</Form>
        </DCCReference>

....
$R*.res

如前所述,我无法复制此内容……但是,如果我删除了“Other.Unit.pas”行中“Other.Unit”后面的分号(;”),则“$R*.res”将显示在项目选项中

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

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

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

编辑:根据我上面的评论:


可能发生的情况是这样的;在某个时候,您可能以某种方式编辑了.dpr文件,使解析器误认为“$R*.res”“是表单名。然后在该状态下保存它,这也将该信息注入到.dproj文件中。IDE试图保持这两件事同步,有时会将.dproj文件作为“主文件”,并更新.dpr文件以匹配。您应该能够安全地从dproj文件中删除$R*.res。

这不会在Delphi XE2 Update 4中重现(见下文)。
更准确地说:您发布的代码不会复制

但是您在注释中描述的场景是这样的:如果
.dproj
被冲洗,IDE将向
.dpr
重新添加不正确的信息。请参阅下面的进一步解释

在这个答案的末尾,一个编辑向您显示了一个在客户端发生的事件:Delphi XE2可能会因为内部状态出错而感到困惑,它会同时写回一个错误的
.dproj
.dpr
文件

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

我已经看到IDE在AV之后的不同地方(包括项目选项)被混淆,或者当.pas或.dpr文件中的行尾不是CRLF,或者当手动编辑.dpr文件时

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

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

如果我将RES声明移到分号之前,我就可以复制它:这是IDE所期望的格式,因此它可以解析.DPR中的表单、数据模块和帧(以及可能的其他设计图面):

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

不复制的主程序:

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.
“选项”对话框:

复制的主程序(注意RES的位置):

编辑20130616

在下面的客户机上遇到的是
.dpr
.dproj
中的before/after的差异(一些名称已匿名)

Delphi XE2不知怎么搞糊涂了:导致这个问题的不是.dpr中的编辑

我怀疑有两件事:

  • 某个地方的访问违规覆盖了某些内部状态,导致内部项目结构受损(该项目取决于要安装的大量第三方软件包,所有这些软件包都处于相同的BDS流程中)
  • .dpr中有很多可能会混淆内部项目结构的代码
我已经将所有的.dpr代码重构成一个单独的模块。希望
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.
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.
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.
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.
        <DCCReference Include="uDBOrm.pas"/>
        <DCCReference Include="..\..\..\Server\trunk\Server\uWinProxySettings.pas"/>
        <DCCReference Include="uDBOrm.pas">
            <Form>$R *.res</Form>
        </DCCReference>
        <DCCReference Include="..\..\..\Server\trunk\Server\uWinProxySettings.pas"/>