呼叫哪個API函式可以實現複製和貼上?
阿新 • • 發佈:2019-01-01
一、概述
---- 在Windows作業系統中存在兩種剪貼板機制:Windows標準剪貼簿和OLE剪貼板機
制。
---- 標準的Windows剪貼簿是一個被所有Windows應用程式共享的系統服務,因此它並
沒有自己的控制代碼或類。但你可以通過CWnd類的成員函式來管理剪貼簿。 ---- 自從OLE(Object Linking and Embedding,物件連結和嵌入)誕生之後,
Windows作業系統中便出現了第二種剪貼板機制——OLE剪貼板機制。標準的Windows剪
貼板API(Application Programming Interface,應用程式程式設計介面)依然可用,但是
他已經被OLE資料傳輸機制來實現了。OLE支援UDT(Uniform Data Transfer,統一資料
傳輸),並可以通過拖放操作實現剪貼簿的剪下、複製和貼上等操作。OLE剪貼簿除了
擁有標準Windows剪貼簿的效能外,還支援傳輸使用者自定義的剪貼簿格式,並能夠在傳
輸資料時繫結OLE格式(如字型、字號等)。OLE剪貼板機制將成為更為主要的資料傳輸
機制。
---- 本文將簡要敘述標準Windows剪貼簿的實現,並將重點放在討論如何通過Visual
C++實現OLE剪貼簿上。
---- 二、選擇適當的剪貼板機制
---- 在選擇使用何種剪貼板機制時通常應遵循下面的原則:
---- 如果應用程式在將來又可能具有新的效能(比如現在只需要傳輸純文字,但將來
有可能需要另外傳輸字型等特性),那麼使用OLE剪貼簿。
---- 如果你正在使用一個OLE應用程式,或者你希望使用任何OLE特性(如拖放等)那
麼你應當使用OLE剪貼板機制。
---- 如果你提供了OLE格式(如字型、字號等),那麼使用OLE剪貼板機制。
---- 三、使用Windows標準剪貼簿
---- 大多數Windows下的應用程式支援剪下或複製資料到Windows剪貼簿中以及從剪貼
板貼上資料至目的地。在這個過程中,剪貼簿資料格式在多種應用程式之間發生了變
化。系統構架僅僅通過實現一些有限的類來支援一些有限的剪貼簿格式,下表列出了
Windows標準剪貼簿支援的格式(第一列“值”將在下面的程式程式碼中使用)。
值 含義
CF_BITMAP 一個對應於點陣圖的控制代碼(HBITMAP)。
CF_DIB 一個包含BITMAPINFO結構並且
跟著點陣圖資料的記憶體物件。
CF_DIF 資料互動格式
CF_DSPBITMAP 有一個私有格式的點陣圖顯示格式。
CF_DSPENHMETAFILE 有一個私有格式的增強的元檔案的顯示格式。
CF_DSPMETAFILEPICT 有一個私有格式的元圖顯示格式。
CF_DSPTEXT 有一個私有格式的文字顯示格式。
CF_ENHMETAFILE 一個增強的元檔案(HENHMETAFILE結構)的控制代碼。
CF_GDIOBJFIRST到 CF_GDIOBJLAST 應用軟體定義
的一系列GDI物件的整型值。
CF_HDROP 一個HDROP型別的控制代碼,用來標識一列檔案。
CF_METAFILEPICT 一個使用METAFILEPICT結構定義的元圖檔案的控制代碼。
CF_OEMTEXT 預定義的字元的文字格式,每一行都繫結
一個CR-LF字元,並且用一個空字元表示資料結尾。
CF_OWNERDISPLAY 剪貼簿擁有者的顯示格式,
剪貼簿的擁有者必須顯示並且更新剪貼簿的觀察器視窗,
並且接收WM_ASKCBFORMATNAME、WM_HSCROLLCLIPBOARD、
WM_PAINTCLIPBOARD、WM_SIZECLIPBOARD以及
WM_VSCROLLCLIPBOARD等訊息,hMem引數必需為NULL。
CF_PALETTE 調色盤的控制代碼
CF_PRIVATEFIRST到CF_PRIVATELAST 私有的剪貼簿格式的整型值。
CF_RIFF 能夠提交比CF_WAVE標準波表文件格式更為複雜的音訊資料
CF_SYLK 微軟公司的SYLK(Symbolic Link,符號連結)格式
CF_TEXT 文字格式
CF_WAVE 使用一種標準波表文件格式如11kHz或22kHz等
PCM(Pulse Code Modulation,脈衝編碼調製器)提交音訊資料。
CF_TIFF TIFF圖形格式
CF_UNICODETEXT Unicode文字格式(
注意:僅適用於Windows NT或Windows 2000作業系統)
---- 表1 常用的標準剪貼簿格式
---- 要編寫一個實現剪下和複製命令的函式,就要在你的應用程式中實現選定操作;
要編寫一個實現貼上命令的函式,就需要請求剪貼簿來檢測它是否包含你的應用程式能
夠支援的資料。下面的程式碼實現了複製命令,其它實現可仿照進行,在此不再贅言。
---- 程式示例:
void CMyView::OnEditCopy()
{
if ( !OpenClipboard() )
{
AfxMessageBox( "無法開啟剪貼簿" );
return;
}
// 刪除目前剪貼簿的內容
if( !EmptyClipboard() )
{
AfxMessageBox( "無法清除剪貼簿" );
return;
}
// 獲取選定的資料
// 檢查是否為剪貼簿支援的格式
if ( ::SetClipboardData( CF_??, hData ) == NULL )
// CF_??指定了剪貼簿中資料的格式,
//表1列出了標準的剪貼簿格式
{
AfxMessageBox( "無法將資料複製到剪貼簿當中" );
CloseClipboard();
return;
}
// ...
CloseClipboard();
}
---- 四、使用OLE剪貼板機制
---- 首先舉個例子給你一些關於OLE剪貼簿的感性認識,同時說明你需要為OLE剪貼簿
做哪些事情:Microsoft Excel為工作表註冊了一個自定義的格式,這個格式能夠比其
它標準格式(如點陣圖或純文字等)提供更多的資訊。當此資料被貼上到一個支援工作表
的程式(比如Lotus 1-2-3)時,所有的原工作表中的公式和數值將被保留,並且還可
能會根據需要被更新。Excel同樣將資料以OLE格式存放在剪貼簿中,這樣它就可以作為
一個OLE物件被嵌入。任何OLE文件包容器(Container)(比如Microsoft Word)能夠
將該資料作為嵌入物件貼上進文件(比如通過“選擇性貼上”,可以在Word中貼上進
Excel工作表物件)。這個嵌入物件能夠通過啟用Microsoft Excel來進行修改(在Word
中可以通過雙擊物件實現)。該工作表甚至可以被貼上到一個繪圖程式(比如的畫
筆)。當然,這時你無論如何都沒有辦法將其中的資料像在工作表中一樣修改,因為它
已經是圖片了。
---- 從上例總結一下,我們應當作的事情大致有:註冊自定義的格式、傳輸格式到剪
貼板上以及實現複製、剪下和貼上。
---- 註冊自定義格式
---- OLE剪貼簿中的資料存在於多種格式。當一個使用者選擇從剪貼簿貼上資料時,應用
程式應當能夠選擇使用何種格式貼上資料。應用程式應當提供大部分格式的資訊,除非
使用者指定使用某一種特定格式貼上(比如只貼上文字或只貼上圖片等)。
---- Windows定義了很多能夠通過剪貼簿傳輸的標準格式(見表1),OLE也定義了很多
特殊的格式。應用程式可以通過獲取更加詳細的資訊來註冊他們自己的剪貼簿格式。這
可以通過使用Win32 API函式RegisterClipboardFormat來實現:
---- RegisterClipboardFormat ( lpszFormat );
---- 說明 lpzxFormat是指向一個字串的指標,用以命名自定義的格式。該函式返回
無符號整數,該數即為格式的ID號
---- 在註冊了自定義的格式之後,便可以使用RegisterClipboardFormat函式的返回值
來標識並使用該格式。
---- 將格式傳輸到剪貼簿上
---- 要增加更多的格式到剪貼簿上,你必須從COleClientItem或COleServerItem繼承
一個類,並且在該類中過載OnGetClipboardData函式。在這個函式中,你應當做按照下
列步驟完成。
---- 將更多的格式放置在剪貼簿上
---- 1. 建立一個COleDataSource物件。
---- 2. 傳遞該資料來源到一個函式,用該函式通過訪問
COleDataSource::CacheGlobalData函式來將你的資料格式新增到支援的格式列表。
---- 3. 通過訪問COleDataSource::CacheGlobalData,為每一個你向支援的格式新增
標準格式。
---- 程式示例:
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;
}
---- 複製、剪下和貼上資料
---- 將資料複製或剪下到剪貼簿上
---- 1. 確定將要被複制的資料是一個本地資料還是一個嵌入物件或連結。
---- 如果資料是一個嵌入物件或連結,建立一個指向被選定資料的COleClientItem指
針。
---- 如果資料是本地化的並且應用程式是一個伺服器,那麼從COleServerItem繼承一
個新的類,並建立該物件。否則,為資料建立一個COleDataSource物件。
---- 2. 訪問選定物件的CopyToClipboard成員函式。
---- 3. 如果使用者選擇剪下命令而不是複製,那麼從你的應用程式中刪除那些資料。
---- 程式示例:
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
}
---- 從剪貼簿貼上資料
---- 貼上資料比複製更加複雜,因為你需要選擇貼上的格式。
---- 1. 在你的視中,實現OnEditPaste來處理使用者從編輯選單選擇貼上命令的操作。
---- 2. 在OnEditPaste函式中,建立一個COleDataObject物件並且訪問它的
AttachClipboard成員函式來將這個物件繫結到剪貼簿。
---- 3. 訪問COleDataObject::IsDataAvailable函式來檢查是否可以使用特殊的格
式。當然,你也可以通過迴圈使用COleDataObject::BeginEnumFormats來尋找其它格式
直到你找到了最適合的格式。
---- 4. 貼上資料。