剪貼簿大觀園(三): Clipboard 問答集 (轉)

worldblog發表於2007-12-11
剪貼簿大觀園(三): Clipboard 問答集 (轉)[@more@] 

Clipboard 問答集  1999.11.23   [Beginner]   平臺: VC5, NT4 SP5:namespace prefix = o ns = "urn:schemas--com::office" />

By to:rmore@cri.com">Randy More

翻譯:陳貴敏(efoxxx)

 

宣告:此譯文僅供網友們學習之用!您可以隨意轉載此譯文,希望您轉載時保留作譯者和此宣告。如有翻譯不當之處,敬請指正:">mailto:efoxxx@263.net。近期,我會在《剪貼簿大觀園》系列中補充大量新的文章,希望與您交流,共同提高!

在我們自己的VC++ / MFC應用中增加剪貼簿功能其實是很簡單的事情。為了讓你的程式可以與剪貼簿對話,本文就其實現中的一些基本問題做一些例項講解。

 


 

複製與貼上文字

 

下邊的演示瞭如何將文字(包含在CString“”中)複製到剪貼簿上。

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.(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() 先將此格式註冊,然後就可以“為所欲為”了。這簡直是太有用了,尤其是在我們自己的應用程式中複製資料。假設我們有下面的結構:

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)

 

一旦剪貼簿上的內容發生改變,我們都希望能夠獲知(經由訊息),這是很有用的。你可以用函式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);


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991442/,如需轉載,請註明出處,否則將追究法律責任。

相關文章