c#系统托盘图标保存位图的问题
本文关键字:问题 位图 保存 系统托盘图标 | 更新日期: 2023-09-27 18:03:44
我正在尝试编辑位图并将其用作我的系统托盘图标的图标。我想知道是否有一种方法可以编辑它并使用它,而不必将其保存为本地文件,因为这似乎很混乱,并在。exe的根目录中留下一个。ico文件。我的代码如下
//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分钟运行一次更新系统托盘图标,它必须传递图标,所以我可以计算出何时必须关闭流。
任何帮助将非常感激,因为这把我难住了。
这个问题解决起来比你制造它要简单。没有理由将位图写入磁盘上的文件。您可以简单地忽略对Save
方法的调用。
GetHIcon
方法是真正的技巧,因为它允许您将Bitmap
转换为Icon
,并且您已经找到了它。
下面是我的示例代码。我将NotifyIcon
和Timer
控件添加到表单中,并以明显的方式连接事件处理程序。rnd
是Random
的类级实例,仅用于测试目的。
[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();
}
工作完美,不需要临时文件。
Edit:修改了上面的代码示例,以解决最终会使应用程序崩溃的GDI对象泄漏。有多快取决于计时器被设置为滴答的间隔(或者无论你如何决定图标应该在你的应用程序中改变)。
事实证明,当您在使用Icon.FromHandle
创建的图标上调用Dispose
方法时,关联的本机GDI对象不会被销毁。我认为这是WinForms实现中的一个bug,因为它违背了程序员的期望,但显然Icon.FromHandle
不假定句柄的所有权。公平地说,文档确实在"备注"部分中说明了这一点,但是谁会读它呢?
如果你不知道这样做,你就会有内存泄漏。为了修复它,你必须P/Invoke Win32函数来销毁GDI图标对象(DestroyIcon
)并显式调用它。
请确保您的应用程序这样做,无论如何,在适当的地方,以确保旧的图标被销毁,并释放相关的内存!