DropTarget リファレンス

フォルダやファイルへのドロップ操作(IDropTarget)をスクリプトから実行する DropTarget オブジェクトのリファレンスです。

記法: P=プロパティ、M=メソッド。メンバー名の照合は大文字小文字を区別しません。

目次

  1. 取得方法
  2. メソッド
  3. プロパティ
  4. 動作の流れとスクリプトのイベント
  5. 定数
  6. 使用例

1. 取得方法

方法 説明
api.DropTarget(item) item(FolderItem・パス文字列など)に対する DropTarget を返す。内部では、項目の親フォルダに IDropTarget を問い合わせる。項目の ItemIDList が得られない場合は何も返らない(空)
FV.Droptarget 現在のフォルダへの DropTarget(FolderView のプロパティ。folderview_reference_jp.md 参照)

2. メソッド

DragEnter / DragOver / Drop は、同じ引数を取ります。

DropTarget.Drop(dataObj, grfKeyState, pt [, pdwEffect [, bSingle [, caller]]])

引数 内容
dataObj ドラッグするデータ。FolderItems(FV.SelectedItems() など)または IDataObject。解釈できないと E_INVALIDARG
grfKeyState キー/ボタンの状態(MK_* の組み合わせ)。例: MK_LBUTTON(左ボタン)、MK_CONTROL(Ctrl)、MK_SHIFT(Shift)
pt ドロップ位置(スクリーン座標)。api.Memory("POINT") か {x, y} 相当のオブジェクト
pdwEffect ドロップ効果(DROPEFFECT_*)。Memory(DWORD) などの添字 0 を持つオブジェクトを渡すと、そこから許可する効果を読み、結果の効果を書き戻す。数値を渡すと許可する効果として使うだけで、結果は返らない。省略すると COPY \| MOVE \| LINK を許可し、結果は返らない
bSingle 真にすると、呼び出したメソッドの段階だけを実行する(4章)。偽/省略では一連の流れを実行する
caller スクリプトのイベント(te.OnDragEnter など)の第1引数 Ctrl に渡すオブジェクト。省略すると、この DropTarget 自身

引数は最低3個(dataObj, grfKeyState, pt)必要です。足りない場合は何も実行せず E_INVALIDARG を返します。

名前 戻り値 説明
DragEnter(dataObj, grfKeyState, pt [, ...]) HRESULT ドラッグがターゲットに入ったことを通知する
DragOver(dataObj, grfKeyState, pt [, ...]) HRESULT ドラッグ中の位置・キー状態を通知し、受け入れ可能か(効果)を調べる
Drop(dataObj, grfKeyState, pt [, ...]) HRESULT ドロップを実行する(実際のコピー/移動/リンクが行われる)
DragLeave() HRESULT ドラッグがターゲットから出たことを通知する。シェル側の DragLeave と、te.OnDragLeave を呼ぶ。シェル側のターゲットが無いときの戻り値は不定(要確認)

戻り値は S_OK(0)で成功、失敗は負値(E_INVALIDARG = 0x80070057 など)です。


3. プロパティ

名前 種別 説明
Type P(読み) 常に CTRL_DT(0x80000)
FolderItem P(読み) この DropTarget の対象項目(FolderItem)。api.DropTarget(item) で作った場合は item

4. 動作の流れとスクリプトのイベント

bSingle を偽(省略)にして呼ぶと、1回の呼び出しの中で、それより前の段階も順に実行されます。

呼び出し 実行される段階
DragEnter(…) DragEnter → DragLeave
DragOver(…) DragEnter → DragOver → DragLeave
Drop(…) DragEnter → DragOver → Drop → DragLeave

通常は Drop(…) を1回呼ぶだけでよく、1つ前の段階を明示的に呼ぶ必要はありません(sync1.js や標準アドオンも、Drop または DragOver を単独で呼んでいます)。 bSingle を真にすると、呼んだ段階だけが実行され、DragLeave も自動では呼ばれません(DragEnter/DragOver/Drop を自分で順に呼び、最後に DragLeave() を呼びたいときに使います)。

スクリプトのイベントとの連携

api.DropTarget(item) で作った DropTarget(対象項目あり)は、各段階で、まずスクリプトのイベント(te.OnDragEnter / te.OnDragOver / te.OnDrop)を呼び、続いてシェル標準の処理を行います。

段階 動作
DragEnter シェル標準の DragEnter を呼んだあと、te.OnDragEnter を呼ぶ。イベントが S_OK を返した場合、その効果を採用する
DragOver まず te.OnDragOver を呼ぶ。S_OK 以外を返す、または効果を変更しなかったときに限り、シェル標準の DragOver も呼ぶ
Drop まず te.OnDrop を呼ぶ。S_OK を返すとシェル標準の Drop は実行されない(スクリプト側で処理したことになる)。S_OK 以外ならシェル標準の Drop が実行される
最後(bSingle が偽) シェル標準の DragLeave を呼ぶ。Drop の場合は te.OnDragLeave も呼ぶ

5. 定数

consts.js で定義されています。

DROPEFFECT_*: DROPEFFECT_NONE = 0 / DROPEFFECT_COPY = 1 / DROPEFFECT_MOVE = 2 / DROPEFFECT_LINK = 4

MK_*: MK_LBUTTON = 1 / MK_RBUTTON = 2 / MK_SHIFT = 4 / MK_CONTROL = 8 / MK_MBUTTON = 0x10 / MK_XBUTTON1 = 0x20 / MK_XBUTTON2 = 0x40

CTRL_DT = 0x80000(Type が返す値)


6. 使用例

// 選択中のファイルを、別のフォルダへ「ドロップ」する(Ctrl 付き=コピー)
const FV = te.Ctrl(CTRL_FV);
const Items = FV.SelectedItems();
const DropTarget = api.DropTarget("C:\\Backup");
if (DropTarget) {
    const pdwEffect = api.Memory("DWORD");
    pdwEffect[0] = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
    const pt = api.Memory("POINT");
    api.GetCursorPos(pt);
    const hr = DropTarget.Drop(Items, MK_LBUTTON | MK_CONTROL, pt, pdwEffect);
    // hr === 0 (S_OK) なら成功。pdwEffect[0] に実際の効果が入る
}

// 効果だけ調べる(実際には実行しない)
const dt = api.DropTarget(dest);
const eff = api.Memory("DWORD");
eff[0] = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
dt.DragOver(Items, MK_LBUTTON, pt, eff);
const canMove = !!(eff[0] & DROPEFFECT_MOVE);

// イベントの中で、標準のドロップ処理に委ねる
te.OnDrop = function (Ctrl, dataObj, pgrfKeyState, pt, pdwEffect) {
    const Target = Ctrl.FolderItem;
    const DropTarget = api.DropTarget(Target);
    if (DropTarget) {
        return DropTarget.Drop(dataObj, pgrfKeyState[0], pt, pdwEffect);
    }
};

// 段階を自分で制御(bSingle = true)
const d = api.DropTarget(dest);
d.DragEnter(Items, MK_LBUTTON, pt, eff, true);
d.DragOver(Items, MK_LBUTTON, pt, eff, true);
d.Drop(Items, MK_LBUTTON, pt, eff, true);
d.DragLeave();

te.OnDrop の中で自分自身のイベントを再び呼び出してしまうと、Ctrl が同じ項目のときに無限に呼び合う可能性があります。標準スクリプトでは api.DropTarget(Target) の Target を Ctrl.FolderItem や HitTest の結果に限定して使っています。

関連