[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;
}

    /// &lt;summary&gt;
    /// Determines whether an overlay should be shown for the shell item with the path 'path' and
    /// the shell attributes 'attributes'.
    /// &lt;/summary&gt;
    /// &lt;param name="path"&gt;The path for the shell item. This is not necessarily the path
    /// to a physical file or folder.&lt;/param&gt;
    /// &lt;param name="attributes"&gt;The attributes of the shell item.&lt;/param&gt;
    /// &lt;returns&gt;
    ///   &lt;c&gt;true&lt;/c&gt; if this an overlay should be shown for the specified item; otherwise, &lt;c&gt;false&lt;/c&gt;.
    /// &lt;/returns&gt;
    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;
        }
    }

    /// &lt;summary&gt;
    /// Called to get the icon to show as the overlay icon.
    /// &lt;/summary&gt;
    /// &lt;returns&gt;
    /// The overlay icon.
    /// &lt;/returns&gt;
    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



  • SharpShell


  • .NET Shell Extensions - Shell Icon Handlers


  • IMPLEMENTING ICON OVERLAY HANDLERS IN C#