2010-02-10 53 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圖標...