gpt4 book ai didi

c# - 绘制光标时出现通用 GDI+ 异常 ~3322 次

转载 作者:行者123 更新时间:2023-11-30 14:00:32 27 4
gpt4 key购买 nike

问题:在循环中使用此代码 3322 次(使用底部方法 1246 次)后,在 GetHIcon() 处抛出通用 GDI+ 异常。

示例项目: http://dl.dropbox.com/u/18919663/TestGDICursorDrawing.zip

我正在尝试做的事情:在一个循环中从位图中绘制一个新光标来做一个简单的聚焦动画。

我已经检查过的内容:我确保所有位图和图形都已处理并监控内存泄漏以确保。还要确保没有其他过程有可见的泄漏。尝试了替代方法和方式来确保正确使用位图。

Google 告诉我的内容:GDI+ 中似乎有一个错误,而且没有人提供解决方案。有人试图创建自己的位图到图标转换器,但它不够灵活,无法处理非通用图像尺寸。

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;
}

我试过的其他方法:

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
}

最佳答案

鉴于其症状,这个问题绝对对我来说看起来像是内存泄漏。它运行了一段时间很好,然后爆炸了。

事实证明,您尝试的第二种方法严重泄漏了 GDI 对象。当你调用 GetIconInfo 填充一个 ICONINFO 结构时,它实际上创建了两个对应于图标/光标的位图,hbmMaskhbmColor。您必须在使用完它们后调用DeleteObject 来删除它们,否则会泄露它们。根据the documentation的备注部分:

GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO. The calling application must manage these bitmaps and delete them when they are no longer necessary.

这也不是您在这里遇到的唯一漏洞。使用任一种方法,我至少看到了两个额外的泄漏:

  • Bitmap.GetHicon 方法要求您在使用完图标后调用 DestroyIcon。你也没有这样做,所以你每次都在泄漏那个图标。

  • 您没有释放 BitmapGraphicsGraphicsPathCursor 对象您在 DrawRingAroundCursor 的紧密 while 循环中创建直到最后,这意味着为每次迭代创建的所有临时对象都被泄漏了。 (我建议将 GDI+ 对象的创建包装在 using 语句中,而不是试图记住调用它们的 Dispose 方法。)

当你修复所有这些漏洞时,执行量会增加一倍以上,以至于我什至无法再看到同心圆了。但我仍然无法让它在不崩溃的情况下无限期地运行,所以肯定会有更多我还没有发现的漏洞。

Thread.Sleep 之类的东西也会发出危险信号,并在我的脑海中敲响响亮的警钟。

也许现在是时候说我强烈建议您尝试不同的设计?创建所有这些对象,即使您正确地管理了它们的生命周期,也会相对昂贵并且似乎没有必要。此外,只要用户将光标移出应用程序窗口并移到其他对象上,Windows 就会向新的悬停窗口发送一条新的 WM_SETCURSOR 消息,并将光标完全更改为其他内容.不费吹灰之力就可以很容易地使这种效果“消失”。

关于c# - 绘制光标时出现通用 GDI+ 异常 ~3322 次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10557474/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com