このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
早速 ColumnPrivider に登録してみよう。
Column フォルダに LinkTargetColumn.cs を追加し、
LoaferShellEx.Column.LinkTargetColumn クラスを作る。
本来は、役割が異なるロジックは分離すべきだが、
とりあえずは動作を試してみたいので、
昨日作ったリンク先の取得のコードも、
LinkTargetColumn の中に含めてしまおう。
========== LinkTargetColumn.cs ==========
using System;
using System.Resources;
using System.Runtime.InteropServices;
using System.Text;
using LoaferShellEx.Interop;
namespace LoaferShellEx.Column {
public class LinkTargetColumn : ColumnBase {
// カラムセットの ID
private static readonly Guid FORMAT_ID
= new Guid("3D75F8D7-93CF-4cb5-B255-9D7AF7E346C5");
// カラムの ID
private const int PROPERTY_ID = 1;
public LinkTargetColumn()
: base(FORMAT_ID, PROPERTY_ID) {}
// カラムの情報を取得
public override void GetInfo(out SHCOLUMNINFO psci) {
// まずは既定の実装を呼び、
base.GetInfo(out psci);
// 固有分を補正
psci.cChars = 40;
psci.wszTitle = "リンク先";
psci.wszDescription = "ショートカットの示す先";
}
// ファイルに対応した値を取得
public override object GetValue(ref SHCOLUMNDATA pscd) {
// ディレクトリにはリンク先情報はない
if ((pscd.dwFileAttributes & FILE_ATTRIBUTE.DIRECTORY) != 0) {
throw new ComFalseException();
}
// 拡張子を調べる
switch (pscd.pwszExt.ToLower()) {
case ".lnk":
// ショートカット
// Shortcut オブジェクトを作成
ShortcutClass obj = new ShortcutClass();
try {
// IPersistFile インタフェースを取得し
UCOMIPersistFile pf = (UCOMIPersistFile)obj;
// ショートカットファイルを読み込み
pf.Load(pscd.wszFile, 0);
// IShellLinkW インタフェースを取得する
IShellLinkW link = (IShellLinkW)obj;
// バッファを用意し
StringBuilder target
= new StringBuilder(Constants.MAX_PATH);
StringBuilder arguments
= new StringBuilder(Constants.INFOTIPSIZE);
// ショートカット先と
link.GetPath(target, target.Capacity,
IntPtr.Zero, SLGP.UNCPRIORITY | SLGP.RAWPATH);
// 引数を取得し
link.GetArguments(arguments, arguments.Capacity);
// コマンドラインを合成する
string command = target.ToString();
// 空白を含み、クォートされてなければクォートする
if (command.IndexOf(' ') >= 0
&& !command.StartsWith("\"")
&& !command.EndsWith("\"")) {
command = '"' + command + '"';
}
// 引数があれば繋げる
if (arguments.Length > 0) {
command += ' ' + arguments.ToString();
}
// 完了
return command;
} finally {
// COM オブジェクトを解放する
Marshal.ReleaseComObject(obj);
}
default:
// 未知の形式なら S_FALSE を返す
throw new ComFalseException();
}
}
}
}
========== end of LinkTargetColumn.cs ==========
LinkTargetColumn はこんな感じとなる。
昨日のコードに手を加え、GetArguments の処理を追加した。
GetPath は実行するファイル名(またはドキュメント)だ。
コマンドに引数がある場合、GetArguments で取得できる。
例えば、「プログラムのアクセスと既定の設定」リンクは、
GetPath が、「%SystemRoot%\system32\control.exe」
GetArguments が「appwiz.cpl,,3」となる。
カラムに表示可能なのは 1 つだけなので、
これらを組み合わせてコマンドライン文字列を作っている。
GetPath が空白を含む場合はダブルクォートで囲み、
引数があれば空白をあけて後ろに続ければ完成となる。
では、ColumnProvider.cs も書き換えて、
LinkTargetColumn を公開しよう。
これは、COLUMNS 配列を変更するだけでいい。
// カラムの定義
private static readonly IColumn[] COLUMNS = new IColumn[] {
new ByteSizeColumn(),
new LinkTargetColumn(),
};
これだけで、「リンク先」が表示されるようになった。