General GDI + Exception when drawing the cursor ~ 3322 times

Problem: . After using this code in a loop 3322 times (1246 times using the bottom method), a general GDI + exception is thrown in GetHIcon ().

Project example: http://dl.dropbox.com/u/18919663/TestGDICursorDrawing.zip

What I'm trying to do: Draw a new cursor from a bitmap in a loop to make a simple focusing animation.

What I already checked: I made sure that all bitmaps and graphics are located and controlled by memory leaks to make sure. Also make sure that no other process has a visible leak. We tried alternative methods and ways to ensure the correct use of bitmaps.

What Google told me: There is a bug in GDI +, and no one has suggested a solution. One person tried to create their own Bitmap to Icon converter, but it is not flexible enough to make non-generic images.

public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot)
{
    //Shows me exactly when the error occurs.
    counter++;
    Console.WriteLine(counter + " GetHicon() calls");

    //GetHicon() is the trouble maker. 
    var newCur = new Cursor(bmp.GetHicon());
    bmp.Dispose();
    bmp = null;

    return newCur;
}

Another method I tried:

public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot)
{
    //Tried this method too, but this method results in an error with even fewer loops.
    Bitmap newBitmap = new Bitmap(bmp);
    // was told to try to make a new bitmap and dispose of the last to ensure that it wasn't locked or being used somewhere. 
    bmp.Dispose();
    bmp = null;
    //error occurs here. 
    IntPtr ptr = newBitmap.GetHicon();
    ICONINFO tmp = new ICONINFO();
    GetIconInfo(ptr, ref tmp);
    tmp.xHotspot = xHotSpot;
    tmp.yHotspot = yHotSpot;
    tmp.fIcon = false;
    ptr = CreateIconIndirect(ref tmp);

    newBitmap.Dispose();
    newBitmap = null;

    return new Cursor(ptr);
}


[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, ref ICONINFO piconinfo);

[DllImport("user32.dll")]
public static extern IntPtr CreateIconIndirect(ref ICONINFO icon);

[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
    public bool fIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
    public Int32 xHotspot;     // Specifies the x-coordinate of a cursor hot spot. If this structure defines an icon, the hot 
    public Int32 yHotspot;     // Specifies the y-coordinate of the cursor hot spot. If this structure defines an icon, the hot 
    public IntPtr hbmMask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
    public IntPtr hbmColor;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
}
+3
source share
2 answers

This problem definitely looks like a memory leak for me, given its symptoms. It works fine and then explodes.

, , , , GDI. GetIconInfo ICONINFO, , /, hbmMask hbmColor. DeleteObject, , , . :

GetIconInfo hbmMask hbmColor ICONINFO. , .

, . :

  • Bitmap.GetHicon , DestroyIcon, . , .

  • Bitmap, Graphics, GraphicsPath Cursor, while DrawRingAroundCursor , , , , . ( GDI + using, , Dispose.)

, , , , . , , .

Thread.Sleep .

, , ? , , . , - , Windows WM_SETCURSOR , - . "" .

+6

, DestroyIcon GetHicon,

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

MSDN: https://msdn.microsoft.com/en-us/library/system.drawing.bitmap.gethicon%28v=vs.110%29.aspx

:

 [DllImport("user32.dll", CharSet = CharSet.Auto)]
 extern static bool DestroyIcon(IntPtr handle);
 public static Icon ConvertoToIcon(Bitmap bmp)
 {
     System.IntPtr icH = bmp.GetHicon();
     var toReturn = (Icon)Icon.FromHandle(icH).Clone();
     DestroyIcon(icH);
     return toReturn;
 }
+2

All Articles