シェル拡張ハンドラーの初期化

シェル拡張ハンドラー オブジェクトの実装の多くは、その型によって決まります。 ただし、一般的な要素がいくつかあります。 このトピックでは、すべてのシェル拡張ハンドラーによって共有される実装のこれらの側面について説明します。

すべてのシェル拡張ハンドラーは、インプロセス コンポーネント オブジェクト モデル (COM) オブジェクトです。 これらは GUID を割り当て、 シェル拡張ハンドラーの登録に関するページの説明に従って登録する必要があります。 これらは DLL として実装され、次の標準関数をエクスポートする必要があります。

  • DllMain。 DLL への標準エントリ ポイント。
  • DllGetClassObject。 オブジェクトのクラス ファクトリを公開します。
  • DllCanUnloadNow。 COM はこの関数を呼び出して、オブジェクトがクライアントにサービスを提供しているかどうかを判断します。 そうでない場合、システムは DLL をアンロードし、関連付けられているメモリを解放できます。

すべての COM オブジェクトと同様に、シェル拡張ハンドラーは IUnknown インターフェイスと クラス ファクトリを実装する必要があります。 ほとんどの場合、Windows XP 以前で IPersistFile または IShellExtInit インターフェイスを実装する必要があります。 これらは、Windows Vista の IInitializeWithStreamIInitializeWithItemおよび IInitializeWithFile に置き換えられました。 シェルは、これらのインターフェイスを使用してハンドラーを初期化します。

IPersistFile インターフェイスは、次のように実装する必要があります。

  • アイコン ハンドラー
  • データ ハンドラー
  • ドロップ ハンドラー

IShellExtInit インターフェイスは、次の方法で実装する必要があります。

  • ショートカット メニュー ハンドラー
  • ドラッグ アンド ドロップ ハンドラー
  • プロパティ シート ハンドラー

このトピックの残りの部分では、次のテーマについて説明します。

IPersistFile の実装

IPersistFile インターフェイスは、オブジェクトの読み込み元またはディスク ファイルへの保存を許可するように設計されています。 IUnknown に加えて 6 つのメソッドがあり、そのうち 5 つのメソッドと、IPersist から継承する GetClassID メソッドがあります。 シェル拡張機能では、 IPersist はシェル拡張ハンドラー オブジェクトの初期化にのみ使用されます。 通常、ディスクから読み取ったりディスクに書き込んだりする必要がないため、 GetClassID メソッドと Load メソッドのみが非トークン実装を必要とします。

シェルは最初に GetClassID を 呼び出し、関数は拡張ハンドラー オブジェクトのクラス識別子 (CLSID) を返します。 次に、シェルは Load を呼び出し、2 つの値を渡します。 1 つ目の pszFile は、シェルが操作しようとしているファイルまたはフォルダーの名前を持つ Unicode 文字列です。 2 つ目は dwMode で、ファイル アクセス モードを示します。 通常はファイルにアクセスする必要がないため、 dwMode は通常 0 です。 メソッドは、後で参照するために必要に応じてこれらの値を格納します。

次のコード フラグメントは、一般的な Shell 拡張ハンドラーが GetClassID メソッドと Load メソッドを実装する方法を示しています。 ANSI または Unicode を処理するように設計されています。 CLSID_SampleExtHandlerは拡張ハンドラー オブジェクトの GUID であり、CSampleShellExtension は インターフェイスの実装に使用されるクラスの名前です。 m_szFileName変数とm_dwMode変数は、ファイルの名前とアクセス フラグを格納するために使用されるプライベート変数です。

class CSampleShellExtension : public IPersistFile
{
    // Method declarations not included

    private:
    WCHAR m_szFileName[MAX_PATH];    // The file name
    DWORD m_dwMode;                  // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
}

// The implementation sample is continued in the next section.

IShellExtInit の実装

IShellExtInit インターフェイスには、IUnknown に加えて、IShellExtInit::Initialize という 1 つのメソッドしかありません。 メソッドには、シェルがさまざまな種類の情報を渡すために使用できる 3 つのパラメーターがあります。 渡される値はハンドラーの種類によって異なります。一部は NULL に設定できます。

  • pidlFolder は、アイテム識別子リスト (PIDL) へのフォルダーのポインターを保持します。 これは絶対 PIDL です。 プロパティ シート拡張の場合、この値は NULL です。 ショートカット メニュー拡張機能の場合、ショートカット メニューが表示されている項目を含むフォルダーの PIDL です。 既定以外のドラッグ アンド ドロップ ハンドラーの場合は、ターゲット フォルダーの PIDL です。
  • pDataObject は、データ オブジェクトの IDataObject インターフェイスへのポインターを保持します。 データ オブジェクトは、1 つ以上のファイル名 をCF_HDROP 形式で保持します。
  • hRegKey は、ファイル オブジェクトまたはフォルダーの種類のレジストリ キーを保持します。

IShellExtInit::Initialize メソッドは、後で使用するために必要に応じて、ファイル名、IDataObject ポインター、およびレジストリ キーを格納します。 次のコード フラグメントは、 IShellExtInit::Initialize の実装を示しています。 わかりやすくするために、この例では、データ オブジェクトに 1 つのファイルのみが含まれていることを前提としています。 一般に、データ オブジェクトには複数のファイルが含まれている場合があり、それぞれのファイルを抽出する必要があります。

// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit
{
    // Method declarations not included
    
    private:
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder;
    
    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you
    // are only interested in a single Shell item. If you need a file system
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
    IDataObject *m_pdtobj;
    
    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable.
    HKEY m_hRegKey;             
}
    
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.

IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
                                                 __in_opt IDataObject *pDataObject, 
                                                 __in_opt HKEY hRegKey) 
{ 
    // In some cases, handlers are initialized multiple times. Therefore, 
    // clear any previous state here.
    CoTaskMemFree(m_pidlFolder);
    m_pidlFolder = NULL;
    
    if (m_pdtobj)
    { 
        m_pdtobj->Release(); 
    }
    
    if (m_hRegKey)
    {
        RegCloseKey(m_hRegKey);
        m_hRegKey = NULL;
    }
    
    // Capture the inputs for use later.
    HRESULT hr = S_OK;
    
    if (pidlFolder)
    {
        m_pidlFolder = ILClone(pidlFolder);   // Make a copy to use later.
        hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
    }
    
    if (SUCCEEDED(hr))
    {
        // If a data object pointer was passed into the method, save it and
        // extract the file name. 
        if (pDataObject) 
        { 
            m_pdtobj = pDataObject; 
            m_pdtobj->AddRef(); 
        }
    
        // It is uncommon to use the registry handle, but if you need it,
        // duplicate it now.
        if (hRegKey)
        {
            LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
            hr = HRESULT_FROM_WIN32(result);
        }
    }
    
    return hr;
}

ヒントのカスタマイズ

ヒントをカスタマイズするには、2 つの方法があります。 1 つの方法は、 IQueryInfo をサポートする オブジェクトを実装し、レジストリ内の適切なサブキーの下にオブジェクトを登録することです (以下を参照)。 または、固定文字列または表示する特定のファイル プロパティの一覧を指定することもできます。

名前空間拡張機能の固定文字列を表示するには、名前空間拡張機能の CLSID キーの下に ヒント というサブキーを作成します。 そのサブキーのデータを、表示する文字列に設定します。

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

ファイルの種類の固定文字列を表示するには、 ヒント を指定するファイルの種類の ProgID キーの下にヒントというサブキーを作成します。 そのサブキーのデータを、表示する文字列に設定します。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = InfoTip string for all files of this type

シェルで特定のファイルの種類のヒントに特定のファイル プロパティを表示する場合は、そのファイルの種類の ProgID キーの下にヒントというサブキーを作成します。 そのサブキーのデータを、セミコロンで区切られた標準プロパティ名のリストまたは {fmtid}、 propname が正規プロパティ名、 {fmtid}、pidFMTID/PID ペアである pid のペアに設定します。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = propname;propname;{fmtid},pid;{fmtid},pid

次のプロパティ名を使用できます。

プロパティ名 説明 取得元
Author ドキュメントの作成者 PIDSI_AUTHOR
タイトル ドキュメントのタイトル PIDSI_TITLE
サブジェクト 件名の概要 PIDSI_SUBJECT
コメント ドキュメント コメント PIDSI_COMMENT またはフォルダー/ドライブのプロパティ
PageCount ページ数 PIDSI_PAGECOUNT
名前 フレンドリ名 標準フォルダー ビュー
OriginalLocation 元のファイルの場所 Briefcase フォルダーとごみ箱フォルダー
DateDeleted ファイルが削除された日付 ごみ箱フォルダー
ファイルの種類 標準フォルダーの詳細ビュー
サイズ ファイルのサイズ 標準フォルダーの詳細ビュー
SyncCopyIn OriginalLocation と同じ OriginalLocation と同じ
修正済み 最終更新日 標準フォルダーの詳細ビュー
作成済み 作成日 標準フォルダーの詳細ビュー
アクセス方法 最終アクセス日 標準フォルダーの詳細ビュー
InFolder ファイルを含むディレクトリ ドキュメントの検索結果
順位 検索一致の品質 ドキュメントの検索結果
FreeSpace 使用可能な記憶域 ディスク ドライブ
NumberOfVisits アクセス数 お気に入りのフォルダー
属性 ファイル属性 標準フォルダーの詳細ビュー
[会社] 会社名 PIDDSI_COMPANY
カテゴリ ドキュメント カテゴリ PIDDSI_CATEGORY
著作権 メディアの著作権 PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML ヒント ファイル フォルダーのDesktop.ini ファイル

 

シェル拡張機能ハンドラーの登録