标签: delphi-xe6

使用我自己构建的调试库和常规DCU在Delphi中管理非常大的代码库

我正在尝试解决此编译错误,仅在Debug配置中发生,并且仅在下面描述的情况下:

[dcc32 Fatal Error] MyIndyTCPChannel.pas(22): F2051 Unit IdIOHandlerSocket was compiled with a different version of IdGlobal.IdDisposeAndNil
Run Code Online (Sandbox Code Playgroud)

我正在开发一个非常大的Delphi代码库,拥有250万行内部代码和300万行组件代码,其中包括几个大型商业Delphi组件套件(Developer Express,TeeChart等),以及大量代码库开源delphi组件,以及一个相当大的内部开发组件集,编号252个包,其中大约140个是设计时+运行时或设计时,其他是运行时包(也被加载到IDE中)在运行时,由其关联的设计时包中的DLL依赖项).

我们的主库路径已经优化到尽可能小,并且它包含Delphi附带的路径作为标准,再加上我们添加的三个,主要的是单个"OurCompanyLibraryDCU"文件夹,其中包含下面的文件夹我们使用的两个平台和两个配置:

c:\dev\OurCompanyLibraryDCU\Win32\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
c:\dev\OurCompanyLibraryDCU\Win64\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
Run Code Online (Sandbox Code Playgroud)

上述每个文件夹都包含一个文件夹中的BPL,DCP和DCU文件集,用于该平台/配置组合.

在项目选项中使用了如下的宏,因此我们可以更改平台和配置,并正确解析目录:

$(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config)

OURCOMPANYLIBRARYDCU是一个环境变量,$(X)是在Delphi IDE的上下文中扩展环境变量的语法.

我正在尝试将最重要和最大的VCL应用程序项目(称为BigApp.dproj)构建,以便项目搜索目录仅包含我们的APPLICATION源文件夹,并且不需要项目搜索路径来包含我们所有的第三方组件LIBRARY源代码.为此,我们需要链接调试DCU或释放DCU.

到目前为止,除了可以使用Debug和Release DCU的情况外,我们一切正常.版本DCU位于库路径中,调试DCU位于IDE设置中的Debug DCU路径中.面对这两个库之间的选择,Delphi的链接器似乎失败,每当存在两组DCU时,这种形式的错误,当我单击Build,并且Build Configuration设置为Release时,我得到F2051错误.F2051错误的普通原因是存在多个不兼容的二进制DCU并且都是可访问的,并且链接器无法使其全部工作.但是,如果你想在库路径中同时使用Debug和Release DCU,我认为这种情况不会发生,因为Linker会为你选择调试或释放DCU.

如果我没有构建调试DCU,则不会发生上述问题.我怀疑我的调试DCU是微妙的"无效"或Delphi中的Debug-DCU选择算法不起作用,但不知道为什么,或如何解决这个问题.

多部分问题:

A.每个平台/配置组合都有一个文件夹,在单个文件夹中包含DCU,BPL和DCP,然后添加到已知导致问题的IDE库路径中?我是否需要三个子文件夹,每个平台+ config + filetype共有12个文件夹,或者我可以通过platform + config将它们保存在一起吗?

B.在包编译情况下,是否可以让IDE库路径包含OurCompanyLibraryDCU文件夹,并将该文件夹配置为DCP输出目录,包输出目录和单元输出目录?我担心的是,通过使输入文件夹和输出文件夹相同,有一种情况是编译器可能无法从.pas源重建单元,只是链接先前编译的DCU.

在此输入图像描述

C.如果我发生了这个问题,我应该如何防止每次构建BigApp时从源代码编译超过250万行的组件LIBRARY代码,而只是通过DCU链接它们,并且仍然有调试并释放dcus正常工作?

D.如果我转到Win32\Debug文件夹并删除IdGlobal.dcu,我可以通过原始错误.这告诉我,我的包编译(用于调试配置)正在生成INVALID IdGlobal.dcu.这甚至可能吗?delphi可以默默输出乱码的DCU吗?

注意:我没有使用,也无法使用Runtime Packages来处理应用程序大小问题.

更新:我应该在这里做的第一件事是验证ZERO额外的DCU文件在我的硬盘驱动器上是任何地方,无论如何.这是标准的F2051错误建议.在我处理完这个问题后,我会更新这个问题.似乎Delphi本身可以将DCU从一个地方复制到另一个地方,或者不在CURRENT搜索路径中的虚假DCU可能已经在某个其他项目的搜索路径中.可能会出现一种坏DCU拷贝的桶式旅.一旦我确定发生了什么样的坏DCU代或副本,我就会更新问题.

更新2:我现在保证在构建之前不存在IdGlobal.dcu的额外副本,并且问题仍然存在.因此,问题随后打开了构建IdGlobal.dcu时使用的编译器选项,版本化了在Debug构建中构建BigApp.dproj时使用的编译器选项.

更新3:虽然我的所有程序包编译似乎都没有错误地完成,但是在启动DCC32.exe或MSBUILD.exe来构建程序包期间,它们似乎没有使用正确的库搜索路径.这个库路径不一致问题似乎是核心问题,感谢Rufo爵士指出这一点.

delphi packages delphi-xe6 delphi-xe7

9
推荐指数
2
解决办法
844
查看次数

在delphi中测试泛型的类型

我想用一些方法在delphi中编写一个函数,如下所示

procedure Foo<T>;
begin
    if T = String then
    begin
        //Do something
    end;

    if T = Double then
    begin
        //Do something else
    end;
end;
Run Code Online (Sandbox Code Playgroud)

即:我希望能够根据泛型类型做不同的事情

我尝试过使用TypeInfo,System但这似乎适合于对象而不是泛型类型.

我甚至不确定帕斯卡是否可行

delphi generics pascal delphi-xe6

9
推荐指数
2
解决办法
1930
查看次数

如何从无模式窗体中显示模态对话框?

我有两种"无模式"形式:

  • 一个是特殊的MainForm
  • 另一种是无模式

在此输入图像描述

你可以看到:

  • 两者都存在于任务栏上
  • 两者都有一个任务栏按钮
  • 两者都可以独立最小化
  • 两者都可以独立恢复
  • 两者都不总是在另一方的顶层(拥有)

现在显示一个模态形式

从这种无模式的形式,我想展示一个模态:

在此输入图像描述

模态形式被构造为:

var
    frmExchangeConfirm: TfrmExchangeConfirm;
begin
    frmExchangeConfirm := TfrmExchangeConfirm.Create(Application);
    try
        //Setting popupMode and popupParent still makes the MainForm disabled
//      frmExchangeConfirm.PopupMode := pmExplicit;
//      frmExchangeConfirm.PopupParent := Self; //owned by us

        frmExchangeConfirm.OwnerForm := Self; //tell the form which owner to use
        frmExchangeConfirm.ShowModal;
    finally
        frmExchangeConfirm.Free;
    end;
Run Code Online (Sandbox Code Playgroud)

模态表单被告知通过新OwnerForm属性使用哪个所有者:

protected
   procedure SetOwnerForm(const Value: TForm);
public
   property OwnerForm: TForm read GetOwnerForm write SetOwnerForm;
end;
Run Code Online (Sandbox Code Playgroud)

这迫使手柄娱乐:

procedure TfrmExchangeConfirm.SetOwnerForm(const Value: …
Run Code Online (Sandbox Code Playgroud)

delphi delphi-xe6

9
推荐指数
1
解决办法
3687
查看次数

什么是TForm.TipMode属性?

这是什么TForm.TipMode属性?

它已在Delphi XE3中添加,但文档中没有提及此属性.

delphi delphi-xe6

8
推荐指数
1
解决办法
1375
查看次数

从TButton继承的自定义按钮不显示

我正在将一个大型项目转换为Firemonkey,并且我们有一些自定义按钮,这些按钮不会显示在表单上.我已将问题分离到一个非常简单的项目:

使用下面的代码,在移动和桌面上(使用Delphi XE6中的默认新应用程序),创建tTestButton1工作正常,但tTestButton2不会在窗体上显示.怎么可能?

type
tTestButton1 = class(TButton);
tTestButton2 = class(tTestButton1);

tMainForm = class(TForm)
private
  fTestButton: TButton;
public
  constructor Create(aOwner: TComponent); override;
end;

constructor tMainForm .Create(aOwner: TComponent);
begin
  inherited;

//  fTestButton := tTestButton1.Create(Self); // this works fine (used instead of next line)
  fTestButton := tTestButton2.Create(Self);  //this button does not show up
  fTestButton.Text := 'Test';
  fTestButton.Parent := Self;
  fTestButton.Visible := True;
  fTestButton.Position.X := 20;
  fTestButton.Position.Y := 20;
end;
Run Code Online (Sandbox Code Playgroud)

delphi firemonkey delphi-xe6

8
推荐指数
1
解决办法
771
查看次数

在pascal中动态分配匿名函数

我希望能够在pascal中动态生成弹出菜单.

我还希望能够为每个菜单项动态分配OnClick处理程序.

这是我习惯于在C#中做的事情,这是我在pascal中的尝试.

菜单项onClick事件处理程序需要属于一个对象(of Object),所以我为此创建一个容器对象.

这是我的代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Menus;

type
  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TFoo = class
    public
      Bar : String;
      Val : Integer;
  end;

  TNotifyEventWrapper = class
    private
      FProc: TProc<TObject>;
      I : Integer;
    public
      constructor Create(Proc: TProc<TObject>);
    published
      procedure Event(Sender: TObject);
  end;

var
  Form1: TForm1;
  NE : TNotifyEventWrapper;

implementation

{$R …
Run Code Online (Sandbox Code Playgroud)

delphi anonymous-function delphi-xe6

8
推荐指数
1
解决办法
830
查看次数

当LineTo成功时,为什么FillRect不会绘制?

我试图改变DateTimePicker的背景颜色,但我的问题与我正在尝试做的无关.

我正在捕捉一个窗口的WM_PAINT消息,让默认的绘图实现发生(即ComCtrl.dll中的一个),然后在此之后出现并在其上面涂鸦.

最初我的代码很简单:

TDateTimePicker = class(Vcl.ComCtrls.TDateTimePicker)
protected
   procedure WMPaint(var Message: TMessage); message WM_PAINT;
end;

procedure TDateTimePicker.WMPaint(var Message: TMessage);
begin
   inherited;
end;
Run Code Online (Sandbox Code Playgroud)

我什么都不做,控件正常涂漆:

在此输入图像描述

现在开始变得有趣了

现在我将进行一些实际绘图.这不是我想要的图画,但它表明它有效.我将在控件的矩形上绘制纵横交错:

procedure TDateTimePicker.WMPaint(var Message: TMessage);
var
    dc: HDC;
    rc: TRect;
    p: HPEN;
begin
    inherited;

    //Get the device context to scribble on    
    dc := GetDC(Self.Handle);
    if dc = 0 then
        Exit;
    try
        rc := Self.GetClientRect;

        //Create a pen to draw a criss-cross
        p := CreatePen(PS_SOLID, 0, ColorToRGB(clLime));
        p …
Run Code Online (Sandbox Code Playgroud)

delphi winapi gdi common-controls delphi-xe6

8
推荐指数
1
解决办法
800
查看次数

如何正确使用无模式窗体出现在任务栏中

我试图实现古老的德尔福梦想,在任务栏中出现一个无模式的形式.

在任务栏中显示无模式表单的正确方法是什么?


研究工作

这些是我尝试解决问题的方法.要使其正常运行需要很多东西- 只需在任务栏上显示一个按钮就不是解决方案.让Windows应用程序作为Windows应用程序正常运行应该是我的目标.

对于那些了解我的人,以及我的"展示研究成果"的深度,坚持下去,因为这将是一个疯狂的骑兔子洞.

问题在标题中,以及上面的水平线以上.以下所有内容仅用于说明为什么有些经常重复的建议是不正确的.

Windows仅为无主窗口创建任务栏按钮

最初我有我的"主表格",从中我展示了另一种无模式形式:

procedure TfrmMain.Button2Click(Sender: TObject);
begin
    if frmModeless = nil then
        Application.CreateForm(TfrmModeless, frmModeless);

    frmModeless.Show;
end;
Run Code Online (Sandbox Code Playgroud)

这会正确显示新表单,但任务栏上不会显示任何新按钮:

在此输入图像描述

没有创建任务栏按钮的原因是因为这是设计的.Windows将仅显示"无主"窗口的任务栏按钮.这种无模式Delphi形式绝对拥有.在我的情况下,它由以下所有Application.Handle:

在此输入图像描述

我的项目名称是ModelessFormFail.dpr,Modelessformfail与所有者关联的Windows类名的来源.

幸运的是,有一种方法可以强制 Windows为窗口创建任务栏按钮,即使窗口是拥有的:

只是用 WS_EX_APPWINDOW

MSDN文档WS_EX_APPWINDOW说:

WS_EX_APPWINDOW 0x00040000L当窗口可见时,强制顶层窗口进入任务栏.

它也是一个众所周知的Delphi技巧,可以覆盖CreateParams并手动添加WS_EX_APPWINDOW样式:

procedure TfrmModeless.CreateParams(var Params: TCreateParams);
begin
    inherited;

    Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; //force owned window to appear in …
Run Code Online (Sandbox Code Playgroud)

windows delphi windows-7 windows-95 delphi-xe6

8
推荐指数
1
解决办法
2254
查看次数

如何断开XE6中的ADO Recordset?

我试图在XE6中使用断开连接的ADO Recordset.这个想法是你正常打开记录集,然后你将记录集的ActiveConnection设置为你的语言相当于null/ Nothing/ nil:

rs.Set_ActiveConnection(null);

Delphi 5中的以下示例工作正常:

var rs: _Recordset;

rs := CoRecordset.Create;
rs.CursorLocation := adUseClient; //the default for a Recordset is adUseServer (Connection.Execute's default is adUseClient)
rs.CursorType := adOpenForwardOnly; //the default
rs.Open(CommandText, Conn,
      adOpenForwardOnly, //CursorType
      adLockReadOnly, //LockType
      adCmdText);

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(nil);
Run Code Online (Sandbox Code Playgroud)

它适用于Delphi 5

问题是我无法在Delphi XE6中使用它.在Delphi 5中我会成功致电:

rs.Set_ActiveConnection(nil);
Run Code Online (Sandbox Code Playgroud)

一切都很出色.它起作用,因为_Recordset接口被声明为:

procedure Set_ActiveConnection(const pvar: IDispatch); safecall;
Run Code Online (Sandbox Code Playgroud)

所以通过是有效的nil; 它起作用了.

在XE6中,退出变为:

procedure Set_ActiveConnection(pvar: OleVariant); …
Run Code Online (Sandbox Code Playgroud)

delphi ado delphi-xe6

8
推荐指数
1
解决办法
365
查看次数

DLL中的VCL样式正在影响应用程序中的TMenuItem

我使用的是Delphi XE6和VCL样式.我有主要的应用程序和dll.我的主应用程序启用了运行时主题,我正在使用vcl样式文件.我对我的DLL做了类似的事情.我启用了运行时主题,并在其中添加了VCL.Themes,VCL.Styles以及其中包含VCL样式文件的资源文件.当加载DLL时,我从资源加载VCL样式并将其设置为DLL gui.主应用程序和DLL不是使用运行时包构建的.

现在我有主要的应用程序GUI风格与自己的风格和DLL gui风格也有自己的风格.这似乎工作正常,直到......

当我点击我的主应用程序中的按钮时,该事件打开TPopupMenu,它的样式与DLL GUI相同,而不是主应用程序样式.如果我浏览菜单,我也会得到AV并且程序崩溃.看一下附图.

我究竟做错了什么?我目前看到的唯一解决方法是使我自己定制的TPopupMenu来自其他一些控件.在此输入图像描述


正如我所承诺的,我准备了一个类似于我的应用程序的简单演示程序.它由具有自己样式的主机应用程序和添加到资源的样式的DLL组成.运行它并单击Popup按钮然后尝试从弹出窗口中选择一些内容.它会崩溃并停在一些StdWindowProc或类似的东西.此外,如果您在尝试从该菜单中选择某些内容时转到窗口系统菜单(左上角),您会注意到系统菜单的样式为DLL gui并且也崩溃了.链接到rar文件:dropbox.com/sh/f2jmbsmw18akpyg/AAA6SWdBmVhf6n6K-mvYLLmua?dl=0

在此输入图像描述

谢谢你的帮助.

delphi dll vcl vcl-styles delphi-xe6

7
推荐指数
2
解决办法
1610
查看次数