11

How to use GetClipboardData(CF_TEXT); without calling and use process id of this in C++?
and which libary does GetClipboardData(CF_TEXT) belong to?

RedRidingHood
  • 568
  • 3
  • 16
behnam27
  • 241
  • 2
  • 4
  • 11
  • Can you clarify the first question? I can't figure out what you're asking. As for the second question, it's answered in the information box at the end of [the documentation for GetClipboardData](http://msdn.microsoft.com/en-us/library/windows/desktop/ms649039(v=vs.85).aspx). – Raymond Chen Feb 07 '13 at 23:23
  • @behnam27: I've added _winapi_ and _clipboard_ tags to your question. – Mr.C64 Feb 07 '13 at 23:32

1 Answers1

54

GetClipboardData() is a Win32 API function.

The handle returned by GetClipboardData() must be first locked with GlobalLock(), then you can retrieve the char* pointer of the ANSI text in the clipboard (note that if you want to retrieve Unicode text, you should use the CF_UNICODETEXT format).

A sample code to retrieve the text from the clipboard and store it in a convenient std::string class instance follows (error management omitted for simplicity):

std::string GetClipboardText()
{
  // Try opening the clipboard
  if (! OpenClipboard(nullptr))
    ... // error

  // Get handle of clipboard object for ANSI text
  HANDLE hData = GetClipboardData(CF_TEXT);
  if (hData == nullptr)
    ... // error

  // Lock the handle to get the actual text pointer
  char * pszText = static_cast<char*>( GlobalLock(hData) );
  if (pszText == nullptr)
    ... // error

  // Save text in a string class instance
  std::string text( pszText );

  // Release the lock
  GlobalUnlock( hData );

  // Release the clipboard
  CloseClipboard();

  return text;
}

You can use C++ RAII pattern and manage error conditions using exceptions, something like this:

#include <exception>
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <windows.h>
using namespace std;

class RaiiClipboard
{
public:
  RaiiClipboard()
  {
    if (! OpenClipboard(nullptr))
      throw runtime_error("Can't open clipboard.");
      // ... or define some custom exception class for clipboard errors.
  }

  ~RaiiClipboard()
  {
    CloseClipboard();
  }

  // Ban copy   
private:
  RaiiClipboard(const RaiiClipboard&);
  RaiiClipboard& operator=(const RaiiClipboard&);
};

class RaiiTextGlobalLock
{
public:
  explicit RaiiTextGlobalLock(HANDLE hData)
    : m_hData(hData)
  {
    m_psz = static_cast<const char*>(GlobalLock(m_hData));
    if (! m_psz)
      throw runtime_error("Can't acquire lock on clipboard text.");  
  }

  ~RaiiTextGlobalLock()
  {
    GlobalUnlock(m_hData);
  }

  const char* Get() const
  { 
    return m_psz;
  }

private:
  HANDLE m_hData;
  const char* m_psz;

  // Ban copy
  RaiiTextGlobalLock(const RaiiTextGlobalLock&);
  RaiiTextGlobalLock& operator=(const RaiiTextGlobalLock&);
};

string GetClipboardText()
{
  RaiiClipboard clipboard;

  HANDLE hData = GetClipboardData(CF_TEXT);
  if (hData == nullptr)
    throw runtime_error("Can't get clipboard text.");

  RaiiTextGlobalLock textGlobalLock(hData);
  string text( textGlobalLock.Get() );

  return text;
}

int main()
{
  static const int kExitOk = 0;
  static const int kExitError = 1;
  try
  {
    cout << GetClipboardText() << endl;
    return kExitOk;
  }
  catch(const exception& e)
  {
    cerr << "*** ERROR: " << e.what() << endl;
    return kExitError;
  }
}
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • 7
    Bad question, very nice answer. The snippet was very useful. – timonsku Mar 15 '14 at 00:48
  • @Mr.C64 why is it working even when I don't lock the handle with `GlobalLock`? – jave.web Nov 26 '14 at 13:53
  • 1
    Your snippet is working, would you please add Non-Text Clipboard example? i.e. FileGroupDescriptor – Abbas Aug 22 '19 at 10:51
  • If you copy-paste this and run the program, chances are you will get this code in your run window. It happened in my case and I was wondering why it's showing its own source code. – Khalilullah Jul 13 '21 at 20:18