一、概述
---- 在Windows操作系統(tǒng)中存在兩種剪貼板機(jī)制:Windows標(biāo)準(zhǔn)剪貼板和OLE剪貼板機(jī) 制。 ---- 標(biāo)準(zhǔn)的Windows剪貼板是一個(gè)被所有Windows應(yīng)用程序共享的系統(tǒng)服務(wù),因此它并
沒有自己的句柄或類。但你可以通過CWnd類的成員函數(shù)來管理剪貼板。 ---- 自從OLE(Object Linking and Embedding,對(duì)象鏈接和嵌入)誕生之后, Windows操作系統(tǒng)中便出現(xiàn)了第二種剪貼板機(jī)制——OLE剪貼板機(jī)制。標(biāo)準(zhǔn)的Windows剪 貼板API(Application Programming Interface,應(yīng)用程序編程接口)依然可用,但是 他已經(jīng)被OLE數(shù)據(jù)傳輸機(jī)制來實(shí)現(xiàn)了。OLE支持UDT(Uniform Data Transfer,統(tǒng)一數(shù)據(jù) 傳輸),并可以通過拖放操作實(shí)現(xiàn)剪貼板的剪切、復(fù)制和粘貼等操作。OLE剪貼板除了 擁有標(biāo)準(zhǔn)Windows剪貼板的性能外,還支持傳輸用戶自定義的剪貼板格式,并能夠在傳 輸數(shù)據(jù)時(shí)綁定OLE格式(如字體、字號(hào)等)。OLE剪貼板機(jī)制將成為更為主要的數(shù)據(jù)傳輸 機(jī)制。 ---- 本文將簡要敘述標(biāo)準(zhǔn)Windows剪貼板的實(shí)現(xiàn),并將重點(diǎn)放在討論如何通過Visual C++實(shí)現(xiàn)OLE剪貼板上。 ---- 二、選擇適當(dāng)?shù)募糍N板機(jī)制 ---- 在選擇使用何種剪貼板機(jī)制時(shí)通常應(yīng)遵循下面的原則: ---- 如果應(yīng)用程序在將來又可能具有新的性能(比如現(xiàn)在只需要傳輸純文本,但將來 有可能需要另外傳輸字體等特性),那么使用OLE剪貼板。 ---- 如果你正在使用一個(gè)OLE應(yīng)用程序,或者你希望使用任何OLE特性(如拖放等)那 么你應(yīng)當(dāng)使用OLE剪貼板機(jī)制。 ---- 如果你提供了OLE格式(如字體、字號(hào)等),那么使用OLE剪貼板機(jī)制。 ---- 三、使用Windows標(biāo)準(zhǔn)剪貼板 ---- 大多數(shù)Windows下的應(yīng)用程序支持剪切或復(fù)制數(shù)據(jù)到Windows剪貼板中以及從剪貼 板粘貼數(shù)據(jù)至目的地。在這個(gè)過程中,剪貼板數(shù)據(jù)格式在多種應(yīng)用程序之間發(fā)生了變 化。系統(tǒng)構(gòu)架僅僅通過實(shí)現(xiàn)一些有限的類來支持一些有限的剪貼板格式,下表列出了
Windows標(biāo)準(zhǔn)剪貼板支持的格式(第一列“值”將在下面的程序代碼中使用)。 值 含義 CF_BITMAP 一個(gè)對(duì)應(yīng)于位圖的句柄(HBITMAP)。
CF_DIB 一個(gè)包含BITMAPINFO結(jié)構(gòu)并且 跟著位圖數(shù)據(jù)的內(nèi)存對(duì)象。 CF_DIF 數(shù)據(jù)交互格式
CF_DSPBITMAP 有一個(gè)私有格式的位圖顯示格式。 CF_DSPENHMETAFILE 有一個(gè)私有格式的增強(qiáng)的元文件的顯示格式。 CF_DSPMETAFILEPICT 有一個(gè)私有格式的元圖顯示格式。 CF_DSPTEXT 有一個(gè)私有格式的文本顯示格式。 CF_ENHMETAFILE 一個(gè)增強(qiáng)的元文件(HENHMETAFILE結(jié)構(gòu))的句柄。 CF_GDIOBJFIRST到 CF_GDIOBJLAST 應(yīng)用軟件定義 的一系列GDI對(duì)象的整型值。 CF_HDROP 一個(gè)HDROP類型的句柄,用來標(biāo)識(shí)一列文件。 CF_METAFILEPICT 一個(gè)使用METAFILEPICT結(jié)構(gòu)定義的元圖文件的句柄。 CF_OEMTEXT 預(yù)定義的字符的文本格式,每一行都綁定 一個(gè)CR-LF字符,并且用一個(gè)空字符表示數(shù)據(jù)結(jié)尾。 CF_OWNERDISPLAY 剪貼板擁有者的顯示格式, 剪貼板的擁有者必須顯示并且更新剪貼板的觀察器窗口, 并且接收WM_ASKCBFORMATNAME、WM_HSCROLLCLIPBOARD、 WM_PAINTCLIPBOARD、WM_SIZECLIPBOARD以及 WM_VSCROLLCLIPBOARD等消息,hMem參數(shù)必需為NULL。 CF_PALETTE 調(diào)色板的句柄 CF_PRIVATEFIRST到CF_PRIVATELAST 私有的剪貼板格式的整型值。 CF_RIFF 能夠提交比CF_WAVE標(biāo)準(zhǔn)波表文件格式更為復(fù)雜的音頻數(shù)據(jù) CF_SYLK 微軟公司的SYLK(Symbolic Link,符號(hào)鏈接)格式 CF_TEXT 文本格式 CF_WAVE 使用一種標(biāo)準(zhǔn)波表文件格式如11kHz或22kHz等 PCM(Pulse Code Modulation,脈沖編碼調(diào)制器)提交音頻數(shù)據(jù)。 CF_TIFF TIFF圖形格式 CF_UNICODETEXT Unicode文本格式( 注意:僅適用于Windows NT或Windows 2000操作系統(tǒng)) ---- 表1 常用的標(biāo)準(zhǔn)剪貼板格式
---- 要編寫一個(gè)實(shí)現(xiàn)剪切和復(fù)制命令的函數(shù),就要在你的應(yīng)用程序中實(shí)現(xiàn)選定操作; 要編寫一個(gè)實(shí)現(xiàn)粘貼命令的函數(shù),就需要請(qǐng)求剪貼板來檢測(cè)它是否包含你的應(yīng)用程序能 夠支持的數(shù)據(jù)。下面的代碼實(shí)現(xiàn)了復(fù)制命令,其它實(shí)現(xiàn)可仿照進(jìn)行,在此不再贅言。 ---- 程序示例: void CMyView::OnEditCopy() { if ( !OpenClipboard() ) { AfxMessageBox( "無法打開剪貼板" ); return; }
// 刪除目前剪貼板的內(nèi)容 if( !EmptyClipboard() ) { AfxMessageBox( "無法清除剪貼板" ); return; } // 獲取選定的數(shù)據(jù) // 檢查是否為剪貼板支持的格式 if ( ::SetClipboardData( CF_??, hData ) == NULL ) // CF_??指定了剪貼板中數(shù)據(jù)的格式, //表1列出了標(biāo)準(zhǔn)的剪貼板格式 { AfxMessageBox( "無法將數(shù)據(jù)復(fù)制到剪貼板當(dāng)中" ); CloseClipboard(); return; } // ... CloseClipboard(); } ---- 四、使用OLE剪貼板機(jī)制 ---- 首先舉個(gè)例子給你一些關(guān)于OLE剪貼板的感性認(rèn)識(shí),同時(shí)說明你需要為OLE剪貼板 做哪些事情:Microsoft Excel為工作表注冊(cè)了一個(gè)自定義的格式,這個(gè)格式能夠比其 它標(biāo)準(zhǔn)格式(如位圖或純文本等)提供更多的信息。當(dāng)此數(shù)據(jù)被粘貼到一個(gè)支持工作表 的程序(比如Lotus 1-2-3)時(shí),所有的原工作表中的公式和數(shù)值將被保留,并且還可 能會(huì)根據(jù)需要被更新。Excel同樣將數(shù)據(jù)以O(shè)LE格式存放在剪貼板中,這樣它就可以作為 一個(gè)OLE對(duì)象被嵌入。任何OLE文檔包容器(Container)(比如Microsoft Word)能夠 將該數(shù)據(jù)作為嵌入對(duì)象粘貼進(jìn)文檔(比如通過“選擇性粘貼”,可以在Word中粘貼進(jìn) Excel工作表對(duì)象)。這個(gè)嵌入對(duì)象能夠通過激活Microsoft Excel來進(jìn)行修改(在Word 中可以通過雙擊對(duì)象實(shí)現(xiàn))。該工作表甚至可以被粘貼到一個(gè)繪圖程序(比如的畫 筆)。當(dāng)然,這時(shí)你無論如何都沒有辦法將其中的數(shù)據(jù)像在工作表中一樣修改,因?yàn)樗? 已經(jīng)是圖片了。
---- 從上例總結(jié)一下,我們應(yīng)當(dāng)作的事情大致有:注冊(cè)自定義的格式、傳輸格式到剪 貼板上以及實(shí)現(xiàn)復(fù)制、剪切和粘貼。 ---- 注冊(cè)自定義格式 ---- OLE剪貼板中的數(shù)據(jù)存在于多種格式。當(dāng)一個(gè)用戶選擇從剪貼板粘貼數(shù)據(jù)時(shí),應(yīng)用 程序應(yīng)當(dāng)能夠選擇使用何種格式粘貼數(shù)據(jù)。應(yīng)用程序應(yīng)當(dāng)提供大部分格式的信息,除非 用戶指定使用某一種特定格式粘貼(比如只粘貼文字或只粘貼圖片等)。 ---- Windows定義了很多能夠通過剪貼板傳輸?shù)臉?biāo)準(zhǔn)格式(見表1),OLE也定義了很多
特殊的格式。應(yīng)用程序可以通過獲取更加詳細(xì)的信息來注冊(cè)他們自己的剪貼板格式。這 可以通過使用Win32 API函數(shù)RegisterClipboardFormat來實(shí)現(xiàn): ---- RegisterClipboardFormat ( lpszFormat ); ---- 說明 lpzxFormat是指向一個(gè)字符串的指針,用以命名自定義的格式。該函數(shù)返回 無符號(hào)整數(shù),該數(shù)即為格式的ID號(hào) ---- 在注冊(cè)了自定義的格式之后,便可以使用RegisterClipboardFormat函數(shù)的返回值 來標(biāo)識(shí)并使用該格式。 ---- 將格式傳輸?shù)郊糍N板上 ---- 要增加更多的格式到剪貼板上,你必須從COleClientItem或COleServerItem繼承 一個(gè)類,并且在該類中重載OnGetClipboardData函數(shù)。在這個(gè)函數(shù)中,你應(yīng)當(dāng)做按照下 列步驟完成。 ---- 將更多的格式放置在剪貼板上 ---- 1. 建立一個(gè)COleDataSource對(duì)象。 ---- 2. 傳遞該數(shù)據(jù)源到一個(gè)函數(shù),用該函數(shù)通過訪問 COleDataSource::CacheGlobalData函數(shù)來將你的數(shù)據(jù)格式添加到支持的格式列表。 ---- 3. 通過訪問COleDataSource::CacheGlobalData,為每一個(gè)你向支持的格式添加 標(biāo)準(zhǔn)格式。 ---- 程序示例: COleDataSource* CMyItem::OnGetClipboardData( BOOL bIncludeLink,LPPOINT pptOffset, LPSIZE pSize) { ASSERT_VALID(this); if (m_pServerNode == NULL) return NULL; COleDataSource* pDataSource = new COleDataSource; TRY { GetNativeClipboardData(pDataSource); GetClipboardData(pDataSource, bIncludeLink, pptOffset, pSize); } CATCH_ALL(e) { delete pDataSource; THROW_LAST(); } END_CATCH_ALL ASSERT_VALID(pDataSource); return pDataSource; } ---- 復(fù)制、剪切和粘貼數(shù)據(jù) ---- 將數(shù)據(jù)復(fù)制或剪切到剪貼板上 ---- 1. 確定將要被復(fù)制的數(shù)據(jù)是一個(gè)本地?cái)?shù)據(jù)還是一個(gè)嵌入對(duì)象或鏈接。 ---- 如果數(shù)據(jù)是一個(gè)嵌入對(duì)象或鏈接,創(chuàng)建一個(gè)指向被選定數(shù)據(jù)的COleClientItem指 針。 ---- 如果數(shù)據(jù)是本地化的并且應(yīng)用程序是一個(gè)服務(wù)器,那么從COleServerItem繼承一 個(gè)新的類,并創(chuàng)建該對(duì)象。否則,為數(shù)據(jù)建立一個(gè)COleDataSource對(duì)象。 ---- 2. 訪問選定對(duì)象的CopyToClipboard成員函數(shù)。 ---- 3. 如果用戶選擇剪切命令而不是復(fù)制,那么從你的應(yīng)用程序中刪除那些數(shù)據(jù)。 ---- 程序示例: void CMainView::OnEditCut() { ASSERT(m_pSelection != NULL); TRY { m_pSelection- >CopyToClipboard(TRUE); OnEditClear(); } CATCH_ALL(e) { AfxMessageBox(IDP_CLIPBOARD_CUT_FAILED); } END_CATCH_ALL } void CMainView::OnEditCopy() { ASSERT(m_pSelection != NULL); TRY { m_pSelection- >CopyToClipboard(TRUE); } CATCH_ALL(e) { AfxMessageBox(IDP_CLIPBOARD_COPY_FAILED); } END_CATCH_ALL } ---- 從剪貼板粘貼數(shù)據(jù) ---- 粘貼數(shù)據(jù)比復(fù)制更加復(fù)雜,因?yàn)槟阈枰x擇粘貼的格式。 ---- 1. 在你的視中,實(shí)現(xiàn)OnEditPaste來處理用戶從編輯菜單選擇粘貼命令的操作。 ---- 2. 在OnEditPaste函數(shù)中,建立一個(gè)COleDataObject對(duì)象并且訪問它的 AttachClipboard成員函數(shù)來將這個(gè)對(duì)象綁定到剪貼板。 ---- 3. 訪問COleDataObject::IsDataAvailable函數(shù)來檢查是否可以使用特殊的格 式。當(dāng)然,你也可以通過循環(huán)使用COleDataObject::BeginEnumFormats來尋找其它格式 直到你找到了最適合的格式。 ---- 4. 粘貼數(shù)據(jù)。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。