2

I want to copy a file by win32 API Functions and "paste" it by (Ctrl+c) in my desktop of other folder of windows.

I Know CopyFileEx and copies file with it but this function copy and paste. I want to just copy file in my main() program (by win32 API function) and "paste" it in desktop or other folder of windows.

I don't want to use SHFileOperation function.

Jack
  • 41
  • 1
  • 2
  • If you want to copy a file from one location to another, then the API function to do it is, believe it or not, [`CopyFile`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851.aspx) or any one of its variants. Why do you need to bring in the whole copy-to-and-paste-from-the-clipboard business here? – In silico Sep 07 '14 at 09:45
  • 4
    The proper Google query is "winapi copy file to clipboard". From there, you'll have little trouble recognizing CF_HDROP and lots of examples on how to use it. – Hans Passant Sep 07 '14 at 12:17
  • Do you want to copy to the clipboard, or paste from the clipboard? – David Heffernan Sep 07 '14 at 14:21
  • I want to copy to clipboard – Jack Sep 14 '14 at 20:47
  • [Copying a file to the clipboard so you can paste it into Explorer or an email message or whatever](http://blogs.msdn.com/b/oldnewthing/archive/2013/05/20/10419965.aspx). – Raymond Chen Sep 15 '14 at 17:59

4 Answers4

6

If you want the actual file to be copied to the destination folder when the clipboard content is pasted to it, you need to put the path string onto the clipboard using the CF_HDROP format, eg:

// error handling omitted for brevity...

LPWSTR path = ...;
int size = sizeof(DROPFILES)+((lstrlenW(path)+2)*sizeof(WCHAR));
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
DROPFILES *df = (DROPFILES*) GlobalLock(hGlobal);
ZeroMemory(df, size);
df->pFiles = sizeof(DROPFILES);
df->fWide = TRUE;
LPWSTR ptr = (LPWSTR) (df + 1);
lstrcpyW(ptr, path);
GlobalUnlock(hGlobal);
SetClipboardData(CF_HDROP, hGlobal);

Update: Alternatively, see the following article on the "The Old New Thing" blog:

Copying a file to the clipboard so you can paste it into Explorer or an email message or whatever

It uses GetUIObjectOfFile() and OleSetClipboard() instead of CF_HDROP. But the end effect is similar - an object placed on the clipboard that represents the target file, and Explorer recognizes that object during a paste operation so it will copy the file to the folder being pasted in.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • LPWSTR ptr = (df + 1); what does it mean?! it give me error Error 34 error C2440: 'initializing' : cannot convert from 'DROPFILES *' to 'LPTSTR' d:\explorer project_93_6_19 - copy\dev\project1\dev.cpp 2582 1 Dev – Jack Sep 16 '14 at 20:04
  • The list of filename(s) being copied immediate follows the `DROPFILES` struct. `df + 1` is using pointer arithmetic to determine the memory address that is `sizeof(DROPFILES)` number of bytes past the memory address pointed to by `df`. That line is equivalent to `LPWSTR ptr = (LPWSTR) (((LPBYTE)df) + sizeof(DROPFILES));`. – Remy Lebeau Sep 16 '14 at 21:57
  • There was a typo in my answer, I have corrected it. However, the compiler should have been complaining about not being able to convert from `DROPFILES*` to `LPWSTR`, not to `LPTSTR`. Nothing in the code I gave you uses `TCHAR` or `LPTSTR`, so that makes me think you did not copy it into your project correctly. – Remy Lebeau Sep 16 '14 at 21:59
  • Thank you again Remy Lebeau. The documentation at https://learn.microsoft.com/en-us/windows/win32/shell/clipboard#cf_hdrop states that CF_HDROP is packaged in a STG_MEDIUM; but I never saw a concrete example and I never got it to worked. – user13947194 Feb 27 '22 at 19:53
  • @user13947194 that doc you linked to is in relation to a [shell data object](https://learn.microsoft.com/en-us/windows/win32/shell/dataobject), not the clipboard. The clipboard doesn't use `STG_MEDIUM` – Remy Lebeau Feb 27 '22 at 20:46
  • I am confused as it clearly says clipboard. – user13947194 Feb 27 '22 at 23:34
  • 1
    @user13947194 clearly you didn't read the very 1st paragraph of that page carefully enough, as it talks about transferring data between source and target via a **shell data object**, which uses `FORMATETC` to describe its data and `STG_MEDIUM` to hold its data. The clipboard is not a shell data object (but it can hold a shell data object, via `OleSetClipboard()`), thus `STG_MEDIUM` is not used to put data on the clipboard. `STG_MEDIUM` is used to put data in a shell data object. – Remy Lebeau Feb 28 '22 at 00:10
6

Here's a minimal working example (console application). It compiles for both unicode and none unicode environments. As this is kind of minimal there's no error handling of any kind (usage see below).

#include <Windows.h>
#include <Shlobj.h> // DROPFILES
#include <tchar.h>  // e.g. _tcslen

int _tmain(int argc, TCHAR* argv[])
{
    // calculate *bytes* needed for memory allocation
    int clpSize = sizeof(DROPFILES);
    for (int i = 1; i < argc; i++)
        clpSize += sizeof(TCHAR) * (_tcslen(argv[i]) + 1); // + 1 => '\0'
    clpSize += sizeof(TCHAR); // two \0 needed at the end

    // allocate the zero initialized memory
    HDROP hdrop   = (HDROP)GlobalAlloc(GHND, clpSize);
    DROPFILES* df = (DROPFILES*)GlobalLock(hdrop);
    df->pFiles    = sizeof(DROPFILES); // string offset
#ifdef _UNICODE
    df->fWide     = TRUE; // unicode file names
#endif // _UNICODE

    // copy the command line args to the allocated memory
    TCHAR* dstStart = (TCHAR*)&df[1];
    for (int i = 1; i < argc; i++)
    {
        _tcscpy(dstStart, argv[i]);
        dstStart = &dstStart[_tcslen(argv[i]) + 1]; // + 1 => get beyond '\0'
    }
    GlobalUnlock(hdrop);

    // prepare the clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_HDROP, hdrop);
    CloseClipboard();

    return 0;
}

Usage:

fclip.exe "C:\full\path\to\file.dat" "C:\more\files.dat"

That's it! Feel free to press ctrl + v to paste the files.

urbanSoft
  • 686
  • 6
  • 14
  • You may checkout my [fclip](https://github.com/urbans0ft/fclip) GitHub repository for precompiled releases. – urbanSoft Feb 26 '21 at 19:56
0

I think the Function you are looking for is this: Windows CopyFile

Example:

BOOL WINAPI CopyFile(
  _In_  LPCTSTR lpExistingFileName,
  _In_  LPCTSTR lpNewFileName,
  _In_  BOOL bFailIfExists
);
Fabian Schmidt
  • 334
  • 1
  • 13
  • 1
    I know this but I want to copy path of file to clipborad and paste it to my Computer Desktop or another Directory of windows – Jack Sep 14 '14 at 20:49
0

Normally a path is a String, so how do you want to paste a String to your Desktop? You only can copy a file and paste it to your Desktop, but not a path (String)!

This is how you copy stuff to your clipboard:

BOOL WINAPI EditCopy(VOID) 
{ 
  PLABELBOX pbox; 
  LPTSTR  lptstrCopy; 
  HGLOBAL hglbCopy; 
  int ich1, ich2, cch; 

  if (hwndSelected == NULL) 
      return FALSE; 

  // Open the clipboard, and empty it. 

  if (!OpenClipboard(hwndMain)) 
      return FALSE; 
  EmptyClipboard(); 

  // Get a pointer to the structure for the selected label. 

  pbox = (PLABELBOX) GetWindowLong(hwndSelected, 0); 

  // If text is selected, copy it using the CF_TEXT format. 

  if (pbox->fEdit) 
  { 
      if (pbox->ichSel == pbox->ichCaret)     // zero length
      {   
          CloseClipboard();                   // selection 
          return FALSE; 
      } 

      if (pbox->ichSel < pbox->ichCaret) 
      { 
          ich1 = pbox->ichSel; 
          ich2 = pbox->ichCaret; 
      } 
      else 
      { 
          ich1 = pbox->ichCaret; 
          ich2 = pbox->ichSel; 
      } 
      cch = ich2 - ich1; 

      // Allocate a global memory object for the text. 

      hglbCopy = GlobalAlloc(GMEM_MOVEABLE, 
          (cch + 1) * sizeof(TCHAR)); 
      if (hglbCopy == NULL) 
      { 
          CloseClipboard(); 
          return FALSE; 
      } 

      // Lock the handle and copy the text to the buffer. 

      lptstrCopy = GlobalLock(hglbCopy); 
      memcpy(lptstrCopy, &pbox->atchLabel[ich1], 
          cch * sizeof(TCHAR)); 
      lptstrCopy[cch] = (TCHAR) 0;    // null character 
      GlobalUnlock(hglbCopy); 

      // Place the handle on the clipboard. 

      SetClipboardData(CF_TEXT, hglbCopy); 
  } 

  // If no text is selected, the label as a whole is copied. 

  else 
  { 
      // Save a copy of the selected label as a local memory 
      // object. This copy is used to render data on request. 
      // It is freed in response to the WM_DESTROYCLIPBOARD 
      // message. 

      pboxLocalClip = (PLABELBOX) LocalAlloc( 
          LMEM_FIXED, 
          sizeof(LABELBOX) 
      ); 
      if (pboxLocalClip == NULL) 
      { 
          CloseClipboard(); 
          return FALSE; 
      } 
      memcpy(pboxLocalClip, pbox, sizeof(LABELBOX)); 
      pboxLocalClip->fSelected = FALSE; 
      pboxLocalClip->fEdit = FALSE; 

      // Place a registered clipboard format, the owner-display 
      // format, and the CF_TEXT format on the clipboard using 
      // delayed rendering. 

      SetClipboardData(uLabelFormat, NULL); 
      SetClipboardData(CF_OWNERDISPLAY, NULL); 
      SetClipboardData(CF_TEXT, NULL); 
  } 

  // Close the clipboard. 

  CloseClipboard(); 

  return TRUE; 
}

Code can be found here (paste code too) http://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx

Fabian Schmidt
  • 334
  • 1
  • 13
  • 1
    in some case people copy whole of the file into clipboard but in some case volume of file is too big and I have to copy path of file into clipboard and paste whole of file into desktop – Jack Sep 15 '14 at 16:15
  • All this does is puts the path string itself on the clipboard and lets it be pasted as text. If you want to paste the actual file itself, you have to use `CF_HDROP` instead of `CF_TEXT`. – Remy Lebeau Sep 15 '14 at 16:16