【发布时间】:2014-05-12 12:44:46
【问题描述】:
我的主应用程序中加载了一个 DLL 应用程序。 DLL 包含在运行时创建的表单。 功能是: 在主应用程序中,我有一个菜单,只要按下它就会从 DLL 中调用一个过程。此过程动态创建表单。
procedure doCreateForm;
var
myForm: TForm1;
begin
myForm := TForm1.Create(nil)
try
...
except
myForm.Free;
end;
end;
关闭程序:
procedure CloseWindow(ASender: TForm1);
begin
FreeAndNil(ASender);
Application.ProcessMessages;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseWindow(Self);
end;
问题(访问冲突)仅在第二次尝试创建表单时出现。不是第一次,不是第 3 次、第 4 次、第 5 次等等。
所以我点击菜单,表单被创建(动态)并关闭(如果在表单创建事件期间不满足条件)。我再次点击菜单,当myForm.Create(nil) 被调用时,AV 就出现了。我再次单击菜单,一切正常。我一次又一次地点击,一切都好。只有在第二次按下时,AV 才会升高。
DLL中动态创建可视化表单有什么问题吗?
更详细的解释:
链条是:
我创建 MyForm (
myForm := TForm1.Create(nil))在显示表单之前,我做了一些条件测试。
如果一切正常,
myForm.Show- 工作正常,我也可以正常关闭 myForm如果有问题:
一)。我创建了一个消息表单myMessageForm := TMyMessageForm.Create(nil),其中包含一个关闭计时器(表单在 10 秒后关闭)。此表单在 onClose 事件中有 action:=caFree
b)。我调用 myForm.Close。此表单在 onClose 事件中也有 action:=caFree - 此表单在 myMessageForm 关闭之前关闭(由于 myMessageForm 中存在计时器)
这两种形式都是用 nil 所有者创建的,但它们以某种方式连接(我不知道为什么)。并且表格的销毁没有正确执行。下次调用 myForm.Create(nil) 或 myMessageForm.Create(nil) 时,会发生访问冲突。 myMessageForm 应该独立于 myForm 创建,并且它的销毁不应以任何方式限制 myForm 的销毁。
unit1;
procedure doCreateForm;
var
myForm: TForm1;
begin
myForm := TForm1.Create(nil)
try
with myForm do
begin
if <test condition true> then Show
else
begin
ShowErrMessage('Error', 'Error message text', errType);
Close;
end;
end;
except
myForm.Free;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
unit2;
procedure ShowErrMessage(title, text: string; err: mtErrType);
var
myMessageForm: TMyMessageForm;
begin
myMessageForm := TMyMessageForm.Create(nil)
try
with myMessageForm do
begin
StepDownCounter := 10;
CloseTimer.Enable := True;
end;
except
myMessageForm.Free;
end;
end;
procedure TMyMessageForm.CloseTimerTimer(Sender: TObject);
begin
StepDownCounter := StepDownCounter - 1;
if (StepDownCounter < 1) then
begin
CloseTimer.Enabled := False;
LabelStepDownText.Visible := False;
Close;
end
else
begin
LabelStepDownText.Caption := 'Window will close in ' + IntToStr(StepDownCounter) + 's';
LabelStepDownText.Visible := True;
end;
end;
procedure TMyMessageForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
【问题讨论】:
-
在您的
OnClose事件中使用Action := caFree;来释放表单。如果您在其他活动中并想释放表单 it-Self,则需要使用Release。 -
您正在从它自己的一种方法中释放表单。这与锯掉你站在树上的树枝完全一样。正如@TLama 所说,要么在你的
FormClose事件中使用Action := caFree,要么使用Release。 -
在此处发布问题之前,我在 CloseWindow 上使用了 Action := caFree 和 ASender.Release,但没有任何改变。发生相同的 AV。我不禁想知道为什么 AV 只在表单的第二次创建时引发,而不是第一次,不是第 3 次,不是第 4 次,依此类推......
-
我按照大卫的建议编辑了这篇文章。不是它更详细地说明了问题。
-
SSCCE 是我可以粘贴到编辑器中、编译和运行的东西。制作一个需要你付出相当多的努力。如果你做了一个,那么你会立即得到答案。因为回答变得非常容易。更重要的是,您会得到问题的答案,因为我们实际上 100% 肯定地知道您的问题是什么。你的问题已经变异了。所以我的答案似乎过时了。谁知道你的真实代码是什么样的?你做。没有其他人这样做。 SSCCE 的强大之处在于它能够传达您的代码的真实情况。