如何在窗口上设置HICON(.ICO有多种尺寸)?

时间:2010-02-10 06:57:43

标签: windows winapi icons

我想定义Win32窗口的应用程序图标,例如通过使用SetClassLong调用GCL_HICON并将句柄传递给图标(请参阅MSDN上的SetClassLong Function)。

这很好用,但我还没弄明白我应该如何加载图标(来自ICO文件)以保持所有可用尺寸(例如16x16,32x32,48x48和全尺寸PNG图标)。当我通过LoadImage将图标文件加载到内存中以获取HICON时,我必须指定我想要的尺寸(请参阅我的reply to a related question)。

我的ICO文件包含一个小尺寸的图像,应该用作窗口图标(标题栏的左上角),并且设计得非常清晰,但也应该在Alt-Tab中显示更大的变体对话,但......

  1. 加载16x16图标会在标题栏中显示正确的图标,但是 - 当然 - 当我使用Alt-Tab时,它是一个丑陋的拉伸版本。任务栏中显示的那个也不是很漂亮。

  2. 加载48x48图标会在我的Alt-Tab时显示一个漂亮的图标,但标题栏中显示的图标模糊,因为它是48x48图标的缩小版本。

    < / LI>

    有没有办法告诉Windows我的Windows有一个多尺寸的图标?是否有一些我错过的明显的API?

3 个答案:

答案 0 :(得分:4)

.ICO文件中包含多个图像。但是HICON只是这些图像的一个。如果您使用LR_DEFAULTSIZE,那么可能会有一些神奇的行为保留到.ico文件的链接并使用相应的图像,但我对此表示怀疑。

如果不这样做,那么什么都不会。

HICON hicon = LoadImage(NULL, "filename.ico", IMAGE_ICON, 
                        0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);

一点背景。

当.ico文件包含在应用程序的资源中时,该文件将被打开,文件中的每个图像都将成为单独的资源。文件头被修改,它成为ICON资源。因此,当LoadIcon / LoadImage传递ICON资源的资源ID时,它实际上是传递其他资源的目录。它会在该时间点选择符合请求的图像并将其转换为HICON。实际执行此操作的函数称为LookupIconIdFromDirectory

这就是为什么当你为{HICON GetIconInfo时,你只能获得一个ICONINFO结构。

typedef struct _ICONINFO {
    BOOL fIcon;
    DWORD xHotspot;
    DWORD yHotspot;
    HBITMAP hbmMask;
    HBITMAP hbmColor;
} ICONINFO;

答案 1 :(得分:2)

GCL_HICON设置“大”图标,GCL_HICONSM设置小图标(大小通常为32x32和16x16,但你应该使用带有SM_CXICON和SM_CXSMICON的GetSystemMetrics来查找实际大小(对于大图标,你也可以只传递LR_DEFAULTSIZE到0大小的LoadImage))

答案 2 :(得分:1)

如果.ico文件不包含256x256全尺寸PNG图标,那么当我写简单时,Windows似乎很高兴:

var assembly = typeof (Xyz).Assembly;
var stream   = assembly.GetManifestResourceStream ("Foo.Resources.Form.ico");
var icon     = new System.Drawing.Icon (stream);

form.Icon = icon;

有了这个,并且名为Form.ico的图标放在我的程序集的Resources文件夹中,其Foo作为其默认名称空间,Windows将使用32x32版本的使用Alt-Tab进行任务栏和任务切换的图像,以及窗口标题的16x16版本。

因此,在使用WinForms'Form.Icon时要小心PNG图标......