このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
まず、バイトサイズのカラムの実装を、
ColumnProvider から、独立したクラスである
ByteSizeColumn に移そう。
========== ByteSizeColumn.cs ==========
using System;
using System.IO;
using LoaferShellEx.Interop;
namespace LoaferShellEx.Column {
public class ByteSizeColumn : ColumnBase {
// カラムセットの ID
private static readonly Guid FORMAT_ID
= new Guid("09f98e7c-f7ef-4e5f-b84f-fa5bf75aad07");
// カラムの ID
private const int PROPERTY_ID = 12345;
// ColumnBase の初期化
public ByteSizeColumn()
: base(FORMAT_ID, PROPERTY_ID) {}
// カラムの情報を取得
public override void GetInfo(out SHCOLUMNINFO psci) {
// まずは既定の実装を呼び、
base.GetInfo(out psci);
// 固有分を補正
psci.vt = VARTYPE.I8;
psci.fmt = LVCFMT.RIGHT;
psci.cChars = 10;
psci.csFlags = SHCOLSTATE.TYPE_INT | SHCOLSTATE.SLOW;
psci.wszTitle = "バイトサイズ";
psci.wszDescription = "バイト単位のファイルサイズ";
}
// ファイルに対応した値を取得
public override object GetValue(ref SHCOLUMNDATA pscd) {
// ディレクトリにはサイズ情報はない
if ((pscd.dwFileAttributes & FILE_ATTRIBUTE.DIRECTORY) != 0) {
throw new ComFalseException();
}
// サイズを返却
return new FileInfo(pscd.wszFile).Length;
}
}
}
========== end of ByteSizeColumn.cs ==========
こんな感じとなる。
ColumnBase から継承しているため、
コードがかなりシンプルになった。
スーパクラスの初期化は、base キーワードを使う。
ColumnBase のコンストラクタに、
カラム固有の GUID と整数値を渡すことで、
ColumnBase で識別子の比較や設定を行う。
次に、ColumnProvider クラスを作り直す。
========== ColumnProvider.cs ==========
using System;
using System.Runtime.InteropServices;
using LoaferShellEx.Interop;
namespace LoaferShellEx.Column {
[Guid("47388840-7A1B-4cfc-BE15-4D9CAF1046A4")]
public class ColumnProvider : IColumnProvider {
// カラムの定義
private static readonly IColumn[] COLUMNS
= new IColumn[] { new ByteSizeColumn() };
// COM に公開する場合、引数なしのコンストラクタが必要
public ColumnProvider() {
}
#region IColumnProvider メンバ
// カラムを表示するフォルダが変更された
public void Initialize(ref SHCOLUMNINIT psci) {
// ここでは何もしない
}
// カラムの情報の列挙
public void GetColumnInfo(uint dwIndex, out SHCOLUMNINFO psci) {
// 範囲外なら、S_FALSE を返す
if (dwIndex < 0 || dwIndex >= COLUMNS.Length) {
throw new ComFalseException();
}
// カラム実装クラスに委託する
COLUMNS[dwIndex].GetInfo(out psci);
}
// ファイルに対するカラムの値の問い合わせ
public void GetItemData(
ref SHCOLUMNID pscid, ref SHCOLUMNDATA pscd,
out object pvarData) {
// 値を問い合わせているカラムを調べる
foreach (IColumn c in COLUMNS) {
// 識別子が一致するか
if (c.EqualsID(ref pscid)) {
// カラム実装クラスから値を取得
pvarData = c.GetValue(ref pscd);
// OK
return;
}
}
// 対応するカラムがない
throw new ComFalseException();
}
#endregion
}
}
========== end of ColumnProvider.cs ==========
役割的には、IColumn を公開するのが ColumnProvider だ。
そのため、ColumnProvider には IColumn の配列を持たせる。
GetColumnInfo では、自分が公開する IColumn に対して、
GetInfo を呼び出して情報の設定を任せる。
GetItemData では、カラムの識別子を調べ、
特定を行った上で、カラムの GetValue に任せる。
まあ、崩れたコレクションのような役割ではあるが、
このように実装しておけば、IColumn の配列に、
要素を追加するだけで、新しいカラムが公開できるので楽だ。