Objek Data Shell

Objek data adalah pusat dari semua transfer data Shell. Ini terutama merupakan kontainer untuk menyimpan data yang ditransfer. Namun, target juga dapat berkomunikasi dengan objek data untuk memfasilitasi beberapa jenis transfer data Shell khusus seperti pemindahan yang dioptimalkan. Topik ini menyediakan diskusi umum tentang cara kerja objek data Shell, bagaimana objek data tersebut dibangun oleh sumber, dan bagaimana objek data tersebut ditangani oleh target. Untuk diskusi terperinci tentang cara menggunakan objek data untuk mentransfer berbagai jenis data Shell, lihat Menangani Skenario Transfer Data Shell.

Cara Kerja Objek Data

Objek data adalah objek Model Objek Komponen (COM), yang dibuat oleh sumber data untuk mentransfer data ke target. Mereka biasanya membawa lebih dari satu item data. Ada dua alasan untuk praktik ini:

  • Meskipun hampir semua jenis data dapat ditransfer dengan objek data, sumber biasanya tidak tahu jenis data apa yang dapat diterima target. Misalnya, data mungkin sebagian dari dokumen teks yang diformat. Meskipun target mungkin dapat menangani informasi pemformatan yang kompleks, target mungkin juga hanya dapat menerima teks ANSI. Untuk alasan ini, objek data sering menyertakan data yang sama dalam beberapa format yang berbeda. Target kemudian dapat mengekstrak data dalam format yang dapat ditanganinya.
  • Objek data juga dapat berisi item data tambahan yang bukan versi data sumber. Jenis item data ini biasanya memberikan informasi tambahan tentang operasi transfer data. Misalnya, Shell menggunakan item data tambahan untuk menunjukkan apakah file akan disalin atau dipindahkan.

Format Clipboard

Setiap item data dalam objek data memiliki format terkait, biasanya disebut format clipboard. Ada sejumlah format clipboard standar, yang dideklarasikan dalam Winuser.h, yang sesuai dengan jenis data yang umum digunakan. Format clipboard adalah bilangan bulat, tetapi biasanya disebut dengan nama yang setara, yang memiliki formulir CF_XXX. Misalnya, format clipboard untuk teks ANSI CF_TEXT.

Aplikasi dapat memperluas rentang format clipboard yang tersedia dengan menentukan format privat. Untuk menentukan format privat, aplikasi memanggil RegisterClipboardFormat dengan string yang mengidentifikasi format. Bilangan bulat yang tidak ditandatangani yang dikembalikan fungsi adalah nilai format valid yang dapat digunakan sama seperti format clipboard standar. Namun, sumber dan target harus mendaftarkan format untuk menggunakannya. Dengan satu pengecualian—CF_HDROP—format clipboard yang digunakan untuk mentransfer data Shell didefinisikan sebagai format privat. Mereka harus didaftarkan oleh sumber dan target sebelum dapat digunakan. Untuk deskripsi format clipboard Shell yang tersedia, lihat Format Clipboard Shell.

Meskipun ada beberapa pengecualian, objek data biasanya hanya berisi satu item data untuk setiap format clipboard yang didukungnya. Korelasi satu-ke-satu antara format dan data ini memungkinkan nilai format digunakan sebagai pengidentifikasi untuk item data terkait. Bahkan, saat membahas konten objek data, item data tertentu biasanya disebut "format" dan disebut dengan nama formatnya. Misalnya, frasa seperti "Ekstrak format CF_TEXT..." biasanya digunakan saat mendiskusikan item data teks ANSI objek data.

Saat target penurunan menerima penunjuk ke objek data, target drop menghitung format yang tersedia untuk menentukan jenis data apa yang tersedia. Kemudian meminta satu atau beberapa format yang tersedia dan mengekstrak data. Cara spesifik target mengekstrak data Shell dari objek data bervariasi menurut format; ini dibahas secara rinci dalam Cara Target Menangani Objek Data.

Dengan transfer data clipboard sederhana, data ditempatkan dalam objek memori global. Alamat objek tersebut ditempatkan di Clipboard, bersama dengan formatnya. Format clipboard memberi tahu target jenis data apa yang akan ditemukannya di alamat terkait. Sementara transfer clipboard sederhana mudah diterapkan:

  • Objek data menyediakan cara yang jauh lebih fleksibel untuk mentransfer data.
  • Objek data lebih cocok untuk mentransfer data dalam jumlah besar.
  • Objek data harus digunakan untuk mentransfer data dengan operasi seret dan letakkan.

Untuk alasan ini, semua transfer data Shell menggunakan objek data. Dengan objek data, format clipboard tidak digunakan secara langsung. Sebagai gantinya, item data diidentifikasi dengan generalisasi format clipboard, struktur FORMATETC .

Struktur FORMATETC

Struktur FORMATETC adalah versi yang diperluas dari format clipboard. Seperti yang digunakan untuk transfer data Shell, struktur FORMATETC memiliki karakteristik berikut:

  • Item data masih diidentifikasi dengan format clipboard-nya, di anggota cfFormat .

  • Transfer data tidak terbatas pada objek memori global. Anggota tymed digunakan untuk menunjukkan mekanisme transfer data yang terkandung dalam struktur STGMEDIUM terkait. Ini diatur ke salah satu nilai TYMED_XXX .

  • Shell menggunakan anggota lIndex dengan format CFSTR_FILECONTENTS untuk memungkinkan objek data berisi lebih dari satu item data per format. Untuk diskusi tentang cara menggunakan format ini, lihat bagian Menggunakan Format CFSTR_FILECONTENTS untuk Mengekstrak Data dari File dalam Menangani Skenario Transfer Data Shell.

  • Anggota dwAspect biasanya diatur ke DVASPECT_CONTENT. Namun, ada tiga nilai yang ditentukan dalam Shlobj.h yang dapat digunakan untuk transfer data Shell.

    Nilai Deskripsi
    DVASPECT_COPY Digunakan untuk menunjukkan bahwa format mewakili salinan data.
    DVASPECT_LINK Digunakan untuk menunjukkan bahwa format mewakili pintasan ke data.
    DVASPECT_SHORTNAME Digunakan dengan format CF_HDROP untuk meminta jalur file dengan nama yang disingkat ke format 8.3.

     

  • Anggota ptd tidak digunakan untuk transfer data Shell dan biasanya diatur ke NULL.

Struktur STGMEDIUM

Struktur STGMEDIUM menyediakan akses ke data yang sedang ditransfer. Tiga mekanisme transfer data didukung untuk data Shell:

Anggota yang ditiru dari struktur STGMEDIUM adalah nilai TYMED_XXX yang mengidentifikasi mekanisme transfer data. Anggota kedua adalah penunjuk yang digunakan oleh target untuk mengekstrak data. Penunjuk dapat menjadi salah satu dari berbagai jenis, tergantung pada nilai yang diikat . Tiga nilai tymed yang digunakan untuk transfer data Shell dirangkum dalam tabel berikut, bersama dengan nama anggota STGMEDIUM yang sesuai.

Nilai tymed Nama anggota Deskripsi
TYMED_HGLOBAL hGlobal Penunjuk ke objek memori global. Jenis pointer ini biasanya digunakan untuk mentransfer data dalam jumlah kecil. Misalnya, Shell menggunakan objek memori global untuk mentransfer string teks pendek seperti nama file atau URL.
TYMED_ISTREAM pstm Penunjuk ke antarmuka IStream . Jenis pointer ini lebih disukai untuk sebagian besar transfer data Shell karena membutuhkan memori yang relatif sedikit dibandingkan dengan TYMED_HGLOBAL. Selain itu, mekanisme transfer data TYMED_ISTREAM tidak mengharuskan sumber untuk menyimpan datanya dengan cara tertentu.
TYMED_ISTORAGE pstg Penunjuk ke antarmuka IStorage . Target memanggil metode antarmuka untuk mengekstrak data. Seperti TYMED_ISTREAM, jenis pointer ini membutuhkan memori yang relatif sedikit. Namun, karena TYMED_ISTORAGE kurang fleksibel daripada TYMED_ISTREAM, itu tidak seperti yang umum digunakan.

 

Cara Sumber Membuat Objek Data

Saat pengguna memulai transfer data Shell, sumber bertanggung jawab untuk membuat objek data dan memuatnya dengan data. Prosedur berikut ini meringkas prosesnya:

  1. Panggil RegisterClipboardFormat untuk mendapatkan nilai format clipboard yang valid untuk setiap format Shell yang akan disertakan dalam objek data. Ingatlah bahwa CF_HDROP sudah merupakan format clipboard yang valid dan tidak perlu didaftarkan.
  2. Agar setiap format ditransfer, masukkan data terkait ke dalam objek memori global atau buat objek yang menyediakan akses ke data tersebut melalui antarmuka IStream atau IStorage . Antarmuka IStream dan IStorage dibuat menggunakan teknik COM standar. Untuk diskusi tentang cara menangani objek memori global, lihat Cara Menambahkan Objek Memori Global ke Objek Data.
  3. Buat struktur FORMATETC dan STGMEDIUM untuk setiap format.
  4. Membuat instans objek data.
  5. Muat data ke dalam objek data dengan memanggil metode IDataObject::SetData untuk setiap format yang didukung dan meneruskan struktur FORMATETC dan STGMEDIUM format.
  6. Dengan transfer data clipboard, panggil OleSetClipboard untuk menempatkan penunjuk ke antarmuka IDataObject objek data pada Clipboard. Untuk transfer seret dan letakkan, mulai perulangan seret dengan memanggil DoDragDrop. Penunjuk IDataObject akan diteruskan ke target penghilangan saat data dihilangkan, mengakhiri perulangan seret.

Objek data sekarang siap untuk ditransfer ke target. Untuk transfer data clipboard, objek hanya ditahan sampai target memintanya dengan memanggil OleGetClipboard. Untuk transfer data seret dan letakkan, objek data bertanggung jawab untuk membuat ikon untuk mewakili data dan memindahkannya saat pengguna memindahkan kursor. Saat objek berada di perulangan seret, sumber menerima informasi status melalui antarmuka IDropSource-nya . Untuk diskusi lebih lanjut, lihat Menerapkan IDropSource.

Sumber tidak menerima pemberitahuan jika objek data diambil dari Clipboard oleh target. Saat objek dihilangkan pada target oleh operasi seret dan letakkan, fungsi DoDragDrop yang dipanggil untuk memulai perulangan seret akan kembali.

Cara Menambahkan Objek Memori Global ke Objek Data

Banyak format data Shell dalam bentuk objek memori global. Gunakan prosedur berikut untuk membuat format yang berisi objek memori global dan memuatnya ke dalam objek data:

  1. Buat struktur FORMATETC . Atur anggota cfFormat ke nilai format clipboard yang sesuai dan anggota yang diikat ke TYMED_HGLOBAL.
  2. Buat struktur STGMEDIUM . Atur anggota tymed ke TYMED_HGLOBAL.
  3. Buat objek memori global dengan memanggil GlobalAlloc untuk mengalokasikan blok memori berukuran yang sesuai.
  4. Tetapkan blok data yang akan ditransfer ke alamat yang dikembalikan oleh GlobalAlloc.
  5. Tetapkan alamat objek memori global ke anggota hGlobal struktur STGMEDIUM .
  6. Muat format ke dalam objek data dengan memanggil IDataObject::SetData dan meneruskan struktur FORMATETC dan STGMEDIUM yang dibuat di langkah-langkah sebelumnya.

Fungsi sampel berikut membuat objek memori global yang berisi nilai DWORD dan memuatnya ke dalam objek data. Parameter pdtobj adalah penunjuk ke antarmuka IDataObject objek data, cf adalah nilai format clipboard, dan dw adalah nilai data.

STDAPI DataObj_SetDWORD(IDataObject *pdtobj, UINT cf, DWORD dw)
{
    FORMATETC fmte = {(CLIPFORMAT) cf, 
                      NULL, 
                      DVASPECT_CONTENT, 
                      -1, 
                      TYMED_HGLOBAL};
    STGMEDIUM medium;

    HRESULT hres = E_OUTOFMEMORY;
    DWORD *pdw = (DWORD *)GlobalAlloc(GPTR, sizeof(DWORD));
    
    if (pdw)
    {
        *pdw = dw;       
        medium.tymed = TYMED_HGLOBAL;
        medium.hGlobal = pdw;
        medium.pUnkForRelease = NULL;

        hres = pdtobj->SetData(&fmte, &medium, TRUE);
 
        if (FAILED(hres))
            GlobalFree((HGLOBAL)pdw);
    }
    return hres;
}

Menerapkan IDataObject

IDataObject adalah antarmuka utama objek data. Ini harus diimplementasikan oleh semua objek data. Ini digunakan oleh sumber dan target untuk berbagai tujuan, termasuk:

  • Memuat data ke dalam objek data.
  • Mengekstrak data dari objek data.
  • Menentukan jenis data apa yang ada di objek data.
  • Memberikan umpan balik ke objek data tentang hasil transfer data.

IDataObject mendukung sejumlah metode. Bagian ini membahas cara mengimplementasikan tiga metode terpenting untuk objek data Shell, SetData, EnumFormatEtc, dan GetData. Untuk diskusi tentang metode lain, lihat referensi IDataObject .

Metode SetData

Fungsi utama metode IDataObject::SetData adalah memungkinkan sumber memuat data ke dalam objek data. Agar setiap format disertakan, sumber membuat struktur FORMATETC untuk mengidentifikasi format dan struktur STGMEDIUM untuk menyimpan penunjuk ke data. Sumber kemudian memanggil metode IDataObject::SetData objek dan meneruskan struktur FORMATETC dan STGMEDIUM format. Metode harus menyimpan informasi ini sehingga tersedia saat target memanggil IDataObject::GetData untuk mengekstrak data dari objek.

Namun, saat mentransfer file, Shell sering menempatkan informasi untuk setiap file yang akan ditransfer ke dalam format CFSTR_FILECONTENTS terpisah. Untuk membedakan file yang berbeda, anggota lIndex dari struktur FORMATETC setiap file diatur ke nilai indeks yang mengidentifikasi file tertentu. Implementasi IDataObject::SetData Anda harus mampu menyimpan beberapa format CFSTR_FILECONTENTS yang hanya berbeda dengan anggota lIndex mereka.

Saat kursor berada di atas jendela target, target dapat menggunakan objek pembantu seret dan letakkan untuk menentukan gambar seret. Objek pembantu seret dan letakkan memanggil IDataObject::SetData untuk memuat format privat ke objek data yang digunakan untuk dukungan lintas proses. Untuk mendukung objek pembantu seret dan letakkan, implementasi IDataObject::SetData Anda harus dapat menerima dan menyimpan format privat arbitrer.

Setelah data dihilangkan, beberapa jenis transfer data Shell mengharuskan target untuk memanggil IDataObject::SetData untuk menyediakan objek data dengan informasi tentang hasil operasi penghilangan. Misalnya, saat memindahkan file dengan operasi pemindahan yang dioptimalkan, target biasanya menghapus file asli, tetapi tidak diperlukan untuk melakukannya. Target menginformasikan objek data apakah file dihapus dengan memanggil IDataObject::SetData dengan format CFSTR_LOGICALPERFORMEDDROPEFFECT . Ada beberapa Format Clipboard Shell lainnya yang juga digunakan oleh target untuk meneruskan informasi ke objek data. Implementasi IDataObject::SetData Anda harus dapat mengenali format ini dan merespons dengan tepat. Untuk diskusi lebih lanjut, lihat Menangani Skenario Transfer Data Shell.

Metode EnumFormatEtc

Ketika target menerima objek data, biasanya memanggil FORMATETC untuk menentukan format apa yang dikandung objek. Metode ini membuat objek enumerasi OLE dan mengembalikan penunjuk ke antarmuka IEnumFORMATETC objek. Target kemudian menggunakan antarmuka untuk menghitung format yang tersedia.

Objek enumerasi harus selalu menghitung format yang tersedia dalam urutan kualitas, dimulai dengan yang terbaik. Kualitas relatif format ditentukan oleh sumber penghilangan. Secara umum, format kualitas tertinggi berisi data terkaya dan paling lengkap. Misalnya, gambar warna 24-bit biasanya akan dianggap berkualitas lebih tinggi daripada versi skala abu-abu dari gambar tersebut. Alasan untuk menghitung format dalam urutan kualitasnya adalah bahwa target biasanya menghitung sampai mereka mencapai format yang mereka dukung, dan kemudian mereka menggunakan format tersebut untuk mengekstrak data. Agar prosedur ini menghasilkan format terbaik yang tersedia yang dapat didukung target, format harus dijumlahkan dalam urutan kualitasnya.

Objek enumerasi untuk data Shell diimplementasikan dengan cara yang sama seperti untuk jenis transfer data lainnya, dengan satu pengecualian penting. Karena objek data biasanya hanya berisi satu item data per format, objek data biasanya menghitung setiap format yang diteruskan ke IDataObject::SetData. Namun, seperti yang dibahas di bagian metode SetData , objek data Shell dapat berisi beberapa format CFSTR_FILECONTENTS .

Karena tujuan IDataObject::EnumFormatEtc adalah untuk memungkinkan target menentukan jenis data apa yang ada, tidak perlu menghitung lebih dari satu format CFSTR_FILECONTENTS . Jika target perlu mengetahui berapa banyak format ini yang dikandung objek data, target dapat mengambil informasi tersebut dari format CFSTR_FILEDESCRIPTOR yang menyertainya. Untuk diskusi lebih lanjut tentang cara mengimplementasikan IDataObject::EnumFormatEtc, lihat dokumentasi referensi metode.

Metode GetData

Target memanggil IDataObject::GetData untuk mengekstrak format data tertentu. Target menentukan format dengan meneruskan struktur FORMATETC yang sesuai. IDataObject::GetData mengembalikan struktur STGMEDIUM format.

Target dapat mengatur anggota yang ditiru dari struktur FORMATETC ke nilai TYMED_XXX tertentu untuk menentukan mekanisme transfer data mana yang akan digunakan untuk mengekstrak data. Namun, target juga dapat membuat permintaan yang lebih umum dan membiarkan objek data memutuskan. Untuk meminta objek data memilih mekanisme transfer data, target menetapkan semua nilai TYMED_XXX yang didukungnya. IDataObject::GetData memilih salah satu mekanisme transfer data ini dan mengembalikan struktur STGMEDIUM yang sesuai. Misalnya, tymed biasanya diatur ke TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE untuk meminta salah satu dari tiga mekanisme transfer data Shell.

Catatan

Karena mungkin ada beberapa format CFSTR_FILECONTENTS , cfFormat dan anggota yang ditiru dari struktur FORMATETC tidak cukup untuk menunjukkan struktur STGMEDIUMmana IDataObject::GetData yang harus dikembalikan. Untuk format CFSTR_FILECONTENTS, IDataObject::GetData juga harus memeriksa anggota lIndex struktur FORMATETC untuk mengembalikan struktur STGMEDIUM yang benar.

 

Format CFSTR_INDRAGLOOP ditempatkan dalam objek data untuk memungkinkan target memeriksa status perulangan seret dan letakkan sambil menghindari penyajian intensif memori data objek. Data format adalah nilai DWORD yang diatur ke nilai bukan nol jika objek data berada dalam perulangan seret. Nilai data format diatur ke nol jika data telah dihilangkan. Jika target meminta format ini dan belum dimuat oleh sumbernya, IDataObject::GetData harus merespons seolah-olah sumber telah memuat format dengan nilai nol.

Saat kursor berada di atas jendela target, target dapat menggunakan objek pembantu seret dan letakkan untuk menentukan gambar seret. Objek pembantu seret dan letakkan memanggil IDataObject::SetData untuk memuat format privat ke objek data yang digunakan untuk dukungan lintas proses. Kemudian memanggil IDataObject::GetData untuk mengambilnya. Untuk mendukung objek pembantu seret dan letakkan, implementasi Objek Data Shell Anda harus dapat mengembalikan format privat arbitrer saat diminta.

Menerapkan IDropSource

Sumber harus membuat objek yang mengekspos antarmuka IDropSource . Antarmuka ini memungkinkan sumber untuk memperbarui gambar seret yang menunjukkan posisi kursor saat ini dan untuk memberikan umpan balik kepada sistem tentang cara mengakhiri operasi seret dan letakkan. IDropSource memiliki dua metode: GiveFeedback dan QueryContinueDrag.

Metode GiveFeedback

Saat berada di perulangan seret, sumber drop bertanggung jawab untuk melacak posisi kursor dan menampilkan gambar seret yang sesuai. Namun, dalam beberapa kasus Anda mungkin ingin mengubah tampilan gambar seret saat berada di atas jendela target penghilangan.

Ketika kursor memasuki atau meninggalkan jendela target dan saat bergerak di atas jendela target, sistem secara berkala memanggil antarmuka IDropTarget target. Target merespons dengan nilai DROPEFFECT yang diteruskan ke sumber melalui metode GiveFeedback . Jika sesuai, sumber dapat memodifikasi tampilan kursor berdasarkan nilai DROPEFFECT . Untuk detail lebih lanjut, lihat referensi GiveFeedback dan DoDragDrop .

Metode QueryContinueDrag

Metode ini dipanggil jika tombol mouse atau status keyboard berubah saat objek data berada di perulangan seret. Ini memberi tahu sumber apakah tombol ESC telah ditekan dan menyediakan status tombol pengubah keyboard saat ini, seperti CTRL atau SHIFT. Nilai pengembalian metode QueryContinueDrag menentukan salah satu dari tiga tindakan:

  • S_OK. Lanjutkan operasi seret
  • DRAGDROP_S_DROP. Hilangkan data. Sistem kemudian memanggil metode IDropTarget::D rop target.
  • DRAGDROP_S_CANCEL. Hentikan perulangan seret tanpa menghilangkan data. Nilai ini biasanya dikembalikan jika tombol ESCAPE ditekan.

Untuk diskusi lebih lanjut, lihat referensi QueryContinueDrag dan DoDragDrop .

Cara Target Menangani Objek Data

Target menerima objek data saat mengambil objek data dari Clipboard atau dihilangkan di jendela target oleh pengguna. Target kemudian dapat mengekstrak data dari objek data. Jika perlu, target juga dapat memberi tahu objek data tentang hasil operasi. Sebelum transfer data Shell, target penurunan harus mempersiapkan dirinya untuk operasi:

  1. Target harus memanggil RegisterClipboardFormat untuk mendapatkan nilai format clipboard yang valid untuk semua format Shell, selain CF_HDROP, yang mungkin disertakan dalam objek data. CF_HDROP sudah merupakan format clipboard yang valid dan tidak perlu didaftarkan.
  2. Untuk mendukung operasi seret dan letakkan, target harus mengimplementasikan antarmuka IDropTarget dan mendaftarkan jendela target. Untuk mendaftarkan jendela target, target memanggil RegisterDragDrop dan melewati handel jendela dan penunjuk antarmuka IDropTarget .

Untuk transfer clipboard, target tidak menerima pemberitahuan apa pun bahwa objek data telah ditempatkan pada Clipboard. Biasanya, aplikasi diberi tahu bahwa objek berada di Clipboard oleh tindakan pengguna, seperti mengklik tombol Tempel pada toolbar aplikasi. Target kemudian mengambil penunjuk IDataObject objek data dari Clipboard dengan memanggil OleGetClipboard. Untuk transfer data seret dan letakkan, sistem menggunakan antarmuka IDropTarget target untuk memberi target informasi tentang kemajuan transfer data:

Untuk diskusi tentang cara menerapkan metode ini, lihat IDropTarget.

Saat data dihilangkan, IDropTarget::D rop menyediakan target dengan penunjuk ke antarmuka IDataObject objek data. Target kemudian menggunakan antarmuka ini untuk mengekstrak data dari objek data.

Mengekstrak Data Shell dari Objek Data

Setelah objek data dihilangkan atau diambil dari Clipboard, target dapat mengekstrak data yang dibutuhkannya. Langkah pertama dalam proses ekstraksi biasanya untuk menghitung format yang terkandung oleh objek data:

  • Panggil IDataObject::EnumFormatEtc. Objek data membuat objek enumerasi OLE standar dan mengembalikan penunjuk ke antarmuka IEnumFORMATETC-nya .
  • Gunakan metode IEnumFORMATETC untuk menghitung format yang dimuat oleh objek data. Operasi ini biasanya mengambil satu struktur FORMATETC untuk setiap format yang dikandung objek. Namun, objek enumerasi biasanya hanya mengembalikan satu struktur FORMATETC untuk format CFSTR_FILECONTENTS , terlepas dari berapa banyak format tersebut yang dimuat oleh objek data.
  • Pilih satu atau beberapa format yang akan diekstrak, dan simpan struktur FORMATETC-nya .

Untuk mengambil format tertentu, teruskan struktur FORMATETC terkait ke IDataObject::GetData. Metode ini mengembalikan struktur STGMEDIUM yang menyediakan akses ke data. Untuk menentukan mekanisme transfer data tertentu, atur nilai yang ditiru dari struktur FORMATETC ke nilai TYMED_XXX yang sesuai. Untuk meminta objek data memilih mekanisme transfer data, target menetapkan nilai TYMED_XXX untuk setiap mekanisme transfer data yang dapat ditangani target. Objek data memilih salah satu mekanisme transfer data ini dan mengembalikan struktur STGMEDIUM yang sesuai.

Untuk sebagian besar format, target dapat mengambil data dengan melewati struktur FORMATETC yang diterimanya saat menghitung format yang tersedia. Satu pengecualian untuk aturan ini adalah CFSTR_FILECONTENTS. Karena objek data dapat berisi beberapa instans format ini, struktur FORMATETC yang dikembalikan oleh enumerator mungkin tidak sesuai dengan format tertentu yang ingin Anda ekstrak. Selain menentukan anggota cfFormat dan tymed , Anda juga harus mengatur anggota lIndex ke nilai indeks file. Untuk diskusi lebih lanjut, lihat bagian Menggunakan Format CFSTR_FILECONTENTS untuk Mengekstrak Data dari File dalam Menangani Skenario Transfer Data Shell

Proses ekstraksi data tergantung pada jenis pointer yang terkandung oleh struktur STGMEDIUM yang dikembalikan. Jika struktur berisi penunjuk ke antarmuka IStream atau IStorage , gunakan metode antarmuka untuk mengekstrak data. Proses mengekstrak data dari objek memori global dibahas di bagian berikutnya.

Mengekstrak objek memori global dari objek data

Banyak format data Shell dalam bentuk objek memori global. Gunakan prosedur berikut untuk mengekstrak format yang berisi objek memori global dari objek data dan tetapkan datanya ke variabel lokal:

  1. Buat struktur FORMATETC . Atur anggota cfFormat ke nilai format clipboard yang sesuai dan anggota yang diikat ke TYMED_HGLOBAL.

  2. Buat struktur STGMEDIUM kosong.

  3. Panggil IDataObject::GetData, dan teruskan penunjuk ke struktur FORMATETC dan STGMEDIUM .

    Ketika IDataObject::GetData kembali, struktur STGMEDIUM akan berisi penunjuk ke objek memori global yang berisi data.

  4. Tetapkan data ke variabel lokal dengan memanggil GlobalLock dan meneruskan anggota hGlobal dari struktur STGMEDIUM .

  5. Panggil GlobalUnlock untuk melepaskan kunci pada objek memori global.

  6. Panggil ReleaseStgMedium untuk merilis objek memori global.

Catatan

Anda harus menggunakan ReleaseStgMedium untuk merilis objek memori global, bukan GlobalFree.

 

Contoh berikut menunjukkan cara mengekstrak nilai DWORD yang disimpan sebagai objek memori global dari objek data. Parameter pdtobj adalah penunjuk ke antarmuka IDataObject objek data, cf adalah format clipboard yang mengidentifikasi data yang diinginkan, dan pdwOut digunakan untuk mengembalikan nilai data.

STDAPI DataObj_GetDWORD(IDataObject *pdtobj, UINT cf, DWORD *pdwOut)
{    STGMEDIUM medium;
   FORMATETC fmte = {(CLIPFORMAT) cf, NULL, DVASPECT_CONTENT, -1, 
       TYMED_HGLOBAL};
    HRESULT hres = pdtobj->GetData(&fmte, &medium);
    if (SUCCEEDED(hres))
   {
       DWORD *pdw = (DWORD *)GlobalLock(medium.hGlobal);
       if (pdw)
       {
           *pdwOut = *pdw;
           GlobalUnlock(medium.hGlobal);
       }
       else
       {
           hres = E_UNEXPECTED;
       }
       ReleaseStgMedium(&medium);
   }
   return hres;
}

Menerapkan IDropTarget

Sistem menggunakan antarmuka IDropTarget untuk berkomunikasi dengan target saat kursor berada di atas jendela target. Respons target diteruskan ke sumber melalui antarmuka IDropSource-nya . Bergantung pada responsnya, sumber dapat memodifikasi ikon yang mewakili data. Jika target penurunan perlu menentukan ikon data, target dapat melakukannya dengan membuat objek pembantu seret dan letakkan.

Dengan operasi seret dan letakkan konvensional, target menginformasikan objek data hasil operasi dengan mengatur parameter pdwEffectIDropTarget::D rop ke nilai DROPEFFECT yang sesuai. Dengan objek data Shell, target mungkin juga perlu memanggil IDataObject::SetData. Untuk diskusi tentang bagaimana target harus merespons skenario transfer data yang berbeda, lihat Menangani Skenario Transfer Data Shell.

Bagian berikut secara singkat membahas cara menerapkan metode IDropTarget::D ragEnter, IDropTarget::D ragOver, dan IDropTarget::D rop . Untuk detail lebih lanjut, lihat dokumentasi referensi.

Metode DragEnter

Sistem memanggil metode IDropTarget::D ragEnter saat kursor memasuki jendela target. Parameternya menyediakan target dengan lokasi kursor, status tombol pengubah keyboard seperti tombol CTRL, dan penunjuk ke antarmuka IDataObject objek data. Target bertanggung jawab untuk menggunakan antarmuka tersebut untuk menentukan apakah dapat menerima salah satu format yang dimuat oleh objek data. Jika bisa, biasanya meninggalkan nilai pdwEffect tidak berubah. Jika tidak dapat menerima data apa pun dari objek data, ia mengatur parameter pdwEffect ke DROPEFFECT_NONE. Sistem meneruskan nilai parameter ini ke antarmuka IDropSource objek data untuk memungkinkannya menampilkan gambar seret yang sesuai.

Target tidak boleh menggunakan metode IDataObject::GetData untuk merender data Shell sebelum dihilangkan. Merender data objek sepenuhnya untuk setiap kejadian tersebut dapat menyebabkan kursor seret terhenti. Untuk menghindari masalah ini, beberapa objek Shell berisi format CFSTR_INDRAGLOOP . Dengan mengekstrak format ini, target dapat memeriksa status perulangan seret sambil menghindari penyajian intensif memori data objek. Nilai data format adalah DWORD yang diatur ke nilai bukan nol jika objek data berada dalam perulangan seret. Nilai data format diatur ke nol jika data telah dihilangkan.

Jika target dapat menerima data dari objek data, target harus memeriksa grfKeyState untuk menentukan apakah ada tombol pengubah yang telah ditekan untuk mengubah perilaku penurunan normal. Misalnya, operasi default biasanya merupakan pemindahan, tetapi menekan tombol CTRL biasanya menunjukkan operasi salin.

Saat kursor berada di atas jendela target, target dapat menggunakan objek pembantu seret dan letakkan untuk mengganti gambar seret objek data dengan gambarnya sendiri. Jika demikian, IDropTarget::D ragEnter harus memanggil IDropTargetHelper::D ragEnter untuk meneruskan informasi yang terkandung dalam parameter DragEnter ke objek pembantu seret dan letakkan.

Metode DragOver

Saat kursor bergerak di dalam jendela target, sistem secara berkala memanggil metode IDropTarget::D ragOver . Parameternya menyediakan target dengan lokasi kursor dan status tombol pengubah keyboard seperti tombol CTRL. IDropTarget::D ragOver memiliki tanggung jawab yang jauh sama dengan IDropTarget::D ragEnter, dan implementasinya biasanya sangat mirip.

Jika target menggunakan objek pembantu seret dan letakkan, IDropTarget::D ragOver harus memanggil IDropTargetHelper::D ragOver untuk meneruskan informasi yang terkandung dalam parameter DragOver ke objek pembantu seret dan letakkan.

Jatuhkan metode

Sistem memanggil metode IDropTarget::D rop untuk memberi tahu target bahwa pengguna telah menghilangkan data, biasanya dengan melepaskan tombol mouse. IDropTarget::D rop memiliki parameter yang sama dengan IDropTarget::D ragEnter. Target biasanya merespons dengan mengekstrak satu atau beberapa format dari objek data. Setelah selesai, target harus mengatur parameter pdwEffect ke nilai DROPEFFECT yang menunjukkan hasil operasi. Untuk beberapa jenis transfer data Shell, target juga harus memanggil IDataObject::SetData untuk meneruskan format dengan informasi tambahan tentang hasil operasi ke objek data. Untuk diskusi terperinci, lihat Menangani Skenario Transfer Data Shell.

Jika target menggunakan objek pembantu seret dan letakkan, IDropTarget::D rop harus memanggil IDropTargetHelper::D rop untuk meneruskan informasi yang terkandung dalam parameter IDropTargetHelper::D ragOver ke objek pembantu seret dan letakkan.

Menggunakan Objek Pembantu Seret dan Letakkan

Objek pembantu seret dan letakkan (CLSID_DragDropHelper) diekspor oleh Shell untuk memungkinkan target menentukan gambar seret saat berada di atas jendela target. Untuk menggunakan objek pembantu seret dan letakkan, buat objek server dalam proses dengan memanggil CoCreateInstance dengan pengidentifikasi kelas (CLSID) CLSID_DragDropHelper. Objek pembantu seret dan letakkan mengekspos dua antarmuka yang digunakan dengan cara berikut:

  • Antarmuka IDragSourceHelper memungkinkan target penghilangan untuk menentukan ikon untuk mewakili objek data.
  • Antarmuka IDropTargetHelper memungkinkan target penghilangan untuk menginformasikan objek pembantu seret dan letakkan lokasi kursor, dan untuk menampilkan atau menyembunyikan ikon data.

Menggunakan Antarmuka IDragSourceHelper

Antarmuka IDragSourceHelper diekspos oleh objek pembantu seret dan letakkan untuk memungkinkan target penghilangan untuk menyediakan gambar yang akan ditampilkan saat kursor berada di atas jendela target. IDragSourceHelper menyediakan dua cara alternatif untuk menentukan bitmap yang akan digunakan sebagai gambar seret:

  • Jatuhkan target yang memiliki jendela dapat mendaftarkan pesan jendela DI_GETDRAGIMAGE untuknya dengan menginisialisasi objek pembantu seret dan letakkan dengan IDragSourceHelper::InitializeFromWindow. Ketika target menerima pesan DI_GETDRAGIMAGE, handler menempatkan informasi bitmap gambar seret dalam struktur SHDRAGIMAGE yang diteruskan sebagai nilai lParam pesan.
  • Target penurunan tanpa jendela menentukan bitmap saat menginisialisasi objek pembantu seret dan letakkan dengan IDragSourceHelper::InitializeFromBitmap.

Menggunakan Antarmuka IDropTargetHelper

Antarmuka ini memungkinkan target penghilangan untuk memberi tahu objek pembantu seret dan letakkan saat kursor memasuki atau meninggalkan target. Saat kursor berada di atas jendela target, IDropTargetHelper memungkinkan target untuk memberi objek pembantu seret dan letakkan informasi yang diterima target melalui antarmuka IDropTarget-nya .

Empat metode IDropTargetHelperIDropTargetHelper::D ragEnter, IDropTargetHelper::D ragLeave, IDropTargetHelper::D ragOver, dan IDropTargetHelper::D rop—dikaitkan dengan metode IDropTarget dengan nama yang sama. Untuk menggunakan objek pembantu seret dan letakkan, masing-masing metode IDropTarget harus memanggil metode IDropTargetHelper yang sesuai untuk meneruskan informasi ke objek pembantu seret dan letakkan. Metode IDropTargetHelper kelima, IDropTargetHelper::Show, memberi tahu objek pembantu seret dan letakkan untuk menampilkan atau menyembunyikan gambar seret. Metode ini digunakan saat menyeret jendela target dalam mode video kedalaman warna rendah. Ini memungkinkan target untuk menyembunyikan gambar seret saat melukis jendela.