DELPHI – Is there a way to free an object created at runtime without getting 'Access Violation?'

huangapple go评论98阅读模式
英文:

DELPHI - Is there a way to free an object created at runtime without getting 'Access Violation?'

问题

这个问题让我疯狂,我有一个编辑框,我在其中输入一些内容。在编辑框的 'change' 事件上,创建了一个ListBox并通过SQL查询填充它。在编写时,它作为提示框起作用。
当我在要选择的项目上按回车键时,列表框应该被释放,但它继续返回 '访问冲突' 给我。以下是代码:

procedure TFTimbra.EditCommessaKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  X, Y, W: Integer;
  QSugg: TAdoQuery;
begin
  if not Assigned(Suggerimento) then
  begin
    Suggerimento := TListBox.Create(Self);
    Y := EditCommessa.Top + EditCommessa.Height;
    X := EditCommessa.Left;
    W := EditCommessa.Width;

    with Suggerimento do
    begin
      Top := Y;
      Left := X;
      Width := W;
      Height := 200;
      Parent := FTimbra;
      BorderStyle := bsNone;
      Font.Size := 14;
      Font.Style := [fsBold];
    end;
  end else
    Suggerimento.Clear;

  if Key = 40 then
    Suggerimento.SetFocus;

  QSugg := TAdoQuery.Create(nil);
  QSugg.ConnectionString := DMMain.DBConnection.ConnectionString;
  QSugg.SQL.Text := Format('select Codice, Descrizione from Commesse where Descrizione like %s',
    [QuotedStr('%' + EditCommessa.Text + '%')]);
  QSugg.Open;

  while not QSugg.Eof do
  begin
    Suggerimento.Items.Add(QSugg.FieldByName('Descrizione').AsString);
    QSugg.Next;
  end;

  QSugg.Close;
  if Assigned(Suggerimento) then Suggerimento.OnKeyDown := SuggerimentoKeyDown;
end;

这是第一部分,这是 "应该" 释放列表框的代码:

procedure TFTimbra.SuggerimentoKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = 13 then
  begin
    Commessa := Suggerimento.Items[Suggerimento.ItemIndex];
    EditCommessa.Text := Commessa;
    Suggerimento.Free;
  end;
end;

我认为问题在于对 OnKeyDown 函数的调用...提前感谢您。

英文:

this problem is driving me crazy, i have an edit box in which i write something. On event 'change' of edit box, a ListBox is created and filled by SQL query. It works as a hint box while writing.
When i hit enter on the item which i want to select, the listbox should 'free', but it continues to return me 'access violation'. Here the code:

procedure TFTimbra.EditCommessaKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  X, Y, W: Integer;
  QSugg: TAdoQuery;
begin
  if not Assigned(Suggerimento) then
  begin
    Suggerimento := TListBox.Create(Self);
    Y := EditCommessa.Top + EditCommessa.Height;
    X := EditCommessa.Left;
    W := EditCommessa.Width;

    with Suggerimento do
    begin
      Top := Y;
      Left := X;
      Width := W;
      Height := 200;
      Parent := FTimbra;
      BorderStyle := bsNone;
      Font.Size := 14;
      Font.Style := [fsBold];
    end;
  end else
    Suggerimento.Clear;

  if Key = 40 then
    Suggerimento.SetFocus;

  QSugg := TAdoQuery.Create(nil);
  QSugg.ConnectionString := DMMain.DBConnection.ConnectionString;
  QSugg.SQL.Text := format('select Codice, Descrizione from Commesse where Descrizione like %s', 
    [quotedstr('%' + EditCommessa.Text + '%')]);
  QSugg.Open;

  while not QSugg.Eof do
  begin
    Suggerimento.Items.Add(QSugg.FieldByName('Descrizione').AsString);
    QSugg.Next;
  end;

  QSugg.Close;
  if Assigned(Suggerimento) then Suggerimento.OnKeyDown := SuggerimentoKeyDown;
end;

This is the first part, and this is the code that "should" free the listbox:

procedure TFTimbra.SuggerimentoKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = 13 then
  begin
    Commessa := Suggerimento.Items[Suggerimento.ItemIndex];
    EditCommessa.Text := Commessa;
    Suggerimento.Free;
  end;
end;

I think the problem is in the call of the OnKeyDown function.. Thank you in advance.

答案1

得分: 6

你不能在对象的事件处理程序中销毁该对象。当事件处理程序返回时,代码会在对象的上下文中继续执行,而你刚刚释放了该对象。通常会导致类似这样的运行时错误。

与其使用动态生存期来管理这个列表框控件,不如以传统方式创建它,使用表单设计器。当你想要隐藏它时,将 Visible 设置为 False。当你想要显示它时,将 Visible 设置为 True

英文:

You can't destroy an object from one of that object's own event handlers. When the event handler returns, the code continues executing in the context of the object, which you just freed. And that typically leads to runtime errors like this.

Rather than use a dynamic lifetime for this list box control, create it in the traditional way, using the form designer. When you want it hidden, set Visible to False. When you want it to show, set Visible to True.

huangapple
  • 本文由 发表于 2020年1月3日 18:06:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/59576594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定