想实现类似SVN样式的文件夹及文件的效果,即如果文件已经有改动,则需要在相应的文件图标上添加一个标志。
下面的几个连接可以提供很多参考
http://msdn.microsoft.com/en-us/library/windows/desktop/bb761265(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/hh127442(v=VS.85).aspx
http://www.codeproject.com/Articles/7484/How-to-overlay-an-icon-over-existing-shell-objects
1 public sealed class ShellInterop 2 { 3 private ShellInterop() 4 { 5 } 6 [DllImport("shell32.dll")] 7 public static extern void SHChangeNotify(int eventID, uint flags, IntPtr item1, IntPtr item2); 8 } 9 10 [ComVisible(false)] 11 [ComImport] 12 [Guid("0C6C4200-C589-11D0-999A-00C04FD655E1")] 13 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 14 public interface IShellIconOverlayIdentifier 15 { 16 17 [PreserveSig] 18 int IsMemberOf([MarshalAs(UnmanagedType.LPWStr)]string path, uint attributes); 19 20 [PreserveSig] 21 int GetOverlayInfo( 22 IntPtr iconFileBuffer, 23 int iconFileBufferSize, 24 out int iconIndex, 25 out uint flags); 26 27 [PreserveSig] 28 int GetPriority(out int priority); 29 } 30 31 [ComVisible(true)] 32 [Guid("B8FA9E43-38E6-4654-8A13-FF905AD22CE5")] 33 public class XavierMyIconOverlay : IShellIconOverlayIdentifier 34 { 35 36 #region IShellIconOverlayIdentifier Members 37 public int IsMemberOf(string path, uint attributes) 38 { 39 //Show everything with icon overlay 40 return 0; // S_OK 41 } 42 43 public int GetOverlayInfo(IntPtr iconFileBuffer, int iconFileBufferSize, out int iconIndex, out uint flags) 44 { 45 46 System.Diagnostics.Debug.WriteLine(string.Format("GetOverlayInfo::{0}", iconFileBuffer)); 47 48 System.Diagnostics.Debug.WriteLine(string.Format("GetOverlayInfo::{0}", iconFileBufferSize)); 49 string fname = @"c:\favicon.ico"; 50 51 int bytesCount = System.Text.Encoding.Unicode.GetByteCount(fname); 52 53 System.Diagnostics.Debug.WriteLine(string.Format("GetOverlayInfo::{0}", bytesCount)); 54 55 byte[] bytes = System.Text.Encoding.Unicode.GetBytes(fname); 56 57 if (bytes.Length + 2 < iconFileBufferSize) 58 { 59 for (int i = 0; i < bytes.Length; i++) 60 { 61 Marshal.WriteByte(iconFileBuffer, i, bytes[i]); 62 } 63 //write the "\0\0" 64 Marshal.WriteByte(iconFileBuffer, bytes.Length, 0); 65 Marshal.WriteByte(iconFileBuffer, bytes.Length + 1, 0); 66 } 67 68 iconIndex = 0; 69 flags = 1; // ISIOI_ICONFILE 70 return 0; // S_OK 71 } 72 73 74 public int GetPriority(out int priority) 75 { 76 priority = 0; // 0-100 (0 is highest priority) 77 return 0; // S_OK 78 } 79 #endregion 80 81 #region Registry 82 [ComRegisterFunction] 83 public static void Register(Type t) 84 { 85 RegistryKey rk = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\_" 86 + t.Name); 87 rk.SetValue(string.Empty, t.GUID.ToString("B").ToUpper()); 88 rk.Close(); 89 ShellInterop.SHChangeNotify(0x08000000, 0, IntPtr.Zero, IntPtr.Zero); 90 } 91 92 [ComUnregisterFunction] 93 public static void Unregister(Type t) 94 { 95 Registry.LocalMachine.DeleteSubKeyTree(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\_" 96 + t.Name); 97 ShellInterop.SHChangeNotify(0x08000000, 0, IntPtr.Zero, IntPtr.Zero); 98 } 99 #endregion 100 }
在项目属性中,选择签名,以产生程序集的强名;然后生成解决方案,会在bin目录的debug或release目录下产生xxx.dll文件
注册服务: regasm xxx.dll /codebase
重启Explorer,即可看到效果
后记:改代码还有不足,首先其编译出的Dll有版本的限制,不能同时支持64位和32位的系统,在选择生成32位的dll注册后,其仅能支持32位的程序,64位的程序不能调用该dll。如果编译成64位dll其原理一样,所以解决该问题需要把X86和x64同时注册到服务中。
在此感谢xuguilin 的帮助,http://www.cnblogs.com/xuguilin/archive/2010/04/05/1704885.html#2709859 参看该篇文章,颇有收获。同时想说CLR的代码托管机制需要更加深入的研究。