2013-03-14 82 views
0

我正在嘗試編輯位圖並將其用作系統托盤圖標的圖標。我想知道是否有辦法編輯它並使用它,而不必將其另存爲本地文件,因爲這看起來很麻煩,並將.ico文件保存在.exe的根目錄中。我擁有的代碼如下。爲系統托盤圖標保存位圖的問題C#

//To Save icon to disk 
bitmap.Save("icon.ico", System.Drawing.Imaging.ImageFormat.Icon); 
Icon createdIcon = Icon.FromHandle(bitmap.GetHicon()); 
bitmap.Dispose(); 
return createdIcon; 

有沒有更優雅的方式來做到這一點,將它保存爲內部資源?或在一個內存流?另一件事是,這個函數每5分鐘運行一次來​​更新系統托盤圖標,並且它必須通過圖標,這樣我才能解決什麼時候我必須關閉流。

任何幫助將不勝感激,因爲這讓我難住。

回答

1

該問題比解決問題要簡單得多。沒有理由將位圖寫入磁盤上的文件。您可以簡單地省略對Save方法的調用。

GetHIcon method是真正的伎倆,因爲它允許您將Bitmap轉換爲Icon,並且您已經找到了一個。

這是我的示例代碼。我將一個NotifyIconTimer控件添加到窗體中,並以明顯的方式連接了事件處理程序。 rndRandom的類級別實例,僅用於測試目的。

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
private static extern bool DestroyIcon(IntPtr hIcon); 

private void timer1_Tick(object sender, EventArgs e) 
{ 
    Icon icon; 

    // Create a temporary new Bitmap with the size of a notification icon. 
    using (Bitmap bmp = new Bitmap(SystemInformation.SmallIconSize.Width, SystemInformation.SmallIconSize.Height)) 
    { 
     // Fill the temporary bitmap with a random number. 
     using (Graphics g = Graphics.FromImage(bmp)) 
     { 
     g.DrawString(rnd.Next().ToString(), 
         SystemFonts.MessageBoxFont, 
         SystemBrushes.ControlText, 
         0.0F, 0.0F); 
     } 

     // Convert this bitmap to an icon. 
     icon = Icon.FromHandle(bmp.GetHicon()); 
    } 

    // Update the notification icon to use our new icon, 
    // and destroy the old icon so we don't leak memory. 
    Icon oldIcon = notifyIcon1.Icon; 
    notifyIcon1.Icon = icon; 
    DestroyIcon(oldIcon.Handle); 
    oldIcon.Dispose(); 
} 

完美地工作,不需要臨時文件。

編輯:修改上面的代碼示例來解決GDI對象泄漏,最終會使您的應用程序癱瘓。取決於計時器設置爲打勾的時間間隔(或者您確定圖標應該在您的應用程序中更改)的速度有多快。

事實證明,當您使用Icon.FromHandle創建的圖標調用Dispose方法時,關聯的本地GDI對象不會被銷燬。我認爲這是WinForms實現中的一個錯誤,因爲它無視程序員的期望,但顯然Icon.FromHandle並不是而是假定句柄的所有權。公平地說,文檔確實在「備註」部分說明了這一點,但誰讀了?

如果你不知道這樣做,你的手上就有內存泄漏。要修復它,你必須P/Invoke Win32函數銷燬一個GDI圖標對象(DestroyIcon)並明確地調用它。

請確保您的應用程序執行此操作(無論何時適用),以確保舊圖標被破壞並釋放關聯的內存!