VC 剪切板操作
下邊的源代碼演示瞭如何將文本(包含在CString對象“source”中)拷貝到剪貼板上。
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();
}
反過來,下面的代碼是用來實現從剪貼板上取得文本的。
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();
}
--------------------------------------------------------------------------------
拷貝與粘貼WMF(enhanced)數據
你想在你的程序中往剪貼板上“畫”以及向剪貼板讀取圖形嗎?請放心,這個――不難!示範代碼如下,其實現的是往剪貼板上寫一enhanced metafile。
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;
}
好啦,該演示反過來怎麼做的代碼了。我們從剪貼板上取得metafile並將其畫到自己的應用程序的客戶區DC(設備上下文)上(僅僅是個試驗而已,實際上你可能更想將它拷貝一份兒)。
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();
}
--------------------------------------------------------------------------------
拷貝與粘貼一張位圖(BitMap)
拷貝和粘貼位圖可是需要一些微妙的處理的,不過基本的思想還是一樣。請看下面的代碼。
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;
}
如下示例代碼是從剪貼板上取得一張位圖,將它粘貼到客戶區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();
}
--------------------------------------------------------------------------------
建立並使用你自己定做的數據格式
如果你要拷貝、粘貼其它格式的數據,可以用RegisterClipboardFormat() API函數先將此格式註冊,然後就可以“爲所欲爲”了。這簡直是太有用了,尤其是在我們自己的應用程序中拷貝資料。假設我們有下面的結構:
struct MyFormatData
{
long val1;
int val2;
};
想將此結構的數據拷貝到剪貼板上。可以這樣實現:
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();
}
想把它從剪貼板上讀下來的話,也容易:
//第二次調用時,此格式已經註冊過了,讀下來就行了
UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
MyFormatData data;
if ( OpenClipboard() )
{
//get the buffer
HANDLE hData = GetClipboardData(format);
MyFormatData * buffer = (MyFormatData *)GlobalLock( hData );
//留一份兒當地拷貝
data = *buffer;
GlobalUnlock( hData );
CloseClipboard();
}
--------------------------------------------------------------------------------
取得剪貼板變化通知(Getting notified of clipboard changes)
一旦剪貼板上的內容發生改變,我們都希望能夠獲知(經由windows消息),這是很有用的。你可以用函數SetClipboardViewer()來捕獲WM_DRAWCLIPBOARD消息。
在你的初始化代碼中調用:
SetClipboardViewer(); //add us to clipboard change notification chain
在你的消息映射(message map)中添加:
ON_MESSAGE(WM_DRAWCLIPBOARD, OnClipChange)
//clipboard change notification
將其定義爲:
afx_msg void OnClipChange(); //clipboard change notification
實現爲:
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();
}
--------------------------------------------------------------------------------
將數據粘貼到其它應用程序窗口中的方法
我覺得如果能把文本拷貝到剪貼板上(參見上面的代碼),然後再在另外一個應用程序中將這些文本粘貼過來,那樣纔有用。我寫了一個很不錯的本地應用程序,此程序使用了含有此技術的第三方的語言翻譯包。很簡單,僅是取得目標窗口的句柄,並向它發送“PASTE”消息就OK了。
SendMessage(m_hTextWnd, WM_PASTE, 0, 0);