英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论