Hello,

I am writing a c++ program for windows using the API. My program needs to be able to get some text from the clipboard, import it to the program's scope as a string, and do work on the string.

[what I have tried]

cout << GetClipboardData(CF_TEXT) << endl;
cout << GetClipboardData(CF_UNICODETEXT) << endl;

Both of these printed/returned zero, which, msdn says, means the functions failed.
I found the MSDN documentation wanting...an example would have been nice.
http://msdn.microsoft.com/en-us/library/ms907128.aspx
Even if the above functions returned a non-zero result, I am not sure how I would use the returned data handle to get the data as a string.

[other ideas]
I could post a paste message to a temporary text file, then import the text using fstream, but this is rather a backwards way of going about it.

I am hoping someone would please shed some light on how to get text from the clipboard as a string into my c++ program.

Thanks,

Dani AI

Generated

If you want a robust way to read text from the Windows clipboard as a C++ string, prefer CF_UNICODETEXT (UTF-16) with a fallback to CF_TEXT. Lock the global memory handle to get a stable pointer, copy the data into your own buffer while the clipboard is open, then unlock and close. Also be prepared to retry briefly because the clipboard may be temporarily busy.

#include <windows.h>
#include <string>

std::string GetClipboardTextUTF8()
{
    std::string result;

    for (int attempt = 0; attempt < 5; ++attempt) {
        if (!IsClipboardFormatAvailable(CF_UNICODETEXT) &&
            !IsClipboardFormatAvailable(CF_TEXT)) {
            return result;
        }
        if (OpenClipboard(nullptr)) {
            const UINT fmt = IsClipboardFormatAvailable(CF_UNICODETEXT) ? CF_UNICODETEXT : CF_TEXT;
            if (HGLOBAL h = GetClipboardData(fmt)) {
                if (fmt == CF_UNICODETEXT) {
                    if (LPCWSTR w = static_cast<LPCWSTR>(GlobalLock(h))) {
                        const int chars = lstrlenW(w); // CF_UNICODETEXT is NUL-terminated
                        const int bytes = WideCharToMultiByte(CP_UTF8, 0, w, chars, nullptr, 0, nullptr, nullptr);
                        result.resize(bytes);
                        WideCharToMultiByte(CP_UTF8, 0, w, chars, result.data(), bytes, nullptr, nullptr);
                        GlobalUnlock(h);
                    }
                } else {
                    if (LPCSTR a = static_cast<LPCSTR>(GlobalLock(h))) {
                        result.assign(a); // CF_TEXT is NUL-terminated ANSI
                        GlobalUnlock(h);
                    }
                }
            }
            CloseClipboard();
            break;
        }
        Sleep(5);
    }
    return result;
}

Notes:

  • Do not free or reallocate the handle returned by GetClipboardData; the clipboard owns it. Only lock/unlock it, and copy the data you need while the clipboard is open (Using the Clipboard).
  • CF_UNICODETEXT data is UTF-16LE and NUL-terminated; CF_TEXT is ANSI in the system code page (Standard Clipboard Formats). Convert with WideCharToMultiByte as shown (WideCharToMultiByte).

Recommended Answers

All 11 Replies

I guess you forgot to open the clipboard first:

HANDLE clip;
    if (OpenClipboard(NULL)) 
        clip = GetClipboardData(CF_TEXT);

Now 'clip' is the adress of the first character of the data on clipboard.

So to print it: cout << (char*) clip;

I tried to cout the text in the clipboard with this

HANDLE clip;
    if (OpenClipboard(NULL)) 
        clip = GetClipboardData(CF_UNICODETEXT);
    string text;
    while (clip != 0)
    {
	text += *clip;
	clip++;
    }
    cout << text;

But it isn't working because a handle can't be dereferenced with *handle. So, how DO you dereference a handle?

EDIT: Oh sorry, didn't see your edit, never mind

EDIT: Oh sorry, didn't see your edit, never mind

Yeah, I made a silly mistake, which I only noticed after 15 minutes... I was kind of hoping that no-one had copied the code already :)

sorry, I still can't make it work... if I try clip++ to move to the next character it says HANDLE: unkown size. How am I supposed to do that?

It says 'HANDLE: unknown size' because HANDLE is actually another way to write (void*). So you need to tell te compiler what type of var it is:

HANDLE clip;
if (OpenClipboard(NULL)) 
    clip = GetClipboardData(CF_TEXT);
cout << (char*)clip; // HANDLE==void*, so cast it

offtopic:
Is this somesort of homework? Because two people show interest at exactly the same moment?

A note regarding clipboard usage, whenever you successfully open the clipboard, don't forget to close it by calling CloseClipboard() when you're done with the clipboard operations.

commented: yup +6

A note regarding clipboard usage, whenever you successfully open the clipboard, don't forget to close it by calling CloseClipboard() when you're done with the clipboard operations.

I swear to god I'm starting get my coding confused after seeing that...

Feels like CSharp when you use uppercased methods, when really it's C++...

Or maybe it's not, since I've heard that the Windows API isn't meant specifically for the C language.

Thanks for the rapid solution!

HANDLE clip;
        
    if (OpenClipboard(NULL)) {
      clip = GetClipboardData(CF_TEXT);
      CloseClipboard();
    }
    string text;
    text = (char*)clip;
    cout << (char*)clip << " same as " << text << endl;

    //=== - O R - ====
    
    unsigned int i = 0;
    text = "";

    while (((char *)clip)[i] != 0) {
      text += ((char *)clip)[i];
      i++;
    }

    cout << text << endl;;

    //=== - O R - ====

    text = "";
    char* pntchr = (char*)clip;

    while (*pntchr != 0) {
      text += *pntchr;
      pntchr++;
    }

    cout << text << endl;

all the above versions of the code output the same text. Thanks again!

p.s. definitely not my homework, though i do work from home ;)

offtopic:
Is this somesort of homework? Because two people show interest at exactly the same moment?

Nope, I don't even know the original poster. I was just browsing around and I found it an interesting topic.
And thanks for all the help!

It seems characters are stored once every 2 bytes in the clipboard (the second is always 0) so you have to increment the pointer by 2 if you want to type all the characters

HANDLE clip;
        
    if (OpenClipboard(NULL)) {
      clip = GetClipboardData(CF_TEXT);
      CloseClipboard();
    }

    < snip >

That was not what I meant to say, below is a basic scheme for doing the intended clipboard operation ... it adds the step of locking/unlocking the respective global memory block

if (OpenClipboard(NULL)) 
{
	// Try grabbing a handle to the non-UNICODE text data
	const HANDLE hglb = GetClipboardData(CF_TEXT); 

	if (hglb != NULL) 
	{ 
		// Try locking the memory block getting a pointer 
		// to the start of the data

		const char * lptstr = (const char *) GlobalLock(hglb);

		if (lptstr != NULL) 
		{ 
			// got it, however, don't make any assumptions 
			// like the data being NULL-terminated and such ...

			// here you can utilize the lptstr pointer ...

			// done, unlock the memory block ...
			GlobalUnlock(hglb); 
		} 
	} 

	// All done with the clipboard operations, close it
	CloseClipboard();
}

Related samples here
http://msdn.microsoft.com/en-us/library/ms649016(VS.85).aspx

Thnks for the code it's realy helpful for me

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.