プログラム系統備忘録ブログ

記事中のコードは自己責任の下でご自由にどうぞ。

FOFX_RECYCLEONDELETEやFOFX_ADDUNDORECORDの振る舞いの実験

確認環境: Windows 10 Version 1809 (OS Build 17763.134), Microsoft Visual Studio Community 2017 Version 15.9.2
IFileOperation関係の前の記事: IFileOperation::NewItem()の使用例

IFileOperation::SetOperationFlagsのドキュメントを読んでも FOFX_ADDUNDORECORD, FOFX_RECYCLEONDELETE が FOF_ALLOWUNDO とどのように違うのかピンとこないので実験しました。

確認結果

DeleteItemの項目は、表示される確認UIで「はい」を選択した場合を表しています。

dwOperationFlags RenameItemの動作 DeleteItemの動作
0 UNDO不可 完全に削除
FOF_ALLOWUNDO UNDO可 ゴミ箱に移動、UNDO可
FOFX_ADDUNDORECORD UNDO可 完全に削除、UNDO履歴抹消
FOFX_RECYCLEONDELETE UNDO不可 ゴミ箱に移動、UNDO不可
FOFX_ADDUNDORECORD bitor FOFX_RECYCLEONDELETE UNDO可 ゴミ箱に移動、UNDO可

表中の「UNDO可」は、Explorerの「元に戻す」に追加されており、その操作で元に戻せることを表します。
「UNDO不可」は、Explorerの「元に戻す」に追加されておらず元に戻せないことを表します。
「UNDO履歴抹消」は、Explorerの「元に戻す」「やり直す」の履歴がすべてクリアされることを表します。

というわけで FOF_ALLOWUNDO を細分化したものが FOFX_ADDUNDORECORD, FOFX_RECYCLEONDELETE であるようです。
UNDO履歴抹消になるパターンが存在する理由は分かりません。

確認コード

#include<ShObjIdl.h>
#include<atlbase.h>
#include<iso646.h>
void Test(int type, DWORD dwOperationFlags) {
    HRESULT hr;

    ::ATL::CComPtr<::IFileOperation> pFileOperation;
    hr = pFileOperation.CoCreateInstance(CLSID_FileOperation);
    if (FAILED(hr)) { return; }

    ::ATL::CComPtr<::IShellItem> pShellItem;
    hr = ::SHCreateItemFromParsingName(LR"(c:\test\foo.txt)", nullptr, IID_PPV_ARGS(&pShellItem));
    if (FAILED(hr)) { return; }

    hr = pFileOperation->SetOperationFlags(dwOperationFlags);
    if (FAILED(hr)) { return; }

    if (type == 0) {
        hr = pFileOperation->RenameItem(pShellItem, L"bar.txt", nullptr);
        if (FAILED(hr)) { return; }
    }
    else {
        hr = pFileOperation->DeleteItem(pShellItem, nullptr);
        if (FAILED(hr)) { return; }
    }

    pFileOperation->PerformOperations();
}

int main() {
    HRESULT hr = S_OK;
    hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
    if (SUCCEEDED(hr)) {
        Test(0, FOF_ALLOWUNDO); // ここの引数を変更して確認
        CoUninitialize();
    }
}