有没有Windows API可以通过Windows资源管理器以编程方式剪切/复制/粘贴文件?

11

我知道 SHFileOperation 可以用于与 Windows资源管理器 进行文件操作,但它只能执行已知源和目标的完整文件操作。

是否有一种API允许应用程序从应用程序中剪切、复制或粘贴到Windows资源管理器中?

回答几个问题:

  • 使用 Windows资源管理器来执行文件/文件夹操作将极大地简化移动多个对象的过程。这对于移动文件夹及其内容尤为重要,因为 MoveFile 不支持将文件夹移动到不同的卷。

  • 使用 Windows资源管理器来执行文件/文件夹操作将允许这些操作被添加到 Windows资源管理器的撤消缓冲区中,以便它们可以被撤消,否则使用控制台应用程序/命令提示符执行的操作将无法撤消。

我确定我看到过可以通过编程方式执行 Windows资源管理器动词,但是似乎找不到适用于这些情况的方法。


在这里快速搜索,发现这个答案可能会有帮助。有一个用于程序访问剪贴板的API。您是否使用.NET或本机代码? - Adam Mihalcin
@AdamMihalcin,嗯,我没有考虑使用剪贴板进行黑客攻击。我做了一些测试,看起来至少可以用这种方式进行剪切/复制,但我不确定粘贴应该如何实现。一个简单的API函数会更好。 - Synetech
这对我有用。 - Miserable Variable
3个回答

1
我在我的文件管理器中实现了它,这是GitHub源代码的链接,用于复制功能。粘贴就在附近。
它通过为感兴趣的文件系统项创建一个不可见的资源管理器上下文菜单来工作,然后从该菜单调用剪切、复制或粘贴命令。它使用C++(因为COM),但我相信你也可以以某种方式从其他语言使用COM。
bool copyObjectsToClipboard(std::vector<std::wstring> objects, void * parentWindow)
{
    ComInitializer comInitializer;

    IContextMenu * imenu = 0;
    HMENU hMenu = NULL;
    if (!prepareContextMenuForObjects(objects, parentWindow, hMenu, imenu) || !hMenu || !imenu)
        return false;

    CComInterfaceReleaser menuReleaser(imenu);

    const char command[] = "Copy";

    CMINVOKECOMMANDINFO info = { 0 };
    info.cbSize = sizeof(info);
    info.hwnd = (HWND)parentWindow;
    info.lpVerb = command;
    info.nShow = SW_SHOWNORMAL;
    const auto result = imenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);

    DestroyMenu(hMenu);

    return SUCCEEDED(result);
}

3
数字26并非契约性质。指令26的含义可能因其他外壳扩展程序的安装而异,也可能意味着“加密”。只需自行将数据对象放入剪贴板即可。 - Raymond Chen
@RaymondChen:我在许多Windows机器上运行这个软件,但还没有看到一个失败的。我不知道如何自己放置它 - 使用其他答案中提到的剪贴板API?它是否与资源管理器兼容?无论哪种方式,感谢提示。另外两个数字是合同吗? - Violet Giraffe
至少按规范名称调用,这是稳定的。菜单ID不是合同性的。 - Raymond Chen
我考虑过名称,但是我可以通过程序获取的名称不是依赖于用户界面语言可翻译的名称吗? @RaymondChen - Violet Giraffe
编程名称不被翻译。 - Raymond Chen
@RaymondChen:谢谢。我已经修复了问题并更新了代码——比我预期的要容易! - Violet Giraffe

1

很难想象为什么会存在这样一个函数,如果它存在的话又有什么好处。

剪切/复制和粘贴是为了方便用户而提供的。它允许他们在以后的某个日期将某些东西移动/复制到其他地方。实现剪切/复制和粘贴功能的应用程序可能不知道数据最终将被粘贴到哪里,但这没关系,因为用户仍然知道。

但是,一个执行剪切/复制-粘贴操作的应用程序并没有太多意义,因为为了使“粘贴”部分起作用,应用程序必须知道该项将被粘贴到哪里。如果它知道这一点,那么它可以直接调用你已经知道的 SHFileOperation 函数。

如果你只是想让用户能够剪切/复制/粘贴一个项目,那么你需要使用剪贴板——就像Windows一样。当一个项目被剪切或复制时,它会被放置在剪贴板上。当一个项目被粘贴时,剪贴板的当前内容将被检索。使用Windows 剪贴板API函数 与剪贴板交互。


2
这是一个例子:你在控制台上。你输入 C:\>cut foobar.txt,然后稍后输入 C:\Somewhere\Else>paste。这很像 pushd/popd - Synetech
@Syn:是的,那就是将某些内容放到剪贴板上。这并没有特殊的API,你只需要使用与剪贴板相关的函数,例如OpenClipboardSetClipboardData - Cody Gray
1
@Synetech 样例程序 - Raymond Chen
@Raymond,谢谢;看起来很有前途。我也会尝试一下。 - Synetech
2
@Down:我没有回答哪个问题?最后一段特别解释了如何使用剪贴板API来完成他的要求。 - Cody Gray
显示剩余6条评论

1
// https://learn.microsoft.com/ja-jp/windows/desktop/dataxchg/standard-clipboard-formats
const char* wichStandardClipboardFormatsIsAvailable()
{
    // Standard Clipboard Formats
    // CF_BITMAP            : 2
    // CF_DIB               : 8
    // CF_DIBV5             :17
    // CF_DIF               : 5
    // CF_DSPBITMAP         :0x0082
    // CF_DSPENHMETAFILE    :0x008E
    // CF_DSPMETAFILEPICT   :0x0082
    // CF_DSPTEXT           :0x0081
    // CF_ENHMETAFILE       :14
    // CF_GDIOBJFIRST       :0x0300
    // CF_GDIOBJLAST        :0x03FF
    // CF_HDROP             :15
    // CF_LOCALE            :16
    // CF_METAFILEPICT      :3
    // CF_OEMTEXT           :7
    // CF_OWNERDISPLAY      :0x0080
    // CF_PALETTE           :9
    // CF_PENDATA           :10
    // CF_PRIVATEFIRST      :0x0200
    // CF_PRIVATELAST       :0x02FF
    // CF_RIFF              :11
    // CF_SYLK              :4
    // CF_TEXT              :1
    // CF_TIFF              :6
    // CF_UNICODETEXT       :13
    // CF_PRIVATELAST       :0x02FF
    // CF_WAVE              :12

    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_BITMAP";
    }
    if ( IsClipboardFormatAvailable(CF_DIB) ) {
        return "CF_DIB";
    }
    if ( IsClipboardFormatAvailable(CF_DIBV5) ) {
        return "CF_DIBV5";
    }
    if ( IsClipboardFormatAvailable(CF_DIF) ) {
        return "CF_DIF";
    }
    if ( IsClipboardFormatAvailable(CF_DSPBITMAP) ) {
        return "CF_DSPBITMAP";
    }
    if ( IsClipboardFormatAvailable(CF_DSPENHMETAFILE) ) {
        return "CF_DSPENHMETAFILE";
    }
    if ( IsClipboardFormatAvailable(CF_DSPMETAFILEPICT) ) {
        return "CF_DSPMETAFILEPICT";
    }
    if ( IsClipboardFormatAvailable(CF_HDROP) ) {
        return "CF_HDROP";
    }
    if ( IsClipboardFormatAvailable(CF_GDIOBJFIRST) ) {
        return "CF_GDIOBJFIRST";
    }
    if ( IsClipboardFormatAvailable(CF_GDIOBJLAST) ) {
        return "CF_GDIOBJLAST";
    }
    if ( IsClipboardFormatAvailable(CF_HDROP) ) {
        return "CF_HDROP";
    }
    if ( IsClipboardFormatAvailable(CF_LOCALE) ) {
        return "CF_LOCALE";
    }
    if ( IsClipboardFormatAvailable(CF_METAFILEPICT) ) {
        return "CF_METAFILEPICT";
    }
    if ( IsClipboardFormatAvailable(CF_OEMTEXT) ) {
        return "CF_OEMTEXT";
    }
    if ( IsClipboardFormatAvailable(CF_OWNERDISPLAY) ) {
        return "CF_OWNERDISPLAY";
    }
    if ( IsClipboardFormatAvailable(CF_PALETTE) ) {
        return "CF_PALETTE";
    }
    if ( IsClipboardFormatAvailable(CF_RIFF) ) {
        return "CF_RIFF";
    }
    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_SYLK";
    }
    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_TEXT";
    }
    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_UNICODETEXT";
    }
    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_PRIVATELAST";
    }
    if ( IsClipboardFormatAvailable(CF_BITMAP) ) {
        return "CF_WAVE";
    }

    return "CF_NOT_STANDARD";
}

https://github.com/WaitrudWeber/source_zip/blob/master/winmain-20190111.zip

  1. 执行winmain_001.exe。
  2. 在资源管理器中复制文件。
  3. 按下ctl,然后按v键
  4. 您可以看到CF_HDROP

您可以在winmain_001.cpp中查看函数:wichStandardClipboardFormatsIsAvailable和https://learn.microsoft.com/ja-jp/windows/desktop/dataxchg/standard-clipboard-formats

我曾经误导过您,对每个人都感到非常抱歉。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接