![]() |
Desktop Development »
Clipboard »
General
Beginner
All you ever wanted to know about the Clipboard...By Randy More |
VC6, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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:
The following source code demonstrates how to place text (contained in the CString "source") onto the clipboard.
CString source; //put your text in 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; //open the clipboard CString fromClipboard; if ( OpenClipboard() ) { HANDLE hData = GetClipboardData( CF_TEXT ); char * buffer = (char*)GlobalLock( hData ); fromClipboard = buffer; GlobalUnlock( hData ); CloseClipboard(); }
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(); //create the metafile DC CMetaFileDC * cDC = new CMetaFileDC(); cDC->CreateEnhanced(GetDC(),NULL,NULL,"the_name"); //call draw routine here that makes GDI calls int cDC //close meta CMetafileDC and get its handle HENHMETAFILE handle = cDC->CloseEnhanced(); //place it on the clipboard SetClipboardData(CF_ENHMETAFILE,handle); CloseClipboard(); //delete the dc 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() ) { //Get the clipboard data HENHMETAFILE handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE); //play it into a DC (our own DC in this example) CClientDC dc(this); CRect client(0,0,200,200); dc.PlayMetaFile(handle,client); //close the clipboard CloseClipboard(); }
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(); //create some data 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); //call draw routine here that makes GDI calls DrawImage(&dc,CString("Bitmap")); //put the data on the clipboard SetClipboardData(CF_BITMAP,junk->m_hObject); CloseClipboard(); //copy has been made on clipboard so we can delete 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() ) { //Get the clipboard data 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(); }
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()) { //make some dummy data MyFormatData data; data.val1 = 100; data.val2 = 200; //allocate some global memory HGLOBAL clipbuffer; EmptyClipboard(); clipbuffer = GlobalAlloc(GMEM_DDESHARE, sizeof(MyFormatData)); MyFormatData * buffer = (MyFormatData*)GlobalLock(clipbuffer); //put the data into that memory *buffer = data; //Put it on the clipboard GlobalUnlock(clipbuffer); SetClipboardData(format,clipbuffer); CloseClipboard(); }
To read it back off we do the inverse:
//second call with just get format already registered UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT"); MyFormatData data; if ( OpenClipboard() ) { //get the buffer HANDLE hData = GetClipboardData(format); MyFormatData * buffer = (MyFormatData *)GlobalLock( hData ); //make a local copy data = *buffer; GlobalUnlock( hData ); CloseClipboard(); }
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(); //add us to clipboard change notification chain In your message map add: ON_MESSAGE(WM_DRAWCLIPBOARD, OnClipChange) //clipboard change notification Which is declared as: afx_msg void OnClipChange(); //clipboard change notification Finally implement: void CDetectClipboardChangeDlg::OnClipChange() { //do something here, for example CTime time = CTime::GetCurrentTime(); SetDlgItemText(IDC_CHANGED_DATE,time.Format("%a, %b %d, %Y -- %H:%M:%S")); DisplayClipboardText(); }
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);
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 22 Nov 1999 Editor: Chris Maunder |
Copyright 1999 by Randy More Everything else Copyright © CodeProject, 1999-2009 Web11 | Advertise on the Code Project |