【发布时间】:2011-08-05 02:58:44
【问题描述】:
我正在编写一个 C# 应用程序来更改桌面上的默认回收站图标。我通过将图标转移到驱动器上的特定位置并更新注册表以指向新图标来做到这一点。这很好用。
但是,问题是当我卸载应用程序并希望将图标设置为默认值时。当我使用 Windows 中的内置功能进行测试时,我注意到 Windows 有时会将注册表更改为 %SystemRoot%\System32\imageres.dll,50 用于空图标,%SystemRoot%\System32\imageres.dll,49 用于完整图标,有时%SystemRoot%\System32\imageres.dll,-55 用于空图标,%SystemRoot%\System32\imageres.dll,-54 用于完整图标。我真的找不到有时使用 50 和 49 有时使用 -55 -54 作为默认回收站图标的逻辑,也找不到有关此问题的任何信息。
我也尝试删除 User\username\AppData\Local 中的图标缓存,但没有任何效果。问题是当我重新设置默认图标(例如使用 50 和 49)时,它不会自动更新。我每次都必须手动刷新才能更改其状态(空/满)。如果我之后转到 Windows 中的内置功能并设置回默认图标,如果我使用 50 和 49,它会更改为 -55 或 -54,然后它就可以工作了。什么?注册表中一定有其他地方触发了这个..你能帮我吗?
我正在使用的注册表中的位置:
HKEY_CURRENT_USER\
Software\
Microsoft\
Windows\
CurrentVersion\
Explorer\
CLSID\
{645FF040-5081-101B-9F08-00AA002F954E}\
DefaultIcon
编辑18/04-2011 在安德斯的帖子之后,我想出了这个:
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern long SendMessageTimeout(int hWnd, int Msg, int wParam, int lParam, int fuFlags, int uTimeout, out int lpdwResult);
private const int SPI_SETICONS = 0x0058;
private const int SPIF_UPDATEINIFILE = 0x1;
private const int SPIF_SENDWININICHANGE = 0x2;
private const int HWND_BROADCAST = 0xffff;
private const int WM_SETTINGCHANGE = 0x001A;
private const int SMTO_ABORTIFHUNG = 0x0002;
private const int SPI_SETNONCLIENTMETRICS = 0x0002;
int res = 0;
RegistryKey iconSizeKey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop\\WindowMetrics", true);
int iconSize = Int16.Parse((string)iconSizeKey.GetValue("Shell Icon Size"));
int newIconSize = iconSize - 1;
iconSizeKey.SetValue("Shell Icon Size", newIconSize, RegistryValueKind.String);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 100000, out res);
iconSizeKey.SetValue("Shell Icon Size", iconSize, RegistryValueKind.String);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 100000, out res);
但这并没有改变任何东西:(
编辑19/02-2011 在安德斯的帖子之后我更新了这个:
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
并尝试了所有这些组合:
SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
SHChangeNotify(0x08000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
SHChangeNotify(0x00008000, 0x1000, IntPtr.Zero, IntPtr.Zero);
SHChangeNotify(0x00002000, 0x1000, IntPtr.Zero, IntPtr.Zero);
还是不行:(
【问题讨论】:
-
我无法想象是什么让你选择这样做。用户拥有桌面并拥有大量进行更改的工具。您依赖注册表中的实现细节不会打扰您吗?
-
它确实困扰着我。但是有什么选择呢?我真的没有看到提供更改图标(使用内置 win 方法)作为选项的指南。
-
@s0mmer 为什么需要这样做?为什么您的用户会接受您以这种方式弄乱他们的系统。如果我在我的机器上安装了执行此操作的软件,我会非常生气并会快速卸载它。
-
@David Heffernan:我想简化在用户计算机上安装特定图标的过程。用户将获得有关过程的通知,并且必须在应用程序执行任何操作之前接受这一点。
-
@s0mmer 为什么用户希望他们的回收站图标改变?这是什么类型的应用程序?