处理Icon和Bitmap有区别吗?

use*_*ame 5 c# gdi resource-leak winforms

我在我的应用程序中调试资源泄漏并创建了一个测试应用程序来测试GDI对象泄漏.在OnPaint中,我创建了新图标和新位图而不进行处理.之后,我检查每个案例中任务管理器中GDi对象的增加.但是,如果我不断重新绘制应用程序的主窗口,则图标的GDI对象数量会增加,但位图没有变化.是否有任何特殊原因导致图标不像位图一样被清理?

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        // 1. icon increases number of GDI objects used by this app during repaint.
        //var icon = Resources.TestIcon;
        //e.Graphics.DrawIcon(icon, 0, 0);

        // 2. bitmap doesn't seem to have any impact (only 1 GDI object)
        //var image = Resources.TestImage;
        //e.Graphics.DrawImage(image, 0, 0);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试结果:

  1. 没有图标和位图 - 30个GDI对象
  2. 使用位图 - 31 GDI对象,数字不会改变.
  3. 使用图标 - 31然后,如果重新绘制窗口,则数字会增加.

gre*_*mes 1

我相信你必须手动处理图标。我做了一些搜索,发现 GC 处理位图,但不处理图标。表单有时会保留自己的图标副本(我不知道为什么)。可以在这里找到处理图标的方法:http://dotnetfacts.blogspot.com/2008/03/things-you-must-dispose.html

[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);

private void GetHicon_Example(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Bitmap myBitmap = new Bitmap(@"c:\FakePhoto.jpg");

// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0);

// Get an Hicon for myBitmap.
IntPtr Hicon = myBitmap.GetHicon();

// Create a new icon from the handle.
Icon newIcon = Icon.FromHandle(Hicon);

// Set the form Icon attribute to the new icon.
this.Icon = newIcon;

// Destroy the Icon, since the form creates
// its own copy of the icon.
DestroyIcon(newIcon.Handle);
}
Run Code Online (Sandbox Code Playgroud)