Menangani Skenario Transfer Data Shell

Dokumen Objek Data Shell membahas pendekatan umum yang digunakan untuk mentransfer data Shell dengan seret dan letakkan atau Clipboard. Namun, untuk menerapkan transfer data Shell dalam aplikasi Anda, Anda juga harus memahami cara menerapkan prinsip dan teknik umum ini ke berbagai cara agar data Shell dapat ditransfer. Dokumen ini menyajikan skenario transfer data Shell umum dan membahas cara mengimplementasikan masing-masing dalam aplikasi Anda.

Catatan

Meskipun masing-masing skenario ini membahas operasi transfer data tertentu, banyak dari mereka berlaku untuk berbagai skenario terkait. Misalnya, perbedaan utama antara sebagian besar transfer Clipboard dan seret dan letakkan adalah bagaimana objek data tiba di target. Setelah target memiliki penunjuk ke antarmuka IDataObject objek data, prosedur untuk mengekstrak informasi sebagian besar sama untuk kedua jenis transfer data. Namun, beberapa skenario terbatas pada jenis operasi tertentu. Lihat skenario individual untuk detailnya.

 

Panduan Umum

Masing-masing bagian berikut membahas skenario transfer data tunggal yang cukup spesifik. Namun, transfer data sering kali lebih kompleks dan mungkin melibatkan aspek dari beberapa skenario. Anda biasanya tidak tahu, terlebih dahulu, skenario mana yang sebenarnya perlu Anda tangani. Berikut adalah beberapa panduan umum yang perlu diingat.

Untuk sumber data:

  • Format Clipboard Shell, dengan pengecualian CF_HDROP, tidak ditentukan sebelumnya. Setiap format yang ingin Anda gunakan harus didaftarkan dengan memanggil RegisterClipboardFormat.
  • Format dalam objek data disediakan dalam urutan preferensi dari sumber. Hitung objek data dan pilih objek pertama yang dapat Anda konsumsi.
  • Sertakan format sebanyak yang dapat Anda dukung. Anda umumnya tidak tahu di mana objek data akan dihilangkan. Praktik ini meningkatkan peluang bahwa objek data akan berisi format yang dapat diterima target penurunan.
  • File yang ada harus ditawarkan dengan format CF_HDROP .
  • Menawarkan data seperti file dengan format CFSTR_FILEDESCRIPTOR CFSTR_FILECONTENTS/. Pendekatan ini memungkinkan target untuk membuat file dari objek data tanpa perlu mengetahui apa pun tentang penyimpanan data yang mendasar. Anda biasanya harus menyajikan data sebagai antarmuka IStream . Mekanisme transfer data ini lebih fleksibel daripada objek memori global dan menggunakan memori yang jauh lebih sedikit.
  • Seret sumber harus menawarkan format CFSTR_SHELLIDLIST saat menyeret item Shell. Objek data untuk item dapat diperoleh melalui metode IShellFolder::GetUIObjectOf atau IShellItem::BindToHandler . Sumber data dapat membuat implementasi objek data standar yang mendukung format CFSTR_SHELLIDLIST dengan menggunakan SHCreateDataObject.
  • Hilangkan target yang ingin beralasan tentang item yang diseret menggunakan model pemrograman item shell dapat mengonversi IDataObject menjadi IShellItemArray menggunakan SHCreateShellItemArrayFromDataObject.
  • Gunakan kursor umpan balik standar.
  • Mendukung seret kiri dan kanan.
  • Gunakan objek data itu sendiri dari objek yang disematkan. Pendekatan ini memungkinkan aplikasi Anda untuk mengambil format tambahan yang ditawarkan objek data dan menghindari pembuatan lapisan penahanan tambahan. Misalnya, objek tersemat dari server A diseret dari server/kontainer B dan dihilangkan pada kontainer C. C harus membuat objek server A yang disematkan, bukan objek server B yang disematkan yang berisi objek server A yang disematkan.
  • Ingatlah bahwa Shell mungkin menggunakan operasi pemindahan yang dioptimalkan atau hapus saat menempelkan file. Aplikasi Anda harus dapat mengenali operasi ini dan merespons dengan tepat.

Untuk target data:

  • Format Clipboard Shell, dengan pengecualian CF_HDROP, tidak ditentukan sebelumnya. Setiap format yang ingin Anda gunakan harus didaftarkan dengan memanggil RegisterClipboardFormat.
  • Menerapkan dan mendaftarkan target penurunan OLE. Hindari menggunakan target Windows 3.1 atau pesan WM_DROPFILES , jika memungkinkan.
  • Format yang dimuat oleh objek data bervariasi, tergantung dari mana objek berasal. Karena Anda umumnya tidak tahu terlebih dahulu dari mana objek data berasal, jangan berasumsi bahwa format tertentu akan ada. Objek data harus menghitung format dalam urutan kualitas, dimulai dengan yang terbaik. Dengan demikian, untuk mendapatkan format terbaik yang tersedia, aplikasi biasanya menghitung format yang tersedia dan menggunakan format pertama dalam enumerasi yang dapat mereka dukung.
  • Mendukung seret kanan. Anda dapat menyesuaikan menu pintasan seret dengan membuat penangan seret dan letakkan.
  • Jika aplikasi Anda akan menerima file yang ada, aplikasi harus dapat menangani format CF_HDROP .
  • Secara umum, aplikasi yang menerima file juga harus menangani format CFSTR_FILEDESCRIPTOR CFSTR_FILECONTENTS/. Sementara file dari sistem file memiliki format CF_HDROP , file dari penyedia seperti ekstensi namespace umumnya menggunakan CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR. Contohnya termasuk folder Windows CE, folder Protokol Transfer File (FTP), folder web, dan folder CAB. Sumber biasanya mengimplementasikan antarmuka IStream untuk menyajikan data dari penyimpanannya sebagai file.
  • Ingatlah bahwa Shell mungkin menggunakan operasi pemindahan yang dioptimalkan atau hapus saat menempelkan file. Aplikasi Anda harus dapat mengenali operasi ini dan merespons dengan tepat.

Menyalin Nama File dari Clipboard ke Aplikasi

Skenario: Pengguna memilih satu atau beberapa file di Windows Explorer dan menyalinnya ke Clipboard. Aplikasi Anda mengekstrak nama file dan menempelkannya ke dalam dokumen.

Skenario ini dapat digunakan, misalnya, untuk memungkinkan pengguna membuat tautan HTML dengan memotong dan menempelkan file ke aplikasi Anda. Aplikasi Anda kemudian dapat mengekstrak nama file dari objek data dan memprosesnya untuk membuat tag jangkar.

Saat pengguna memilih file di Windows Explorer dan menyalinnya ke Clipboard, Shell membuat objek data. Kemudian memanggil OleSetClipboard untuk menempatkan penunjuk ke antarmuka IDataObject objek data pada Clipboard.

Saat pengguna memilih perintah Tempel dari menu atau toolbar aplikasi Anda:

  1. Panggil OleGetClipboard untuk mengambil antarmuka IDataObject objek data.
  2. Panggil IDataObject::EnumFormatEtc untuk meminta objek enumerator.
  3. Gunakan antarmuka IEnumFORMATETC objek enumerator untuk menghitung format yang dimuat oleh objek data.

Catatan

Dua langkah terakhir dalam prosedur ini disertakan untuk kelengkapan. Mereka biasanya tidak diperlukan untuk transfer file sederhana. Semua objek data yang digunakan untuk jenis transfer data ini harus berisi format CF_HDROP , yang dapat digunakan untuk menentukan nama file yang dimuat oleh objek . Namun, untuk transfer data yang lebih umum, Anda harus menghitung format dan memilih yang terbaik yang dapat ditangani aplikasi Anda.

 

Mengekstrak Nama File dari Objek Data

Langkah selanjutnya adalah mengekstrak satu atau beberapa nama file dari objek data dan menempelkannya ke aplikasi Anda. Perhatikan bahwa prosedur yang dibahas di bagian ini untuk mengekstrak nama file dari objek data berlaku sama baiknya untuk transfer seret dan letakkan.

Cara paling sederhana untuk mengambil nama file dari objek data adalah format CF_HDROP :

  1. Hubungi IDataObject::GetData. Atur anggota cfFormat dari struktur FORMATETC ke CF_HDROP dan anggota yang ditiru ke TYMED_HGLOBAL. Anggota dwAspect biasanya diatur ke DVASPECT_CONTENT. Namun, jika Anda perlu memiliki jalur file dalam format pendek (8,3), atur dwAspect ke DVASPECT_SHORT.

    Ketika IDataObject::GetData kembali, anggota hGlobal dari struktur STGMEDIUM menunjuk ke objek memori global yang berisi data.

  2. Buat variabel HDROP dan atur ke anggota hGlobal dari struktur STGMEDIUM . Variabel HDROP sekarang menjadi handel ke struktur DROPFILES diikuti oleh string ganda yang dihentikan null yang berisi jalur file yang sepenuhnya memenuhi syarat dari file yang disalin.

  3. Tentukan berapa banyak jalur file dalam daftar dengan memanggil DragQueryFile dengan parameter iFile diatur ke 0xFFFFFFFF. Fungsi mengembalikan jumlah jalur file dalam daftar. Indeks berbasis nol jalur file dalam daftar ini digunakan pada langkah berikutnya untuk mengidentifikasi jalur tertentu.

  4. Ekstrak jalur file dari objek memori global dengan memanggil DragQueryFile sekali untuk setiap file, dengan iFile diatur ke indeks file.

  5. Proses jalur file sesuai kebutuhan dan tempelkan ke aplikasi Anda.

  6. Panggil ReleaseStgMedium dan teruskan penunjuk ke struktur STGMEDIUM yang Anda berikan ke IDataObject::GetData di langkah 1. Setelah Anda merilis struktur, nilai HDROP yang Anda buat di langkah 2 tidak lagi valid dan tidak boleh digunakan.

Menyalin Konten File yang Dijatuhkan ke Dalam Aplikasi

Skenario: Pengguna menyeret satu atau beberapa file dari Windows Explorer dan meletakkannya di jendela aplikasi Anda. Aplikasi Anda mengekstrak konten file dan menempelkannya ke dalam aplikasi.

Skenario ini menggunakan seret dan letakkan untuk mentransfer file dari Windows Explorer ke aplikasi. Sebelum operasi, aplikasi Anda harus:

  1. Panggil RegisterClipboardFormat untuk mendaftarkan format Clipboard Shell yang diperlukan.
  2. Panggil RegisterDragDrop untuk mendaftarkan jendela target dan antarmuka IDropTarget aplikasi Anda.

Setelah pengguna memulai operasi dengan memilih satu atau beberapa file dan mulai menyeretnya:

  1. Windows Explorer membuat objek data dan memuat format yang didukung ke dalamnya.
  2. Windows Explorer memanggil DoDragDrop untuk memulai perulangan seret.
  3. Saat gambar seret mencapai jendela target Anda, sistem akan memberi tahu Anda dengan memanggil IDropTarget::D ragEnter.
  4. Untuk menentukan apa yang dikandung objek data, panggil metode IDataObject::EnumFormatEtc objek data. Gunakan objek enumerator yang dikembalikan oleh metode untuk menghitung format yang dimuat oleh objek data. Jika aplikasi Anda tidak ingin menerima salah satu format ini, kembalikan DROPEFFECT_NONE. Untuk tujuan skenario ini, aplikasi Anda harus mengabaikan objek data apa pun yang tidak berisi format yang digunakan untuk mentransfer file, seperti CF_HDROP.
  5. Saat pengguna menghilangkan data, sistem memanggil IDropTarget::D rop.
  6. Gunakan antarmuka IDataObject untuk mengekstrak konten file.

Ada beberapa cara berbeda untuk mengekstrak konten objek Shell dari objek data. Secara umum, gunakan urutan berikut:

  • Jika file berisi format CF_TEXT , datanya adalah teks ANSI. Anda dapat menggunakan format CF_TEXT untuk mengekstrak data, daripada membuka file itu sendiri.
  • Jika file berisi objek OLE yang ditautkan atau disematkan, objek data berisi format CF_EMBEDDEDOBJECT. Gunakan teknik OLE standar untuk mengekstrak data. File scrap selalu berisi format CF_EMBEDDEDOBJECT.
  • Jika objek Shell berasal dari sistem file, objek data berisi format CF_HDROP dengan nama file. Ekstrak nama file dari CF_HDROP dan panggil OleCreateFromFile untuk membuat objek baru yang ditautkan atau disematkan. Untuk diskusi tentang cara mengambil nama file dari format CF_HDROP , lihat Menyalin Nama File dari Clipboard ke Aplikasi.
  • Jika objek data berisi format CFSTR_FILEDESCRIPTOR , Anda dapat mengekstrak konten file dari format CFSTR_FILECONTENTS file. Untuk diskusi tentang prosedur ini, lihat Menggunakan Format CFSTR_FILECONTENTS untuk Mengekstrak Data dari File.
  • Sebelum Shell versi 4.71, aplikasi menunjukkan bahwa aplikasi mentransfer jenis file pintasan dengan mengatur FD_LINKUI di anggota dwFlags dari struktur FILEDESCRIPTOR . Untuk versi Shell yang lebih baru, cara yang disukai untuk menunjukkan bahwa pintasan sedang ditransfer adalah dengan menggunakan format CFSTR_PREFERREDDROPEFFECT yang diatur ke DROPEFFECT_LINK. Pendekatan ini jauh lebih efisien daripada mengekstrak struktur FILEDESCRIPTOR hanya untuk memeriksa bendera.

Jika proses ekstraksi data akan panjang, Anda mungkin ingin melakukan operasi secara asinkron pada utas latar belakang. Utas utama Anda kemudian dapat dilanjutkan tanpa penundaan yang tidak perlu. Untuk diskusi tentang cara menangani ekstraksi data asinkron, lihat Menyeret dan Menghilangkan Objek Shell Secara Asinkron.

Menggunakan Format CFSTR_FILECONTENTS untuk Mengekstrak Data dari File

Format CFSTR_FILECONTENTS menyediakan cara yang sangat fleksibel dan kuat untuk mentransfer konten file. Bahkan tidak perlu data disimpan sebagai satu file. Semua yang diperlukan untuk format ini adalah bahwa objek data menyajikan data ke target seolah-olah itu adalah file. Misalnya, data aktual mungkin merupakan bagian dari dokumen teks atau blok data yang diekstrak dari database. Target dapat memperlakukan data sebagai file dan tidak perlu mengetahui apa pun tentang mekanisme penyimpanan yang mendasar.

Ekstensi namespace biasanya menggunakan CFSTR_FILECONTENTS untuk mentransfer data karena format ini tidak mengasumsikan mekanisme penyimpanan tertentu. Ekstensi namespace dapat menggunakan mekanisme penyimpanan apa pun yang nyaman, dan menggunakan format ini untuk menyajikan objeknya ke aplikasi seolah-olah mereka adalah file.

Mekanisme transfer data untuk CFSTR_FILECONTENTS biasanya TYMED_ISTREAM. Mentransfer penunjuk antarmuka IStream membutuhkan memori yang jauh lebih sedikit daripada memuat data ke dalam objek memori global, dan IStream adalah cara yang lebih sederhana untuk mewakili data daripada IStorage.

Format CFSTR_FILECONTENTS selalu disertai dengan format CFSTR_FILEDESCRIPTOR . Anda harus memeriksa isi format ini terlebih dahulu. Jika lebih dari satu file sedang ditransfer, objek data akan benar-benar berisi beberapa format CFSTR_FILECONTENTS , satu untuk setiap file. Format CFSTR_FILEDESCRIPTOR berisi nama dan atribut setiap file, dan menyediakan nilai indeks untuk setiap file yang diperlukan untuk mengekstrak format CFSTR_FILECONTENTS file tertentu.

Untuk mengekstrak format CFSTR_FILECONTENTS :

  1. Ekstrak format CFSTR_FILEDESCRIPTOR sebagai nilai TYMED_HGLOBAL .
  2. Anggota hGlobal dari struktur STGMEDIUM yang dikembalikan menunjuk ke objek memori global. Kunci objek tersebut dengan meneruskan nilai hGlobal ke GlobalLock.
  3. Transmisikan penunjuk yang dikembalikan oleh GlobalLock ke penunjuk FILEGROUPDESCRIPTOR . Ini akan menunjuk ke struktur FILEGROUPDESCRIPTOR diikuti oleh satu atau beberapa struktur FILEDESCRIPTOR . Setiap struktur FILEDESCRIPTOR berisi deskripsi file yang dimuat oleh salah satu format CFSTR_FILECONTENTS yang menyertainya.
  4. Periksa struktur FILEDESCRIPTOR untuk menentukan mana yang sesuai dengan file yang ingin Anda ekstrak. Indeks berbasis nol dari struktur FILEDESCRIPTOR tersebut digunakan untuk mengidentifikasi format CFSTR_FILECONTENTS file. Karena ukuran blok memori global tidak tepat byte, gunakan anggota nFileSizeLow dan nFileSizeHigh struktur untuk menentukan berapa banyak byte yang mewakili file dalam objek memori global.
  5. Panggil IDataObject::GetData dengan anggota cfFormat dari struktur FORMATETC yang diatur ke nilai CFSTR_FILECONTENTS dan anggota lIndex diatur ke indeks yang Anda tentukan di langkah sebelumnya. Anggota tymed biasanya diatur ke TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE. Objek data kemudian dapat memilih mekanisme transfer data pilihannya.
  6. Struktur STGMEDIUM yang dikembalikan IDataObject::GetData akan berisi pointer ke data file. Periksa anggota struktur yang ditiru untuk menentukan mekanisme transfer data.
  7. Jika tymed diatur ke TYMED_ISTREAM atau TYMED_ISTORAGE, gunakan antarmuka untuk mengekstrak data. Jika tymed diatur ke TYMED_HGLOBAL, data terkandung dalam objek memori global. Untuk diskusi tentang cara mengekstrak data dari objek memori global, lihat bagian Mengekstrak objek memori global dari objek dataObjek Data Shell.
  8. Panggil GlobalLock untuk membuka kunci objek memori global yang Anda kunci di langkah 2.

Menangani Operasi Pemindahan yang Dioptimalkan

Skenario: File dipindahkan dari sistem file ke ekstensi namespace menggunakan pemindahan yang dioptimalkan.

Dalam operasi pemindahan konvensional, target membuat salinan data dan sumber menghapus yang asli. Prosedur ini bisa tidak efisien karena memerlukan dua salinan data. Dengan objek besar seperti database, operasi pemindahan konvensional mungkin bahkan tidak praktis.

Dengan langkah yang dioptimalkan, target menggunakan pemahamannya tentang bagaimana data disimpan untuk menangani seluruh operasi pemindahan. Tidak pernah ada salinan data kedua, dan tidak perlu sumber menghapus data asli. Data shell sangat cocok untuk pemindahan yang dioptimalkan karena target dapat menangani seluruh operasi menggunakan Shell API. Contoh umumnya adalah memindahkan file. Setelah target memiliki jalur file yang akan dipindahkan, target dapat menggunakan SHFileOperation untuk memindahkannya. Sumber tidak perlu menghapus file asli.

Catatan

Shell biasanya menggunakan pemindahan yang dioptimalkan untuk memindahkan file. Untuk menangani transfer data Shell dengan benar, aplikasi Anda harus mampu mendeteksi dan menangani pemindahan yang dioptimalkan.

 

Pemindahan yang dioptimalkan ditangani dengan cara berikut:

  1. Sumber memanggil DoDragDrop dengan parameter dwEffect diatur ke DROPEFFECT_MOVE untuk menunjukkan bahwa objek sumber dapat dipindahkan.

  2. Target menerima nilai DROPEFFECT_MOVE melalui salah satu metode IDropTarget-nya , menunjukkan bahwa pemindahan diizinkan.

  3. Target menyalin objek (pemindahan yang tidak optimal) atau memindahkan objek (pemindahan yang dioptimalkan).

  4. Target kemudian memberi tahu sumber apakah perlu menghapus data asli.

    Pemindahan yang dioptimalkan adalah operasi default, dengan data dihapus oleh target. Untuk menginformasikan sumber bahwa pemindahan yang dioptimalkan dilakukan:

      • Target menetapkan nilai pdwEffect yang diterimanya melalui metode IDropTarget::D rop ke beberapa nilai selain DROPEFFECT_MOVE. Biasanya diatur ke DROPEFFECT_NONE atau DROPEFFECT_COPY. Nilai akan dikembalikan ke sumber oleh DoDragDrop.
      • Target juga memanggil metode IDataObject::SetData objek data dan meneruskannya pengidentifikasi format CFSTR_PERFORMEDDROPEFFECT diatur ke DROPEFFECT_NONE. Panggilan metode ini diperlukan karena beberapa target penurunan mungkin tidak mengatur parameter pdwEffectDoDragDrop dengan benar. Format CFSTR_PERFORMEDDROPEFFECT adalah cara yang dapat diandalkan untuk menunjukkan bahwa langkah yang dioptimalkan telah terjadi.

    Jika target melakukan pemindahan yang tidak optimal, data harus dihapus oleh sumbernya. Untuk menginformasikan sumber bahwa langkah yang tidak optimal telah dilakukan:

      • Target menetapkan nilai pdwEffect yang diterimanya melalui metode IDropTarget::D rop ke DROPEFFECT_MOVE. Nilai akan dikembalikan ke sumber oleh DoDragDrop.
      • Target juga memanggil metode IDataObject::SetData objek data dan meneruskannya pengidentifikasi format CFSTR_PERFORMEDDROPEFFECT diatur ke DROPEFFECT_MOVE. Panggilan metode ini diperlukan karena beberapa target penurunan mungkin tidak mengatur parameter pdwEffectDoDragDrop dengan benar. Format CFSTR_PERFORMEDDROPEFFECT adalah cara yang dapat diandalkan untuk menunjukkan bahwa langkah yang tidak optimal telah terjadi.
  5. Sumber memeriksa dua nilai yang dapat dikembalikan oleh target. Jika keduanya diatur ke DROPEFFECT_MOVE, keduanya menyelesaikan pemindahan yang tidak optimal dengan menghapus data asli. Jika tidak, target melakukan pemindahan yang dioptimalkan dan data asli telah dihapus.

Menangani Operasi Delete-on-Paste

Skenario: Satu atau beberapa file dipotong dari folder di Windows Explorer dan ditempelkan ke ekstensi namespace. Windows Explorer membiarkan file disorot hingga menerima umpan balik tentang hasil operasi tempel.

Secara tradisional, ketika pengguna memotong data, ia segera menghilang dari tampilan. Ini mungkin tidak efisien, dan dapat menyebabkan masalah kegunaan jika pengguna menjadi khawatir tentang apa yang telah terjadi pada data. Pendekatan alternatif adalah menggunakan operasi delete-on-paste.

Dengan operasi delete-on-paste, data yang dipilih tidak segera dihapus dari tampilan. Sebaliknya, aplikasi sumber menandainya sebagai dipilih, mungkin dengan mengubah font atau warna latar belakang. Setelah aplikasi target menempelkan data, aplikasi memberi tahu sumber tentang hasil operasi. Jika target melakukan pemindahan yang dioptimalkan, sumber cukup memperbarui tampilannya. Jika target melakukan pemindahan normal, sumber juga harus menghapus salinan datanya. Jika penempelan gagal, aplikasi sumber memulihkan data yang dipilih ke tampilan aslinya.

Catatan

Shell biasanya menggunakan delete-on-paste saat operasi potong/tempel digunakan untuk memindahkan file. Operasi hapus saat ditempelkan dengan objek Shell biasanya menggunakan langkah yang dioptimalkan untuk memindahkan file. Untuk menangani transfer data Shell dengan benar, aplikasi Anda harus mampu mendeteksi dan menangani operasi delete-on-paste.

 

Persyaratan penting untuk delete-on-paste adalah target harus melaporkan hasil operasi ke sumber. Namun, teknik Clipboard standar tidak dapat digunakan untuk menerapkan delete-on-paste karena tidak menyediakan cara bagi target untuk berkomunikasi dengan sumbernya. Sebagai gantinya, aplikasi target menggunakan metode IDataObject::SetData objek data untuk melaporkan hasilnya ke objek data. Objek data kemudian dapat berkomunikasi dengan sumber melalui antarmuka privat.

Prosedur dasar untuk operasi delete-on-paste adalah sebagai berikut:

  1. Sumber menandai tampilan layar data yang dipilih.
  2. Sumber membuat objek data. Ini menunjukkan operasi potong dengan menambahkan format CFSTR_PREFERREDDROPEFFECT dengan nilai data DROPEFFECT_MOVE.
  3. Sumber menempatkan objek data di Clipboard menggunakan OleSetClipboard.
  4. Target mengambil objek data dari Clipboard menggunakan OleGetClipboard.
  5. Target mengekstrak data CFSTR_PREFERREDDROPEFFECT . Jika diatur ke hanya DROPEFFECT_MOVE, target dapat melakukan pemindahan yang dioptimalkan atau hanya menyalin data.
  6. Jika target tidak melakukan pemindahan yang dioptimalkan, target memanggil metode IDataObject::SetData dengan format CFSTR_PERFORMEDDROPEFFECT diatur ke DROPEFFECT_MOVE.
  7. Ketika penempelan selesai, target memanggil metode IDataObject::SetData dengan format CFSTR_PASTESUCCEEDED diatur ke DROPEFFECT_MOVE.
  8. Ketika metode IDataObject::SetData sumber dipanggil dengan format CFSTR_PASTESUCCEEDED diatur ke DROPEFFECT_MOVE, metode tersebut harus memeriksa apakah metode tersebut juga menerima format CFSTR_PERFORMEDDROPEFFECT diatur ke DROPEFFECT_MOVE. Jika kedua format dikirim oleh target, sumber harus menghapus data. Jika hanya format CFSTR_PASTESUCCEEDED yang diterima, sumbernya cukup menghapus data dari tampilannya. Jika transfer gagal, sumber memperbarui tampilan ke tampilan aslinya.

Mentransfer Data ke dan dari Folder Virtual

Skenario: Pengguna menyeret objek dari atau meletakkannya di folder virtual.

Folder virtual berisi objek yang umumnya bukan bagian dari sistem file. Beberapa folder virtual, seperti Keranjang Sampah, dapat mewakili data yang disimpan di hard disk tetapi bukan sebagai objek sistem file biasa. Beberapa dapat mewakili data tersimpan yang ada di sistem jarak jauh, seperti PC genggam, atau situs FTP. Lainnya, seperti folder Printer, berisi objek yang tidak mewakili data tersimpan sama sekali. Meskipun beberapa folder virtual adalah bagian dari sistem, pengembang juga dapat membuat dan menginstal folder virtual kustom dengan menerapkan ekstensi namespace layanan.

Terlepas dari jenis data atau cara penyimpanannya, folder dan objek file yang dimuat oleh folder virtual disajikan oleh Shell seolah-olah itu adalah file dan folder normal. Adalah tanggung jawab folder virtual untuk mengambil data apa pun yang ada di dalamnya dan menyajikannya ke Shell dengan tepat. Persyaratan ini berarti bahwa folder virtual biasanya mendukung transfer data drag-and-drop dan Clipboard.

Dengan demikian ada dua kelompok pengembang yang perlu khawatir dengan transfer data ke dan dari folder virtual:

  • Pengembang yang aplikasinya perlu menerima data yang ditransfer dari folder virtual.
  • Pengembang yang ekstensi namespace layanannya perlu mendukung transfer data dengan benar.

Menerima Data dari Folder Virtual

Folder virtual dapat mewakili hampir semua jenis data dan dapat menyimpan data tersebut dengan cara apa pun yang mereka pilih. Beberapa folder virtual mungkin benar-benar berisi file dan folder sistem file normal. Yang lain mungkin, misalnya, mengemas semua objek mereka ke dalam satu dokumen atau database.

Ketika objek sistem file ditransfer ke aplikasi, objek data biasanya berisi format CF_HDROP dengan jalur objek yang sepenuhnya memenuhi syarat. Aplikasi Anda dapat mengekstrak string ini dan menggunakan fungsi sistem file normal untuk membuka file dan mengekstrak datanya. Namun, karena folder virtual biasanya tidak berisi objek sistem file normal, folder tersebut umumnya tidak menggunakan CF_HDROP.

Alih-alih CF_HDROP, data biasanya ditransfer dari folder virtual dengan format CFSTR_FILECONTENTS CFSTR_FILEDESCRIPTOR/. Format CFSTR_FILECONTENTS memiliki dua keunggulan dibandingkan CF_HDROP:

  • Tidak ada metode penyimpanan data tertentu yang diasumsikan.
  • Formatnya lebih fleksibel. Ini mendukung tiga mekanisme transfer data: objek memori global, antarmuka IStream , atau antarmuka IStorage .

Objek memori global jarang digunakan untuk mentransfer data ke atau dari objek virtual karena data harus disalin ke dalam memori secara keseluruhan. Mentransfer penunjuk antarmuka hampir tidak memerlukan memori dan jauh lebih efisien. Dengan file yang sangat besar, penunjuk antarmuka mungkin satu-satunya mekanisme transfer data praktis. Biasanya, data diwakili oleh pointer IStream , karena antarmuka tersebut agak lebih fleksibel daripada IStorage. Target mengekstrak pointer dari objek data dan menggunakan metode antarmuka untuk mengekstrak data.

Untuk diskusi lebih lanjut tentang cara menangani format CFSTR_FILECONTENTS CFSTR_FILEDESCRIPTOR/, lihat Menggunakan Format CFSTR_FILECONTENTS untuk Mengekstrak Data dari File.

Mentransfer Data ke dan dari Ekstensi NameSpace

Saat Anda menerapkan ekstensi namespace, Anda biasanya ingin mendukung kemampuan seret dan letakkan. Ikuti rekomendasi untuk menghilangkan sumber dan target yang dibahas dalam Pedoman Umum. Secara khusus, ekstensi namespace harus:

  • Mampu menangani format CFSTR_FILECONTENTS CFSTR_FILEDESCRIPTOR/. Kedua format ini biasanya digunakan untuk mentransfer objek ke dan dari ekstensi namespace.
  • Mampu menangani gerakan yang dioptimalkan. Shell mengharapkan bahwa objek Shell akan dipindahkan dengan langkah yang dioptimalkan.
  • Dapat menangani operasi delete-on-paste . Shell menggunakan delete-on-paste saat objek dipindahkan dari Shell dengan operasi potong/tempel.
  • Mampu menangani transfer data melalui antarmuka IStream atau IStorage . Transfer data ke atau dari folder virtual biasanya ditangani dengan mentransfer salah satu dari dua penunjuk antarmuka ini, biasanya penunjuk IStream . Target kemudian memanggil metode antarmuka untuk mengekstrak data:
      • Sebagai sumber penghilangan, ekstensi namespace harus mengekstrak data dari penyimpanan dan meneruskannya melalui antarmuka ini ke target.
      • Sebagai target penghilangan, ekstensi namespace harus menerima data dari sumber melalui antarmuka ini dan menyimpannya dengan benar.

Menjatuhkan File di Keranjang Sampah

Skenario: Pengguna menjatuhkan file di Keranjang Sampah. Ekstensi aplikasi atau namespace Anda menghapus file asli.

Keranjang Sampah adalah folder virtual yang digunakan sebagai repositori untuk file yang tidak lagi diperlukan. Selama Keranjang Sampah belum dikosongkan, pengguna nantinya dapat memulihkan file dan mengembalikannya ke sistem file.

Untuk sebagian besar, mentransfer objek Shell ke Keranjang Sampah berfungsi seperti folder lainnya. Namun, ketika pengguna menjatuhkan file di Keranjang Sampah, sumber perlu menghapus yang asli, bahkan jika umpan balik dari folder menunjukkan operasi salin. Biasanya, sumber drop tidak memiliki cara untuk mengetahui folder mana objek datanya telah dihilangkan. Namun, untuk sistem Windows 2000 dan yang lebih baru, ketika objek data dihilangkan pada Keranjang Sampah, Shell akan memanggil metode IDataObject::SetData objek data dengan format CFSTR_TARGETCLSID diatur ke pengidentifikasi kelas Keranjang Sampah (CLSID) (CLSID_RecycleBin). Untuk menangani kasus Keranjang Sampah dengan benar, objek data Anda harus dapat mengenali format ini dan mengomunikasikan informasi ke sumber melalui antarmuka privat.

Catatan

Ketika IDataObject::SetData dipanggil dengan format CFSTR_TARGETCLSID diatur ke CLSID_RecycleBin, sumber data harus menutup handel terbuka apa pun ke objek yang sedang ditransfer sebelum kembali dari metode . Jika tidak, Anda dapat membuat pelanggaran berbagi.

 

Membuat dan Mengimpor File Scrap

Skenario: Pengguna menyeret beberapa data dari file data aplikasi OLE dan meletakkannya di desktop atau Windows Explorer.

Windows memungkinkan pengguna untuk menyeret objek dari file data aplikasi OLE dan meletakkannya di desktop atau folder sistem file. Operasi ini membuat file scrap, yang berisi data atau tautan ke data. Nama file diambil dari nama pendek yang terdaftar untuk CLSID objek dan data CF_TEXT . Agar Shell membuat file scrap yang berisi data, antarmuka IDataObject aplikasi harus mendukung format CF_EMBEDSOURCE Clipboard. Untuk membuat file yang berisi tautan, IDataObject harus mendukung format CF_LINKSOURCE.

Ada juga tiga fitur opsional yang dapat diterapkan aplikasi untuk mendukung file scrap:

  • Dukungan pulang-pergi
  • Format data singgahan
  • Penyajian tertunda

Dukungan Pulang Pergi

Perjalanan pulang pergi melibatkan transfer objek data ke kontainer lain lalu kembali ke dokumen asli. Misalnya, pengguna dapat mentransfer sekelompok sel dari spreadsheet ke desktop, membuat file scrap dengan data. Jika pengguna kemudian mentransfer sisanya kembali ke spreadsheet, data perlu diintegrasikan ke dalam dokumen seperti sebelum transfer asli.

Saat Shell membuat file scrap, shell mewakili data sebagai objek penyematan. Ketika scrap ditransfer ke kontainer lain, itu ditransfer sebagai objek penyematan, bahkan jika dikembalikan ke dokumen asli. Aplikasi Anda bertanggung jawab untuk menentukan format data yang terkandung dalam scrap dan menempatkan data kembali ke format aslinya jika perlu.

Untuk membuat format objek yang disematkan, tentukan CLSID-nya dengan mengambil format CF_OBJECTDESCRIPTOR objek. Jika CLSID menunjukkan format data milik aplikasi, CLSID harus mentransfer data asli alih-alih memanggil OleCreateFromData.

Format Data Singgahan

Saat Shell membuat file scrap, Shell memeriksa registri untuk daftar format yang tersedia. Secara default, ada dua format yang tersedia: CF_EMBEDSOURCE dan CF_LINKSOURCE. Namun, ada sejumlah skenario di mana aplikasi mungkin perlu memiliki file scrap dalam format yang berbeda:

  • Untuk memungkinkan scrap ditransfer ke kontainer non-OLE, yang tidak dapat menerima format objek yang disematkan.
  • Untuk memungkinkan suite aplikasi berkomunikasi dengan format privat.
  • Untuk membuat perjalanan pulang pergi lebih mudah ditangani.

Aplikasi dapat menambahkan format ke scrap dengan menyimpannya dalam registri. Ada dua jenis format cache:

  • Format cache prioritas. Untuk format ini, data disalin secara keseluruhan ke dalam scrap dari objek data.
  • Format yang dirender penundaan. Untuk format ini, objek data tidak disalin ke scrap. Sebaliknya, penyajian tertunda hingga target meminta data. Penyajian penundaan dibahas secara lebih rinci di bagian berikutnya.

Untuk menambahkan cache prioritas atau format yang dirender penundaan, buat subkunci DataFormat di bawah kunci CLSID aplikasi yang merupakan sumber data. Di bawah subkunci tersebut, buat subkunci PriorityCacheFormats atau DelayRenderFormats . Untuk setiap cache prioritas atau format yang dirender penundaan, buat subkunci bernomor yang dimulai dengan nol. Atur nilai kunci ini ke string dengan nama format terdaftar atau nilai #X, di mana X mewakili nomor format format Clipboard standar.

Sampel berikut menunjukkan format cache untuk dua aplikasi. Aplikasi MyProg1 memiliki format teks kaya sebagai format cache prioritas, dan format privat "Format Saya" sebagai format yang dirender penundaan. Aplikasi MyProg2 memiliki format CF_BITMAP (#8") sebagai format cache prioritas.

HKEY_CLASSES_ROOT
   CLSID
      {GUID}
         (Default) = MyProg1
         DataFormats
            PriorityCacheFormats
               0
                  (Default) = Rich Text Format
            DelayRenderFormats
               0
                  (Default) = My Format
      {GUID}
         (Default) = MyProg2
         DataFormats
            PriorityCacheFormats
               0
                  (Default) = #8

Format tambahan dapat ditambahkan dengan membuat subkunci bernomor tambahan.

Penyajian Tertunda

Format penyajian yang tertunda memungkinkan aplikasi untuk membuat file scrap tetapi menunda pengeluaran penyajian data hingga diminta oleh target. Antarmuka IDataObject dari scrap akan menawarkan format penyajian yang tertunda ke target bersama dengan data asli dan cache. Jika target meminta format penyajian tertunda, Shell akan menjalankan aplikasi dan memberikan data ke target dari objek aktif.

Catatan

Karena penyajian yang tertunda agak berisiko, itu harus digunakan dengan hati-hati. Ini tidak akan berfungsi jika server tidak tersedia, atau pada aplikasi yang tidak diaktifkan OLE.

 

Menyeret dan Menghilangkan Objek Shell Secara Asinkron

Skenario: Pengguna mentransfer blok besar data dari sumber ke target. Untuk menghindari pemblokiran kedua aplikasi untuk sejumlah besar waktu, target mengekstrak data secara asinkron.

Biasanya, seret dan letakkan adalah operasi sinkron. Singkatnya:

  1. Sumber drop memanggil DoDragDrop dan memblokir utas utamanya hingga fungsi kembali. Memblokir utas utama biasanya memblokir pemrosesan UI.
  2. Setelah metode IDropTarget::D rop target dipanggil, target mengekstrak data dari objek data pada utas utamanya. Prosedur ini biasanya memblokir pemrosesan UI target selama proses ekstraksi.
  3. Setelah data diekstrak, target mengembalikan panggilan IDropTarget::D rop , sistem mengembalikan DoDragDrop, dan kedua utas dapat dilanjutkan.

Singkatnya, transfer data sinkron dapat memblokir utas utama kedua aplikasi untuk waktu yang signifikan. Secara khusus, kedua utas harus menunggu sementara target mengekstrak data. Untuk sejumlah kecil data, waktu yang diperlukan untuk mengekstrak data kecil dan transfer data sinkron bekerja dengan cukup baik. Namun, mengekstrak data dalam jumlah besar secara sinkron dapat menyebabkan penundaan yang panjang dan mengganggu UI target dan sumber.

Antarmuka IAsyncOperation/IDataObjectAsyncCapability adalah antarmuka opsional yang dapat diimplementasikan oleh objek data. Ini memberi target penurunan kemampuan untuk mengekstrak data dari objek data secara asinkron pada utas latar belakang. Setelah ekstraksi data diserahkan ke utas latar belakang, utas utama dari kedua aplikasi bebas untuk dilanjutkan.

Menggunakan IASyncOperation/IDataObjectAsyncCapability

Catatan

Antarmuka awalnya bernama IAsyncOperation, tetapi ini kemudian diubah menjadi IDataObjectAsyncCapability. Jika tidak, kedua antarmuka tersebut identik.

 

Tujuan IAsyncOperation/IDataObjectAsyncCapability adalah untuk memungkinkan sumber drop dan drop target untuk menegosiasikan apakah data dapat diekstraksi secara asinkron. Prosedur berikut menguraikan bagaimana sumber penghilangan menggunakan antarmuka:

  1. Buat objek data yang mengekspos IAsyncOperation/IDataObjectAsyncCapability.
  2. Panggil SetAsyncMode dengan fDoOpAsync diatur ke VARIANT_TRUE untuk menunjukkan bahwa operasi asinkron didukung.
  3. Setelah DoDragDrop kembali, panggil InOperation:
    • Jika InOperation gagal atau mengembalikan VARIANT_FALSE, transfer data sinkron normal telah terjadi dan proses ekstraksi data selesai. Sumber harus melakukan pembersihan apa pun yang diperlukan, dan melanjutkan.
    • Jika InOperation mengembalikan VARIANT_TRUE, data sedang diekstrak secara asinkron. Operasi pembersihan harus ditangani oleh EndOperation.
  4. Merilis objek data.
  5. Ketika transfer data asinkron selesai, objek data biasanya memberi tahu sumber melalui antarmuka privat.

Prosedur berikut menguraikan bagaimana target penurunan menggunakan antarmuka IAsyncOperation/IDataObjectAsyncCapability untuk mengekstrak data secara asinkron:

  1. Saat sistem memanggil IDropTarget::D rop, panggil IDataObject::QueryInterface dan minta antarmuka IAsyncOperation/IDataObjectAsyncCapability (IID_IAsyncOperation/IID_IDataObjectAsyncCapability) dari objek data.
  2. Hubungi GetAsyncMode. Jika metode mengembalikan VARIANT_TRUE, objek data mendukung ekstraksi data asinkron.
  3. Buat utas terpisah untuk menangani ekstraksi data dan memanggil StartOperation.
  4. Kembalikan panggilan IDropTarget::D rop , seperti yang Anda lakukan untuk operasi transfer data normal. DoDragDrop akan mengembalikan dan membuka blokir sumber drop. Jangan panggil IDataObject::SetData untuk menunjukkan hasil operasi pemindahan atau delete-on-paste yang dioptimalkan. Tunggu hingga operasi selesai.
  5. Ekstrak data pada utas latar belakang. Utas utama target tidak diblokir dan bebas untuk melanjutkan.
  6. Jika transfer data adalah operasi pemindahan atau penghapusan saat tempel yang dioptimalkan , panggil IDataObject::SetData untuk menunjukkan hasilnya.
  7. Beri tahu objek data bahwa ekstraksi selesai dengan memanggil EndOperation.