0

我有一个所有者绘制的列表框,其中包含代表项目的结构列表。这个结构有两个属性,一个图标和一个要显示的字符串。它可以很好地显示 16x16 等小图标。但是,我尝试调整此列表框以显示文件夹中的图片,并且出现了一些莫名其妙的错误。

public static System.Drawing.Icon BitmapToIcon (System.String String_Bitmap, System.Drawing.Icon Object_Default)
{
    try
    {
        //return System.Drawing.Icon.FromHandle(((System.Drawing.Bitmap)(System.Drawing.Bitmap.FromFile(String_Bitmap))).GetHicon());
        System.IO.Stream s = new System.IO.MemoryStream(System.IO.File.ReadAllBytes(String_Bitmap));
        System.Drawing.Bitmap b = ((System.Drawing.Bitmap)(System.Drawing.Bitmap.FromStream(s, true, true)));
        System.Drawing.Icon i = System.Drawing.Icon.FromHandle(b.GetHicon());
        s.Close();
        b.Dispose();
        return i;
    }
    catch
    {
        return Object_Default;
    }
}

别处:

BitmapToIcon("D:/pictures/picture001.jpg", null);

该目录有大约 400 张各种形状和格式的图像,但实际上只有大约 60 张随机间隔地出现在列表框中。在 ListBox.DrawItem() 中,Graphics.DrawIcon() 正在抛出 DivideByZero 函数。在捕获异常时,它将图标注册为 0x0。很明显,我的函数被编写为在发生错误时返回默认图标(在这种情况下为 null)。

我知道 Windows ICO 格式有 256x256 的限制,但据我所知,这不是这里发生的情况。它绘制的一些图像确实要大得多,而且它们也不是正方形的。此外,它不会在 400 个列表中加载的所有图像都可以在 10 个列表中加载。我认为 GDI 可能有太多句柄或其他东西,所以我更改了函数以处理我的源位图并添加了一个睡眠语句但都没有帮助。将列表框更改为使用位图而不是图标修复了绘图问题,但它现在消耗更多内存。

GetHIcon() 是否有某种原因会返回这样奇怪的结果,我该怎么办?

4

2 回答 2

0

您应该在 catch 子句中捕获错误,以查看导致返回默认图标的异常类型。

如果您从不调用DestroyIcon并重复调用此方法,则很可能是您的 GDI 资源不足。

我还可以建议此代码等效于您的代码并且更易于阅读:

    using ( var b = (Bitmap)Image.FromFile(String_Bitmap))
        return Icon.FromHandle(b.GetHicon());

另外 - 你为什么不改变你的列表框的结构来使用位图而不是图标,然后摆脱这个图标问题?:-)

于 2012-05-23T12:15:17.390 回答
0

瑞安,埃里克的意思是,最好使用 using 指令来避免以下代码:

System.Drawing.Bitmap b = ((System.Drawing.Bitmap)(System.Drawing.Bitmap.FromStream(s, true, true)));

重构后它看起来像:

using System.Drawing.Bitmap;

Bitmap b = ((Bitmap)(Bitmap.FromStream(s, true, true)));

很难阅读您提供的代码。尝试使用 Image.FromFile() 函数加载图像或使用带有路径参数的位图构造函数。

    Bitmap b = new Bitmap(String_Bitmap);
    Icon i = Icon.FromHandle(b.GetHicon());
于 2012-05-23T04:49:40.927 回答