Entering Passive Mode

カテゴリ 'COM' の記事
< 1 2 3 4 5 6 7 >

ファイルサイズの表示

カラム

今日はちゃんとファイルサイズを表示してみよう。

ColumnProvider.cs を開き、
GetColumnInfo の一部を以下のように書き換える。

    // カラムの情報を設定する
    psci.scid.fmtid = FORMAT_ID;
    psci.scid.pid = PROPERTY_ID;
    psci.vt = VARTYPE.I8;
    psci.fmt = LVCFMT.RIGHT;
    psci.cChars = 10;
    psci.csFlags = SHCOLSTATE.TYPE_INT | SHCOLSTATE.SLOW;
    psci.wszTitle = "バイトサイズ";
    psci.wszDescription = "バイト単位のファイルサイズ";

システムへの登録

カラム

さて、作った ColumnProvider をシステムに登録する。
登録には 2 種類ある。COM ライブラリとしての登録と、
シェルのカラムハンドラへの登録だ。

まず COM ライブラリの登録だが、
.NET でプロジェクトのプロパティの設定をしておけば、
ビルド後に自動的に COM ライブラリ用の登録が行われる。

次にシェルのカラムハンドラへの登録だが、
これはレジストリに値を書き込むことで行われる。

ColumnProvider を作る

今日は、IColumnProvider のプロトコルを確認するため、
IColumnProvider の実装系を作ってみよう。

まず、プロジェクトのルートに Column フォルダを追加する。
フォルダは自動的に名前空間として使用されるので、
Column の中は、LoaferShellEx.Column 名前空間となる。

この中にクラスを追加し、ColumnProvider クラスを作る。
このクラスには IColumnProvider を実装するので、
using LoaferShellEx.Interop で空間をインポートしておく。

MarshalAs による文字列変換

もう 1 つ構造体が残っている。
GetItemData メソッドに出てくる、SHCOLUMNDATA だ。

以前も MarshalAsAttribute という属性が出てきたが、
今日は、さらにこの属性が活躍する。

定義を見てみよう。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/structures/shcolumndata.asp

    typedef struct {
        ULONG dwFlags;
        DWORD dwFileAttributes;
        ULONG dwReserved;
        WCHAR *pwszExt;
        WCHAR wszFile[MAX_PATH];
    } SHCOLUMNDATA, *LPSHCOLUMNDATA;

型指定の列挙体

Initialize メソッドは終わった。
次は、GetColumnInfo メソッドで定義されている、
SHCOLUMNINFO 構造体だ。

今までと同じように、定義を参照する。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/structures/shcolumninfo.asp

    typedef struct {
        SHCOLUMNID scid;
        VARTYPE vt;
        DWORD fmt;
        UINT cChars;
        DWORD csFlags;
        WCHAR wszTitle[MAX_COLUMN_NAME_LEN];
        WCHAR wszDescription[MAX_COLUMN_DESC_LEN];
    } SHCOLUMNINFO, *LPSHCOLUMNINFO;

構造体のパッキング

シェルのインタフェースには構造体が良く出てくる。
これらは、インタフェースの皮をかぶった API だと
考えてもいい程、低水準の定義が多いのだ。

基本的には、C# では値型の struct で
色々な型を並べた構造を扱うすることができるが、
C 言語の構造体を定義する場合、注意点がある。
それは、パッキングやアラインメントと呼ばれる機構だ。

.NET では「型」と「名前」を使ってアクセスするので、
フィールド定義の順番や型などを気にしないのだが、
シェルの構造体は「メモリレイアウト」であり、
「定義の順序」や「型の大きさ」が大きな意味を持つ。

COM メソッドのシグネチャ

IColumnProvider のメソッドは IUnknown を除くと 3 つ。
Initialize, GetColumnInfo, GetItemData の順だ。

まず、MSDN ライブラリを参考にし、
メソッドのシグネチャを調べる。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/icolumnprovider/icolumnprovider.asp

基本的に C++ 用の定義で書いてあるので、
C# 用に変換しなければならない。
これは、避けて通れない道だ。

IColumnProvider の枠組み

.NET では、API だけでなく、COM インタフェースも
ソースに定義することで利用することができる。

Visual Basic で API を利用する時は、
Declare 文で定義して利用していたが、
.NET では、これらの定義になるべく特殊な構文を使わず、
通常と同じようなソースの定義に対して、
「属性」を付けることによってコンパイラに指示をだす。

さて、IColumnProvider を .NET に移植しよう。
プロジェクトに IColumnProvider.cs を追加し、
IColumnProvider の基本的な記述を書く。

COM インタフェースと .NET

エクスプローラにカラムを追加するには、
シェルで定義されている COM 用のインタフェースである、
IColumnProvider を実装したクラスを公開する必要がある。

.NET は、新しい COM サーバを作成するには便利なのだが、
COM で定義されているインタフェースを利用する場合、
それらを使うために少し面倒な手順を踏む必要がある。

COM のインタフェースは、そのまま .NET で利用できない。
古い技術である COM は .NET のことを知らないからだ。
.NET で COM のインタフェースを利用するためには、
COM の定義を .NET 用に変換して読み込む必要がある。
それには、以下の二つの方法がある。

プロジェクトの作成

開発環境には、そこそこ普及が進んでいる、
Visual Studio .NET 2003 を使うことにしよう。

ColumnProvider は、COM のインプロセスサーバに実装する。
.NET で言えば、クラスライブラリに相当するものだ。
クラスライブラリを利用するのはシェルであり、
ColumnProvider は、プラグインの開発に似ている。

まず、プロジェクトを作成しよう。
新規作成→プロジェクトを選び、
Visual C# プロジェクトの「クラスライブラリ」を選ぶ。
プロジェクト名は適当に「LoaferShellEx」とでもつける。

< 1 2 3 4 5 6 7 >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS