是否有通过 Windows 资源管理器以编程方式剪切/复制/粘贴文件的 Windows API?
Posted
技术标签:
【中文标题】是否有通过 Windows 资源管理器以编程方式剪切/复制/粘贴文件的 Windows API?【英文标题】:Is there a Windows API to programmatically Cut / Copy / Paste files via Windows Explorer? 【发布时间】:2012-04-08 08:36:33 【问题描述】:我知道SHFileOperation 可用于与Windows Explorer 执行文件操作,但它仅在源和目标都已知的情况下执行完整的文件操作。
是否有允许应用程序从应用程序在 Windows 资源管理器中剪切、复制或粘贴的 API?
回答几个问题:
使用 Windows 资源管理器执行文件/文件夹操作将大大简化移动多个对象的过程。这对于移动文件夹及其内容尤其重要,因为MoveFile
不支持将文件夹移动到不同的卷。
使用 Windows 资源管理器执行文件/文件夹操作将允许将操作添加到 Windows 资源管理器的撤消缓冲区,以便它们可以撤消,否则使用控制台应用程序/命令提示符完成的操作无法撤消。
我确信我已经看到可以以编程方式执行 Windows Explorer 动词,但我似乎无法找到一种方法来执行这些操作。
【问题讨论】:
在 SO 上的快速搜索显示 this answer 可能会有所帮助。有一个用于以编程方式访问剪贴板的 API。您使用的是 .NET 还是本机代码? @AdamMihalcin,嗯,我没想过用剪贴板破解它。我做了一些测试,看起来至少可以通过这种方式进行剪切/复制,但我不确定如何实现粘贴。一个简单的 API 函数会更好。 This 为我工作 【参考方案1】:很难想象为什么会有这样的功能,或者如果它存在会有什么好处。
为了方便用户,提供了剪切/复制和粘贴功能。它允许他们在以后将某些东西移动/复制到其他地方。实现剪切/复制和粘贴功能的应用程序可能不知道数据最终将被粘贴到哪里,但这没关系,因为用户仍然知道。
但是应用程序执行剪切/复制-粘贴操作没有多大意义,因为为了让“粘贴”部分起作用,应用程序必须知道项目将被粘贴到哪里。如果它知道这一点,那么它可以调用您已经知道的SHFileOperation
函数。
如果您真的只是在谈论为用户提供剪切/复制/粘贴项目的能力,那么您将需要使用剪贴板——就像 Windows 一样。当一个项目被剪切或复制时,它被放置在剪贴板上。粘贴项目时,将检索剪贴板的当前内容。使用 Windows clipboard API functions 与剪贴板进行交互。
【讨论】:
这里有一个例子:你在控制台。您输入C:\>cut foobar.txt
,然后输入C:\Somewhere\Else>paste
。很像pushd/popd
。
@Syn:是的,这是在剪贴板上放置一些东西。没有特殊的 API,你只需使用剪贴板相关的函数,如 OpenClipboard
和 SetClipboardData
。
是的,我可以很容易地看到如何以这种方式完成复制和剪切,但看不到以这种方式进行粘贴的方法。我想它可以读取剪贴板并手动根据 CF_HDROP 的 DropEffect 执行文件操作,但这有点乱,这就是为什么我希望有某种快捷方式可以挂钩Explorer 的剪切/复制/粘贴功能。
@Synetech Sample program.
@Down:我没有回答哪个问题?最后一段具体解释了如何使用剪贴板 API 来完成他所要求的工作。【参考方案2】:
我在我的文件管理器中实现了它,here's the link to the GitHub source 用于复制功能。粘贴就在附近。
它的工作原理是为感兴趣的文件系统项目创建一个不可见的资源管理器上下文菜单,然后从该菜单调用剪切、复制或粘贴命令。它是用 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);
【讨论】:
数字 26 不是合同规定的。命令 26 可能意味着“加密”,具体取决于安装的其他 shell 扩展。只需自己将数据对象放在剪贴板上 @RaymondChen:我在许多 Windows 机器上运行这个软件,但还没有看到它失败的地方。我不知道如何自己把它放在那里 - 使用另一个答案中提到的剪贴板 API?它会与资源管理器兼容吗?不管怎样,谢谢你的提示。其他两个数字是合同性的吗? 好吧,至少通过规范名称调用,这是稳定的。菜单 ID 不是合同性的。 @RaymondChen:我考虑过名称,但这些名称不是我可以通过编程方式获得依赖于 UI 语言的可翻译名称吗? 程序名称未翻译。【参考方案3】:// https://docs.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
-
执行 winmain_001.exe。
在探索中复制文件。
按 ctl 然后按 v
你可以看到 CF_HDROP
您会看到函数:winmain_001.cpp 中的 wichStandardClipboardFormatsIsAvailable 和https://docs.microsoft.com/ja-jp/windows/desktop/dataxchg/standard-clipboard-formats
有一次我误导了你,对大家很抱歉。
【讨论】:
以上是关于是否有通过 Windows 资源管理器以编程方式剪切/复制/粘贴文件的 Windows API?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在资源管理器窗口中以编程方式将文件夹添加到 Windows 10 快速访问面板?