标签: delphi-10.1-berlin

处理Delphi中的循环强引用

我有两个类(在我的示例中为TObject1和TObject2),它们通过接口(IObject1,IObject2)相互了解.正如您在Delphi中可能知道的那样,这将导致内存泄漏,因为参考计数器将始终保持在零以上.通常的解决方案是将一个引用声明为弱.这在大多数情况下都适用,因为你通常知道哪一个会被破坏,或者一旦它被销毁就不一定需要弱引用后面的对象.

这说我尝试以这样的方式解决问题,即两个对象都保持活着,直到两者都不再被引用:(因为我使用[unsafe]属性需要Delphi 10.1)

program Project14;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  IObject2 = interface;

  IObject1 = interface
    ['{F68D7631-4838-4E15-871A-BD2EAF16CC49}']
    function GetObject2: IObject2;
  end;

  IObject2 = interface
    ['{98EB60DA-646D-4ECF-B5A7-6A27B3106689}']
  end;

  TObject1 = class(TInterfacedObject, IObject1)
    [unsafe] FObj2: IObject2;
    constructor Create;
    destructor Destroy; override;

    function GetObject2: IObject2;
  end;

  TObject2 = class(TContainedObject, IObject2)
    [unsafe] FObj1: IObject1;
    constructor Create(aObj1: IObject1);
    destructor Destroy; override;
  end;

constructor TObject1.Create;
begin
  FObj2 := TObject2.Create(Self);
end;

destructor TObject1.Destroy;
begin
  TContainedObject(FObj2).Free;
  inherited Destroy;
end;

function TObject1.GetObject2: IObject2;
begin
  Result := FObj2;
end;

constructor TObject2.Create(aObj1: …
Run Code Online (Sandbox Code Playgroud)

delphi interface reference-counting delphi-10.1-berlin

6
推荐指数
1
解决办法
736
查看次数

PathDelim VS DirectorySeparatorChar

一个人可以使用

  • System.IOUtils.TPath.DirectorySeparatorChar

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.IOUtils.TPath.DirectorySeparatorChar

要么

  • System.SysUtils.PathDelim

是否有任何特殊的差异,使用System.IOUtils.Tath中的另一个部分的好处是更面向对象的接口?

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.SysUtils

delphi io delphi-10.1-berlin

6
推荐指数
1
解决办法
1306
查看次数

如何从父类调用子类构造函数?

有没有办法从父类调用子类的创建?下面是这个Duplicate方法,我希望调用子类的构造函数,以便底部的测试成功.

type

  IBla<T> = interface(IInvokable)
    ['{34E812BF-D021-422A-A051-A492F25534C4}']
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  TClassA<T> = class(TInterfacedObject, IBla<T>)
  protected
    function GetInt(): Integer; virtual;
  public
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  TClassB = class(TClassA<Integer>, IBla<Integer>)
  protected
    function GetInt(): Integer; override;
  end;

function TClassA<T>.Duplicate: IBla<T>;
begin
  Exit(TClassA<T>.Create());
end;

function TClassA<T>.GetInt: Integer;
begin
  Exit(1);
end;

function TClassA<T>.GetIntFromIface: Integer;
begin
  Exit(GetInt());
end;

function TClassB.GetInt: Integer;
begin
  Exit(2);
end;

procedure TestRandomStuff.Test123;
var
  o1, o2: IBla<Integer>;
begin
  o1 := TClassB.Create();
  o2 := o1.Duplicate();    
  Assert.AreEqual(o2.GetIntFromIface, 2);
end;
Run Code Online (Sandbox Code Playgroud)

delphi delphi-10.1-berlin

6
推荐指数
1
解决办法
200
查看次数

Delphi通过引用传递数组

在C++中,可以通过const引用以这种方式将函数传递给函数:

void test(const std::vector<int>& a);
Run Code Online (Sandbox Code Playgroud)

当向量非常大并且我想避免浪费时间来复制它时,这很有用.我知道Delphi中的相同代码是:

procedure test(const [Ref] a: array of Integer);
Run Code Online (Sandbox Code Playgroud)

它是否也具有与C++相同的效果(传递地址而不是副本并优化/节省时间)?这是唯一的方法还是还有其他优化参数传递的方法?

delphi delphi-10.1-berlin

6
推荐指数
2
解决办法
1661
查看次数

错误的MessageDlg图标与DlgType mtConfirmation常量?

在Delphi 10.1.2 Berlin中,在一个Vcl.Dialogs.MessageDlg函数中,DlgType常量mtInformationmtConfirmation创建相同的对话框图标.例如:

if Vcl.Dialogs.MessageDlg('Do you really want to remove the selected item?',  mtConfirmation, mbOKCancel, 0) = mrOk then
begin
  RemoveTheSelectedItem;
end;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

if Vcl.Dialogs.MessageDlg('Do you really want to remove the selected item?',  mtInformation, mbOKCancel, 0) = mrOk then
begin
  RemoveTheSelectedItem;
end;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

但不应该DlgType常数mtConfirmation显示一个问号图标,(作为其他DlgType常量mtWarningmtError创建每个不同的图标)?

如何使用常量获得问号图标?DlgTypemtConfirmation

delphi dialog delphi-10.1-berlin

6
推荐指数
1
解决办法
1687
查看次数

无法从Datasnap Server检索大于260.000字节的TStream

我有一个Delphi 10.1 Berlin Datasnap Server,它不能返回大于260.000字节的数据包(通过TStream).

我在Delphi 的\ Object Pascal\DataSnap\FireDAC示例之后编写了它,它也显示了这个问题.

只需打开该示例,在ServerMethodsUnit.pas上将qOrders组件的IndexFieldName设置为空白,并将其SQL属性更改为:

select * from Orders
union 
select * from Orders
Run Code Online (Sandbox Code Playgroud)

现在要发送的数据量超过260.000字节,这似乎是您无法从客户端检索它的点.获得EFDException [FireDAC] [Stan] -710.二进制存储格式无效.

数据作为Stream从服务器上的FDSchemaAdapter获取,然后加载到客户端上的另一个FDSchemaAdpater.客户端和服务器之间的连接也是FireDAC.

这是服务器返回该流的方式:

function TServerMethods.StreamGet: TStream;
begin
  Result := TMemoryStream.Create;
  try
    qCustomers.Close;
    qCustomers.Open;
    qOrders.Close;
    qOrders.Open;
    FDSchemaAdapter.SaveToStream(Result, TFDStorageFormat.sfBinary);
    Result.Position := 0;
  except
    raise;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

这就是客户端检索它的方式:

procedure TClientForm.GetTables;
var
  LStringStream: TStringStream;
begin
  FDStoredProcGet.ExecProc;
  LStringStream := TStringStream.Create(FDStoredProcGet.Params[0].asBlob);
  try
    if LStringStream <> nil then
    begin
      LStringStream.Position := 0;
      DataModuleFDClient.FDSchemaAdapter.LoadFromStream(LStringStream, TFDStorageFormat.sfBinary);
    end;
  finally
    LStringStream.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

客户端无法获取Blob参数的所有数据.我在服务器上保存Stream的内容,以及在客户端上到达Blob参数的内容,并且它们具有相同的大小,但Blob参数的内容的内容被截断,最后几个Kbytes为零.

这就是我在服务器上保存将转到Stream的内容的方法:

FDSchemaAdapter.SaveToFile('C:\Temp\JSON_Server.json', TFDStorageFormat.sfJSON); …
Run Code Online (Sandbox Code Playgroud)

delphi datasnap firedac delphi-10.1-berlin

5
推荐指数
1
解决办法
1173
查看次数

Async InputQuery不处理"取消"按钮

我正在使用TDialogServiceAsync.InputQuery()单个输入进行简单的调用.它只是忽略了Cancel按钮和窗口的X关闭按钮.

Ok按钮工作正常.

这是我的代码:

uses
  FMX.DialogService.Async;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TDialogServiceAsync.InputQuery('Title',
   ['Insert value'], ['bla bla'],
  procedure(const AResult: TModalResult; const AValues: array of string)
  begin
    if Aresult = mrOk then
      ShowMessage('Ok!');

    if Aresult = mrCancel then
      ShowMessage('Cancel!'); // this is never called
  end);
end;
Run Code Online (Sandbox Code Playgroud)

如果我按下Cancel,则InputQuery窗口不会关闭,并且不会调用我的回调过程.

按下Cancel按钮后如何关闭InputQuery表单?

我正在使用RADStudio 10.1柏林.


编辑:

我做了几个测试:

  1. 在Windows 32位的取消按钮工作
  2. 在Windows 64位取消按钮工作
  3. 在iOS 64位取消按钮正常工作
  4. 在Android 32位取消按钮正常工作

delphi firemonkey delphi-10.1-berlin

5
推荐指数
1
解决办法
1115
查看次数

有什么方法可以避免隐藏的表单显示在任务栏迷你窗口悬停上?

这与具有子窗体的Delphi应用程序有关,该子窗体已显示然后隐藏但未释放。如果用户将鼠标悬停在应用程序的(Windows 10)任务栏“迷你视图”上,则隐藏的窗体将变得可见(在悬停期间)。当用户单击迷你视图以将焦点更改为时,它们将隐藏。应用程序。有什么办法可以避免这种情况?

重新创建:

  1. 创建一个新的VCL窗体应用程序。
  2. 将新窗体添加到项目并将其设置为自动创建。
  3. 添加一个按钮以显示然后隐藏表单(或使用ShowModal打开它)
  4. 运行应用程序
  5. 单击按钮显示第二个窗体,然后将其关闭。
  6. 将鼠标悬停在应用程序任务栏按钮上可以显示主窗口的迷你视图。
  7. 将鼠标悬停在迷你视图上,可以看到隐藏的窗口出现在主窗体上。

请注意,最小化应用程序并还原它可以“修复”影响,直到下次显示表单为止。也许这是导致问题的线索或解决方法的线索?这并不是一个大问题,因为它似乎并没有引起任何实际问题,但是看起来确实不专业。

根据要求添加代码(但是,这不会很有趣。)

program Project1;
uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

// Only code that was added to TForm1:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Show and then hide the form or use ShowModal and close it before testing the hover.
  Form2.Show;
  Form2.Hide;
  // Form2.ShowModal;
end;
Run Code Online (Sandbox Code Playgroud)

更新:如何仅使用Delphi IDE显示问题。

  1. 运行德尔福
  2. 打开任何代码文件并搜索字符串,然后使用F3直到出现对话框“找不到搜索匹配项”,“从文件开头重新开始搜索”
  3. 关闭第2步中的“找不到搜索匹配项”窗口。
  4. 将鼠标悬停在Delphi任务栏按钮上,然后将其移至迷你预览。
  5. 您应该会在Delphi主窗口上方看到“找不到搜索匹配项”窗口。我已经在柏林和东京(10.2.1)对此进行了验证

delphi delphi-10.1-berlin delphi-10.2-tokyo

5
推荐指数
1
解决办法
375
查看次数

Delphi异常消息文本的语言错误

我有一个应用程序,我捕获异常并向用户显示消息文本作为错误消息的一部分.尽管RAD Studio(10.1)设置为英语,并且在所有目标的版本信息选项中将区域设置ID设置为409英语,但错误消息以德语输出.这种情况发生在德国Windows 10和其他语言的其他Windows机器上,即使是日本客户也是如此.

例外是一个系统异常,例如无法打开文件,找不到文件,但它似乎发生在我不用我自己的消息文本引发的所有类型的异常上.

该项目最近已从Delphi 2007迁移,我不得不在项目文件中对版本号进行一些手动清理.但是检查项目文件中的Locale并不奇怪:1033 - > $ 0409 - 英语.

可能是德国消息的原因在哪里?

delphi exception delphi-10.1-berlin

5
推荐指数
1
解决办法
531
查看次数

PostMessage用于特定表单的所有实例(ClassName):

在VCL Forms程序中,我有一个Form,它实现了一种处理Windows消息和更新Form上某些控件的方法,如:

procedure OnMsgTest (var Msg: TMessage); message WM_CUSTOMTEST;
Run Code Online (Sandbox Code Playgroud)

我使用PostMessage自定义消息到此表单,使用如下代码:

  h := FindWindow('TFrmTest', nil);    
  if IsWindow(h) then begin    
    PostMessage(h, WM_CUSTOMTEST, 0, 0);    
  end;
Run Code Online (Sandbox Code Playgroud)

当Form实例化多次时,使用上面的代码发送消息,只有一个Form实例更新屏幕上的信息.我希望所有打开和实例化的表单都能收到消息.

一个重要的注意事项:PostMessage可以在Form进程本身内发生,也可以从另一个进程发生.所以,我认为通过Forms的循环不起作用.

达到目标的最佳方法是什么?

delphi delphi-10.1-berlin

5
推荐指数
1
解决办法
337
查看次数