How to copy string to clipboard in C?

44,693

Solution 1

Read the MSDN documentation for the SetClipboardData function. It appears you are missing a few steps and releasing the memory prematurely. First of all, you must call OpenClipboard before you can use SetClipboardData. Secondly, the system takes ownership of the memory passed to the clipboard and it must be unlocked. Also, the memory must be movable, which requires the GMEM_MOVEABLE flag as used with GlobalAlloc (instead of LocalAlloc).

const char* output = "Test";
const size_t len = strlen(output) + 1;
HGLOBAL hMem =  GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();

Solution 2

I wrote an open source command line tool to do this in Windows:

http://coffeeghost.net/2008/07/25/ccwdexe-copy-current-working-directory-command/

ccwd.exe copies the current working directory to the clipboard. It's handy when I'm several levels deep into a source repo and need to copy the path.

Here's the complete source:

#include "stdafx.h"
#include "windows.h"
#include "string.h"
#include <direct.h>

int main()
{
    LPWSTR cwdBuffer;

    // Get the current working directory:
    if( (cwdBuffer = _wgetcwd( NULL, 0 )) == NULL )
        return 1;

    DWORD len = wcslen(cwdBuffer);
    HGLOBAL hdst;
    LPWSTR dst;

    // Allocate string for cwd
    hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1) * sizeof(WCHAR));
    dst = (LPWSTR)GlobalLock(hdst);
    memcpy(dst, cwdBuffer, len * sizeof(WCHAR));
    dst[len] = 0;
    GlobalUnlock(hdst);

    // Set clipboard data
    if (!OpenClipboard(NULL)) return GetLastError();
    EmptyClipboard();
    if (!SetClipboardData(CF_UNICODETEXT, hdst)) return GetLastError();
    CloseClipboard();

    free(cwdBuffer);
    return 0;
}
Share:
44,693
Admin
Author by

Admin

Updated on June 03, 2020

Comments

  • Admin
    Admin about 4 years

    The SetClipboardData function requires a HANDLE reference; I'm having trouble converting my string for use in the function.

    Here is my code:

    char* output = "Test";
    HLOCAL hMem =  LocalAlloc( LHND,1024);
    char* cptr = (char*) LocalLock(hMem);
    memcpy( cptr, output, 500 );
    SetClipboardData(CF_TEXT, hMem);
    LocalUnlock( hMem );
    LocalFree( hMem );
    CloseClipboard();
    

    What am I doing wrong here and what's the proper way to do it?

    Thanks.

  • Admin
    Admin almost 15 years
    Well, I've already looked at that, and came up with the code which doesn't work.
  • vishwas kumar
    vishwas kumar almost 15 years
    You might just try copying the exact code and see if it works. Then you can go from there.
  • Harvey
    Harvey about 12 years
    Works for me too... with two corrections: GMEM_MOVEABLE and no parameter passed in OpenClipboard();
  • Jack
    Jack about 10 years
    Why copy the null-byte-terminattor too?
  • Elkvis
    Elkvis almost 10 years
    because SetClipboardData doesn't accept a length parameter, so it has to figure out where the end of the string is, when you use CF_TEXT. See msdn.microsoft.com/en-us/library/windows/desktop/… for more info
  • Pyjong
    Pyjong about 9 years
    Do I understand correctly, if the call to SetClipboardData succeeds system calls free(hMem) for you?
  • Yakov Galka
    Yakov Galka over 7 years
    @Pyjong: Yes, except that it's GlobalFree.
  • MultiplyByZer0
    MultiplyByZer0 over 5 years
    Note that if you are copying a wchar_t* instead of a char*, use CF_UNICODETEXT instead of CF_TEXT.
  • Berkyjay
    Berkyjay over 5 years
    Accoring to the documentation, this answer is wrong. You must pass a valid HWND to OpenClipboard. Quote: "If an application calls OpenClipboard with hwnd set to NULL, EmptyClipboard sets the clipboard owner to NULL; this causes SetClipboardData to fail"
  • Jan Bergström
    Jan Bergström over 5 years
    +1 Yes, it is simple to read, copy and it works right on, just what I was looking for. And the CF_UNICODETEXT is a horror not getting. CF_TEXT makes only one letter in normal US ASCII. The DWORD len should be a size_t len (not getting compiler complaints).
  • Y K
    Y K about 2 years
    This doesn't work as @GetFree said.