11

I know that SHFileOperation can be used to perform file operatons with Windows Explorer, but it only performs complete file operations where both the source and destination are known.

Is there an API that allows a application to cut, copy, or paste in Windows Explorer from an application?

To answer a couple of questions:

  • Using Windows Explorer to perform file/folder operations would greatly simplify moving multiple objects. This is particularly important for moving folders and their contents since MoveFile does not support moving folders to different volumes.

  • Using Windows Explorer to perform file/folder operations would allow the operations to be added to Windows Explorer’s undo buffer so that they can be undone, otherwise operations done with console applications/the command-prompt cannot be undone.

I am sure that I have seen it possible to perform Windows Explorer verbs programmatically, but I can’t seem to find a way to do so for these.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
Synetech
  • 9,643
  • 9
  • 64
  • 96
  • A quick search here on SO revealed [this answer](http://stackoverflow.com/q/2097664/960195) that might prove helpful. There is an API for programmatic access to the clipboard. Are you using .NET or native code? – Adam Mihalcin Mar 23 '12 at 19:05
  • @AdamMihalcin, hmm, I hadn’t thought of hacking it with the clipboard. I did some tests and it looks like at least cut/copy can be done that way, but I’m not sure how paste would be implemented. A simple API function would be much nicer. – Synetech Mar 23 '12 at 19:11
  • [This](http://stackoverflow.com/questions/17189010/how-to-copy-cut-a-file-not-the-contents-to-the-clipboard-in-windows-on-the-com/17248125#comment30694875_17354470) worked for me – Miserable Variable Apr 21 '14 at 21:34

3 Answers3

1

I implemented it in my file manager, here's the link to the GitHub source for the copy function. Paste is nearby.

It works by creating an invisible Explorer context menu for the file system items of interest, and then invoking the Cut, Copy, or Paste command from that menu. It's in C++ (because COM), but I'm sure you can use COM from other languages as well somehow.

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);
}
Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • 3
    The number 26 is not contractual. Command 26 might mean "encrypt" depending on what other shell extensions are installed. Just put the data object on the clipboard yourself – Raymond Chen Dec 27 '15 at 21:47
  • @RaymondChen: I'm running this software on numerous Windows machines, and have yet to see one where it fails. I don't have a slightest idea how to put it there myself - with the Clipboard API mentioned in the other answer? Will it be compatible with Explorer? Either way, thanks for the hint. Are the other two numbers contractual? – Violet Giraffe Dec 27 '15 at 21:57
  • Well at least invoke by canonical name, which is stable. Menu ids are not contractual. – Raymond Chen Dec 27 '15 at 22:10
  • @RaymondChen: I thought about names, but aren't the names I can get programmatically translatable names that depend on the UI language? – Violet Giraffe Dec 27 '15 at 22:16
  • Programmatic names are not translated. – Raymond Chen Dec 28 '15 at 02:35
  • @RaymondChen: thank you. I've fixed the problem and updated the code - it was easier than I expected! – Violet Giraffe Dec 28 '15 at 06:33
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. execute winmain_001.exe.
  2. copy file in the explore.
  3. press ctl and then v
  4. you could see CF_HDROP

you see the function: wichStandardClipboardFormatsIsAvailable in winmain_001.cpp and https://learn.microsoft.com/ja-jp/windows/desktop/dataxchg/standard-clipboard-formats

once I misslead you and am so sorry to everyone.

1

It's difficult to imagine why such a function would exist, or what good it would be if it did.

Cut/copy and paste are provided for the convenience of the user. It allows them to move/copy something somewhere else at a later date. The application that implements cut/copy and paste functionality may not know where the data is ultimately going to be pasted, but that's okay because the user still knows.

But an application doing a cut/copy-paste action doesn't make a lot of sense because in order for the "paste" part to work, the application has to know where the item is going to be pasted. And if it knows that, then it could just call the SHFileOperation function that you already know about.

If you are really just talking about providing the user with the ability to cut/copy/paste an item, then you will want to use the clipboard—just like Windows does. When an item is cut or copied, it's placed on the clipboard. When an item is pasted, the current contents of the clipboard are retrieved. Use the Windows clipboard API functions to interact with the clipboard.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    Here’s an example: You’re at the console. You type `C:\>cut foobar.txt`, then later, `C:\Somewhere\Else>paste`. It’s a lot like `pushd/popd`. – Synetech Mar 23 '12 at 21:20
  • @Syn: Yes, that's placing something onto the clipboard. There's no special API for that, you just use the clipboard-related functions like `OpenClipboard` and `SetClipboardData`. – Cody Gray - on strike Mar 23 '12 at 21:21
  • Yes, and I can easily see how both copy and cut could be accomplished in that manner, but cannot see a way to do a paste that way. I suppose it could read the clipboard and *manually* perform a file-operation depending on the DropEffect of the CF_HDROP, but that’s kind of messy, which is why I was hoping there was some sort of shortcut to hook into Explorer’s cut/copy/paste functions. – Synetech Mar 23 '12 at 21:49
  • @Syn: They didn't hide the `GetClipboardData` function. Explorer doesn't use or expose a special API for this, and I still don't understand why you think it should. – Cody Gray - on strike Mar 23 '12 at 21:51
  • Simulate a drop onto the folder's `IDropTarget`. – Raymond Chen Mar 23 '12 at 22:36
  • *> I still don't understand why you think it should.*   Accessing the cut/copy/paste function in Explorer (e.g., `hExplorer->Cut(); hExplorer->Paste();`) would be *much* easier than manually entering or processing the data into the clipboard. It’s not toooo bad for a single file, but for multiple objects… – Synetech Mar 23 '12 at 22:50
  • @RaymondChen, that sounds even more involved. I’m going to throw together a test program using the library of clipboard functions I wrote a while back (some of them do in fact include OLE though). – Synetech Mar 23 '12 at 22:53
  • 1
    @Synetech [Sample program](http://blogs.msdn.com/b/oldnewthing/archive/2008/07/24/8768095.aspx). – Raymond Chen Mar 23 '12 at 23:05
  • @Raymond, thanks; that looks promising. I’ll try that out as well. – Synetech Mar 24 '12 at 03:25
  • 2
    @Down: Which question did I not answer? The last paragraph specifically explains how to use the clipboard APIs to do what he asks. – Cody Gray - on strike Mar 25 '12 at 07:31
  • Here's how I use it: I spend most of my time in `emacs` or command line. But I often like to attache files in e-mails. So I use [File2Clip](http://stackoverflow.com/questions/17189010/how-to-copy-cut-a-file-not-the-contents-to-the-clipboard-in-windows-on-the-com/17248125#comment30694875_17354470) to copy the file from Emacs and paste it in my e-mail. Without this, I would have to either navigate to the folder from Outlook attachments pop-up or open the folder in Explorer and then drag and drop to Outlook – Miserable Variable Apr 21 '14 at 21:36