我有一个在我的主应用程序中加载的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
如果出现问题:
A)。我创建了一个包含结账计时器的消息表单myMessageForm := TMyMessageForm.Create(nil)
(表单在10秒后关闭)。此表单在onClose事件中有action:= caFree
B)。我叫myForm.Close。这个表单还有一个动作:= onClose事件中的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;
答案 0 :(得分:1)
您正在销毁正在执行当前方法的对象。在销毁对象之后执行的该对象中的所有代码都是无效的。
您应该将关闭操作设置为caFree
,或使用Release
,如上所述。这些工作通过向队列发布消息以允许在当前方法返回后销毁对象。你正在通过调用ProcessMessages
调用队列来破坏它。移除对ProcessMessages
的呼叫。