Cara kerja clipboard dan seret-dan-lepas — menangani transfer data OLE dengan benar di aplikasi bisnis
· Diperbarui pada: · Go Komura · Windows, Clipboard, Seret dan lepas, OLE, COM, Pengembangan Windows, WinForms, WPF
Riwayat revisi (6 pembaruan, terakhir pada 31 Aug 2026)
Catatan perubahan yang dilakukan pada artikel ini. Jika versi sebelumnya telah diarsipkan, versi itu tetap dapat dibaca melalui tautan permanen dengan DOI.
- Diterjemahkan ulang sebagai terjemahan lengkap dari naskah Jepang. Versi bahasa Indonesia sebelumnya adalah ringkasan yang hanya memindahkan sebagian naskah, sehingga bagian, tabel, gambar Mermaid, keterangan gambar, dan FAQ tidak ada. Semuanya dipulihkan sesuai naskah Jepang, dan klaim teknisnya sama dengan versi Jepang.
- Memeriksa ulang seluruh relasi peta pengetahuan dan memperbaiki relasi yang tidak sesuai dengan teks penjelasan (arah terbalik, generalisasi berlebihan, predikat tertukar). Penjelasan di badan artikel tidak diubah.
- Memeriksa ulang seluruh relasi peta pengetahuan dan memperbaiki relasi yang tidak sesuai dengan teks penjelasan (arah terbalik, generalisasi berlebihan, predikat tertukar). Penjelasan di badan artikel tidak diubah.
- Memeriksa ulang seluruh relasi peta pengetahuan dan memperbaiki relasi yang tidak sesuai dengan teks penjelasan (arah terbalik, generalisasi berlebihan, predikat tertukar). Penjelasan di badan artikel tidak diubah.
- Memeriksa ulang seluruh relasi peta pengetahuan dan memperbaiki relasi yang tidak sesuai dengan teks penjelasan (arah terbalik, generalisasi berlebihan, predikat tertukar). Penjelasan di badan artikel tidak diubah.
- Mengubah relasi peta pengetahuan dari "kebijakan riwayat clipboard mencegah clipboard" menjadi "mencegah pengambilan ke riwayat dan sinkronisasi antarperangkat". Tempel biasa tetap berfungsi. Penjelasan di badan artikel tidak diubah.
- Publikasi pertama
Mengutip artikel ini(DOI (arsip terdaftar): 10.5281/zenodo.22176605)
DOI di bawah mengarah ke versi yang telah diarsipkan sebelumnya dan mungkin berbeda dari teks saat ini. Gunakan URL halaman ini untuk merujuk teks saat ini.
Go Komura (2026). Cara kerja clipboard dan seret-dan-lepas — menangani transfer data OLE dengan benar di aplikasi bisnis. KomuraSoft LLC. https://comcomponent.com/id/blog/windows-clipboard-drag-drop-ole-data-transfer/
- DOI (arsip terdaftar)
- 10.5281/zenodo.22176605
- DOI (versi terakhir yang didaftarkan)
- 10.5281/zenodo.22176606
“Tabel yang disalin dari Excel berantakan pemformatannya saat ditempel. Kami ingin bisa menempel sebagai tabel.” “Isi yang disalin di aplikasi kami menjadi aneh ketika ditempel ke Word.” “Kami ingin bisa menerima berkas lewat seret dan lepas.” — Dalam konsultasi perbaikan aplikasi bisnis, permintaan seputar salin-dan-tempel serta seret dan lepas (D&D) adalah hal yang rutin muncul.
Justru karena dianggap “fitur yang sudah pasti ada”, cara kerjanya sering tidak diketahui. Jika clipboard dianggap “kotak untuk satu data”, sulit menjelaskan mengapa salinan yang sama hasilnya berbeda tergantung tujuan tempel, atau mengapa menempel gagal setelah aplikasi sumber ditutup. Clipboard yang sebenarnya adalah mekanisme yang menaruh isi yang sama dalam beberapa format sekaligus, lalu sisi tempel memilih format yang dipahaminya.
Seret dan lepas, pada intinya, adalah transfer data OLE yang menyerahkan representasi data yang sama persis dengan clipboard (IDataObject) lewat antarmuka COM. Dengan kata lain, salin-tempel dan D&D adalah saudara: jika satu dipahami dengan benar, yang lain langsung terlihat.
Artikel ini ditujukan kepada staf IT di perusahaan kecil dan menengah serta pengembang aplikasi Windows. Ia merangkai, dalam satu gambaran, cara kerja format clipboard, praktik di sisi tempel dan sisi salin, cara mengawasi yang benar, kebijakan pengelolaan riwayat clipboard, sinkronisasi awan, dan RDP, serta struktur dan jebakan seret-dan-lepas OLE.
1. Kesimpulan lebih dulu
- Clipboard adalah satu area yang dipakai bersama oleh aplikasi di desktop yang sama (window station), dan yang ditaruh di sana bukan “satu data” melainkan isi yang sama dalam beberapa format sekaligus. Sesi berbeda seperti RDP pada dasarnya punya clipboard sendiri; fitur pengalihan yang menjembatani keduanya. Karena tujuan tempel memilih format yang dipahaminya, salinan yang sama hasilnya berbeda tergantung ke mana ia ditempel.12
- Untuk teks, pakai CF_UNICODETEXT. CF_TEXT adalah ANSI yang bergantung pada code page, dan di lingkungan Jepang ia menjadi sumber karakter rusak. Sistem mengonversi keduanya secara implisit, tetapi yang benar adalah sisi Unicode.3
- Berkas diserahkan sebagai CF_HDROP (larik path yang diakhiri double-NUL), dan teks berformat memakai format terdaftar “HTML Format”. HTML Format punya struktur khas: teks UTF-8 dengan header offset byte.45
- Penyebab “aplikasi sumber ditutup lalu tidak bisa menempel” adalah delayed rendering. Mekanisme ini menaruh janji “akan dibuat ketika diminta”, bukan isi data. Jika perwujudan saat berakhir dilalaikan (respons terhadap WM_RENDERALLFORMATS, atau OleFlushClipboard untuk OLE), menempel tidak bisa dilakukan.26
- Perlakukan data yang ditempel sebagai masukan tidak tepercaya dari luar. Microsoft sendiri menyatakan dengan tegas bahwa “data clipboard tidak tepercaya. Parse dengan hati-hati”.7
- Untuk mengawasi, satu-satunya pilihan adalah AddClipboardFormatListener + WM_CLIPBOARDUPDATE. Jangan memakai polling atau SetClipboardViewer lama (rantai viewer). Format terdaftar untuk menjaga rahasia agar tidak masuk riwayat dan sinkronisasi (ExcludeClipboardContentFromMonitorProcessing dan semacamnya) juga disediakan.81
- Riwayat clipboard (Win+V) dan sinkronisasi awan adalah objek pengelolaan IT. Keduanya dapat dikendalikan dengan AllowClipboardHistory dan AllowCrossDeviceClipboard lewat GPO/Intune (Policy CSP), dan pengalihan clipboard RDP punya kebijakan khusus.91011
- Seret dan lepas, pada intinya, adalah COM. IDataObject yang sama dengan clipboard diserahkan antara IDropSource (sumber seret) dan IDropTarget (tujuan lepas) lewat loop DoDragDrop. RegisterDragDrop mensyaratkan inisialisasi dengan OleInitialize (STA).1213
- Berkas tidak bisa dilepas dari File Explorer berhak biasa ke aplikasi yang di-elevate. Penyebabnya UIPI (pemblokiran pesan menurut tingkat integritas), dan ini kendala yang harus diketahui sejak tahap desain.14
Berikut ini ditelusuri dari fondasi clipboard secara berurutan.
Pada diagram, garis utuh menunjukkan relasi yang selalu berlaku dan garis putus-putus menunjukkan relasi bersyarat (syaratnya ada pada penjelasan masing-masing relasi di halaman rincian). Daftar lengkap relasi (total 20, beserta bukti dan tingkat kepastian) serta definisi konsep utama dikumpulkan di halaman rincian peta pengetahuan (dalam bahasa Jepang). Data: JSON-LD / Turtle
2. Apa sebenarnya clipboard — bukan “satu data”, melainkan “beberapa format untuk isi yang sama”
Clipboard adalah mekanisme berbagi data bersama yang dapat diakses semua aplikasi yang memakai desktop yang sama (lebih tepatnya per window station: sesi pengguna berbeda atau sesi RDP masing-masing punya clipboard sendiri. Salin-tempel lewat RDP berhasil karena fitur pengalihan menjembatani keduanya — Bab 7). Prinsip utamanya adalah dipicu pengguna: sikap desain resmi adalah tidak menaruh atau mengambil data di belakang pengguna.1
Poin pentingnya: operasi salin tidak menaruh “satu data”. Jendela yang menyalin mengosongkan clipboard, lalu menaruh beberapa format berurutan, mengekspresikan isi yang sama dari format yang lebih kaya ke yang lebih miskin.2 Misalnya, ketika tabel disalin di aplikasi spreadsheet, secara konseptual hal-hal berikut ada sekaligus.
| Urutan prioritas | Format | Isi |
|---|---|---|
| 1 | Format privat aplikasi | Representasi internal lengkap, termasuk rumus dan pemformatan (untuk menempel kembali ke aplikasi yang sama) |
| 2 | HTML Format | Fragmen HTML yang menjaga struktur tabel dan pemformatan |
| 3 | CSV | Teks yang dibatasi sel |
| 4 | CF_UNICODETEXT | Teks biasa yang dipisah tab |
| 5 | Format gambar | Bitmap tampilan tabel |
Sisi tempel memilih format yang dipahaminya dari daftar itu, lalu mengambilnya. Menempel ke Word menghasilkan tabel berformat, menempel ke Notepad menghasilkan teks dipisah tab — karena format yang dipilih keduanya berbeda. “Hasil berbeda tergantung tujuan tempel” bukan bug, melainkan konsekuensi normal dari mekanisme ini.
flowchart TB
accTitle: Mengapa salinan yang sama hasilnya berbeda tergantung tujuan tempel
accDescr: Sisi salin menaruh isi yang sama dalam beberapa format di clipboard, lalu sisi tempel memilih format yang dipahaminya, sehingga Word menjadi tabel berformat dan Notepad menjadi teks dipisah tab
copy["Sisi salin: aplikasi spreadsheet"] --> cb["Clipboard (beberapa format untuk isi yang sama)"]
cb --> f1["Format privat aplikasi"]
cb --> f2["HTML Format"]
cb --> f3["CSV"]
cb --> f4["CF_UNICODETEXT"]
f2 -->|"Dipilih Word"| word["Tabel berformat"]
f4 -->|"Dipilih Notepad"| notepad["Teks dipisah tab"]
Sebaliknya, keluhan di awal tentang “pemformatan berantakan” atau “yang menempel aneh” hampir semuanya dapat dikembalikan ke cara memilih atau menyediakan format di salah satu sisi. Sisi tempel dibahas di Bab 4, sisi salin di Bab 5.
3. Format standar dan format terdaftar — CF_UNICODETEXT, CF_HDROP, HTML Format
3.1. Format standar — untuk teks, pakai sisi Unicode
Format yang sudah didefinisikan OS disebut format standar. Yang sering muncul di aplikasi bisnis adalah daftar berikut.3
| Format | Nilai | Isi |
|---|---|---|
| CF_TEXT | 1 | Teks ANSI (bergantung pada code page) |
| CF_UNICODETEXT | 13 | Teks Unicode. Untuk teks, yang benar adalah ini |
| CF_HDROP | 15 | Daftar path berkas (handle HDROP) |
| CF_DIB | 8 | Bitmap independen perangkat |
| CF_LOCALE | 16 | Pengenal locale yang terkait dengan teks |
CF_TEXT dan CF_UNICODETEXT dikonversi secara implisit oleh sistem (format sintetis). Konversi kode karakter saat itu memakai code page yang terkait dengan CF_LOCALE.3 Jika mengandalkan konversi, karakter yang tidak dapat diwakili di sisi ANSI (misalnya simbol khusus Unicode atau karakter gabungan) hilang. Karena itu prinsipnya: aplikasi membaca dan menulis hanya CF_UNICODETEXT (DataFormats.UnicodeText di .NET).
flowchart LR
accTitle: Konversi implisit CF_UNICODETEXT dan CF_TEXT
accDescr: Aplikasi hanya membaca dan menulis CF_UNICODETEXT; CF_TEXT disintesis sistem lewat konversi implisit dengan code page CF_LOCALE. Karakter yang tidak dapat diwakili sisi ANSI hilang dalam konversi ini
apprw["Baca-tulis aplikasi"] --> uni["CF_UNICODETEXT (yang benar)"]
uni <-->|"Sistem mengonversi secara implisit (code page CF_LOCALE)"| ansi["CF_TEXT (ANSI, bergantung pada code page)"]
ansi -.-> loss["Karakter yang tidak dapat diwakili hilang saat konversi (sumber karakter rusak)"]
3.2. CF_HDROP — berkas diserahkan sebagai “daftar path”
Yang dipakai saat berkas disalin di File Explorer, atau saat berkas diseret dan dilepas, adalah CF_HDROP. Isinya bukan badan berkas, melainkan blok memori yang berisi header struktur DROPFILES, diikuti larik string path lengkap yang dipisah karakter NUL, dengan string kosong di akhir (“double-NUL terminated”). pFiles di header menunjukkan offset awal daftar path, dan fWide menunjukkan apakah string Unicode.4
[Header DROPFILES: pFiles=offset awal daftar path, fWide=1(Unicode)]
C:\data\a.txt(NUL)C:\data\b.txt(NUL)(NUL)
Di kode native, path diambil satu per satu dengan DragQueryFile; di .NET diterima sebagai string[] lewat DataFormats.FileDrop. Poin “yang diserahkan hanya path, bukan badan berkas” juga berlaku di D&D pada Bab 8–9.
flowchart TB
accTitle: Struktur blok memori CF_HDROP
accDescr: Di awal memori global ada struktur DROPFILES; pFiles adalah offset awal daftar path, fWide menunjukkan Unicode. Lalu path lengkap dipisah NUL berjajar, diakhiri string kosong (double-NUL). Yang diserahkan hanya path, bukan badan berkas
hdr["Struktur DROPFILES (pFiles = offset awal daftar / fWide = 1)"] --> p1["C:\\data\\a.txt + NUL"]
p1 --> p2["C:\\data\\b.txt + NUL"]
p2 --> tail["String kosong di akhir (double-NUL)"]
hdr -.-> note["Yang diserahkan hanya path, bukan badan berkas"]
3.3. Format terdaftar — RegisterClipboardFormat dan “HTML Format”
Untuk data yang tidak dapat diwakili format standar, aplikasi dapat mendaftarkan format sendiri dengan menentukan nama. Jika nama diserahkan ke RegisterClipboardFormat, ID format dikembalikan, dan pendaftaran dengan nama yang sama di aplikasi lain mengembalikan ID yang sama, sehingga data dapat dibagi antaraplikasi asal namanya disepakati.1 Untuk menyerahkan data terstruktur di antara aplikasi internal, pakai nama yang tidak bentrok seperti KomuraSoft.Report.RowData.
Wakil format terdaftar adalah “HTML Format” untuk teks berformat (bersama RTF, ini dua format teks kaya utama). Isinya teks UTF-8, tetapi strukturnya khas: header yang mencantumkan offset byte di bagian depan.5
Version:0.9
StartHTML:<posisi byte awal HTML keseluruhan>
EndHTML:<posisi byte akhir HTML keseluruhan>
StartFragment:<posisi byte awal fragmen>
EndFragment:<posisi byte akhir fragmen>
<html><body>
<!--StartFragment--><b>Tebal</b> teks fragmen<!--EndFragment-->
</body></html>
Setiap offset adalah posisi byte dari awal data, termasuk header itu sendiri. Praktik standar adalah menyediakan ruang dengan lebar tetap (misalnya 10 digit), merakit badan, lalu menulis kembali nilai terukur. StartFragment/EndFragment menunjukkan awal dan akhir “fragmen yang benar-benar dipilih pengguna” dalam satuan byte (bukan satuan karakter). Di UTF-8 yang memuat bahasa Jepang, jumlah karakter dan jumlah byte tidak sama, sehingga jika perhitungan offset salah, awal atau akhir terpotong saat menempel di aplikasi lain. Jika HTML Format dibuat sendiri, header harus diisi dengan posisi byte setelah dienkode ke UTF-8.5
flowchart TB
accTitle: Hubungan header HTML Format dan offset
accDescr: StartHTML dan EndHTML di header menunjuk HTML keseluruhan, StartFragment dan EndFragment menunjuk fragmen yang dipilih pengguna, semuanya sebagai posisi byte dari awal data. Di UTF-8 jumlah karakter dan byte tidak sama, jadi isi dengan posisi byte yang diukur setelah enkode
header["Header (Version / StartHTML / EndHTML / StartFragment / EndFragment)"] --> html["HTML keseluruhan (StartHTML–EndHTML)"]
html --> frag["Fragmen yang dipilih (StartFragment–EndFragment)"]
header -.-> byte["Setiap offset = posisi byte dari awal data (ukur setelah enkode UTF-8, lalu tulis kembali)"]
Selain itu, untuk data tabular, CSV (DataFormats.CommaSeparatedValue di .NET) juga sering dipakai. Untuk interoperabilitas dengan Excel, sediakan HTML Format (berformat), CSV (nilai saja), dan CF_UNICODETEXT (dipisah tab) bersama-sama agar tujuan tempel tidak perlu dipilih.
4. Praktik sisi tempel — prioritas format dan validasi
4.1. Cari dari format yang lebih kaya
Format di clipboard diurutkan sesuai urutan penempatan sisi salin (= urutan kekayaan representasi). Dasar sisi tempel adalah mencari, dari yang paling kaya informasi di antara format yang dapat ditangani. Di Win32, enumerasi dilakukan dengan EnumClipboardFormats lalu format pertama yang dikenali dipakai, atau daftar prioritas sendiri diserahkan ke GetPriorityClipboardFormat.2
Di .NET, percabangannya seperti berikut.
// Tempel tabel: cari dari yang kaya ke yang biasa
var data = Clipboard.GetDataObject();
if (data is null) return;
// Meski mengaku format tertentu, isinya belum tentu string. Pakai cabang ini
// hanya jika tipe terkonfirmasi; jika tidak, jatuhkan ke kandidat berikutnya
if (data.GetDataPresent(DataFormats.Html)
&& data.GetData(DataFormats.Html) is string html)
{
// Validasi header HTML Format, lalu ambil sebagai tabel
}
else if (data.GetDataPresent(DataFormats.CommaSeparatedValue))
{
// Ambil sebagai CSV
}
else if (data.GetDataPresent(DataFormats.UnicodeText))
{
// Ambil sebagai teks dipisah tab
}
Itulah jawaban untuk keluhan di awal, “tabel Excel berantakan saat ditempel”. Struktur tabel tidak sampai ke aplikasi yang hanya membaca teks biasa. Format mana saja yang diterima adalah keputusan desain sisi tempel.
flowchart TB
accTitle: Percabangan tempel, mencari dari yang lebih kaya
accDescr: Jika HTML Format ada dan isinya string, ambil sebagai tabel; jika tidak, CSV; jika itu pun tidak ada, teks dipisah tab. Jika tidak ada kandidat, tolak
startsel["Mulai menempel"] --> h{"Ada HTML Format dan isinya string?"}
h -->|"Ya"| useh["Validasi header, lalu ambil sebagai tabel"]
h -->|"Tidak"| c{"Ada CSV?"}
c -->|"Ya"| usec["Ambil sebagai CSV"]
c -->|"Tidak"| t{"Ada UnicodeText?"}
t -->|"Ya"| uset["Ambil sebagai teks dipisah tab"]
t -->|"Tidak"| giveup["Tidak diterima"]
4.2. Data tempel adalah masukan eksternal
Sering terlewat: isi clipboard adalah data dari luar, tanpa diketahui aplikasi mana yang menaruhnya. Microsoft juga memperingatkan di dokumentasi clipboard OLE: “data clipboard tidak tepercaya. Parse dengan hati-hati sebelum dipakai aplikasi”.7
- Validasi bahwa offset header HTML Format tidak menunjuk di luar rentang (aplikasi yang mengeluarkan header rusak memang ada).
- Nilai yang diambil sebagai angka, tanggal, atau kode harus melewati validasi yang sama dengan masukan layar.
- Pasang pertahanan terhadap data raksasa. Desainnya: meski gambar ratusan MB atau teks jutaan baris ditempel, UI tidak diblokir, dan ditolak jika melewati batas. Perhatian: GetData di .NET, pada saat dipanggil (termasuk memicu delayed rendering), mewujudkan seluruh data sampai string terkelola, jadi memeriksa ukuran setelah GetData bukan pertahanan. Memeriksa HGLOBAL yang dikembalikan GetClipboardData di Win32 dengan GlobalSize dapat menahan tahap “jangan lanjutkan konversi/parse ke string terkelola untuk data raksasa”, tetapi untuk format delayed rendering GetClipboardData itu sendiri memicu rendering, jadi perwujudan di sumber salinan tidak dapat dicegah. Agar UI tidak membeku, pindahkan pengambilan ke luar thread UI (dalam kasus itu pun Clipboard .NET mensyaratkan STA, jadi jangan thread pool Task.Run (MTA); pakai thread khusus yang disetel STA — bagian 5.1).
Cara pikir “nilai yang masuk dari luar, apa pun jalurnya, divalidasi dulu baru dipakai” sama dengan yang disusun di “Jangan memakai nilai hasil baca QR code begitu saja”. Anggapan bahwa menempel aman karena itu operasi pengguna adalah sumber insiden.
flowchart LR
accTitle: Alur memvalidasi data tempel sebelum dipakai
accDescr: Data yang diambil dari clipboard dilewatkan berurutan lewat konfirmasi keberadaan format, konfirmasi tipe isi, batas ukuran, dan validasi isi; jika gagal di salah satu tahap, ditolak atau dijatuhkan ke format kandidat berikutnya
present["Konfirmasi keberadaan format (GetDataPresent)"] --> type["Konfirmasi tipe isi (is string / string[])"]
type --> size["Konfirmasi batas ukuran"]
size --> content["Validasi isi (header, path, nilai)"]
content --> ok["Ambil"]
type -.->|"Tipe berbeda"| rej["Tolak / ke format kandidat berikutnya"]
size -.->|"Terlalu besar"| rej
content -.->|"Tidak sah"| rej
5. Praktik sisi salin — menyediakan beberapa format sekaligus dan delayed rendering
5.1. Menaruh beberapa format sekaligus
Praktik sisi salin adalah kebalikan 4.1: menyediakan format kaya dan format biasa secara bersamaan. Dengan DataObject WinForms/WPF, itu dapat ditulis dalam beberapa baris.15
// WinForms (System.Windows.Forms). WPF juga bentuk yang sama dengan DataObject/Clipboard di System.Windows
var data = new DataObject();
data.SetData(DataFormats.Html, htmlFormatText); // string HTML Format berheader
data.SetData(DataFormats.CommaSeparatedValue, csv); // CSV
data.SetData(DataFormats.UnicodeText, plainText); // teks biasa
Clipboard.SetDataObject(data, copy: true); // copy:true = tetap ada setelah aplikasi berakhir
Dua catatan. Pertama, kelas Clipboard .NET hanya dapat dipakai dari thread STA.15 Thread UI WinForms/WPF sudah STA berkat [STAThread], jadi biasanya tidak bermasalah, tetapi menyentuhnya dari thread latar gagal (dasar STA/MTA ada di “Pengetahuan dasar COM STA/MTA”). Kedua, arti copy: true terkait delayed rendering di bagian berikutnya.
5.2. Delayed rendering — penyebab “ditutup lalu tidak bisa menempel”
Membuat data besar dalam banyak format setiap kali adalah pemborosan, jadi clipboard punya mekanisme delayed rendering. Jika handle data SetClipboardData diisi NULL, yang didaftarkan bukan isi data melainkan janji “akan dibuat ketika diminta”; ketika seseorang meminta format itu, WM_RENDERFORMAT sampai ke sumber salinan, dan data baru dibuat saat itu.2
Konsekuensi mekanisme ini adalah “aplikasi sumber ditutup lalu tidak bisa menempel” di awal artikel. Sumber salinan, sebelum berakhir, menerima WM_RENDERALLFORMATS dan berkewajiban mewujudkan semua format yang belum dirender; jika berakhir tanpa itu, format tersebut hilang.2
flowchart TB
accTitle: Alur delayed rendering dan "ditutup lalu tidak bisa menempel"
accDescr: Sumber salin hanya mendaftarkan janji dengan handle NULL, lalu mewujudkan data dengan WM_RENDERFORMAT ketika ada permintaan. Saat berakhir, ia berkewajiban mewujudkan semua format dengan WM_RENDERALLFORMATS; jika dilalaikan, format itu hilang
promise["Sumber salin: hanya mendaftarkan janji dengan SetClipboardData(format, NULL)"] --> req["Sisi tempel meminta format itu"]
req --> render["WM_RENDERFORMAT → data dibuat di tempat"]
promise --> quit["Sumber salin akan berakhir"]
quit -->|"Diwujudkan dengan WM_RENDERALLFORMATS"| ok["Bisa menempel setelah berakhir"]
quit -->|"Perwujudan dilalaikan"| lost["Format itu hilang (ditutup lalu tidak bisa menempel)"]
Pada clipboard OLE (cara menaruh IDataObject dengan OleSetClipboard), hubungan ini lebih jelas. Yang dipegang clipboard hanyalah pointer ke objek data, dan memanggil OleFlushClipboard saat aplikasi berakhir mewujudkan data di clipboard, sehingga menempel tetap bisa setelah berakhir.6 Clipboard.SetDataObject(data, copy: true) di .NET adalah yang menentukan gerakan “tetap ada setelah berakhir” ini.
Ketika rentang besar disalin di Excel lalu aplikasi akan ditutup, muncul pertanyaan “Ada informasi besar di clipboard. Apakah akan disimpan?” — itu konfirmasi apakah pemrosesan penentuan (flush) ini dijalankan. Jika delayed rendering dipakai di aplikasi sendiri, ingat bahwa pemrosesan penentuan saat berakhir adalah satu paket. Delayed rendering adalah optimasi kinerja, dan permintaan rendering berjalan secara sinkron selama pemrosesan pesan, jadi ada juga trade-off UI membeku untuk data yang lama dibuat.2
6. Praktik mengawasi clipboard — listener, coba ulang, pengecualian riwayat
6.1. Pakai AddClipboardFormatListener
Untuk kebutuhan seperti “mendeteksi nilai pemindai barcode atau salinan dari sistem inti lalu mengambilnya otomatis”, pengawasan perubahan clipboard diperlukan. Secara historis ada tiga cara, tetapi jawaban yang benar saat ini hanya satu.8
| Cara | Penilaian |
|---|---|
| Membaca berkala dengan timer (polling) | Banyak pemborosan dan bisa terlewat. Jangan dipakai |
| SetClipboardViewer (rantai viewer) | Gangguan di satu aplikasi dalam rantai merusak keseluruhan. Hanya tersisa untuk kompatibilitas mundur |
| AddClipboardFormatListener | Direkomendasikan. WM_CLIPBOARDUPDATE sampai ke jendela yang didaftarkan |
flowchart LR
accTitle: Alur pengawasan clipboard
accDescr: Daftarkan dengan AddClipboardFormatListener saat handle dibuat, lalu WM_CLIPBOARDUPDATE sampai setiap kali ada aplikasi yang menyalin. Pembacaan dilakukan dengan coba ulang, dan dilepas secara simetris dengan RemoveClipboardFormatListener saat handle dihancurkan
created["OnHandleCreated: AddClipboardFormatListener"] --> wait["Menunggu"]
anyapp["Ada aplikasi yang menyalin"] --> notify["WM_CLIPBOARDUPDATE sampai"]
wait --> notify
notify --> readtry["Baca dengan coba ulang (bagian 6.2)"]
readtry --> wait
destroyed["OnHandleDestroyed: RemoveClipboardFormatListener"] -.->|"Dilepas secara simetris"| created
// Implementasi minimum di WinForms
public partial class MainForm : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
const int WM_CLIPBOARDUPDATE = 0x031D;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
AddClipboardFormatListener(Handle);
}
protected override void OnHandleDestroyed(EventArgs e)
{
// Lepas secara simetris mengikuti penghancuran/pembuatan ulang handle
RemoveClipboardFormatListener(Handle);
base.OnHandleDestroyed(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CLIPBOARDUPDATE)
{
// Di sini baca Clipboard.GetDataObject() dan ambil jika formatnya diperlukan
}
base.WndProc(ref m);
}
}
6.2. Coba ulang jika tidak bisa dibuka
Yang dapat membuka clipboard hanya satu jendela pada satu waktu; selama proses lain membukanya, OpenClipboard gagal.2 Tepat setelah WM_CLIPBOARDUPDATE diterima, sering kali sumber salinan atau aplikasi pengawas lain sedang beroperasi, jadi kegagalan baca sementara adalah peristiwa normal. Selalu masukkan beberapa kali coba ulang dengan jeda singkat (puluhan milidetik). Overload kelas Clipboard .NET yang dapat menentukan jumlah dan interval coba ulang hanya ada di sisi tulis, SetDataObject. Sisi baca (GetDataObject dan semacamnya) tidak memilikinya, jadi tulis sendiri kode yang menangkap ExternalException di WinForms atau COMException di WPF, lalu menunggu dan mencoba lagi.
flowchart LR
accTitle: Alur coba ulang pembacaan clipboard
accDescr: Yang dapat membuka clipboard hanya satu jendela pada satu waktu, jadi pembacaan tepat setelah notifikasi perubahan dapat gagal karena bersaing dengan proses lain. Jika ada pengecualian, tunggu puluhan milidetik lalu coba lagi; jika batas tercapai, batalkan kali ini dan ambil pada pembaruan berikutnya
upd["WM_CLIPBOARDUPDATE"] --> tryread["Coba membaca"]
tryread -->|"Berhasil"| useok["Ke pengambilan (validasi Bab 4)"]
tryread -->|"Gagal (jendela lain sedang memakai)"| waitretry["Jeda puluhan milidetik"]
waitretry -->|"Coba lagi hingga beberapa kali"| tryread
waitretry -->|"Batas tercapai"| giveup2["Batalkan kali ini (ambil pada pembaruan berikutnya)"]
6.3. Jangan masukkan ke riwayat dan sinkronisasi — pertimbangan fitur salin yang menangani rahasia
Windows punya riwayat clipboard (Win+V) dan sinkronisasi antarperangkat (clipboard awan), dan data yang ditaruh aplikasi secara default menjadi sasarannya. Aplikasi yang menaruh rahasia seperti kata sandi atau nomor rekening pada fitur salin ikut menaruh format terdaftar untuk dikecualikan dari riwayat dan sinkronisasi.1
- ExcludeClipboardContentFromMonitorProcessing: jika ini ditaruh, seluruh isi salinan itu tidak masuk riwayat maupun sinkronisasi.
- CanIncludeInClipboardHistory (DWORD 0): hanya menahan riwayat.
- CanUploadToCloudClipboard (DWORD 0): hanya menahan sinkronisasi antarperangkat.
Alasan kata sandi yang disalin pengelola kata sandi tidak tertinggal di Win+V adalah mekanisme ini. Cukup serahkan nama ke RegisterClipboardFormat untuk mendapatkan ID format, lalu setel berdampingan dengan data biasa, sehingga layak diimplementasikan di aplikasi bisnis yang menangani rahasia.
7. Clipboard dari sudut pandang IT — pengendalian riwayat, sinkronisasi awan, dan RDP
Sedikit menjauh dari pengembangan, poin dari sudut pandang administrator. Riwayat clipboard menumpuk isi salinan terbaru, dan clipboard awan menyinkronkan isi salinan antarperangkat yang masuk dengan akun Microsoft / Microsoft Entra yang sama.10 Di sisi lain yang nyaman, residu dan lintas batas informasi terjadi: data pribadi yang disalin dari sistem inti menumpuk di riwayat, atau isi yang disalin di PC dinas tersinkron ke PC pribadi.
Kebijakan pengendalian di organisasi ada dua berikut.
| Sasaran pengendalian | GPO (Konfigurasi Komputer > Templat Administratif > Sistem > Kebijakan OS) | Policy CSP (Intune) | Bawaan |
|---|---|---|---|
| Riwayat clipboard | Izinkan riwayat clipboard | Experience/AllowClipboardHistory | Izinkan |
| Sinkronisasi antarperangkat | Izinkan sinkronisasi clipboard antarperangkat | Privacy/AllowCrossDeviceClipboard | Izinkan |
Keduanya tersedia di Windows 10 versi 1809 dan yang lebih baru. Jika dinonaktifkan, item terkait di aplikasi Pengaturan menjadi abu-abu, dan kebijakan berlaku segera.910
Yang rutin lainnya adalah pengalihan clipboard RDP (Remote Desktop). Secara default salin-tempel berjalan antara PC lokal dan sesi jarak jauh, sehingga dapat menjadi jalur membawa keluar rahasia di server. Kebijakan “Jangan izinkan pengalihan clipboard” (nilai registri fDisableClip) dapat memblokir kedua arah.11 Windows Server / Windows 11 belakangan juga menambah kebijakan yang lebih halus, misalnya membatasi hanya arah server ke klien dan hanya teks. Melarang total atau membatasi bertahap diputuskan dengan menyeimbangkan operasi dan keamanan.
flowchart LR
accTitle: Jalur penyebaran isi clipboard dan titik pengendalian
accDescr: Isi yang disalin secara default menjadi sasaran riwayat dan sinkronisasi awan, dan di RDP berpindah ke sesi lain lewat pengalihan. Masing-masing dapat dikendalikan dengan kebijakan, dan sisi aplikasi dapat mengeluarkannya dari riwayat dan sinkronisasi dengan format pengecualian
cb["Clipboard"] --> hist["Riwayat (Win+V)"]
cb --> cloud["Sinkronisasi awan → perangkat lain"]
cb --> rdp["Pengalihan RDP → sesi lain"]
hist -.-> p1["Pengendalian: AllowClipboardHistory"]
cloud -.-> p2["Pengendalian: AllowCrossDeviceClipboard"]
rdp -.-> p3["Pengendalian: fDisableClip"]
cb -.-> p4["Sisi aplikasi: kecualikan dengan ExcludeClipboardContentFromMonitorProcessing dll. (bagian 6.3)"]
8. Seret dan lepas, pada intinya, adalah COM — IDataObject + IDropSource + IDropTarget
8.1. Data yang sama dengan clipboard, cara angkut yang berbeda
OLE seret-dan-lepas bergerak dengan tiga peran berikut.12
| Peran | Yang mengimplementasikan | Tugas |
|---|---|---|
| IDataObject | Sumber seret | Isi data yang diangkut. Objek data beberapa format yang sama dengan clipboard |
| IDropSource | Sumber seret | Keputusan lanjut/batal seret dan umpan balik kursor |
| IDropTarget | Tujuan lepas | Menyatakan diterima atau tidak dan menerima di DragEnter/DragOver/DragLeave/Drop |
Ketika sumber seret memanggil DoDragDrop, loop seret dimulai. Ketika mouse masuk ke jendela tujuan lepas, notifikasi sampai ke IDropTarget-nya, dan saat lepas IDataObject diserahkan. Dokumentasi resmi juga menyatakan: “D&D menyediakan fungsi yang sama persis dengan salin-dan-tempel clipboard. Jika aplikasi sudah mengimplementasikan salin-tempel, tambahannya sedikit”.12 Artinya DataObject beberapa format yang dibuat di Bab 2–5 langsung menjadi muatan D&D.
flowchart LR
accTitle: Alur seret-dan-lepas OLE
accDescr: Sumber seret memanggil DoDragDrop dengan IDataObject sebagai muatan sehingga loop seret dimulai; IDropTarget tujuan lepas menyatakan diterima atau tidak di DragEnter dan DragOver, lalu di Drop memilih format dari IDataObject dan mengambilnya
src["Sumber seret: IDataObject + IDropSource"] -->|"DoDragDrop"| loop["Loop seret"]
loop -->|"Mouse masuk jendela"| enter["IDropTarget.DragEnter/DragOver (nyatakan Effect setiap kali)"]
enter -->|"Tombol dilepas"| drop["IDropTarget.Drop"]
drop --> data["Pilih format dari IDataObject dan ambil"]
8.2. OleInitialize (STA) wajib
Jendela yang menjadi tujuan lepas didaftarkan dengan RegisterDragDrop, tetapi di sini ada jebakan klasik. Jika COM diinisialisasi dengan CoInitialize/CoInitializeEx, RegisterDragDrop selalu gagal dengan E_OUTOFMEMORY, dan harus diinisialisasi dengan OleInitialize.13 OleInitialize menginisialisasi COM sebagai STA, karena D&D berakar pada dunia STA berupa jendela dan message pump. Thread pemanggil juga wajib menjalankan message pump; jika dilalaikan, aplikasi lain yang sedang menyeret hang.13 Latar belakang ini adalah pembahasan model thread di “Pengetahuan dasar COM STA/MTA”.
Di aplikasi WinForms/WPF, kerangka kerja menggantikan inisialisasi OLE dan implementasi antarmuka, sehingga pengembang cukup menulis event.
// WinForms: menerima lepas berkas
listView1.AllowDrop = true;
listView1.DragEnter += (s, e) =>
{
// Konfirmasi juga bahwa sisi sumber mengizinkan Copy (ada sumber yang hanya mengizinkan Move/Link)
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
&& (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy
? DragDropEffects.Copy // dapat diterima: terima sebagai salinan
: DragDropEffects.None; // tidak dapat diterima
};
listView1.DragDrop += (s, e) =>
{
// Data seret juga masukan eksternal. Meski mengaku FileDrop, isinya bisa null
// atau tipe lain, dan pengambilan itu sendiri bisa gagal
object data;
try { data = e.Data.GetData(DataFormats.FileDrop); }
catch (COMException) { return; }
if (data is not string[] paths) return;
foreach (var path in paths)
{
// Validasi path, lalu ambil (bagian 9.3)
}
};
Di WPF strukturnya sama: terima dengan AllowDrop="True" pada elemen dan event DragOver/Drop, lalu ambil larik path dengan e.Data.GetData(DataFormats.FileDrop). Menyatakan diterima atau tidak (Effect) setiap kali di DragEnter/DragOver adalah cara IDropTarget; jika ini dihilangkan, kursor tetap “dilarang” dan tidak berubah — itu bug-nya.
9. Jebakan D&D — elevasi, Move, validasi path
9.1. Tidak bisa melepas ke aplikasi yang di-elevate sebagai administrator
Berkas yang dilepas dari File Explorer ke aplikasi “Jalankan sebagai administrator” tidak bereaksi — ini bukan kesalahan implementasi, melainkan spesifikasi OS. UIPI (User Interface Privilege Isolation) secara default memblokir pesan dari proses tingkat integritas lebih rendah ke jendela tingkat integritas lebih tinggi, sehingga notifikasi lepas dari File Explorer berhak biasa (integritas sedang) tidak sampai ke aplikasi elevated.14
flowchart LR
accTitle: Cara UIPI memblokir lepas ke aplikasi elevated
accDescr: Notifikasi lepas dari File Explorer integritas sedang ke aplikasi elevated integritas tinggi secara default diblokir UIPI dan tidak sampai. Jika UI tetap pada hak biasa dan pemrosesan istimewa dipisah, lepas sampai
explorer["File Explorer (integritas sedang)"] -->|"Notifikasi lepas"| uipi{"UIPI"}
uipi -->|"Diblokir (default)"| elevated["Aplikasi elevated (integritas tinggi): tidak bereaksi"]
uipi -->|"Lolos"| normal["UI hak biasa: lepas sampai"]
normal -.->|"Hanya minta pemrosesan istimewa"| broker["Proses terpisah untuk pekerjaan yang membutuhkan elevasi"]
Ada solusi yang mengizinkan pesan tertentu seperti WM_DROPFILES satu per satu dengan ChangeWindowMessageFilterEx,14 tetapi yang lolos hanya notifikasi lepas lama (WM_DROPFILES); OLE D&D secara keseluruhan tidak terselesaikan. Pedoman praktis jelas: berhenti merancang aplikasi agar selalu berjalan elevated. Jika hanya pekerjaan yang membutuhkan elevasi dipisah ke proses lain, badan UI tetap pada hak biasa dan dapat menerima D&D (desain pemisahan diuraikan di “Hak administrator aplikasi Windows dan proses broker”).
9.2. Arti DragDropEffects — Move adalah kontrak “sumber hilang”
Copy/Move/Link pada DragDropEffects bukan hiasan, melainkan kontrak antara sumber seret dan tujuan lepas. Sumber seret menyatakan himpunan efek yang diizinkan di DoDragDrop, tujuan lepas memilih efek aktual, dan jika Move terbentuk, sumber seret menghapus data (berkas) — itu aturannya. Jika sisi terima tanpa pikir panjang mengembalikan Move, terjadi insiden “berkas sumber hilang setelah dilepas”. Untuk keperluan pengambilan di aplikasi bisnis, sisi terima secara eksplisit menyatakan Copy adalah default yang aman.
flowchart LR
accTitle: Kontrak DragDropEffects — pada Move, sumber hilang
accDescr: Sumber seret menyatakan himpunan efek yang diizinkan di DoDragDrop, tujuan lepas memilih efek aktual. Jika Move terbentuk, sumber seret menghapus berkas, jadi untuk pengambilan sisi terima secara eksplisit menyatakan Copy agar aman
srcdecl["Sumber seret: menyatakan efek yang diizinkan (Copy | Move | Link)"] --> tgtsel["Tujuan lepas: memilih efek aktual"]
tgtsel -->|"Copy"| copyok["Berkas sumber tetap ada (sisi aman untuk pengambilan)"]
tgtsel -->|"Move"| moveact["Sumber seret menghapus berkas — sumber insiden sumber hilang"]
9.3. Validasi path yang dilepas
Yang diserahkan dengan CF_HDROP/FileDrop hanya path (bagian 3.2). Sebelum diambil, lewatkan validasi sebagai masukan eksternal, sama seperti tempel.
- Berkas atau folder: tentukan sebagai spesifikasi kasus folder dilepas utuh (ambil secara rekursif, atau tolak).
- Placeholder OneDrive: jika path ada tetapi badan berkas tidak lokal (“berkas sesuai permintaan”), unduhan berjalan pada saat dibuka, dan gagal jika luring. Perilaku dan penanganannya ada di “OneDrive Files On-Demand dan aplikasi bisnis”.
- Path panjang dan path khusus: path di atas MAX_PATH, path jaringan (UNC), path di media lepas — konfirmasi dulu apakah pemrosesan lanjutan dapat menanganinya sebelum diterima.
- Jumlah dan ukuran total: agar UI tidak membeku saat ribuan berkas dilepas, buat pengambilan asinkron, dan sediakan batas serta tampilan progres.
10. Ringkasan
- Clipboard adalah mekanisme yang menaruh isi yang sama dalam beberapa format sekaligus di satu area yang dipakai bersama di dalam desktop yang sama (window station). Karena tujuan tempel memilih format, hasil salinan yang sama berubah.
- Teks adalah CF_UNICODETEXT, berkas adalah CF_HDROP, teks berformat adalah HTML Format terdaftar (header offset byte + UTF-8).
- Sisi tempel mencari format dari yang kaya ke yang biasa, dan memvalidasi isi sebagai masukan eksternal. Sisi salin menyediakan beberapa format sekaligus, dan jika delayed rendering dipakai, implementasikan sampai penentuan saat berakhir (WM_RENDERALLFORMATS/OleFlushClipboard).
- Pengawasan memakai AddClipboardFormatListener + WM_CLIPBOARDUPDATE. Siapkan coba ulang untuk persaingan OpenClipboard, dan kecualikan rahasia dari riwayat dan sinkronisasi dengan ExcludeClipboardContentFromMonitorProcessing dan semacamnya.
- IT dapat mengendalikan riwayat clipboard, sinkronisasi awan, dan pengalihan RDP dengan GPO/Intune. Default semuanya izinkan, jadi di lingkungan yang menangani rahasia putuskan secara sadar.
- D&D, pada intinya, adalah COM; IDataObject yang sama dengan clipboard diserahkan oleh IDropSource/IDropTarget. RegisterDragDrop mensyaratkan OleInitialize (STA).
- Lepas ke aplikasi elevated diblokir UIPI. Move pada DragDropEffects adalah kontrak “sumber hilang”; validasi path yang dilepas sebelum diambil.
Salin-tempel dan D&D, bagi pengguna, seperti udara. Justru karena itu, pengalaman memburuk besar ketika “tidak bisa menempel”, “berantakan”, atau “hilang” terjadi; sebaliknya, aplikasi yang menyediakan beberapa format dan menerima lepas dengan baik membuat operasi harian lebih lancar. Semoga ini menjadi bahan pertimbangan saat memikirkan prioritas perbaikan.
Artikel terkait
- Apa itu COM / ActiveX / OCX — merangkum perbedaan dan hubungannya
- Pengetahuan dasar COM STA/MTA — model thread dan cara menghindari hang
- Integrasi shell Windows saat ini — menu klik kanan, asosiasi berkas, dan perubahan di Windows 11
- Masalah EXCEL.EXE tersisa saat mengoperasikan Excel dari C# — pola pelepasan referensi COM dan keputusan penggantian
- Desain UX aplikasi Windows — prioritas menurut lingkungan pemakaian
- OneDrive Files On-Demand dan aplikasi bisnis — asumsi yang dipecah placeholder dan penanganannya
Area konsultasi terkait
Di 合同会社小村ソフト, kami menangani desain dan implementasi dukungan salin-dan-tempel serta seret-dan-lepas pada aplikasi bisnis (penyediaan beberapa format, integrasi Excel, pengambilan lepas berkas), investigasi penyebab gangguan seperti “berantakan saat ditempel” atau “salinan hilang”, otomasi masukan dengan pengawasan clipboard, dan implementasi penanganan riwayat serta sinkronisasi untuk informasi rahasia. Kasus yang melibatkan lapisan bawah COM atau OLE juga boleh dimulai dari pemisahan gejalanya.
- Pengembangan aplikasi Windows
- Pengembangan komponen COM
- Konsultasi teknis dan tinjauan desain
- Kontak
Tautan referensi
-
Microsoft Learn, Clipboard Formats. Tentang jendela yang dapat menaruh informasi yang sama dalam beberapa format clipboard, format terdaftar lewat RegisterClipboardFormat (pendaftaran nama yang sama mengembalikan nilai yang sama dan dapat dibagi antaraplikasi), format sintetis, serta pengecualian dari riwayat clipboard / sinkronisasi awan dengan ExcludeClipboardContentFromMonitorProcessing, CanIncludeInClipboardHistory, dan CanUploadToCloudClipboard. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Clipboard Operations. Tentang clipboard yang hanya dapat dibuka satu jendela pada satu waktu, menaruh dari format yang lebih kaya saat menyalin, pemilihan format saat menempel dengan EnumClipboardFormats/GetPriorityClipboardFormat, delayed rendering dengan menyerahkan NULL ke SetClipboardData serta kewajiban WM_RENDERFORMAT/WM_RENDERALLFORMATS, dan trade-off delayed rendering. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Standard Clipboard Formats. Tentang definisi format standar seperti CF_TEXT (ANSI), CF_UNICODETEXT, CF_HDROP, CF_DIB, CF_LOCALE, dan bahwa CF_TEXT serta CF_UNICODETEXT dikonversi secara implisit oleh sistem memakai code page yang terkait dengan CF_LOCALE. ↩ ↩2 ↩3
-
Microsoft Learn, Shell Clipboard Formats. Tentang CF_HDROP yang terdiri dari struktur DROPFILES dan larik string path lengkap double-NUL terminated, pengambilan path satu per satu dengan DragQueryFile, dan bahwa format shell CFSTR_ memerlukan pendaftaran lewat RegisterClipboardFormat. ↩ ↩2
-
Microsoft Learn, HTML Clipboard Format. Tentang nama terdaftar “HTML Format”, struktur header yang punya offset (satuan byte) seperti Version, StartHTML, EndHTML, StartFragment, EndFragment, bahwa encoding selalu UTF-8, dan konvensi komentar StartFragment/EndFragment. ↩ ↩2 ↩3
-
Microsoft Learn, OleFlushClipboard function (ole2.h). Tentang OleSetClipboard yang hanya membuat clipboard memegang pointer ke objek data, OleFlushClipboard yang mewujudkan data di clipboard sehingga menempel tetap bisa setelah aplikasi berakhir, dan bahwa jika tidak perlu disisakan saat berakhir seharusnya dikosongkan dengan OleSetClipboard(NULL). ↩ ↩2
-
Microsoft Learn, OleGetClipboard function (ole2.h). Tentang cara mendapatkan IDataObject dari clipboard, dan peringatan bahwa “data clipboard tidak tepercaya, jadi harus di-parse dengan hati-hati sebelum dipakai aplikasi”. ↩ ↩2
-
Microsoft Learn, Using the clipboard. Tentang perbandingan tiga cara mengawasi clipboard (jendela viewer, nomor urut, format listener), bahwa program baru seharusnya memakai listener AddClipboardFormatListener, bahwa rantai viewer rapuh terhadap kegagalan menjaga rantai, dan bahwa nomor urut tidak boleh dipakai untuk polling. ↩ ↩2
-
Microsoft Learn, Policy CSP - Experience. Tentang izin/larangan riwayat clipboard dengan kebijakan Experience/AllowClipboardHistory, ketersediaan di Windows 10 versi 1809 dan yang lebih baru, default mengizinkan, serta bahwa di GPO dipetakan di bawah “Sistem > Kebijakan OS” dan perubahan berlaku segera. ↩ ↩2
-
Microsoft Learn, Policy CSP - Privacy. Tentang izin/larangan sinkronisasi clipboard antarperangkat dengan kebijakan Privacy/AllowCrossDeviceClipboard, bahwa sinkronisasi terjadi antarperangkat yang masuk dengan akun Microsoft / Microsoft Entra yang sama, dan default mengizinkan. ↩ ↩2 ↩3
-
Microsoft Learn, Policy CSP - ADMX_TerminalServer. Tentang TS_CLIENT_CLIPBOARD (“Jangan izinkan pengalihan clipboard”, nilai registri fDisableClip) yang dapat melarang berbagi clipboard lokal/jarak jauh pada sesi Remote Desktop, dan bahwa secara default pengalihan diizinkan. ↩ ↩2
-
Microsoft Learn, Drag and Drop (COM). Tentang OLE seret-dan-lepas yang bergerak dengan tiga pihak IDropSource (sumber seret), IDropTarget (tujuan lepas), dan DoDragDrop (loop yang disediakan OLE), bahwa ia menyediakan fungsi yang sama dengan salin-dan-tempel clipboard sehingga aplikasi yang sudah mengimplementasikan salin-tempel tinggal menambah sedikit, serta jenis umpan balik. ↩ ↩2 ↩3
-
Microsoft Learn, RegisterDragDrop function (ole2.h). Tentang cara mendaftarkan jendela tujuan lepas dan IDropTarget, bahwa jika COM diinisialisasi dengan CoInitialize/CoInitializeEx selalu gagal dengan E_OUTOFMEMORY dan OleInitialize diperlukan, serta bahwa aplikasi sumber seret hang jika thread pemanggil tidak menjalankan message pump. ↩ ↩2 ↩3
-
Microsoft Learn, ChangeWindowMessageFilterEx function (winuser.h). Tentang UIPI sebagai mekanisme keamanan yang secara default memblokir penerimaan pesan dari pengirim tingkat integritas lebih rendah, dan bahwa filter pesan per jendela dapat mengizinkan pesan tertentu (MSGFLT_ALLOW). ↩ ↩2 ↩3
-
Microsoft Learn, How to add data to the Clipboard (Windows Forms). Tentang cara menaruh data beberapa format sekaligus dengan DataObject dan Clipboard.SetDataObject, bahwa seharusnya ditambah dalam beberapa format agar aplikasi lain mengenalinya, dan bahwa kelas Clipboard hanya dapat dipakai dari thread STA sehingga [STAThread] diperlukan. ↩ ↩2
Artikel terkait
Artikel terbaru dengan tag yang sama untuk mendalami topik-topik terdekat.
Apa sebenarnya "Tidak Merespons" — cara Windows menilai aplikasi hang, dan desain agar tidak hang
"Tidak Merespons" di Windows adalah mekanisme OS: jika jendela tidak mengambil pesan selama 5 detik, OS menilainya hang dan menggantinya ...
Pengantar aksesibilitas aplikasi Windows — bersiap menghadapi UI Automation dan kewajiban akomodasi wajar
Dengan latar belakang amandemen Undang-Undang Penghapusan Diskriminasi terhadap Penyandang Disabilitas yang berlaku April 2024, artikel i...
Integrasi shell Windows saat ini ── menu klik kanan, asosiasi file, dan perubahan di Windows 11
Mengapa di Windows 11 item menu klik kanan tersembunyi di balik "Tampilkan opsi selengkapnya": dari dasar asosiasi ekstensi → ProgID → ve...
API thread pool Win32 — konkurensi tanpa membuat thread, lewat CreateThreadpoolWork
Apakah kode native masih menumpuk CreateThread? Artikel ini menjelaskan API thread pool Win32 yang didesain ulang di Vista: empat objek w...
Named pipe dalam praktik — IPC andalan Windows, dari desain sampai keamanan
Penjelasan praktis named pipe, IPC andalan di Windows. Dari sumber primer: memilih mode byte versus mode pesan, desain server yang menang...
Topik terkait
Halaman-halaman ini menempatkan topik dalam konteks layanan dan keputusan yang lebih luas.
Topik teknis Windows
Portal tentang pengembangan Windows, investigasi bug, dan pemanfaatan aset yang ada.
Migrasi ActiveX
Keputusan untuk mempertahankan, membungkus, atau mengganti komponen COM / ActiveX / OCX.
Thread UI dan timer
Thread UI WPF / WinForms, alur asinkron, Dispatcher, dan desain timer.
Layanan yang terkait dengan topik ini
Artikel ini berkaitan langsung dengan layanan berikut.
Pengembangan aplikasi Windows
Aplikasi bisnis, integrasi perangkat, dan alat komunikasi, dari kebutuhan hingga pengembangan.
Pemanfaatan ulang dan migrasi aset yang ada
Pemanfaatan ulang dan migrasi aset COM / ActiveX / OCX serta dependensi 32/64-bit.
Pertanyaan yang sering diajukan
Pertanyaan yang sering muncul dalam konsultasi tentang topik artikel ini.
- Mengapa tabel yang disalin dari Excel berantakan pemformatannya ketika ditempel ke aplikasi kita?
- Clipboard tidak menyimpan "satu data". Isi yang sama ditaruh sekaligus dalam beberapa format (format privat aplikasi, HTML Format, CSV, teks Unicode, dan sebagainya), lalu aplikasi tujuan memilih format yang dipahaminya dan mengambilnya. Jika pemformatan berantakan, penyebab khasnya adalah sisi tempel hanya membaca teks biasa (CF_UNICODETEXT). Agar struktur tabel ikut diterima, implementasikan sisi tempel agar lebih dulu mengambil HTML Format atau CSV. Sebaliknya, jika salinan dari aplikasi sendiri harus menempel dengan benar di aplikasi lain, sediakan format kaya dan format biasa secara bersamaan saat menyalin.
- Mengapa menempel gagal setelah aplikasi sumber salinan ditutup?
- Karena sumber memakai delayed rendering. Aplikasi yang menangani data besar tidak menaruh isi data saat menyalin; mereka hanya mendaftarkan janji di clipboard bahwa data akan "dibuat ketika diminta". Jika sumber keluar tanpa mewujudkan data sebagai respons terhadap WM_RENDERALLFORMATS saat berakhir, format yang belum dirender hilang. Aplikasi yang memakai clipboard OLE (IDataObject) dapat menjaga agar menempel tetap bisa setelah keluar dengan memanggil OleFlushClipboard saat berakhir agar data diwujudkan.
- Bagaimana aplikasi sendiri dapat mengawasi perubahan clipboard?
- Cara yang saat ini direkomendasikan adalah mendaftarkan jendela sendiri sebagai listener dengan AddClipboardFormatListener, lalu menangani pesan WM_CLIPBOARDUPDATE yang datang setiap kali isi berubah. Polling isi dengan timer banyak membuang kerja, dan rantai viewer lama berbasis SetClipboardViewer hanya dipertahankan untuk kompatibilitas mundur karena gangguan di satu aplikasi dalam rantai merusak seluruh rantai. Perhatikan juga bahwa OpenClipboard saat membaca dapat gagal karena bersaing dengan proses lain, jadi implementasikan coba ulang dengan jeda singkat agar pembacaan stabil.
- Ada cara agar rahasia seperti kata sandi tidak tertinggal di riwayat clipboard (Win+V)?
- Ada dua jalur: sisi aplikasi dan sisi kebijakan. Di sisi aplikasi, jika format terdaftar ExcludeClipboardContentFromMonitorProcessing ditaruh bersama saat menyalin, isi itu tidak masuk riwayat maupun sinkronisasi antarperangkat. Pengendalian terpisah juga bisa dengan CanIncludeInClipboardHistory (hanya riwayat) dan CanUploadToCloudClipboard (hanya sinkronisasi). Pengelola kata sandi memakai mekanisme ini. Jika ingin mematikannya untuk seluruh organisasi, riwayat dan sinkronisasi awan itu sendiri dapat dinonaktifkan dengan AllowClipboardHistory dan AllowCrossDeviceClipboard lewat Group Policy atau Intune (Policy CSP).
- Mengapa berkas tidak bisa diseret dan dilepas ke aplikasi yang dijalankan sebagai administrator?
- Karena mekanisme keamanan UIPI (User Interface Privilege Isolation) memblokir pengiriman pesan dari proses dengan tingkat integritas lebih rendah ke jendela dengan tingkat integritas lebih tinggi. File Explorer berjalan dengan hak biasa (integritas sedang), jadi notifikasi seret-dan-lepas tidak sampai ke jendela aplikasi yang di-elevate. Ada solusi yang mengizinkan pesan seperti WM_DROPFILES satu per satu dengan ChangeWindowMessageFilterEx, tetapi itu hanya berlaku untuk notifikasi drop lama. Pendekatan yang benar adalah berhenti merancang aplikasi agar selalu berjalan elevated, dan memisahkan hanya pekerjaan yang membutuhkan elevasi ke proses lain.
Profil penulis
Halaman perkenalan penulis artikel.
Go Komura
Direktur KomuraSoft LLC
Berspesialisasi dalam pengembangan perangkat lunak Windows, konsultasi teknis, dan investigasi bug, terutama pada proyek dengan sistem yang sudah ada dan bug yang sulit direproduksi.