我怎样才能确定在我的VCL应用程序生命周期的某些时刻Application.MainForm
是有效的,所以我可以向它发布一条消息(来自MadExcept ExceptionHandler)。
这可能是我的应用程序中的任何点(在任何线程的上下文中)(也是initialization
,finalization
等...)
我在想:
if Assigned(Application)
and (not Application.Terminated)
and Assigned(Application.MainForm)
and Application.MainForm.HandleAllocated then
begin
PostMessage(Application.MainForm.Handle, MyMessage, 0, 0);
end;
这是对的吗?
答案 0 :(得分:3)
我怎么能确定在我的VCL应用程序生命周期的某些时候,Application.MainForm是有效的,所以我可以向它发布消息。
行。
这可能是我的应用程序中的任何点(在任何线程的上下文中)(也是初始化,终结等...)
哦,哦。
...
这是对的吗?
不,当然不是。您的代码永远不会成为线程安全的,因为它不允许从主线程外部访问VCL对象。
在您的特定情况下,请考虑以下事件序列:
if
中执行测试,最终评估Application.MainForm.HandleAllocated
为True
。暂时忽略你在主线程之外这样做的事实。PostMessage
。但在这种情况下,主要形式被摧毁。Application.MainForm
时,它已经消失了。你需要在这里努力一点。你需要做这样的事情:
// interface section of some unit
procedure RegisterMainFormHandle(Wnd: HWND);
procedure UnregisterMainFormHandle;
procedure PostMessageToMainForm(...);
// implementation section
var
MainFormHandleLock: TCriticalSection;
MainFormHandle: HWND;
procedure RegisterMainFormHandle(Wnd: HWND);
begin
MainFormHandleLock.Acquire;
try
MainFormHandle := Wnd;
finally
MainFormHandleLock.Release;
end;
end;
procedure UnregisterMainFormHandle;
begin
MainFormHandleLock.Acquire;
try
MainFormHandle := 0;
finally
MainFormHandleLock.Release;
end;
end;
procedure PostMessageToMainForm(...);
begin
MainFormHandleLock.Acquire;
try
if MainFormHandle <> 0 then
PostMessage(MainFormHandle, ...)
finally
MainFormHandleLock.Release;
end;
end;
你还需要创建和销毁关键部分,但我认为你知道如何做到这一点。
在您的主要表单中,您可以覆盖CreateWnd
和DestroyWnd
,并安排他们致电RegisterMainFormHandle
和UnregisterMainFormHandle
。
然后你可以随时从任何线程中调用PostMessageToMainForm
。
当然,如果重新创建主窗体的窗口,那么您将丢失一些消息。这听起来像是一个问题。使用AllocateHwnd
创建一个窗口,您可以控制其生命周期,这比使用主窗体的窗口更好。
答案 1 :(得分:0)
在开头创建一些全局变量标记= false
。
让你的主变形转为true
。
检查该标志以查看主表单是否已初始化。
您可以从主要形式的OnActivate
事件或覆盖TMainForm.Loaded
方法
同样,当你的应用程序终止并且主窗体被隐藏(后来甚至被破坏)时 - 你会将标志重置回false