C# - WPF - 添加图标后的项目大小(从资源加载图标或从项目EXE拉取)

时间:2015-05-22 21:02:05

标签: c# .net wpf icons

Edit1:已编辑的标题

Edit2:添加了方法3

Edit3:添加了方法4

我正在创建一个非常小的应用/实用程序,总共只有20KB。我的图标文件包含各种大小,为40KB。

我添加图标的方法是右键单击解决方案资源管理器中的项目,然后单击"现有项目...",然后我再次右键单击我的项目,转到&# 34;属性" - > "用途"并且在"图标和清单"我在那里为整个项目选择了我的新图标。

这样做会在我的所有表单,exe,任务栏等中显示我的图标...除了系统托盘图标。

我加载系统托盘图标的方法是从EXE中提取图标:

方法1:

Icon ico = System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
notifyIcon.Icon = ico;

现在我加载了所有图标的项目总大小为20KB + 40KB = 60KB< - 这就是我所追求的。

我想知道这是否是加载我所有图标的正确方法?

我知道我可以在项目中添加我的图标"资源"并做:

方法2:

notifyIcon.Icon = PROJECTNAME.Properties.Resources.icon;

但是,这只会使图标大小翻倍,然后在顶部添加项目大小。所以:

20KB(项目规模)+ 40KB(EXE图标)+ 40KB(资源图标)= 100KB

方法3

"不和谐"已经在下面的答案中发布了另一种直接从可执行资源中获取文件的方法。

IntPtr hIcon = LoadIcon(GetModuleHandle(null), new IntPtr(32512));
notifyIcon.Icon = Icon.FromHandle(hIcon);

[DllImport("user32.dll")]
static extern IntPtr LoadIcon (IntPtr hInstance, IntPtr iconName);
[DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle (string moduleName);

现在方法1和方法3的唯一问题是图标在32x32中提取,然后缩小到16x16,这在系统托盘中看起来不太好。

此答案由" vanmelle":Avoiding duplicate icon resources in a .NET (C#) project描述了如何在16x16中获取图标,但不确定这是否会获得32x32版本的HiDPI分辨率

方法4

从项目EXE中提取图标似乎要么是16x16还是32x32,具体取决于所使用的代码。不能做到这两点并让操作系统选择它想要的HiDPI系统。不幸的是,我打算使用我的系统托盘图标创建另一个图标文件,只有我的应用程序图标的16x16和32x32版本,然后像这样使用它:(幸运的是我的16x16,32x32应用程序图标只有4KB)

notifyIcon.Icon = new System.Drawing.Icon(Properties.Resources.ico, System.Windows.Forms.SystemInformation.SmallIconSize);

如果需要,此方法将调用16x16图标或32x32图标。

你可以这样做:

notifyIcon.Icon = new System.Drawing.ico;

但是这将始终调用32x32图标并将其缩小到16x16,这在系统托盘中可能看起来不太好。

最初,我这样做的方法是将图标添加到"资源"并让notifyIcon从那里调用它。然后在解决方案资源管理器 - 项目名称 - > "属性" - > "用途"我会在那里选择项目图标。这会加载我的图标大小两次,使我的项目从(20KB + 40KB图标)跳到100KB

目前,我正在使用方法1.我想知道是否有更好的方法来加载我的图标并保持我的应用程序大小较小而不是两次添加图标大小?

虽然我确实知道60KB和100KB之间的差异并不是什么大不了的事情,但我只想在将来的参考资料中学到这一点。另外,想知道我的第一种方法是否有任何警告?

我来自Web开发背景,是C#和WPF的新手。

2 个答案:

答案 0 :(得分:2)

您在项目属性中添加的图标将添加到标识符为32512(IDI_APPLICATION)的可执行文件资源(.rsrc部分)中。如果您不想依赖Icon.ExtractAssociatedIcon,则可以使用LoadIcon函数以更直接的方式提取它。它不是用.NET包装的,所以还有更多代码:

IntPtr hIcon = LoadIcon(GetModuleHandle(null), new IntPtr(32512));
notifyIcon.Icon = Icon.FromHandle(hIcon);

[DllImport("user32.dll")]
static extern IntPtr LoadIcon (IntPtr hInstance, IntPtr iconName);
[DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle (string moduleName);

有关详细信息,请参阅Using the same icon for the .exe and a form in a Windows Forms application without duplicating it?问题。

WPF包含在HICONImageSource之间来回转换图标的方法,因此,如果您想在表单上显示图标,您也可以这样做(请参阅{{1等等。)。

如果Imaging.CreateBitmapSourceFromHIcon工作正常,我认为没有理由为此烦恼。但可能是一些问题,此功能可能不会提取所有图标,而只提取特定尺寸。

另见Avoiding duplicate icon resources in a .NET C# project问题。

答案 1 :(得分:0)

这些方法中的任何一种都可以正常工作。对于像这样简单的事情,没有正确的方法,只要代码完成工作,没有人会抱怨。

使用WPF时,您的可执行文件大小会非常快,我正在使用几十兆字节的WPF .exe。