【发布时间】:2009-11-25 14:54:43
【问题描述】:
有没有办法从代码中更改 WPF 程序集图标?我指的不是窗口图标,而是 .exe 文件中出现的图标。
编辑:
我正在尝试在应用程序图标的表示中实现交互性 - 不同的用户启动操作与当前状态相结合应该会导致不同的应用程序图标。我依赖应用程序的可视化表示,因为它没有可见窗口,并且交互基于热键和一般系统使用模式。
【问题讨论】:
有没有办法从代码中更改 WPF 程序集图标?我指的不是窗口图标,而是 .exe 文件中出现的图标。
编辑:
我正在尝试在应用程序图标的表示中实现交互性 - 不同的用户启动操作与当前状态相结合应该会导致不同的应用程序图标。我依赖应用程序的可视化表示,因为它没有可见窗口,并且交互基于热键和一般系统使用模式。
【问题讨论】:
概述
更改 .exe 文件中的图标很简单,但有点麻烦。您可能需要做三件事:
详情
第 3 步 - 实际编辑 .exe 文件 - 是最有趣的,所以我将从那里开始。您将在kernel32.dll 中使用BeginUpdateResource()、UpdateResource() 和EndUpdateResource() 调用。基本上你这样做:
byte[] data = File.ReadAllBytes(newIconFilePath);
// Or otherwise load icon data
IntPtr hUpdate = BeginUpdateResource(exePath, false);
UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), LANG_SYSTEM_DEFAULT,
data, data.Length);
EndUpdateResource(hUpdate, false);
您需要为函数添加DllImport 声明并实现常量。有关BeginUpdateResource、UpdateResource 和EndUpdateResource 工作原理的详细信息,请参阅the documentation on MSDN。
对于第 1 步 - 防止 .exe 被锁定 - 简单的解决方案是将代码添加到应用程序启动中,以检查当前 .exe 是否从临时目录 (Path.GetTempPath()) 运行。如果没有,它会使用File.Copy() 将 .exe 以及所需的任何其他文件复制到临时目录,然后使用一个提供原始 .exe 位置的附加命令行参数执行它。然后原始进程退出,解除对 .exe 文件的锁定。
对于第 2 步 - 更正权限 - 这只是修改 ACL 并可能触发 UAC 对话的问题。那里有很多例子,你可能不需要这样做,所以我将跳过进一步的解释
最后说明
上述步骤实际上允许您编辑真实 .exe 文件的实际图标。但是,如果您只需要更改视觉图标,我建议您使用快捷方式并改为编辑其图标。
【讨论】:
您在文件夹窗口中查看 exe 时看到的图标设置在 exe 中,可以通过代码更改该图标,但比您想象的要麻烦。
您在开始菜单、桌面和快速启动工具栏上看到的图标是在快捷方式文件中设置的(每个位置都有不同的文件),编辑这些文件并不难。
您可以使用 Com 和 IShellLink 做到这一点 http://msdn.microsoft.com/en-us/library/bb776891%28VS.85%29.aspx
这是一个简化事情的包装类: http://vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/Creating_and_Modifying_Shortcuts/article.asp
您也可以使用 windows 脚本主机来执行此操作: http://www.codeproject.com/KB/dotnet/shelllink.aspx
【讨论】:
Nir's suggestion 如果你想改变实际的桌面图标,使用快捷方式确实是你最好的方法。
对于无窗口应用程序来说,更好的方法可能是在通知区域安装一个图标。您可以在通知区here 阅读有关在win32 中添加/更改图标的详细信息。 .NET 通过System.Windows.Forms.NotifyIcon 支持此功能。这些 API 中的任何一个都可以让您根据需要更改/动画图标;给您一个批准的地方来通知用户事件;并为您提供一个中心位置,让用户使用菜单与您的应用程序进行交互。这还有一个好处,即使窗口最大化,您的图标仍然可见(假设用户没有隐藏它,在这种情况下您可能希望让他们这样做)。
另请参阅Windows 7 guidelines,了解通知区域的礼貌用法。使用操作系统总是比使用操作系统更容易。
【讨论】:
嗯,您不应该在运行时更改 exe 文件!
程序集图标在项目文件中定义。您可以在构建过程中更改它,但不能在应用程序运行后更改
你想达到什么目的?
【讨论】:
来自msdn:
当系统显示一个图标时,它必须从 .exe 或 .dll 文件中提取适当的图标图像。系统使用以下步骤选择图标图像:
1) 选择 RT_GROUP_ICON 资源。如果存在多个此类资源,Microsoft Windows NT/Windows 2000/Windows XP 使用资源脚本中列出的第一个资源,而 Windows 95/Windows 98/Windows Millennium Edition (Windows Me) 选择按字母顺序列出的第一个资源。
2) 从 RT_GROUP_ICON 资源中选择合适的 RT_ICON 图像。如果存在多个图像,系统将使用以下标准选择图像:
选择尺寸最接近请求尺寸的图像。
如果存在两个或多个该尺寸的图像,则选择与显示器颜色深度匹配的图像。如果没有图像与显示器的颜色深度完全匹配,则选择具有最大颜色深度且不超过显示器颜色深度的图像。如果都超过颜色深度,则选择颜色深度最低的那个。
对我来说,解决这个问题的自然方式是改变 Windows 资源管理器的行为方式。 我建议你看看 shell 扩展。您也许可以编写一个 shell 扩展,根据某些状态更改图标或使用图标覆盖来指示状态。其中最棘手的部分是让您的 shell 扩展了解应用程序状态。
一个可执行文件可以有多个图标资源,一个外壳扩展可以从应用程序中提供的图标中获取一个特定的图标。
【讨论】: