2010-02-10 51 views
3

我想定义一个Win32窗口的应用程序图标,例如通过调用SetClassLongGCL_HICON并传递一个图标的句柄(请参阅MSDN上的SetClassLong Function)。如何在窗口上设置HICON(多种尺寸的.ICO)?

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

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

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

  2. 加载48x48图标显示一个很好的图标,当我按Alt-Tab时,但标题栏中显示的图标模糊不清,因为它是48x48图标的缩小版。

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

回答

2

GCL_HICON设置“大”图标,GCL_HICONSM设置小图标(大小通常是32×32和16×16,但你应该使用SM_CXICON和SM_CXSMICON GetSystemMetrics的发现实际尺寸(大图标,你可以也只是通过LR_DEFAULTSIZE 0大小))

+0

目前,我无法使SetClassLong在我的WinForms应用程序上按预期工作。默认的WinForms图标获胜;当我用Alt-Tab时,我会看到我的图标,但是默认的WinForms图标被绘制在我的头顶上。奇怪。如果我不能自己弄清楚,我会在堆栈溢出上发布另一个问题。 – 2010-02-12 16:18:46

+0

其他问题在这里,如果你想知道:http://stackoverflow.com/questions/2266479 – 2010-02-17 13:43:33

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; 
+0

对于LR_DEFAULTSIZE MSDN说:‘如果资源包含多个图像,函数使用第一个图像的大小’ – Anders 2010-02-10 13:40:26

+0

@Anders :是的。但.NET ICON似乎会跟踪.ico源代码,并且当您要求它从旧的图标创建一个新图标时,它会回到源代码中,而不仅仅是延伸。我认为这对于非托管图标来说也是如此,但我无论如何都没有确定的知识。 – 2010-02-11 00:08:56

+1

谢谢你的想法和解释。然而,LR_DEFAULTSIZE并没有做我们梦寐以求的魔法行为。我想我将不得不使用GCL_HICON和GCL_HICONSM;我会通过评论安德斯的回复报告。 – 2010-02-12 16:02:38

1

到的LoadImage如果.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图标...