2006 年 6 月 28 日 19 時 5 分

ByteSizeColumn クラス


このアーカイブは同期化されません。 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 の配列に、
要素を追加するだけで、新しいカラムが公開できるので楽だ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.