地址 00xxxxx 处的 Delphi 访问冲突

问题描述 投票:0回答:1

我正在学习 Delphi,当我调用执行逻辑的私有函数时,我在显示对话框时遇到问题。它看起来像一个空指针引用,但我找不到它在哪里。

image

这是代码:

unit SandBox;

interface

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

type
  TForm1 = class(TForm)
    AhojButton: TButton;
    procedure AhojButtonClick(Sender: TObject);

  private
    procedure ShowDialog(amount: Integer);

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ShowDialog(amount: Integer);

  var td: TTaskDialog;
  var tb: TTaskDialogBaseButtonItem;
begin

  try
    td := TTaskDialog.Create(nil);
    tb := TTaskDialogBaseButtonItem.Create(nil);

    td.Caption := 'Warning';
    td.Text := 'Continue or Close?';
    td.MainIcon := tdiWarning;
    td.CommonButtons := [];

    tb := td.Buttons.Add;
    tb.Caption := 'Continue';
    tb.ModalResult := 100;

    tb := td.Buttons.Add;
    tb.Caption := 'Close';
    tb.ModalResult := 101;

    td.Execute;

    if td.ModalResult = 100 then
      ShowMessage('Continue')
    else if td.ModalResult = 101 then
      ShowMessage('Close');

  finally
    td.Free;
    tb.Free;
  end;

end;

procedure TForm1.AhojButtonClick(Sender: TObject);
begin
  ShowDialog(100);
end;

end.

我尝试实例化并释放

TTaskDialog
TTaskDialogBaseButtonItem

此行抛出错误:

tb := TTaskDialogBaseButtonItem.Create(nil);
delphi dialog
1个回答
0
投票

您确实有一个

nil
指针取消引用,并且您可以在您提到的代码行中看到
nil

tb := TTaskDialogBaseButtonItem.Create(nil);
                                       ^^^

TTaskDialogBaseButtonItem
TCollectionItem
的后代。 它的构造函数接受
TCollection
作为输入,但您没有传入一个。虽然
TCollectionItem
本身不需要
TCollection
,但
TTaskDialogBaseButtonItem
需要,正如您在其构造函数中看到的那样:

constructor TTaskDialogBaseButtonItem.Create(Collection: TCollection);
begin
  inherited;
  FCaption := '';
  FClient := TCustomtaskDialog(Collection.Owner); // <-- HERE
  FEnabled := True;
  FModalResult := ID + 100; // Avoid mrNone..mrYesToAll and IDOK..IDCONTINUE
end;

因此,要修复错误,您可能会考虑传入对话框的

Buttons
集合,例如:

tb := TTaskDialogBaseButtonItem.Create(td.Buttons);

但这会引发不同的运行时错误:

无效的属性值

这是因为

Buttons
集合实际上需要
TTaskDialogButtonItem
,它是
TTaskDialogBaseButtonItem
的后代:

tb := TTaskDialogButtonItem.Create(td.Buttons);

现在代码将运行而不会崩溃。 但是,您的对话框将有第三个不需要的按钮!

image

您还会造成内存泄漏,因为您将

tb
指定为指向一个对象,然后立即将其重新指定为指向这一行上的另一个对象:

tb := td.Buttons.Add;

您根本不需要手动创建任何按钮对象。 让对话框为您创建按钮。

试试这个:

procedure TForm1.ShowDialog(amount: Integer);
var
  td: TTaskDialog;
  tb: TTaskDialogBaseButtonItem;
begin
  td := TTaskDialog.Create(nil);
  try
    td.Caption := 'Warning';
    td.Text := 'Continue or Close?';
    td.MainIcon := tdiWarning;
    td.CommonButtons := [];

    tb := td.Buttons.Add;
    tb.Caption := 'Continue';
    tb.ModalResult := 100;

    tb := td.Buttons.Add;
    tb.Caption := 'Close';
    tb.ModalResult := 101;

    td.Execute;

    if td.ModalResult = 100 then
      ShowMessage('Continue')
    else if td.ModalResult = 101 then
      ShowMessage('Close');
  finally
    td.Free;
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.