• 图标覆盖之IShellIconOverlayIdentifier


    想实现类似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的代码托管机制需要更加深入的研究。

    Demo:下载

  • 相关阅读:
    python字符串与字典转换
    B站弹幕爬取 / jieba分词
    【计算机网络】第四章 网络层(1)
    【计算机网络】第三章 传输层(4)
    【计算机网络】第三章 传输层(3)
    【计算机网络】第三章 传输层(2)
    【计算机网络】第三章 传输层(1)
    【计算机网络】第二章 网络应用(5)
    【计算机网络】第二章 网络应用(4)
    【计算机网络】第二章 网络应用(3)
  • 原文地址:https://www.cnblogs.com/caosenianhuan/p/3108662.html
Copyright © 2020-2023  润新知