Download clipboard demo project
- 12 Kb
Download notification demo project - 12 Kb
Adding clipboard support to a VC++ / MFC application is
extremely simple. This article covers the
basic steps involved in getting your applictions talking to the clipboard.
In it are examples of the following:
Reading and writing text
The following source code demonstrates how to place text (contained in the CString "source") onto the clipboard.
CString source;
if(OpenClipboard())
{
HGLOBAL clipbuffer;
char * buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(source));
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
The source code below demonstrates the converse, how to retrieve text from the clipboard.
char * buffer = NULL;
CString fromClipboard;
if ( OpenClipboard() )
{
HANDLE hData = GetClipboardData( CF_TEXT );
char * buffer = (char*)GlobalLock( hData );
fromClipboard = buffer;
GlobalUnlock( hData );
CloseClipboard();
}
Reading and writing WMF (enhanced) data
Writing and reading images to and from the clipboard can be very useful,
and it is really very easy! The following example writes an enhanced
metafile to the clipboard.
if ( OpenClipboard() )
{
EmptyClipboard();
CMetaFileDC * cDC = new CMetaFileDC();
cDC->CreateEnhanced(GetDC(),NULL,NULL,"the_name");
HENHMETAFILE handle = cDC->CloseEnhanced();
SetClipboardData(CF_ENHMETAFILE,handle);
CloseClipboard();
delete cDC;
}
Here is the converse. We get the metafile from the clipboard and draw it into our own client
DC (just as a test, really you would want to make a copy).
if ( OpenClipboard() )
{
HENHMETAFILE handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
CClientDC dc(this);
CRect client(0,0,200,200);
dc.PlayMetaFile(handle,client);
CloseClipboard();
}
Reading and writing a bitmap
Reading and writing a bitmap is only marginally trickier. The basic idea remains the same.
Here is an example of saving a bitmap to the clipboard.
if ( OpenClipboard() )
{
EmptyClipboard();
CBitmap * junk = new CBitmap();
CClientDC cdc(this);
CDC dc;
dc.CreateCompatibleDC(&cdc);
CRect client(0,0,200,200);
junk->CreateCompatibleBitmap(&cdc,client.Width(),client.Height());
dc.SelectObject(junk);
DrawImage(&dc,CString("Bitmap"));
SetClipboardData(CF_BITMAP,junk->m_hObject);
CloseClipboard();
delete junk;
}
As with the other examples, here is an example of getting a bitmap from the clipboard. In this simple example we will just Blt it to the cleint DC.
if ( OpenClipboard() )
{
HBITMAP handle = (HBITMAP)GetClipboardData(CF_BITMAP);
CBitmap * bm = CBitmap::FromHandle(handle);
CClientDC cdc(this);
CDC dc;
dc.CreateCompatibleDC(&cdc);
dc.SelectObject(bm);
cdc.BitBlt(0,0,200,200,&dc,0,0,SRCCOPY);
CloseClipboard();
}
Setting up and using your own custom format
By using the RegisterClipboardFormat() API you can copy and paste any type of data you want. This can
be very useful in moving data between your own applications. Let's say we have a structure:
struct MyFormatData
{
long val1;
int val2;
};
that we want to move on the clipboard. We can copy as follows:
UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
if(OpenClipboard())
{
MyFormatData data;
data.val1 = 100;
data.val2 = 200;
HGLOBAL clipbuffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, sizeof(MyFormatData));
MyFormatData * buffer = (MyFormatData*)GlobalLock(clipbuffer);
*buffer = data;
GlobalUnlock(clipbuffer);
SetClipboardData(format,clipbuffer);
CloseClipboard();
}
To read it back off we do the inverse:
UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
MyFormatData data;
if ( OpenClipboard() )
{
HANDLE hData = GetClipboardData(format);
MyFormatData * buffer = (MyFormatData *)GlobalLock( hData );
data = *buffer;
GlobalUnlock( hData );
CloseClipboard();
}
Getting notified of clipboard changes
It is very useful to be notified (via a windows message) whenever the clipboard has changed. To do this
you use SetClipboardViewer() and then catch WM_DRAWCLIPBOARD
In your initialization code call:
SetClipboardViewer();
In your message map add:
ON_MESSAGE(WM_DRAWCLIPBOARD, OnClipChange)
Which is declared as:
afx_msg void OnClipChange();
Finally implement:
void CDetectClipboardChangeDlg::OnClipChange()
{
CTime time = CTime::GetCurrentTime();
SetDlgItemText(IDC_CHANGED_DATE,time.Format("%a, %b %d, %Y -- %H:%M:%S"));
DisplayClipboardText();
}
Pasting data to another app's window
One thing that I have found useful is to copy text to the clipboard (see above) and then to "paste" it to ANOTHER
application!. I wrote a nice localization app that used a third party language translation package using this technique.
Simply get the handle to the target window and send a "PASTE" to it.
SendMessage(m_hTextWnd, WM_PASTE, 0, 0);