[C#]使用SharpShell實現Shell Icon Overlay功能

[C#]使用SharpShell實現Shell Icon Overlay功能

有在使用DropBox或是SVN之類的軟體的使用者應該都會注意到,這類型的軟體在透過檔案總管瀏覽時,都會透過icon的變化來明確的告知目前的狀態,既炫又清楚。這樣的功能稱做Shell Icon Overlay,在.NET中我們可以透過SharpShell來輕易的實現這樣的功能。

 

(因為SharpShell實現這樣的功能過於簡單,筆者就不另行建立範例,直接拿SharpShell裡面的範例來做說明。)

 

首先我們要先準備好要覆蓋到上面的Icon,用以表示當前的狀態。Icon圖檔建議要內含16×16、24×24 、32×32、48×48、64×64、256×256這幾種尺寸,且背景要透明處理。

 

因為範例的功能是當檔案是唯獨時附加狀態告知,因此這邊範例準備的圖檔是個大鎖。

image

 

圖檔準備好後開始進入程式的編碼。首先要建立個dll的專案,然後添加個類別來告知系統要怎樣覆蓋Icon,以及要用甚麼樣的Icon覆蓋。該類別需繼承至SharpIconOverlayHandler,並覆寫GetPriority、CanShowOverlay、與GetOverlayIcon三個抽象方法。

 

其中GetPriority是設定處理的優先權,值的範圍需介於0~100之間,0代表優先權最高,100則是最低的優先權,當指定的檔案有多個Shell Icon Overlay可供處理時系統會由此優先權值去做抉擇。

 

CanShowOverlay則是用來決定系統何時要為我們覆蓋上狀態Icon,因為這範例是唯獨時要附加狀態告知,故這邊會由帶進來的path參數去讀出檔案屬性,當檔案屬性是唯獨時帶回true,若是非唯獨檔案則回傳false。

 

GetOverlayIcon就更簡單了,很明顯的就是回傳我們要覆蓋上去的狀態Icon,也就是我們一開始準備好的大鎖圖。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using SharpShell.Interop;
using SharpShell.SharpIconOverlayHandler;

namespace ReadOnlyFileIconOverlayHandler
{
    /// <summary>
    /// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
    /// a padlock icon over files that are read only.
    /// </summary>
    [ComVisible(true)]
    public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler
    {
        /// <summary>
        /// Called by the system to get the priority, which is used to determine
        /// which icon overlay to use if there are multiple handlers. The priority
        /// must be between 0 and 100, where 0 is the highest priority.
        /// </summary>
        /// <returns>
        /// A value between 0 and 100, where 0 is the highest priority.
        /// </returns>
        protected override int GetPriority()
        {
            //  The read only icon overlay is very low priority.
            return 90;
        }

        /// <summary>
        /// Determines whether an overlay should be shown for the shell item with the path 'path' and
        /// the shell attributes 'attributes'.
        /// </summary>
        /// <param name="path">The path for the shell item. This is not necessarily the path
        /// to a physical file or folder.</param>
        /// <param name="attributes">The attributes of the shell item.</param>
        /// <returns>
        ///   <c>true</c> if this an overlay should be shown for the specified item; otherwise, <c>false</c>.
        /// </returns>
        protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
        {
            try
            {
                //  Get the file attributes.
                var fileAttributes = new FileInfo(path);

                //  Return true if the file is read only, meaning we'll show the overlay.
                return fileAttributes.IsReadOnly;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Called to get the icon to show as the overlay icon.
        /// </summary>
        /// <returns>
        /// The overlay icon.
        /// </returns>
        protected override System.Drawing.Icon GetOverlayIcon()
        {
            //  Return the read only icon.
            return Properties.Resources.ReadOnly;
        }
    }
}

 

最後記得要為剛撰寫的類別附加ComVisibleAttribute,並為程式加上強命名簽章。

image

 

到這邊實現功能所需要的組件已經準備好了。接著我們必須跟系統註冊,透過.NET Framework內建的命令提是字元輸入命令"regasm [ShellIconHandler.dll] /codebase",告知系統我們有一些自訂的處理動作。(若需要解除註冊,可下命令"regasm [ShellIconHandler.dll] /u")

image

 

命令下完後若是輸出畫面沒有任何異常,應該就是成功的完成了註冊的動作。若不夠放心我們也可以透過登錄檔做一下確認,沒意外的話HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers下應該會看到對應的機碼。

image

 

若到上述的動作都完成了,我們可以開始測試一下程式的運作是否如我們的預期,這邊我們需要將explorer.exe給關閉重啟,讓我們跟系統註冊的功能能夠生效。

image

image

 

重啟後在檔案總管隨便找個檔案將其改為唯獨狀態,我們可以如預期地看到檔案的Icon被附加了狀態Icon。

image

 

Link