Delphi:在运行时释放动态控件

时间:2010-11-30 19:18:54

标签: delphi

是否存在释放Delphi控件的故障保护方法?

我有一个TStringGrid后代,我在其中“嵌入”一个自定义控件用于内部编辑器。当用户通过Tab键或箭头键在网格的单元格内导航时,如果单元格是可编辑的,我需要创建一个动态控件。我已经挂钩了所需的事件,并利用自定义控件的OnKeyDown事件将导航键传递回父TStringGrid。

以前,TStringGrid后代只会在嵌入式控件上调用FreeAndNil,但在某些情况下,这会导致UpdateUIState / GetParentForm内部的访问冲突。看看调用堆栈,有时在控件被释放后,有时会发生WM_KEYDOWN(TWinControl.WMKeyDown)消息。

我已准备好查看并实施How to free control inside its event handler?中讨论的更改。这似乎已经解决了这个问题,但我想知道这种方法是否还有其他问题。

实际上,此解决方法只是将控件的销毁延迟到发布CM_RELEASE消息之后队列中的所有现有消息之后。

发布CM_RELEASE后,是否有可能将所有准备好的WM_KEY *或类似消息发布到消息队列中?

我当前的CM_RELEASE处理程序如下所示:

procedure TMyCustomControl.HandleRelease(var Msg: TMessage);
begin
  Free;
end;

那么,这在所有情况下都是安全的还是我应该做些什么来清除队列中的任何其他消息? (想到SendMessage(Self.Handle,WM_DESTROY,0,0))

2 个答案:

答案 0 :(得分:0)

通常,您不应销毁该控件的事件处理程序中的控件。

但是因为你的函数是一个简单的非虚拟消息处理程序,它永远不会从该控件的内部代码调用,所以你应该没问题。从风格的角度来看,我不太喜欢,但我认为你的用例没问题。

但自定义消息可能更清晰。

  

发布CM_RELEASE后,是否有可能将所有准备好的WM_KEY *或类似消息发布到消息队列中?

如果队列中的消息会导致大问题,则永远无法安全地销毁控件,因为消息可以从其他线程和应用程序发布。只需确保应用程序的正常运行不依赖于每种情况下处理的消息。

答案 1 :(得分:0)

SendMessage发送消息并等待它返回,这就是为什么你不能在你正在释放的控件的事件处理程序中安全地使用它。

另一方面,

PostMessage将发送消息并在事件退出后处理(如果事件中没有更多代码)。