【问题标题】:C# - WPF - Project size after adding icons (load icon from resources or pull from project EXE)C# - WPF - 添加图标后的项目大小(从资源加载图标或从项目 EXE 中提取)
【发布时间】:2015-05-22 21:02:04
【问题描述】:

Edit1:编辑的标题

Edit2:添加方法 3

Edit3:添加方法 4


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

我添加图标的方式是在解决方案资源管理器中右键单击我的项目并单击“现有项目...”,然后我将再次右键单击我的项目,转到“属性”->“应用程序”在“图标和清单”下,我为整个项目选择了我的新图标。

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

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

方法一:

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

现在我加载所有图标的总项目大小为 20KB + 40KB = 60KB

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

我知道我可以在项目“资源”中添加我的图标并执行以下操作:

方法二:

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

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

20KB(项目大小)+ 40KB(EXE 图标)+ 40KB(资源图标)= 100KB

方法3

“Discord”在下面的答案中发布了另一种直接从可执行资源中获取文件的方法。

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 分辨率版本

方法四

根据使用的代码,从项目 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 非常陌生。

【问题讨论】:

    标签: c# .net wpf icons


    【解决方案1】:

    您在项目属性中添加的图标将添加到标识符为 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 之间来回转换图标的方法,因此,例如,如果您想在表单上显示图标,您也可以这样做(参见Imaging.CreateBitmapSourceFromHIcon 等)。

    如果Icon.ExtractAssociatedIcon 工作正常,我认为没有理由为此烦恼。 可能有一些问题,这个函数可能不会提取所有图标,而只会提取特定的大小。

    另请参阅Avoiding duplicate icon resources in a .NET C# project 问题。

    【讨论】:

    • 非常感谢您提供的示例和链接。这无疑对我有所帮助,并增加了更多完成我需要的方法。我知道您所说的“尽管可能存在一些问题”是什么意思。从 EXE 中拉出图标只会获得 32x32 的系统托盘图标并将其缩小到 16x16,这看起来不如仅抓取 16x16 版本的图标。不过,我仍在努力寻找方法。
    • @hyperexpert 试试LoadImage
    【解决方案2】:

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

    使用 WPF 时,您的可执行文件会很快变得非常大,我正在开发一个数十兆字节的 WPF .exe。

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2019-09-15
      • 2015-03-25
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多