问题描述
我有一个程序可以在图形上添加一系列斑点:
I have a program that adds a series of "blips" to a graph:
PictureBox blip = new PictureBox();
blip.Location = new Point(blipHours, blipAltitude);
blip.Size = new Size(6, 6);
blip.BackColor = System.Drawing.Color.Lime;
blip.Text = "";
blip.Name = callsign;
this.Controls.Add(blip);
this.Controls.SetChildIndex(blip, 0);
-
我如何有一个按钮清除所有
How do I have a button clear all of the "blips" that have been created with this code?
使用此代码创建的 blip吗?当其名称等于某个<$ c $时,是否可以更改blip的背景颜色? c>呼号?每个笔触都与 ListBox
中的选择相关联,我想在用户选择笔触时更改其颜色。
Is there a way to change a blip's background color when its name is equal to a certain callsign
? Each blip is associated with a selection in a ListBox
, and I would like to change the blip's color when the user selects it.
推荐答案
每个人都忘记了非常的重要细节:您必须Dispose()控件或它将永远泄漏:
Everybody is forgetting a very important detail: you have to Dispose() the control or it will leak forever:
for (int ix = this.Controls.Count - 1; ix >= 0; ix--) {
if (this.Controls[ix] is PictureBox) this.Controls[ix].Dispose();
}
我会放一些更加强调 forever 子句,在注释中大声疾呼,Control类的行为不像其他任何.NET类。控件通过其 Handle
属性保持活动状态。其中存储本机Windows句柄。只要存在本机窗口,就无法销毁Control对象。
I'll put some more emphasis on the forever clause, lots of clamor about it in the comments, the Control class does not behave like any other .NET class. A Control is kept alive by its Handle
property. Which stores the native Windows handle. As long as the native window exists, the Control object cannot be destroyed.
这要求您在使用Clear()或Remove()时人为地保持对象活动。从其父级中删除该控件。 Winforms使用所谓的停车窗口作为此类控件的宿主。与其他任何窗口一样,它是普通的本机窗口,只是不可见。它的工作是成为这些孤立控件的父级。
This requires the object to be kept alive artificially when you use Clear() or Remove() and remove the control from its parent. Winforms uses the so-called "parking window" as the host of such controls. It is a normal native window like any other, it is just not visible. Its job is to be the parent of such orphaned controls.
停车窗口允许许多整洁的技巧,这些技巧在Windows中通常很难做到。例如,您可以在运行时打开和关闭ShowInTaskbar属性。窗口的属性通常只能在创建窗口时指定(WS_EX_APPWINDOW样式,在CreateWindowEx()调用中指定)。即使在创建窗口后,Winforms仍可以执行此操作,方法是将窗体的控件移到停车窗口,销毁该窗口,再次创建它,然后将控件移回。整洁。
The parking window permits lots of neat tricks that are normally very hard to do in Windows. You can for example turn the ShowInTaskbar property on and off at runtime. A property of a window that can normally only be specified when you create the window (WS_EX_APPWINDOW style, specified in the CreateWindowEx() call). Winforms can do it even after you created the window by moving the controls of the form to the parking window, destroying the window, creating it again and moving the controls back. Neat.
但是,如果您删除控件并不要调用,那么不太好的挂断就是这个答案的主题。其Dispose()方法,它将继续在停车窗口中保留。永远。真正的泄漏。垃圾收集器对此无能为力,只能看到对该对象的有效引用。完全严重违反IDisposable合同,调用Dispose()是可选的,但对于Control类来说不是不是。
But with the not-so-neat hangup that's the topic of this answer, if you remove the control and don't call its Dispose() method then it will continue to survive on the parking window. Forever. A true leak. Nothing that the garbage collector can do about it, it sees a valid reference to the object. A pretty gross violation of the IDisposable contract, calling Dispose() is optional but it is not for the Control class.
幸运的是,这样的错误非常容易诊断,不需要任何特殊工具,您可以在任务管理器的进程选项卡中查看泄漏。添加用户对象列。
Luckily such a bug is pretty easy to diagnose, it doesn't require any special tooling, you can see the leak in Task Manager's Processes tab. Add the "USER Objects" column.
这篇关于在C#中删除动态创建的控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!