[英]GDI objects memory leak: Custom ToolStripControlHost within ContextMenuStrip is not disposing
我有各種基於ToolStripControlHost的自定義上下文菜單。 它們包裝在ContextMenuStrip中,並放置在DataGridView列的標頭中(取決於某些條件),如下所示:
if (this.DGV.Columns[DGVColname] != null)
{
ContextMenuStrip cstr = null;
// there is always only one item in context menu
// I tried disposing in different manners, this is an example of my efforts
if (this.DGV.Columns[DGVColname].HeaderCell.ContextMenuStrip != null)
{
cstr = this.DGV.Columns[DGVColname].HeaderCell.ContextMenuStrip;
if (cstr.Items[0] != null)
{
cstr.Items[0].Dispose();
cstr.Items.Clear();
}
}
else
{
cstr = new ContextMenuStrip();
cstr.Opened += new EventHandler(cstr_Opened);
}
TextBoxToolStrip tsHost = new TextBoxToolStrip();
tsHost.Size = new System.Drawing.Size(172, 20);
tsHost.TextChanged += new EventHandler(myToolStrip_TextChanged);
cstr.ShowCheckMargin = false;
cstr.ShowImageMargin = false;
cstr.Margin = new Padding(0);
cstr.Padding = new Padding(0);
cstr.Items.Add(tsHost);
cstr.MaximumSize = new Size(tsHost.Width + 10, tsHost.Height + 10);
cstr.Size = cstr.MaximumSize;
cstr.LayoutStyle = ToolStripLayoutStyle.Flow;
DGV.Columns[DGVColname].HeaderCell.ContextMenuStrip = cstr;
}
盡管調用了dispose和/或進行了任何設置,但我可以使我的應用程序處理的GDI對象數仍然為零,並且仍在穩定增長。 我的DataGridView中有20個帶有菜單的列,每次調用該代碼時,都會得到+30或+34(准確)。
在此示例中,TextBoxToolStrip擴展了ToolStripControlHost並包含單個TextBox:
public class TextBoxToolStrip : ToolStripControlHost
{
// .... some string or bool Properties here ....
public TextBox TextBoxControl
{
get { return Control as TextBox; }
}
public TextBoxToolStrip()
: base(new TextBox())
{
this.TextBoxControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TextBoxControl.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.TextBoxControl.Location = new System.Drawing.Point(0, 3);
this.TextBoxControl.ReadOnly = false;
this.TextBoxControl.Font =
new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.TextBoxControl.Size = new System.Drawing.Size(172, 20);
this.Size = new System.Drawing.Size(172, 20);
this.TextBoxControl.TabIndex = 0;
this.TextBoxControl.TextAlign = System.Windows.Forms.HorizontalAlignment.Left;
this.MouseHover += new EventHandler(TextBoxToolStrip_Enter);
this.AutoSize = false;
this.TextBoxControl.PreviewKeyDown += new PreviewKeyDownEventHandler(TextBoxPreviewKeyDown);
this.TextBoxControl.KeyDown += new KeyEventHandler(TextBoxControl_KeyDown);
}
protected override void OnSubscribeControlEvents(Control control)
{
base.OnSubscribeControlEvents(control);
TextBox tb = control as TextBox;
if (tb != null)
{
tb.TextChanged += new EventHandler(OnTextChanged);
}
}
protected override void OnUnsubscribeControlEvents(Control control)
{
base.OnUnsubscribeControlEvents(control);
TextBox tb = control as TextBox;
if (tb != null)
{
tb.TextChanged -= OnTextChanged;
}
}
private void TextBoxToolStrip_Enter(object sender, EventArgs e)
{
this.Focus();
}
private void TextBoxPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Menu)
e.IsInputKey = true;
}
private void TextBoxControl_KeyDown(object sender, KeyEventArgs e)
{
TextBox txb = sender as TextBox;
ToolStripDropDown tsd = (ToolStripDropDown)txb.Parent;
if (e.KeyCode == Keys.Enter)
{
tsd.Close();
}
}
/// <summary>
/// Expose TextChanged event
/// </summary>
public new event EventHandler TextChanged;
private void OnTextChanged(object sender, EventArgs e)
{
if (TextChanged != null)
{
TextChanged(this, e);
}
}
題:
如何正確處理上下文菜單?
事實證明,它不是事件,靜態引用或任何常見的東西。 我在TreeView上看到了ToolStripControlHosts,發現只有那些在泄漏。 看來TreeView會很高興地自行泄漏資源:當CheckBoxes屬性設置為true時,用於處理選中和未選中復選框的位圖的句柄在處理TreeView時不會正確釋放(每次在我的視圖中都剩下4個)情況),這會導致GDI對象內存泄漏。 我不得不手動處理復選框圖像列表。
這里描述了問題和解決方案。 盡管我在這里使用屬性而不是事件:
public new bool CheckBoxes
{
get
{
return base.CheckBoxes;
}
set
{
if (base.CheckBoxes == false)
{
base.CheckBoxes = true;
IntPtr handle = SendMessage(this.Handle, TVM_GETIMAGELIST, new
IntPtr(TVSIL_STATE), IntPtr.Zero);
if (handle != IntPtr.Zero)
_checkboxImageList = handle;
}
}
}
在我的情況下,StyleChanged事件不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.