許多應用程式可讓使用者透過使用滑鼠或剪貼簿來拖放數據,將數據傳輸到另一個應用程式。 可傳輸的許多數據類型包括Shell物件,例如檔案或資料夾。 Shell 資料傳輸可以在兩個應用程式之間進行,但使用者也可以在桌面或 Windows 檔案總管之間傳輸 Shell 資料。
雖然檔案是最常傳輸的Shell物件,但Shell資料傳輸可能會牽涉到 Shell命名空間中找到的任何各種物件,。 例如,您的應用程式可能需要將檔案傳送至虛擬資料夾,例如回收站,或接受非Microsoft命名空間延伸模組中的物件。 如果您要實作命名空間擴展,它必須能夠正常運作,作為拖放的來源和目標。
本文件討論應用程式如何使用Shell物件實作拖放和剪貼簿資料傳輸。
如何使拖放功能與 Shell 物件進行運作
應用程式通常需要為使用者提供傳輸 Shell 資料的方式。 一些範例包括:
- 從 Windows 檔案總管或桌面拖曳檔案,並將其放在應用程式上。
- 將檔案在 Windows 檔案總管複製到剪貼簿,然後貼到應用程式中。
- 將檔案從應用程式拖曳至回收站。
如需如何處理這些案例和其他案例的詳細討論,請參閱 處理殼層數據傳輸案例。 本檔著重於Shell數據傳輸背後的一般原則。
Windows 提供兩種標準方式讓應用程式傳輸 Shell 數據:
- 使用者剪下或複製Shell資料,例如一或多個檔案至剪貼簿。 其他應用程式會從剪貼簿擷取數據。
- 使用者拖曳代表來源應用程式數據的圖示,並將圖示放在目標所擁有的視窗上。
在這兩種情況下,傳輸的數據會包含在 資料物件中,。 資料物件是元件物件模型(COM)物件,並公開 IDataObject 介面。 就概略而言,所有Shell數據傳輸都必須遵循三個基本步驟:
- 來源會建立數據物件,代表要傳輸的數據。
- 目標會接收數據物件的 IDataObject 介面指標。
- 目標會呼叫 IDataObject 介面,從中擷取數據。
剪貼簿和拖放數據傳輸之間的差異主要在於如何將 IDataObject 指標從來源傳輸至目標。
剪貼簿數據傳輸
剪貼簿是傳輸Shell資料最簡單的方式。 基本程式類似於標準剪貼簿數據傳輸。 不過,由於您正在傳送數據物件的指標,而不是數據本身,因此您必須使用 OLE 剪貼簿 API,而不是標準剪貼簿 API。 下列程式概述如何使用 OLE 剪貼簿 API 搭配剪貼簿傳輸 Shell 資料:
- 數據源會建立數據物件來包含數據。
- 數據源會呼叫 OleSetClipboard,這會在剪貼簿上放置數據物件的 IDataObject 介面指標。
- 目標會呼叫 OleGetClipboard,以擷取數據物件的 IDataObject 介面指標。
- 目標會呼叫 IDataObject::GetData 方法來擷取數據。
- 使用某些 Shell 數據傳輸時,目標可能也需要呼叫數據物件的 IDataObject::SetData 方法,以針對數據傳輸結果提供數據對象的意見反應。 如需這種類型的作業範例,請參閱 處理優化移動作業。
拖放資料傳輸
雖然實作較為複雜,但拖放數據傳輸在剪貼簿上具有一些顯著優勢:
- 拖放傳輸可以使用簡單的滑鼠移動來完成,讓作業比剪貼簿更有彈性且直覺。
- 拖放功能為使用者提供作業的視覺表示法。 當圖示從來源移動到目標時,用戶可以進行追蹤。
- 當資料可用時,拖放操作會通知目標。
拖放作業也會使用資料物件來傳輸資料。 不過,拖放來源必須提供超出剪貼簿傳輸所需的功能:
- 拖放來源也必須建立一個物件,以提供 IDropSource 介面。 當作業進行時,系統會使用 IDropSource 與來源通訊。
- 拖放數據物件負責追蹤游標移動,並顯示圖示來代表數據物件。
拖放目標也必須提供比處理剪貼簿傳輸所需的功能更多的功能。
- 卸除目標必須公開 IDropTarget 介面。 當游標位於目標視窗上方時,系統會使用 IDropTarget 來提供游標位置等資訊,並在數據被釋放時通知目標。
- 拖放目標必須藉由呼叫 RegisterDragDrop向系統註冊自身。 此函式為系統提供目標視窗的控制代碼,以及目標應用程式的 IDropTarget 介面指標。
注意
針對拖放作業,您的應用程式必須使用 OleInitialize初始化 COM,而不是 CoInitialize。
下列程式概述一般用來以拖放方式傳輸 Shell 資料的基本步驟:
- 目標會呼叫 RegisterDragDrop,讓系統將指標指向其 IDropTarget 介面,並將視窗註冊為拖放目標。
- 當使用者啟動拖放作業時,來源會建立數據物件,並藉由呼叫 doDragDrop呼叫DoDragDrop 來起始 拖曳迴圈。
- 當游標位於目標視窗上方時,系統會呼叫目標的其中一個 IDropTarget 方法,以通知目標。 當游標進入目標視窗時,系統會呼叫 IDropTarget::D ragEnter,並在游標通過目標視窗時 IDropTarget::D ragOver。 這兩種方法都會提供置放目標,其中包含目前的游標位置和鍵盤輔助按鍵的狀態,例如 CTRL 或 ALT。 當游標離開目標視窗時,系統會呼叫 IDropTarget::D ragLeave來通知目標。 當其中任何一種方法傳回時,系統會呼叫 IDropSource 介面,將傳回值傳遞至來源。
- 當使用者放開滑鼠按鈕以卸除數據時,系統會呼叫目標的 IDropTarget::D rop 方法。 方法的參數之一是一個指向數據物件的 IDataObject 介面的指標。
- 目標會呼叫數據物件的 IDataObject::GetData 方法來擷取數據。
- 使用某些 Shell 數據傳輸時,目標可能也需要呼叫數據物件的 IDataObject::SetData 方法,以針對數據傳輸的結果提供意見反應給來源。
- 當目標完成資料物件時,它會從 IDropTarget::Drop傳回。 系統會傳回來源的 DoDragDrop 呼叫,以通知來源數據傳輸已完成。
- 根據特定的 數據傳輸情境,來源可能需要根據 DoDragDrop 所傳回的值,以及目標傳遞至數據物件的值,採取額外行動。 例如,移動檔案時,來源必須檢查這些值,以判斷它是否必須刪除源檔。
- 來源會釋放數據物件。
雖然上述程序為 Shell 數據傳輸提供了良好的一般模型,但 Shell 數據物件中可能包含許多不同類型的數據。 您的應用程式可能需要處理許多不同的數據傳輸案例。 每個數據類型和案例都需要一種稍微不同的方法,才能執行程式中的三個主要步驟:
- 來源如何建構數據物件以包含Shell數據。
- 目標如何從數據物件擷取Shell數據。
- 來源如何完成數據傳輸作業。
Shell 資料物件 提供來源如何建構 Shell 資料物件,以及如何由目標處理該數據物件的一般討論。 處理 Shell 數據傳輸場景 詳細討論如何處理一些常見的 Shell 數據傳輸場景。