Delphi:在运行时释放动态控件 [英] Delphi: Freeing a dynamic control at runtime

查看:260
本文介绍了Delphi:在运行时释放动态控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否存在释放Delphi控件的故障安全方法?

Is there a failsafe way of freeing a Delphi control?

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

I have a TStringGrid descendent which I am "embedding" a custom control in it for an inplace editor. When the user navigates within the cells of the grid via the tab key or arrow keys, I need to create a dynamic control if the cell is editable. I have hooked the needed events and am utilizing the OnKeyDown event of my custom control to pass the navigation keys back to the parent TStringGrid.

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

Previously, the TStringGrid descendent would simply call FreeAndNil on the embedded control, but under some circumstances this would cause access violations inside of UpdateUIState/GetParentForm. Looking at the call stack, it appears that sometimes after the control was free'd, a WM_KEYDOWN (TWinControl.WMKeyDown) message was still happening.

我已经准备好了查看并实施了如何在其事件处理程序中释放控制权中讨论的更改?。这似乎已经解决了问题,但是我想知道这种方法是否还有其他需要注意的地方。

I've all ready looked at and implemented the changes discussed in How to free control inside its event handler?. This appears to have resolved the issue, but I am wondering if there are any other cavet's to this approach.

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

In effect, this workaround has simply delayed the destruction of the control until after all the existing messages on the queue at the time the CM_RELEASE message was posted.

在发布CM_RELEASE之后,不可能再将另一个WM_KEY *或类似的消息都准备好了吗?

Would it not be possible that after the CM_RELEASE was posted, another WM_KEY* or similar message could all ready have been posted to the message queue?

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

My current CM_RELEASE handler looks like:

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

因此,这在所有情况下都是安全的还是我应该做一些事情来清除队列? (想到了SendMessage(Self.Handle,WM_DESTROY,0,0))

So, will this be safe in all instances or should I do something to clear any other messages from the queue? ( SendMessage(Self.Handle, WM_DESTROY, 0, 0) comes to mind )

推荐答案

通常,您不应该破坏控件在该控件的事件处理程序中。

In general you should not destroy a control in an event-handler of that control.

但是由于您的函数是普通的非虚拟消息处理程序,因此从未从该控件的内部代码中调用过,所以您应该没事。从样式的角度来看,我不太喜欢,但我认为您的用例还可以。

But since your function is a plain non virtual message handler which is never called from internal code in that control you should be ok. I don't like too too much from a style point of view, but I think it's ok for your use-case.

但是自定义消息可能更简洁。

But a custom message might be cleaner.


在发布CM_RELEASE之后,不可能再将另一个WM_KEY *或类似的消息都准备好了吗?

Would it not be possible that after the CM_RELEASE was posted, another WM_KEY* or similar message could all ready have been posted to the message queue?

如果队列中的消息会引起严重的问题,则由于无法从其他线程和应用程序中发布消息,因此您永远无法安全地销毁控件。只要确保您的应用程序的正确功能不取决于每种情况下处理的那些消息即可。

If messages in queue would cause big problems you could never safely destroy a control since messages can be posted from other threads and applications. Just make sure the correct functioning of your application doesn't depends on those messages being handles in every case.

这篇关于Delphi:在运行时释放动态控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆