【问题标题】:Avoiding duplicate icon resources in a .NET (C#) project避免 .NET (C#) 项目中的重复图标资源
【发布时间】:2010-10-10 10:57:57
【问题描述】:

我正在使用 Visual C# 2008 Express。我想为应用程序(即.exe 显示的图标)和主窗体使用相同的图标。不幸的是,VC# 对此似乎不太聪明,并且坚持要复制图标数据。

似乎没有办法选择“已嵌入”图标以在表单或项目图标中使用(仅选择一个文件),并且对两个图标使用相同的文件只会将文件嵌入两倍我所看到的。这没什么大不了的(硬盘空间现在很便宜,对吗?),但它让我很烦恼。

知道如何避免这种情况吗?有没有办法以编程方式加载可执行文件的图标,以便在构建表单时使用,比如说?一些关于类似事情的论坛帖子似乎表明 .NET 资源不使用普通的旧 Windows 资源系统——在获取旧式资源的框架内有没有办法?还是我必须绑定 Win32 API 函数才能做到这一点?

【问题讨论】:

  • 为什么不使用继承?在一个自定义表单类中定义图标并在任何地方使用它。
  • 我记得我的 Delphi 编程时代... self.Icon = Application.Icon; :P ...在.NET中太难了:D

标签: c# winforms winapi resources


【解决方案1】:

你是对的,这很烦人。

您必须自己加载图标,而不是依赖设计器生成的代码。将图标保存为项目资源,然后将该资源加载到表单构造函数中的表单Icon 属性中:

this.Icon = Properties.Resources.myIconResourceName;

【讨论】:

  • 这并不能解决问题:将图标作为项目资源嵌入与在表单设计器中设置相同——它复制了图标数据,这是我试图避免的.
  • 添加图标为项目图标的时候应该已经嵌入为资源了吧?
  • 我看不到...用于可执行文件的图标似乎完全独立于 .NET 资源系统。
  • 与可执行文件关联的图标存储为普通的win32图标资源。这是您在 XN 资源编辑器中查看时看到的资源。这与 .NET 资源系统不同(它确实将资源存储在可执行文件中,但格式不同)。
  • 如果您像我一样想在运行时更改表单的图标,则此答案很有用。您只需要在项目资源中添加图标,并在加载时更改表单的图标
【解决方案2】:

您正在寻找Icon.ExtractAssociatedIcon。调用传递您的可执行文件:

var icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);

【讨论】:

  • 请解释一下为什么这么慢?如果是因为它使用反射可以通过使用 Application.ExecutablePath 而不是 Assembly.GetExecutingAssembly().Location 轻松解决。
  • 最佳解决方案!它不会在资源中重复图标并在任务栏中显示最佳质量图标。谢谢!
  • 对您来说可能没问题,但请注意这不适用于 UNC 路径。
【解决方案3】:

是的,这很烦人。但是 Icon.ExtractAssociatedIcon 的建议答案的问题是它会检索 32x32 图标,然后在表单窗口或任务栏上下采样到 16x16 图标,除非您的 32x32 图标非常巧妙地构建,否则这看起来很糟糕。

我这样做的方式是使用互操作(将第一行放在表单构造函数中):

this.Icon = ExtractSmallIconFromLibrary(Application.ExecutablePath);
...

public static Icon ExtractSmallIconFromLibrary(string file) {
    IntPtr[] reficon = new IntPtr[1];
    int nextracted = ExtractIconEx(file, 0, null, reficon, 1);
    if (nextracted < 1)
        return null;
    Icon unmanaged_icon = Icon.FromHandle(reficon[0]);
    Icon icon = (Icon)unmanaged_icon.Clone();
    DestroyIcon(unmanaged_icon.Handle);
    return icon;
}

[DllImport("Shell32", CharSet = CharSet.Auto)]
extern static int ExtractIconEx(
    [MarshalAs(UnmanagedType.LPTStr)] 
    string lpszFile,
    int nIconIndex,
    IntPtr[] phIconLarge,
    IntPtr[] phIconSmall,
    int nIcons
    );

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

但这也不是很好,因为您确实想要像 Alt-Tab 图标列表这样的 32x32 图标。所以你真的需要提取 整个 图标,这是一项更大的工作。也许有一种简单的方法可以将两个图标组合成一个。或者你可以像这个codeproject 程序那样做,它首先用一大堆代码提取整个图标。

【讨论】:

    【解决方案4】:

    我也遇到过类似的问题。

    我有一个 exe 图标,我想在不增加文件大小的情况下重复用于子表单。

    //From MyApp
    MySubForm msf = new MySubForm();
    msf.Icon = this.Icon;
    msf.Show();
    

    我不知道这是否有用,但我还是想分享它。

    【讨论】:

      【解决方案5】:

      我认为在许多情况下,包括重复图标最终比尝试从非托管资源中提取它更有效 - 考虑到您不能将 Icon.ExtractAssociatedIcon 用于 UNC 路径。

      【讨论】:

        猜你喜欢
        • 2011-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多