cor*_*ulu 3 .net c# gdi+ bitmap cursor
问题:在循环中使用此代码3322次(使用底部方法1246次)后,GetHIcon()抛出了一个通用的GDI +异常.
示例项目: http ://dl.dropbox.com/u/18919663/TestGDICursorDrawing.zip
我正在尝试做的事情:从循环中的位图绘制一个新光标来做一个简单的聚焦动画.
我已经检查过的内容:我确保所有位图和图形都被处理并监视内存泄漏以确保.还确保没有其他过程有明显的泄漏.试图确保正确使用位图的替代方法和方法.
谷歌告诉我的: GDI +似乎有一个错误,没有人提供解决方案.一个人试图创建自己的Bitmap to Icon转换器,但它不够灵活,不能做非通用的图像尺寸.
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;
}
Run Code Online (Sandbox Code Playgroud)
我试过的其他方法:
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's hot spot. If this structure defines an icon, the hot
public Int32 yHotspot; // Specifies the y-coordinate of the cursor's 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
}
Run Code Online (Sandbox Code Playgroud)
鉴于其症状,这个问题肯定看起来像是内存泄漏给我.它运行良好一段时间,然后爆炸.
事实证明,你尝试的第二种方法是严重泄漏GDI对象.当您调用GetIconInfo填充ICONINFO结构时,它实际上会创建与图标/光标对应的两个位图,hbmMask并且hbmColor.完成使用后,您必须调用DeleteObject删除它们,否则您将泄露它们.根据文件的备注部分:
GetIconInfo创建位图hbmMask和hbmColor成员ICONINFO.调用应用程序必须管理这些位图,并在不再需要时删除它们.
这不是你在这里唯一的泄漏.无论采用哪种方法,我都会看到至少两个额外的泄漏:
该Bitmap.GetHicon方法要求您在DestroyIcon完成图标使用后进行调用.你还没有这样做,所以你每次都会泄漏那个图标.
你不是在处置Bitmap,Graphics,GraphicsPath,和Cursor你正在创建的紧内物体while的循环DrawRingAroundCursor,直到最后一刻,这意味着每次迭代中创建的所有这些临时对象泄露.(我建议在一个using语句中包装GDI +对象的创建,而不是试图记住调用它们的Dispose方法.)
当你修复所有这些泄漏时,执行的次数会增加一倍以上,这使得我甚至无法看到同心圆出现了.但是我仍然无法让它在没有崩溃的情况下无限期地运行,所以在那里肯定会发现一些我没有找到的更多泄漏.
像这样的东西Thread.Sleep也会引起红旗,并在我脑海中响起警告.
也许现在是时候说我强烈建议您尝试不同的设计?创建所有这些对象,即使你正确管理它们的生命周期,也会相对昂贵,而且似乎没有必要.此外,只要用户将光标移动到应用程序窗口和其他对象之外,Windows就会向WM_SETCURSOR新的悬停窗口发送新消息,并将光标完全更改为其他内容.用最小的努力使这种效果"消失"太容易了.