क्लिपबोर्ड और ड्रैग एंड ड्रॉप कैसे काम करते हैं — व्यावसायिक ऐप में OLE डेटा ट्रांसफ़र सही सँभालना
· Go Komura · Windows, क्लिपबोर्ड, ड्रैग एंड ड्रॉप, OLE, COM, Windows विकास, WinForms, WPF
“Excel से कॉपी की तालिका चिपकाने पर फ़ॉर्मेटिंग बिखर जाती है। हम चाहते हैं कि तालिका के रूप में चिपके।” “हमारे ऐप में कॉपी की सामग्री Word में चिपकाने पर कुछ अजीब हो जाती है।” “हम फ़ाइलें ड्रैग एंड ड्रॉप से लेना चाहते हैं।” — व्यावसायिक-ऐप परिवर्तनों पर परामर्श बातचीत में, कॉपी-एंड-पेस्ट और ड्रैग एंड ड्रॉप (D&D) के आसपास के अनुरोध नियमित हैं।
ठीक इसलिए कि ये “वे सुविधाएँ हैं जिन्हें सब स्वाभाविक मानते हैं”, वे वास्तव में कैसे काम करती हैं आश्चर्यजनक रूप से कम ज्ञात है। यदि क्लिपबोर्ड को “वह डिब्बा जिसमें एक टुकड़ा डेटा रखते हैं” सोचें, तो नहीं समझा सकते कि वही कॉपी चिपकाने की जगह के अनुसार भिन्न परिणाम क्यों देती है, या स्रोत ऐप बंद करने के बाद चिपकाना क्यों रुक जाता है। वास्तविक क्लिपबोर्ड वह तंत्र है जो एक ही सामग्री कई फ़ॉर्मेट में एक साथ रखता है, और चिपकाने वाले पक्ष को वह फ़ॉर्मेट चुनने देता है जिसे वह समझता है।
और ड्रैग एंड ड्रॉप, मूल में, OLE डेटा ट्रांसफ़र है जो ठीक वही डेटा प्रतिनिधित्व जो क्लिपबोर्ड का है (IDataObject), COM इंटरफ़ेस से सौंपता है। अर्थात्, कॉपी-एंड-पेस्ट और D&D भाई-बहन हैं: एक सही समझें तो दूसरा वहीं है।
यह लेख छोटे और मझोले उद्यमों के IT कर्मचारियों और Windows ऐप डेवलपरों के लिए है। यह एक चित्र में बाँधता है कि क्लिपबोर्ड फ़ॉर्मेट कैसे काम करते हैं, चिपकाने वाले पक्ष और कॉपी पक्ष की प्रथाएँ, क्लिपबोर्ड देखने का सही तरीका, क्लिपबोर्ड इतिहास, क्लाउड सिंक, और RDP की प्रशासनिक नीतियाँ, तथा OLE ड्रैग एंड ड्रॉप की संरचना और जाल।
1. निष्कर्ष पहले
- क्लिपबोर्ड एक ही डेस्कटॉप (विंडो स्टेशन) के ऐप द्वारा साझा एकल क्षेत्र है, और वहाँ जो बैठता है वह “एक टुकड़ा डेटा” नहीं बल्कि एक ही सामग्री कई फ़ॉर्मेट में एक साथ है। RDP जैसा भिन्न सेशन मूलतः भिन्न क्लिपबोर्ड रखता है; रीडायरेक्शन सुविधा दोनों को जोड़ती है। क्योंकि गंतव्य वह फ़ॉर्मेट चुनता है जिसे समझता है, वही कॉपी चिपकाने की जगह के अनुसार भिन्न परिणाम देती है।12
- पाठ के लिए CF_UNICODETEXT उपयोग करें। CF_TEXT ANSI और कोड-पेज निर्भर है, और जापानी सिस्टम पर mojibake का प्रजनन स्थल है। सिस्टम दोनों के बीच निहित रूपांतरण करता है, पर प्रामाणिक पक्ष यूनिकोड है।3
- फ़ाइलें CF_HDROP (पथों की डबल-NUL-समाप्त सरणी) के रूप में चलती हैं, और फ़ॉर्मेटेड पाठ पंजीकृत फ़ॉर्मेट “HTML Format” उपयोग करता है। HTML Format असामान्य संरचना रखता है: बाइट ऑफ़सेट के हेडर वाला UTF-8 पाठ।45
- “स्रोत ऐप बंद किया और चिपकाना बंद हो गया” का वास्तविक कारण विलंबित रेंडरिंग है। यह तंत्र पेलोड नहीं, केवल “माँगे जाने पर बनाने” का वादा रखता है; यदि निकास पर मूर्त करना छोड़ें (WM_RENDERALLFORMATS का उत्तर, या OLE के लिए OleFlushClipboard), चिपकाना रुक जाता है।26
- चिपकाए डेटा को बाहर से अविश्वसनीय इनपुट मानें। Microsoft स्वयं साफ़ कहता है कि “क्लिपबोर्ड डेटा विश्वसनीय नहीं। उसे सावधानी से पार्स करें”।7
- क्लिपबोर्ड देखने के लिए, AddClipboardFormatListener + WM_CLIPBOARDUPDATE एकमात्र विकल्प है। पोलिंग उपयोग न करें, और पुराना SetClipboardViewer (व्यूअर श्रृंखला) उपयोग न करें। रहस्यों को इतिहास और सिंक से बाहर रखने वाले पंजीकृत फ़ॉर्मेट (ExcludeClipboardContentFromMonitorProcessing और साथी) भी दिए गए हैं।81
- क्लिपबोर्ड इतिहास (Win+V) और क्लाउड सिंक IT-प्रबंधन चिंता हैं। उन्हें GPO / Intune (Policy CSP) से AllowClipboardHistory और AllowCrossDeviceClipboard से नियंत्रित कर सकते हैं, और RDP क्लिपबोर्ड रीडायरेक्शन की अपनी समर्पित नीति है।91011
- ड्रैग एंड ड्रॉप COM है। क्लिपबोर्ड जैसा वही IDataObject IDropSource (ड्रैग स्रोत) और IDropTarget (ड्रॉप लक्ष्य) के बीच DoDragDrop लूप से सौंपा जाता है। RegisterDragDrop को OleInitialize (STA) से आरंभीकरण चाहिए।1213
- साधारण-विशेषाधिकार File Explorer से ऊँचे ऐप पर ड्रॉप नहीं कर सकते। UIPI (अखंडता स्तर से संदेश अवरोध) कारण है, और यह बाधा डिज़ाइन समय जाननी चाहिए।14
नीचे इसे क्लिपबोर्ड की बुनियाद से चलते हैं।
2. क्लिपबोर्ड वास्तव में क्या है — “एक टुकड़ा डेटा” नहीं, “एक ही सामग्री कई फ़ॉर्मेट में”
क्लिपबोर्ड एक सामान्य डेटा-साझा तंत्र है जिसे एक ही डेस्कटॉप साझा करने वाला हर ऐप पहुँच सकता है (अधिक सटीक, यह प्रति विंडो स्टेशन है: भिन्न उपयोगकर्ता सेशन या RDP सेशन प्रत्येक अपना क्लिपबोर्ड रखते हैं। RDP पर कॉपी-एंड-पेस्ट काम करता है क्योंकि रीडायरेक्शन सुविधा दोनों को जोड़ती है — अध्याय 7)। पहला सिद्धांत यह है कि यह उपयोगकर्ता-चालित है: आधिकारिक डिज़ाइन रुख है कि उपयोगकर्ता की पीठ पीछे डेटा न रखें न निकालें।1
महत्त्वपूर्ण बिंदु यह है कि कॉपी “एक टुकड़ा डेटा” नहीं रखती। कॉपी करने वाली विंडो क्लिपबोर्ड खाली करती है और फिर कई फ़ॉर्मेट पंक्ति में रखती है, एक ही सामग्री को अधिक सक्षम फ़ॉर्मेट से कम सक्षम तक व्यक्त करते हुए।2 उदाहरण के लिए, स्प्रेडशीट में तालिका कॉपी करने पर, अवधारणात्मक रूप से क्लिपबोर्ड पर एक साथ कुछ ऐसा होता है।
| प्राथमिकता | फ़ॉर्मेट | सामग्री |
|---|---|---|
| 1 | ऐप-निजी फ़ॉर्मेट | सूत्र और फ़ॉर्मेटिंग सहित पूर्ण आंतरिक प्रतिनिधित्व (उसी ऐप में वापस चिपकाने के लिए) |
| 2 | HTML Format | तालिका संरचना और फ़ॉर्मेटिंग रखने वाला HTML खंड |
| 3 | CSV | सेल-सीमांकित पाठ |
| 4 | CF_UNICODETEXT | टैब-अलग सादा पाठ |
| 5 | छवि फ़ॉर्मेट | तालिका कैसी दिखती है उसका बिटमैप |
चिपकाने वाला पक्ष इस सूची से वह फ़ॉर्मेट चुनता है जिसे समझता है और उसे निकालता है। Word में चिपकाएँ तो फ़ॉर्मेटेड तालिका मिलती है; Notepad में चिपकाएँ तो टैब-अलग पाठ — क्योंकि दोनों ने भिन्न फ़ॉर्मेट चुने। “परिणाम चिपकाने की जगह पर निर्भर करता है” बग नहीं; इस डिज़ाइन का सामान्य परिणाम है।
flowchart TB
accTitle: वही कॉपी चिपकाने की जगह के अनुसार भिन्न परिणाम क्यों देती है
accDescr: कॉपी पक्ष एक ही सामग्री क्लिपबोर्ड पर कई फ़ॉर्मेट में रखता है, और चिपकाने वाला पक्ष वह फ़ॉर्मेट चुनता है जिसे समझता है, इसलिए Word को फ़ॉर्मेटेड तालिका मिलती है और Notepad को टैब-अलग पाठ
copy["कॉपी: स्प्रेडशीट"] --> cb["क्लिपबोर्ड(कई फ़ॉर्मेट)"]
cb --> rich["अधिक समृद्ध फ़ॉर्मेट"]
cb --> plain["अधिक सादे फ़ॉर्मेट"]
rich --> f1["ऐप-निजी"]
rich --> f2["HTML Format"]
plain --> f3["CSV"]
plain --> f4["CF_UNICODETEXT"]
f2 -->|"Word"| word["फ़ॉर्मेटेड तालिका"]
f4 -->|"Notepad"| notepad["टैब-अलग पाठ"]
चित्र 1: वही कॉपी गंतव्य के चुने फ़ॉर्मेट के अनुसार भिन्न परिणाम देती है; “बिखर जाता है” अक्सर फ़ॉर्मेट चुनाव की समस्या है।
उलटा कहें, शुरुआती शिकायतें — “फ़ॉर्मेटिंग बिखर जाती है”, “कुछ अजीब चिपकता है” — लगभग सब एक पक्ष के फ़ॉर्मेट चुनने, या दूसरे पक्ष के उन्हें देने, की समस्या पर आती हैं। अध्याय 4 चिपकाने वाला पक्ष कवर करता है; अध्याय 5 कॉपी पक्ष।
3. मानक फ़ॉर्मेट और पंजीकृत फ़ॉर्मेट — CF_UNICODETEXT, CF_HDROP, HTML Format
3.1. मानक फ़ॉर्मेट — पाठ के लिए यूनिकोड पक्ष उपयोग करें
जो फ़ॉर्मेट OS पहले से परिभाषित करता है उन्हें मानक फ़ॉर्मेट कहते हैं। व्यावसायिक ऐप में लगातार दिखने वाले निम्नलिखित हैं।3
| फ़ॉर्मेट | मान | सामग्री |
|---|---|---|
| CF_TEXT | 1 | ANSI पाठ(कोड-पेज निर्भर) |
| CF_UNICODETEXT | 13 | यूनिकोड पाठ। यह पाठ का प्रामाणिक फ़ॉर्मेट है |
| CF_HDROP | 15 | फ़ाइल पथों की सूची(HDROP हैंडल) |
| CF_DIB | 8 | डिवाइस-स्वतंत्र बिटमैप |
| CF_LOCALE | 16 | पाठ से जुड़ा लोकैल पहचानकर्ता |
CF_TEXT और CF_UNICODETEXT सिस्टम द्वारा एक-दूसरे में निहित रूपांतरित होते हैं (संश्लेषित फ़ॉर्मेट)। वर्ण-कोड रूपांतरण CF_LOCALE से जुड़े कोड पेज उपयोग करता है।3 उस रूपांतरण पर भरोसा करना वे वर्ण गिराता है जिन्हें ANSI व्यक्त नहीं कर सकता (उदाहरण के लिए केवल-यूनिकोड प्रतीक और संयोजन वर्ण), इसलिए नियम है ऐप जो पढ़े और लिखे उसे CF_UNICODETEXT (.NET में DataFormats.UnicodeText) पर एक करें।
flowchart TB
accTitle: CF_UNICODETEXT और CF_TEXT के बीच निहित रूपांतरण
accDescr: ऐप केवल CF_UNICODETEXT पढ़ता और लिखता है; सिस्टम CF_LOCALE कोड पेज से निहित रूपांतरण कर CF_TEXT संश्लेषित करता है। जो वर्ण ANSI व्यक्त न कर सके वे उस रूपांतरण में गिरते हैं
apprw["ऐप पढ़ता और लिखता है"] --> uni["CF_UNICODETEXT"]
uni <-->|"CF_LOCALE रूपांतरण"| ansi["CF_TEXT(ANSI)"]
ansi -.-> loss["अव्यक्त वर्ण गिरते हैं"]
चित्र 2: ऐप यूनिकोड पक्ष पर एक करे; ANSI रूपांतरण सिस्टम का है, और वहाँ वर्ण गिर सकते हैं।
3.2. CF_HDROP — फ़ाइलें “पथों की सूची” के रूप में चलती हैं
CF_HDROP वह है जो File Explorer में फ़ाइलें कॉपी करने, या फ़ाइलें ड्रैग एंड ड्रॉप करने पर उपयोग होता है। पेलोड फ़ाइलें स्वयं नहीं; वह मेमोरी ब्लॉक है जो एक “डबल-NUL-समाप्त” सरणी बिछाता है: DROPFILES संरचना हेडर के बाद, NUL वर्णों से अलग पूर्ण-पथ स्ट्रिंग, और अंत में खाली स्ट्रिंग। हेडर का pFiles पथ सूची का प्रारंभ ऑफ़सेट है, और fWide कहता है कि स्ट्रिंग यूनिकोड हैं या नहीं।4
[DROPFILES header: pFiles=start offset of the path list, fWide=1(Unicode)]
C:\data\a.txt(NUL)C:\data\b.txt(NUL)(NUL)
नेटिव कोड में उन्हें DragQueryFile से एक-एक निकालते हैं; .NET में DataFormats.FileDrop से string[] के रूप में पाते हैं। यह तथ्य कि “जो चलता है केवल पथ हैं, फ़ाइलें स्वयं नहीं” अध्याय 8 और 9 के D&D में फिर महत्त्व रखेगा।
flowchart TB
accTitle: CF_HDROP का मेमोरी-ब्लॉक लेआउट
accDescr: ग्लोबल मेमोरी के प्रारंभ पर DROPFILES संरचना बैठती है; pFiles पथ सूची का प्रारंभ ऑफ़सेट है और fWide कहता है यूनिकोड है या नहीं। फिर पूर्ण पथ NUL-अलग आते हैं, और ब्लॉक खाली स्ट्रिंग(डबल NUL)से खत्म होता है। जो चलता है केवल पथ हैं, फ़ाइलें नहीं
hdr["DROPFILES(pFiles / fWide)"] --> p1["C:\\data\\a.txt + NUL"]
p1 --> p2["C:\\data\\b.txt + NUL"]
p2 --> tail["खाली स्ट्रिंग(डबल NUL)"]
hdr -.-> note["केवल पथ चलते हैं, फ़ाइलें नहीं"]
चित्र 3: CF_HDROP फ़ाइलें नहीं ढोता; पथों की सूची ढोता है। आयात से पहले पथ सत्यापन अध्याय 9।
3.3. पंजीकृत फ़ॉर्मेट — RegisterClipboardFormat और “HTML Format”
जिस डेटा को मानक फ़ॉर्मेट व्यक्त न कर सकें, ऐप नाम चुनकर अपना फ़ॉर्मेट पंजीकृत कर सकता है। RegisterClipboardFormat को नाम दें तो फ़ॉर्मेट ID मिलता है; भिन्न ऐप से उसी नाम से पंजीकरण वही ID लौटाता है, इसलिए नाम पर सहमत होने पर ऐप के बीच डेटा साझा कर सकते हैं।1 अपने ऐप सूट में संरचित डेटा सौंपते समय ऐसा नाम उपयोग करें जो न टकराए, जैसे KomuraSoft.Report.RowData।
प्रतिनिधि पंजीकृत फ़ॉर्मेट “HTML Format” है, फ़ॉर्मेटेड पाठ के लिए (RTF के साथ, दो प्रमुख समृद्ध-पाठ फ़ॉर्मेट में से एक)। पेलोड UTF-8 पाठ है, पर असामान्य संरचना है: बाइट ऑफ़सेट गिनाने वाला हेडर आगे जुड़ा होता है।5
Version:0.9
StartHTML:<byte offset of the start of the whole HTML>
EndHTML:<byte offset of the end of the whole HTML>
StartFragment:<byte offset of the start of the fragment>
EndFragment:<byte offset of the end of the fragment>
<html><body>
<!--StartFragment--><b>bold</b> fragment text<!--EndFragment-->
</body></html>
हर ऑफ़सेट डेटा के प्रारंभ से बाइट स्थिति है, हेडर स्वयं सहित; सामान्य प्रथा है निश्चित चौड़ाई आरक्षित करना (उदाहरण के लिए 10 अंक) और बॉडी बनाने के बाद मापे मान वापस लिखना। StartFragment/EndFragment “उपयोगकर्ता ने वास्तव में चुना खंड” का प्रारंभ और अंत बाइट में चिह्नित करते हैं (वर्णों में नहीं)। जापानी सहित UTF-8 में, वर्ण संख्या और बाइट संख्या अलग हो जाती हैं, इसलिए यदि यह ऑफ़सेट गणना गलत हो, दूसरे ऐप में चिपकाना प्रारंभ या अंत गिरा देता है। यदि HTML Format स्वयं बनाएँ, हेडर को UTF-8 में एन्कोड करने के बाद मापी बाइट स्थितियों से भरना चाहिए।5
flowchart TB
accTitle: HTML Format हेडर ऑफ़सेट से कैसे संबंधित है
accDescr: हेडर के StartHTML और EndHTML पूरे HTML की ओर इशारा करते हैं, और StartFragment तथा EndFragment उपयोगकर्ता द्वारा चुने खंड की ओर, दोनों डेटा के प्रारंभ से बाइट स्थितियाँ हैं। UTF-8 में वर्ण संख्या और बाइट संख्या अलग होती हैं, इसलिए हेडर को एन्कोड के बाद मापी बाइट स्थितियों से भरें
header["हेडर(बाइट ऑफ़सेट)"] --> html["पूरा HTML"]
html --> frag["चुना खंड"]
header -.-> byte["ऑफ़सेट UTF-8 बाद बाइट हैं"]
चित्र 4: HTML Format ऑफ़सेट वर्ण नहीं बाइट हैं; UTF-8 में एन्कोड के बाद मापें, वरना चिपकाना कट जाता है।
CSV (.NET में DataFormats.CommaSeparatedValue) सारणीबद्ध डेटा के लिए भी सामान्य उपयोग होता है। Excel के साथ इंटरऑप के लिए, HTML Format (फ़ॉर्मेटिंग सहित), CSV (केवल मान), और CF_UNICODETEXT (टैब-अलग) एक साथ देने का अर्थ है एक ही चिपकाने का गंतव्य नहीं चुनना पड़ता।
4. चिपकाने वाले पक्ष की प्रथाएँ — फ़ॉर्मेट प्राथमिकता और सत्यापन
4.1. समृद्ध फ़ॉर्मेट से नीचे देखें
क्लिपबोर्ड पर फ़ॉर्मेट उस क्रम में पंक्तिबद्ध हैं जिस क्रम में कॉपी पक्ष ने उन्हें रखा (अर्थात् अधिक अभिव्यक्त से कम तक)। चिपकाने वाले पक्ष की आधाररेखा है जिन फ़ॉर्मेट को सँभाल सकते हैं उनमें से सबसे अधिक जानकारी वाले से देखना। Win32 में या तो EnumClipboardFormats से गिनें और पहला पहचाना फ़ॉर्मेट उपयोग करें, या अपनी प्राथमिकता सूची GetPriorityClipboardFormat को दें और उसे चुनने दें।2
.NET में शाखा कुछ ऐसी दिखती है।
// Pasting a table: look from rich to plain
var data = Clipboard.GetDataObject();
if (data is null) return;
// Advertising a format does not guarantee the payload is a string. Use this
// branch only when the type also checks out; otherwise fall through to the next candidate
if (data.GetDataPresent(DataFormats.Html)
&& data.GetData(DataFormats.Html) is string html)
{
// Validate the HTML Format header, then import as a table
}
else if (data.GetDataPresent(DataFormats.CommaSeparatedValue))
{
// Import as CSV
}
else if (data.GetDataPresent(DataFormats.UnicodeText))
{
// Import as tab-separated text
}
यही शुरुआती शिकायत का उत्तर है, “Excel तालिका चिपकाना बिखर जाता है”। केवल सादा पाठ पढ़ने वाला ऐप तालिका संरचना कभी नहीं पाता। फ़ॉर्मेट सूची कितनी नीचे तक स्वीकार करें यह चिपकाने वाले पक्ष का डिज़ाइन निर्णय है।
flowchart TB
accTitle: समृद्ध फ़ॉर्मेट से नीचे देखने वाली चिपकाने की शाखा
accDescr: यदि HTML Format मौजूद हो और पेलोड भी स्ट्रिंग हो, तालिका के रूप में आयात करें; अन्यथा CSV आज़माएँ; यदि वह भी न हो, टैब-अलग पाठ पर गिरें। यदि कोई उम्मीदवार मौजूद न हो, अस्वीकार करें
startsel["चिपकाना शुरू"] --> h{"HTML Format + स्ट्रिंग?"}
h -->|"हाँ"| useh["हेडर सत्यापित → तालिका"]
h -->|"नहीं"| c{"CSV मौजूद?"}
c -->|"हाँ"| usec["CSV के रूप में आयात"]
c -->|"नहीं"| t{"UnicodeText?"}
t -->|"हाँ"| uset["टैब-अलग पाठ"]
t -->|"नहीं"| giveup["अस्वीकार"]
चित्र 5: चिपकाने वाला पक्ष समृद्ध से सादे तक देखता है; केवल सादा पाठ पढ़ें तो तालिका संरचना कभी नहीं आती।
4.2. चिपकाया डेटा बाहरी इनपुट है
आसानी से छूटता है, पर क्लिपबोर्ड सामग्री बाहर का डेटा है, और नहीं जानते किस ऐप ने रखा। Microsoft OLE क्लिपबोर्ड दस्तावेज़ में भी चेताता है कि “क्लिपबोर्ड डेटा विश्वसनीय नहीं। ऐप में उपयोग से पहले सावधानी से पार्स करें”।7
- सत्यापित करें कि HTML Format हेडर ऑफ़सेट बफ़र के बाहर न इशारा करें (टूटे हेडर निकालने वाले ऐप मौजूद हैं)।
- जिन्हें संख्या, तिथि, या कोड के रूप में आयात करें वे स्क्रीन इनपुट जैसी ही सत्यापन से गुज़रें।
- विशाल डेटा के विरुद्ध बचाव लगाएँ। भले कोई सैकड़ों-मेगाबाइट छवि या लाखों पंक्तियाँ पाठ चिपकाए, UI ब्लॉक न करें, और सीमा पार होने पर अस्वीकार करें। सावधानी: .NET का GetData, जिस क्षण बुलाते हैं, पूरा पेलोड प्रबंधित स्ट्रिंग में मूर्त करता है (और विलंबित रेंडरिंग उसके भाग के रूप में चलती है), इसलिए GetData के बाद आकार जाँच बचाव नहीं। Win32 में, GetClipboardData द्वारा लौटे HGLOBAL पर GlobalSize जाँचना “प्रबंधित स्ट्रिंग के रूप में रूपांतरण और पार्सिंग में आगे न बढ़ें” के चरण पर बचाव देता है, पर विलंबित-रेंडरिंग फ़ॉर्मेट के लिए GetClipboardData स्वयं रेंडरिंग शुरू करता है, इसलिए कॉपी-स्रोत पक्ष पर मूर्तीकरण फिर भी नहीं रोक सकते। UI जमने से बचाने के लिए, लाना UI थ्रेड से हटाएँ (और तब भी, क्योंकि .NET का Clipboard STA माँगता है, Task.Run थ्रेड-पूल थ्रेड (MTA) पर नहीं, STA सेट समर्पित थ्रेड पर करें — खंड 5.1)।
यह विचार कि “बाहर से आने वाला मान, पथ जो भी हो, उपयोग से पहले सत्यापित होता है” वही है जो “QR कोड के डिकोड मान को ज्यों का त्यों कभी उपयोग न करें” में रखा गया है। यह धारणा कि चिपकाना सुरक्षित है क्योंकि यह उपयोगकर्ता क्रिया है, दुर्घटनाएँ कैसे शुरू होती हैं।
flowchart TB
accTitle: चिपकाए डेटा को उपयोग से पहले सत्यापित करें
accDescr: क्लिपबोर्ड से लिया डेटा फ़ॉर्मेट-मौजूद, पेलोड-प्रकार, आकार-सीमा, और सामग्री सत्यापन से उसी क्रम में गुज़रता है; कोई भी विफल हो तो अस्वीकार करें या अगले उम्मीदवार फ़ॉर्मेट पर गिरें
present["फ़ॉर्मेट मौजूद?"] --> type["पेलोड प्रकार ठीक?"]
type --> size["आकार सीमा में?"]
size --> content["सामग्री सत्यापित करें"]
content --> ok["आयात"]
type -.->|"गलत प्रकार"| rej["अस्वीकार / अगला फ़ॉर्मेट"]
size -.->|"बहुत बड़ा"| rej
content -.->|"अमान्य"| rej
चित्र 6: चिपकाना बाहरी इनपुट है; फ़ॉर्मेट, प्रकार, आकार और सामग्री सत्यापन न पास करें तो स्वीकार न करें।
5. कॉपी पक्ष की प्रथाएँ — कई फ़ॉर्मेट एक साथ देना, और विलंबित रेंडरिंग
5.1. कई फ़ॉर्मेट एक साथ रखें
कॉपी पक्ष की प्रथा 4.1 की उलटी है: समृद्ध फ़ॉर्मेट और सादा फ़ॉर्मेट एक साथ दें। WinForms/WPF DataObject से कुछ पंक्तियों में लिख सकते हैं।15
// WinForms (System.Windows.Forms). WPF is the same shape with System.Windows DataObject/Clipboard
var data = new DataObject();
data.SetData(DataFormats.Html, htmlFormatText); // HTML Format string including the header
data.SetData(DataFormats.CommaSeparatedValue, csv); // CSV
data.SetData(DataFormats.UnicodeText, plainText); // Plain text
Clipboard.SetDataObject(data, copy: true); // copy:true = keep after the app exits
दो नोट। पहला, .NET का Clipboard वर्ग केवल STA थ्रेड से उपयोग हो सकता है।15 WinForms/WPF UI थ्रेड [STAThread] के कारण STA है, इसलिए सामान्यतः समस्या नहीं, पर पृष्ठभूमि थ्रेड से छूना विफल होता है (STA/MTA की बुनियाद “COM STA/MTA की बुनियाद” में है)। दूसरा, copy: true का अर्थ अगले उपखंड की विलंबित रेंडरिंग से जुड़ा है।
5.2. विलंबित रेंडरिंग — “स्रोत बंद करें और चिपकाना बंद” क्यों
हर बार कई फ़ॉर्मेट में बड़ा पेलोड बनाना बर्बादी है, इसलिए क्लिपबोर्ड में विलंबित रेंडरिंग नामक तंत्र है। SetClipboardData को डेटा हैंडल के रूप में NULL दें तो, पेलोड के बजाय केवल “माँगे जाने पर बनाने” का वादा पंजीकृत होता है; जब कोई वह फ़ॉर्मेट माँगे, कॉपी स्रोत पर WM_RENDERFORMAT आता है, और तभी डेटा बनता है।2
इस डिज़ाइन का परिणाम शुरुआती “स्रोत ऐप बंद किया और चिपकाना बंद हो गया” है। निकलने से पहले, कॉपी स्रोत WM_RENDERALLFORMATS पाता है और हर अभी-नरेंडर फ़ॉर्मेट मूर्त करने का जिम्मेदार है; बिना किए निकलें तो फ़ॉर्मेट खो जाता है।2
flowchart TB
accTitle: विलंबित रेंडरिंग और बंद-कर-चिपकाओ विफलता क्यों होती है
accDescr: कॉपी स्रोत NULL हैंडल से केवल वादा पंजीकृत करता है, और माँग पर WM_RENDERFORMAT से मूर्त करता है। निकास पर हर फ़ॉर्मेट WM_RENDERALLFORMATS से मूर्त करने का जिम्मेदार है; वह छोड़ें तो फ़ॉर्मेट खो जाता है
promise["SetClipboardData NULL = वादा"] --> req["चिपकाने वाला पक्ष माँगता है"]
req --> render["WM_RENDERFORMAT → अभी बनाएँ"]
promise --> quit["कॉपी स्रोत निकलने वाला है"]
quit -->|"RENDERALLFORMATS"| ok["निकास बाद चिपकाना काम करता है"]
quit -->|"मूर्त छोड़ें"| lost["बंद बाद फ़ॉर्मेट खोया"]
चित्र 7: विलंबित रेंडरिंग वादा रखती है; निकास पर मूर्तीकरण छोड़ें तो चिपकाना मर जाता है।
OLE क्लिपबोर्ड पर (OleSetClipboard से IDataObject रखने वाली शैली), यह संबंध और भी स्पष्ट है। क्लिपबोर्ड केवल डेटा ऑब्जेक्ट का पॉइंटर रखता है, और ऐप निकास पर OleFlushClipboard कॉल करना डेटा क्लिपबोर्ड पर मूर्त करता है, इसलिए निकास के बाद भी चिपकाना काम करता है।6 .NET का Clipboard.SetDataObject(data, copy: true) यही “निकास के बाद रखें” व्यवहार निर्दिष्ट करता है।
Excel में बड़ी श्रेणी कॉपी कर निकलने की कोशिश करने पर संकेत “There is a large amount of information on the Clipboard. Do you want to be able to paste this information into another program later?” ठीक इसी मूर्तीकरण (flush) को चलाना है या नहीं की पुष्टि है। यदि अपने ऐप में विलंबित रेंडरिंग उपयोग करें, याद रखें कि निकास-समय मूर्तीकरण उसी सेट का भाग है। विलंबित रेंडरिंग प्रदर्शन अनुकूलन है, और क्योंकि रेंडर अनुरोध संदेश प्रोसेसिंग के भीतर सिंक्रोनस चलता है, बनने में लंबा लगने वाले डेटा का UI जमने का समझौता है।2
6. क्लिपबोर्ड देखने की प्रथाएँ — श्रोता, पुनः-प्रयास, और इतिहास बहिष्करण
6.1. AddClipboardFormatListener उपयोग करें
“बारकोड-रीडर मान या लाइन-ऑफ़-बिज़नेस सिस्टम से कॉपी पकड़कर स्वतः आयात करना चाहते हैं” जैसी आवश्यकताएँ क्लिपबोर्ड परिवर्तन देखने की माँग करती हैं। ऐतिहासिक रूप से तीन विधियाँ हैं; आज सही उत्तर एक है।8
| विधि | आकलन |
|---|---|
| टाइमर पर पढ़ना(पोलिंग) | बर्बादी, और अपडेट चूक सकते हैं। उपयोग न करें |
| SetClipboardViewer(व्यूअर श्रृंखला) | श्रृंखला के एक ऐप का बग पूरी श्रृंखला तोड़ता है। केवल पिछड़ी संगतता के लिए रखा |
| AddClipboardFormatListener | अनुशंसित। पंजीकृत विंडो पर WM_CLIPBOARDUPDATE आता है |
flowchart TB
accTitle: क्लिपबोर्ड देखने का प्रवाह
accDescr: हैंडल बनने पर AddClipboardFormatListener से पंजीकृत करें, और WM_CLIPBOARDUPDATE आता है चाहे जिस ऐप ने कॉपी की। पुनः-प्रयास से पढ़ें, और हैंडल नष्ट होने पर RemoveClipboardFormatListener से सममित अपंजीकृत करें
created["AddClipboardFormatListener"] --> wait["प्रतीक्षा"]
anyapp["कोई ऐप कॉपी करता है"] --> notify["WM_CLIPBOARDUPDATE"]
wait --> notify
notify --> readtry["पुनः-प्रयास से पढ़ें(6.2)"]
readtry --> wait
destroyed["RemoveClipboardFormatListener"] -.->|"अपंजीकृत"| created
चित्र 8: क्लिपबोर्ड देखना श्रोता + पुनः-प्रयास है; पोलिंग और पुरानी व्यूअर श्रृंखला उपयोग न करें।
// Minimal WinForms implementation
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)
{
// Unregister symmetrically to match handle destruction / recreation
RemoveClipboardFormatListener(Handle);
base.OnHandleDestroyed(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CLIPBOARDUPDATE)
{
// Read Clipboard.GetDataObject() here and import if the format is one you need
}
base.WndProc(ref m);
}
}
6.2. जब खोल न सकें तो पुनः-प्रयास करें
एक समय में केवल एक विंडो क्लिपबोर्ड खोल सकती है; जब दूसरा प्रोसेस खुला रखे, OpenClipboard विफल होता है।2 WM_CLIPBOARDUPDATE के तुरंत बाद, कॉपी स्रोत या दूसरा दर्शक अक्सर अभी काम कर रहा होता है, इसलिए अस्थायी पढ़ने की विफलता सामान्य घटना है। हमेशा कुछ पुनः-प्रयास छोटी प्रतीक्षा (दसियों मिलीसेकंड) के साथ लगाएँ। ध्यान दें कि पुनः-प्रयास संख्या और अंतराल निर्दिष्ट करने वाले .NET Clipboard ओवरलोड केवल लिखने वाले पक्ष, SetDataObject पर मौजूद हैं। पढ़ने वाले पक्ष (GetDataObject और साथी) पर समकक्ष नहीं, इसलिए catch-wait-retry स्वयं लिखें — WinForms पर ExternalException, WPF पर COMException।
flowchart TB
accTitle: क्लिपबोर्ड-पढ़ने का पुनः-प्रयास प्रवाह
accDescr: एक समय में केवल एक विंडो क्लिपबोर्ड खोल सकती है, इसलिए परिवर्तन सूचना के तुरंत बाद पढ़ना दूसरे प्रोसेस से दौड़ कर विफल हो सकता है। अपवाद पर दसियों ms प्रतीक्षा कर पुनः-प्रयास करें; सीमा लगे तो इस बार छोड़ें और अगले अपडेट पर लें
upd["WM_CLIPBOARDUPDATE"] --> tryread["पढ़ने का प्रयास"]
tryread -->|"सफलता"| useok["आयात(अ. 4 जाँच)"]
tryread -->|"उपयोग में"| waitretry["दसियों ms प्रतीक्षा"]
waitretry -->|"पुनः-प्रयास"| tryread
waitretry -->|"सीमा"| giveup2["इस बार छोड़ें"]
चित्र 9: सूचना के तुरंत बाद पढ़ना विफल होना सामान्य है; छोटी प्रतीक्षा वाला पुनः-प्रयास रखें।
6.3. इतिहास और सिंक से बाहर रखें — रहस्य सँभालने वाली कॉपी सुविधाओं की देखभाल
Windows में क्लिपबोर्ड इतिहास (Win+V) और डिवाइस-पार सिंक (क्लाउड क्लिपबोर्ड) हैं, और ऐप द्वारा रखी सामग्री डिफ़ॉल्ट पर दोनों के दायरे में है। पासवर्ड या खाता संख्या जैसे रहस्य कॉपी सुविधा पर रखने वाला ऐप वह पंजीकृत फ़ॉर्मेट भी रखता है जो सामग्री को इतिहास और सिंक से बहिष्कृत करता है।1
- ExcludeClipboardContentFromMonitorProcessing: इसे रखें तो उस कॉपी की सामग्री न इतिहास में आती है न सिंक में।
- CanIncludeInClipboardHistory (DWORD 0): केवल इतिहास दबाएँ।
- CanUploadToCloudClipboard (DWORD 0): केवल डिवाइस-पार सिंक दबाएँ।
पासवर्ड मैनेजर द्वारा कॉपी पासवर्ड Win+V पर न रहने का कारण यही तंत्र है। नाम RegisterClipboardFormat को देकर फ़ॉर्मेट ID पाते हैं और साधारण डेटा के साथ सेट करते हैं, इसलिए रहस्य सँभालने वाले किसी भी व्यावसायिक ऐप में लागू करने योग्य है।
7. IT की दृष्टि से क्लिपबोर्ड — इतिहास, क्लाउड सिंक, और RDP नियंत्रण
विकास से थोड़ा हटकर, यहाँ वे बिंदु हैं जो प्रशासक के लिए महत्त्व रखते हैं। क्लिपबोर्ड इतिहास हाल की कॉपी जमा करता है, और क्लाउड क्लिपबोर्ड उसी Microsoft खाता / Microsoft Entra खाता से साइन-इन डिवाइस पार कॉपी सिंक करता है।10 जितना सुविधाजनक, उतना अवशेष और फैलाव भी पैदा करता है: लाइन-ऑफ़-बिज़नेस सिस्टम से कॉपी व्यक्तिगत जानकारी इतिहास में जमा होती है, और काम PC पर कॉपी सामग्री व्यक्तिगत PC पर सिंक होती है।
संगठन में इसे नियंत्रित करने वाली दो नीतियाँ निम्नलिखित हैं।
| जो नियंत्रित करें | GPO(Computer Configuration > Administrative Templates > System > OS Policies) | Policy CSP(Intune) | डिफ़ॉल्ट |
|---|---|---|---|
| क्लिपबोर्ड इतिहास | Allow Clipboard History | Experience/AllowClipboardHistory | अनुमति |
| डिवाइस-पार सिंक | Allow Clipboard synchronization across devices | Privacy/AllowCrossDeviceClipboard | अनुमति |
दोनों Windows 10 संस्करण 1809 से उपलब्ध हैं; अक्षम करें तो Settings ऐप में संगत वस्तुएँ धूसर हो जाती हैं, और नीति तुरंत प्रभावी होती है।910
दूसरा नियमित RDP (Remote Desktop) क्लिपबोर्ड रीडायरेक्शन है। डिफ़ॉल्ट पर, स्थानीय PC और रिमोट सेशन के बीच कॉपी-एंड-पेस्ट काम करता है, इसलिए यह सर्वर से रहस्य निकालने का पथ बन सकता है। “Do not allow clipboard redirection” नीति (रजिस्ट्री मान fDisableClip) दोनों दिशाएँ रोक सकती है।11 हाल के Windows Server / Windows 11 रिलीज़ ने महीन नीतियाँ भी जोड़ी हैं, जैसे सर्वर-से-क्लाइंट दिशा को केवल पाठ तक सीमित करना। पूरी तरह प्रतिबंधित करें या चरणों में सीमित करें यह संचालन और सुरक्षा का संतुलन है।
flowchart TB
accTitle: क्लिपबोर्ड सामग्री फैल सकने वाले पथ, और नियंत्रण बिंदु
accDescr: कॉपी सामग्री डिफ़ॉल्ट पर इतिहास और क्लाउड सिंक के दायरे में है, और RDP पर रीडायरेक्शन से दूसरे सेशन तक जाती है। हर पथ नीति से नियंत्रित हो सकता है, और ऐप पक्ष बहिष्करण फ़ॉर्मेट से स्वयं को इतिहास और सिंक से बाहर रख सकता है
cb["क्लिपबोर्ड"] --> hist["इतिहास(Win+V)"]
cb --> cloud["क्लाउड सिंक"]
cb --> rdp["RDP रीडायरेक्शन"]
hist -.-> p1["AllowClipboardHistory"]
cloud -.-> p2["AllowCrossDeviceClipboard"]
rdp -.-> p3["fDisableClip"]
cb -.-> p4["ऐप बहिष्करण फ़ॉर्मेट(6.3)"]
चित्र 10: इतिहास, क्लाउड सिंक और RDP डिफ़ॉल्ट पर खुले हैं; रहस्य सँभालने वाले वातावरण में जानबूझकर तय करें।
8. ड्रैग एंड ड्रॉप COM है — IDataObject + IDropSource + IDropTarget
8.1. क्लिपबोर्ड जैसा वही डेटा, ढोने का भिन्न तरीका
OLE ड्रैग एंड ड्रॉप निम्नलिखित तीन भूमिकाओं से चलता है।12
| भूमिका | कौन लागू करता है | काम |
|---|---|---|
| IDataObject | ड्रैग स्रोत | ढोया जा रहा पेलोड। क्लिपबोर्ड जैसा वही बहु-फ़ॉर्मेट डेटा ऑब्जेक्ट |
| IDropSource | ड्रैग स्रोत | ड्रैग जारी रहे या रद्द हो यह तय करना, और कर्सर फ़ीडबैक |
| IDropTarget | ड्रॉप लक्ष्य | DragEnter/DragOver/DragLeave/Drop में स्वीकार/अस्वीकार घोषित करना, और ड्रॉप पाना |
ड्रैग स्रोत DoDragDrop बुलाता है, ड्रैग लूप शुरू होता है, और जब माउस ड्रॉप-लक्ष्य विंडो में प्रवेश करे वह IDropTarget सूचित होता है; ड्रॉप पर, IDataObject सौंपा जाता है। आधिकारिक दस्तावेज़ यह भी कहता है कि “D&D ठीक वही कार्यक्षमता देता है जो क्लिपबोर्ड कॉपी-एंड-पेस्ट। यदि ऐप पहले से कॉपी-एंड-पेस्ट लागू करता हो, जोड़ छोटा है”।12 अर्थात्, अध्याय 2 से 5 में बनाया बहु-फ़ॉर्मेट DataObject ज्यों का त्यों D&D पेलोड बन जाता है।
flowchart TB
accTitle: OLE ड्रैग एंड ड्रॉप का प्रवाह
accDescr: ड्रैग स्रोत IDataObject पेलोड में रखता है और DoDragDrop से ड्रैग लूप शुरू करता है; ड्रॉप लक्ष्य का IDropTarget DragEnter और DragOver में स्वीकार/अस्वीकार घोषित करता है, और Drop पर IDataObject से फ़ॉर्मेट चुनकर निकालता है
src["IDataObject + IDropSource"] -->|"DoDragDrop"| loop["ड्रैग लूप"]
loop -->|"माउस प्रवेश"| enter["DragEnter/Over: Effect"]
enter -->|"बटन ऊपर"| drop["IDropTarget.Drop"]
drop --> data["फ़ॉर्मेट चुनें और निकालें"]
चित्र 11: D&D क्लिपबोर्ड जैसा वही IDataObject ढोता है; कॉपी-एंड-पेस्ट हो तो जोड़ छोटा है।
8.2. OleInitialize (STA) आवश्यक है
जो विंडो ड्रॉप लक्ष्य बनेगी वह RegisterDragDrop से पंजीकृत होती है, और यहाँ क्लासिक जाल है। यदि COM CoInitialize/CoInitializeEx से आरंभीकृत किया, RegisterDragDrop हमेशा E_OUTOFMEMORY से विफल होता है; OleInitialize से आरंभीकरण करना चाहिए।13 OleInitialize COM को STA के रूप में आरंभीकृत करता है, क्योंकि D&D विंडो और मैसेज पंप की STA दुनिया में जड़ी सुविधा है। कॉल करने वाले थ्रेड को मैसेज पंप भी चलाना चाहिए; छोड़ें तो ड्रैग के दौरान अन्य ऐप हैंग होते हैं।13 यहाँ की पृष्ठभूमि ठीक “COM STA/MTA की बुनियाद” की थ्रेडिंग-मॉडल चर्चा है।
WinForms/WPF ऐप में फ़्रेमवर्क OLE आरंभीकरण और इंटरफ़ेस इम्प्लीमेंटेशन सँभालता है, इसलिए डेवलपर को केवल इवेंट लिखने होते हैं।
// WinForms: accept dropped files
listView1.AllowDrop = true;
listView1.DragEnter += (s, e) =>
{
// Also check that the source allows Copy (some sources only allow Move/Link)
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
&& (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy
? DragDropEffects.Copy // Accept: receive as a copy
: DragDropEffects.None; // Do not accept
};
listView1.DragDrop += (s, e) =>
{
// Drag data is also untrusted input. Even if it advertises FileDrop, the payload
// can be null or a different type, and GetData itself can fail
object data;
try { data = e.Data.GetData(DataFormats.FileDrop); }
catch (COMException) { return; }
if (data is not string[] paths) return;
foreach (var path in paths)
{
// Validate the path before importing (Section 9.3)
}
};
रूप WPF में वही है: एलिमेंट पर AllowDrop="True" और DragOver/Drop इवेंट से पाते हैं, और पथ सरणी e.Data.GetData(DataFormats.FileDrop) से निकालते हैं। हर DragEnter/DragOver पर स्वीकार/अस्वीकार (Effect) घोषित करना IDropTarget प्रथा है; छोड़ें तो वह बग मिलता है जहाँ कर्सर “अनुमति नहीं” पर रहता है और कभी नहीं बदलता।
9. D&D के जाल — ऊँचाई, Move, और पथ सत्यापन
9.1. एडमिनिस्ट्रेटर के रूप में ऊँचे ऐप पर ड्रॉप नहीं कर सकते
File Explorer से “Run as administrator” से चलाए ऐप पर फ़ाइल ड्रॉप करें और कुछ न हो — यह इम्प्लीमेंटेशन बग नहीं, OS व्यवहार है। UIPI (User Interface Privilege Isolation) निम्न-अखंडता प्रोसेस से उच्च-अखंडता विंडो तक संदेश डिफ़ॉल्ट पर रोकता है, इसलिए साधारण-विशेषाधिकार (मध्यम-अखंडता) File Explorer से ड्रॉप सूचनाएँ ऊँचे ऐप तक पहुँचती ही नहीं।14
flowchart TB
accTitle: UIPI ऊँचे ऐप पर ड्रॉप कैसे रोकता है
accDescr: मध्यम-अखंडता File Explorer से उच्च-अखंडता ऊँचे ऐप तक ड्रॉप सूचनाएँ UIPI डिफ़ॉल्ट पर रोकता है और पहुँचती नहीं। UI साधारण विशेषाधिकार पर रखें और विशेषाधिकार काम अलग करें, तो ड्रॉप पहुँचता है
explorer["Explorer(मध्यम)"] -->|"ड्रॉप सूचना"| uipi{"UIPI"}
uipi -->|"रोका"| elevated["ऊँचा ऐप: ड्रॉप नहीं"]
uipi -->|"गुज़रता"| normal["साधारण UI: ड्रॉप पहुँचता है"]
normal -.->|"विशेषाधिकार काम सौंपें"| broker["अलग ऊँचा प्रोसेस"]
चित्र 12: ऊँचे ऐप पर ड्रॉप UIPI रोकता है; UI साधारण विशेषाधिकार पर रखें तो ड्रॉप आता है।
ChangeWindowMessageFilterEx से WM_DROPFILES जैसे विशिष्ट संदेश व्यक्तिगत अनुमति देने वाला उपाय जाना-माना है,14 पर जो वह गुज़रने देता है वह पुरानी (WM_DROPFILES) ड्रॉप सूचना है; OLE D&D समग्र हल नहीं करता। व्यावहारिक मार्गदर्शन स्पष्ट है: ऐप को हमेशा ऊँचा चलाने वाला डिज़ाइन छोड़ें। केवल ऊँचाई चाहिए वाला काम अलग प्रोसेस में अलग करें, और UI स्वयं साधारण विशेषाधिकार पर रह D&D पा सकता है (पृथक्करण डिज़ाइन “Windows ऐप में "केवल एडमिनिस्ट्रेटर विशेषाधिकार चाहिए वाले काम" को ठोस रूप से अलग कैसे करें” में विस्तार से है)।
9.2. DragDropEffects का अर्थ — Move वह अनुबंध है कि “मूल चला जाता है”
DragDropEffects पर Copy/Move/Link सजावट नहीं; वे ड्रैग स्रोत और ड्रॉप लक्ष्य के बीच अनुबंध हैं। ड्रैग स्रोत DoDragDrop में अनुमति प्रभावों का सेट घोषित करता है, ड्रॉप लक्ष्य वास्तविक प्रभाव चुनता है, और जब Move सफल हो, ड्रैग स्रोत डेटा (फ़ाइल) मिटाता है — यही प्रथा है। यदि पाने वाला पक्ष बिना सोचे Move लौटाए, वह दुर्घटना मिलती है “ड्रॉप किया और मूल फ़ाइल गायब हो गई”। व्यावसायिक ऐप के आयात उपयोग के लिए, पाने वाला पक्ष Copy बताना सुरक्षित डिफ़ॉल्ट है।
flowchart TB
accTitle: DragDropEffects अनुबंध — Move मूल मिटाता है
accDescr: ड्रैग स्रोत DoDragDrop में अनुमति प्रभावों का सेट घोषित करता है, और ड्रॉप लक्ष्य वास्तविक प्रभाव चुनता है। Move सफल होने पर स्रोत फ़ाइल मिटाता है, इसलिए आयात के लिए पाने वाला पक्ष Copy बताए
srcdecl["स्रोत: अनुमति प्रभाव"] --> tgtsel["लक्ष्य: Effect चुनें"]
tgtsel -->|"Copy"| copyok["मूल रहता है(आयात)"]
tgtsel -->|"Move"| moveact["स्रोत फ़ाइल मिटाता है"]
चित्र 13: आयात पर पाने वाला पक्ष Copy बताए; Move मूल फ़ाइल मिटाने का अनुबंध है।
9.3. ड्रॉप किए पथ का सत्यापन
CF_HDROP/FileDrop में जो चलता है केवल पथ है (खंड 3.2)। आयात से पहले, चिपकाने जैसी ही अविश्वसनीय-इनपुट सत्यापन से गुज़ारें।
- फ़ाइल या फ़ोल्डर: विनिर्देश के रूप में तय करें कि पूरा फ़ोल्डर ड्रॉप होने पर क्या होता है (पुनरावर्ती आयात, या अस्वीकार)।
- OneDrive प्लेसहोल्डर: पथ मौजूद हो सकता है जबकि फ़ाइल बॉडी स्थानीय न हो — ऑन-डिमांड फ़ाइल। खोलते ही डाउनलोड शुरू होता है, और ऑफ़लाइन विफल होता है। व्यवहार और उपाय “OneDrive "Files On-Demand" और व्यावसायिक ऐप” में हैं।
- लंबे पथ और असामान्य पथ: MAX_PATH से अधिक पथ, नेटवर्क (UNC) पथ, और हटाने योग्य मीडिया पर पथ तभी स्वीकार करें जब पुष्टि हो कि आगे की प्रोसेसिंग उन्हें सँभाल सकती है।
- संख्या और कुल आकार: ताकि हज़ारों फ़ाइलें ड्रॉप करने से UI न जमे, आयात असिंक्रोनस करें और सीमा तथा प्रगति प्रदर्शन लगाएँ।
10. सारांश
- क्लिपबोर्ड वह तंत्र है जो एक ही डेस्कटॉप (विंडो स्टेशन) के भीतर साझा एकल क्षेत्र में एक ही सामग्री कई फ़ॉर्मेट में एक साथ रखता है। चिपकाने वाला पक्ष फ़ॉर्मेट चुनता है, इसलिए वही कॉपी भिन्न परिणाम देती है।
- पाठ CF_UNICODETEXT है, फ़ाइलें CF_HDROP, और फ़ॉर्मेटेड पाठ पंजीकृत फ़ॉर्मेट HTML Format (बाइट-ऑफ़सेट हेडर + UTF-8)।
- चिपकाने वाला पक्ष समृद्ध से सादे तक देखता है और पेलोड को बाहरी इनपुट मानता है। कॉपी पक्ष कई फ़ॉर्मेट एक साथ देता है, और यदि विलंबित रेंडरिंग उपयोग करे तो निकास-समय मूर्तीकरण (WM_RENDERALLFORMATS / OleFlushClipboard) भी लागू करता है।
- देखना AddClipboardFormatListener + WM_CLIPBOARDUPDATE है। OpenClipboard दौड़ के लिए पुनः-प्रयास तैयार रखें, और रहस्यों को ExcludeClipboardContentFromMonitorProcessing और साथी से इतिहास तथा सिंक से बाहर रखें।
- IT क्लिपबोर्ड इतिहास, क्लाउड सिंक, और RDP रीडायरेक्शन GPO / Intune से नियंत्रित कर सकता है। डिफ़ॉल्ट सबके लिए अनुमति है, इसलिए रहस्य सँभालने वाले वातावरण में जानबूझकर तय करें।
- D&D COM है: IDropSource/IDropTarget क्लिपबोर्ड जैसा वही IDataObject सौंपते हैं। RegisterDragDrop को OleInitialize (STA) चाहिए।
- ऊँचे ऐप पर ड्रॉप UIPI रोकता है। DragDropEffects पर Move वह अनुबंध है कि “मूल चला जाता है”; ड्रॉप किए पथ को आयात से पहले सत्यापित करें।
कॉपी-एंड-पेस्ट और D&D उपयोगकर्ता के लिए वायु जैसी सुविधाएँ होनी चाहिए। ठीक इसलिए “चिपक नहीं सकता”, “बिखर जाता है”, और “गायब हो गया” अनुभव इतना चोट पहुँचाते हैं — और जो ऐप कई फ़ॉर्मेट देता और ड्रॉप सही सँभालता है वह रोज़ के संचालन को स्वयं सहज बनाता है। आशा है जब तय करें कि पहले क्या ठीक करें, यह उपयोगी सामग्री हो।
संबंधित लेख
- COM / ActiveX / OCX क्या हैं? — अंतर और संबंध समझाए गए
- COM STA/MTA की बुनियाद — थ्रेडिंग मॉडल और हैंग से बचना
- आज Windows शेल एकीकरण — कॉन्टेक्स्ट मेनू, फ़ाइल एसोसिएशन, और Windows 11 में क्या बदला
- C# Excel COM ऑटोमेशन के बाद EXCEL.EXE प्रोसेस क्यों रहते हैं — संदर्भ रिलीज़ पैटर्न और प्रतिस्थापन निर्णय
- Windows ऐप UX डिज़ाइन — उपयोग वातावरण के अनुसार प्राथमिकताएँ
- OneDrive “Files On-Demand” और व्यावसायिक ऐप — प्लेसहोल्डर कौन सी धारणाएँ तोड़ते हैं और उनसे कैसे निपटें
संबंधित परामर्श क्षेत्र
KomuraSoft LLC व्यावसायिक ऐप में कॉपी-एंड-पेस्ट और ड्रैग-एंड-ड्रॉप समर्थन का डिज़ाइन और इम्प्लीमेंटेशन सँभालता है (कई फ़ॉर्मेट देना, Excel इंटरऑप, ड्रॉप फ़ाइलें आयात करना), “चिपकाने पर बिखर जाता है” या “कॉपी गायब हो जाती है” जैसी समस्याओं की मूल-कारण जाँच, क्लिपबोर्ड देखने वाला इनपुट स्वचालन, तथा गोपनीय डेटा को इतिहास और सिंक से बाहर रखने वाली इम्प्लीमेंटेशन। COM और OLE की निचली परतों वाले मामले लक्षण अलग करने से शुरू करने पर भी स्वागत योग्य हैं।
संदर्भ लिंक
-
Microsoft Learn, Clipboard Formats. विंडो के एक ही जानकारी कई क्लिपबोर्ड फ़ॉर्मेट में रख सकने पर; RegisterClipboardFormat से पंजीकृत फ़ॉर्मेट पर (उसी नाम से पंजीकरण वही मान लौटाता है, इसलिए ऐप साझा कर सकते हैं); संश्लेषित फ़ॉर्मेट पर; और ExcludeClipboardContentFromMonitorProcessing, CanIncludeInClipboardHistory, तथा CanUploadToCloudClipboard से सामग्री को क्लिपबोर्ड इतिहास / क्लाउड सिंक से बहिष्कृत करने पर। ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Clipboard Operations. एक समय में केवल एक विंडो के क्लिपबोर्ड खोल सकने पर; कॉपी समय अधिक अभिव्यक्त से कम अभिव्यक्त फ़ॉर्मेट रखने पर; चिपकाने समय EnumClipboardFormats / GetPriorityClipboardFormat से फ़ॉर्मेट चयन पर; SetClipboardData को NULL देकर विलंबित रेंडरिंग और WM_RENDERFORMAT / WM_RENDERALLFORMATS जिम्मेदारियों पर; और विलंबित रेंडरिंग के समझौतों पर। ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Standard Clipboard Formats. मानक फ़ॉर्मेट CF_TEXT (ANSI), CF_UNICODETEXT, CF_HDROP, CF_DIB, और CF_LOCALE की परिभाषाओं पर, और सिस्टम के CF_TEXT तथा CF_UNICODETEXT को CF_LOCALE से जुड़े कोड पेज से निहित रूपांतरित करने पर। ↩ ↩2 ↩3
-
Microsoft Learn, Shell Clipboard Formats. CF_HDROP के DROPFILES संरचना प्लस पूर्ण-पथ स्ट्रिंग की डबल-NUL-समाप्त सरणी से बने होने पर; DragQueryFile से व्यक्तिगत पथ निकालने पर; और CFSTR_ शेल फ़ॉर्मेट के RegisterClipboardFormat से पंजीकरण चाहिए होने पर। ↩ ↩2
-
Microsoft Learn, HTML Clipboard Format. पंजीकृत नाम के “HTML Format” होने पर; Version, StartHTML, EndHTML, StartFragment, और EndFragment जैसे बाइट ऑफ़सेट वाले हेडर संरचना पर; एन्कोडिंग के हमेशा UTF-8 होने पर; और StartFragment/EndFragment टिप्पणी प्रथा पर। ↩ ↩2 ↩3
-
Microsoft Learn, OleFlushClipboard function (ole2.h). OleSetClipboard के क्लिपबोर्ड पर केवल डेटा ऑब्जेक्ट का पॉइंटर रखने पर; OleFlushClipboard के डेटा क्लिपबोर्ड पर मूर्त करने पर ताकि ऐप निकास बाद भी चिपकाना काम करे; और निकास पर रखने की ज़रूरत न हो तो OleSetClipboard(NULL) से क्लिपबोर्ड खाली करने पर। ↩ ↩2
-
Microsoft Learn, OleGetClipboard function (ole2.h). क्लिपबोर्ड से IDataObject पाने के तरीके पर, और चेतावनी पर कि क्लिपबोर्ड डेटा विश्वसनीय नहीं और ऐप उपयोग से पहले सावधानी से पार्स करना चाहिए। ↩ ↩2
-
Microsoft Learn, Using the clipboard. क्लिपबोर्ड देखने के तीन तरीकों (व्यूअर विंडो, अनुक्रम संख्या, और फ़ॉर्मेट श्रोता) की तुलना पर; नए प्रोग्राम के AddClipboardFormatListener से श्रोता उपयोग करने की अपेक्षा पर; श्रृंखला रखरखाव अधूरा होने पर व्यूअर श्रृंखला के नाज़ुक होने पर; और अनुक्रम संख्याओं को पोल न करने पर। ↩ ↩2
-
Microsoft Learn, Policy CSP - Experience. Experience/AllowClipboardHistory नीति से क्लिपबोर्ड इतिहास अनुमति या अस्वीकार करने पर; Windows 10 संस्करण 1809 से उपलब्धता पर; डिफ़ॉल्ट अनुमति होने पर; और “System > OS Policies” के अधीन GPO मैपिंग तथा परिवर्तनों के तुरंत प्रभावी होने पर। ↩ ↩2
-
Microsoft Learn, Policy CSP - Privacy. Privacy/AllowCrossDeviceClipboard नीति से डिवाइस-पार क्लिपबोर्ड सिंक अनुमति या अस्वीकार करने पर; उसी Microsoft खाता / Microsoft Entra खाता से साइन-इन डिवाइस के बीच सिंक होने पर; और डिफ़ॉल्ट अनुमति होने पर। ↩ ↩2 ↩3
-
Microsoft Learn, Policy CSP - ADMX_TerminalServer. TS_CLIENT_CLIPBOARD (“Do not allow clipboard redirection”, रजिस्ट्री मान fDisableClip) के Remote Desktop सेशन में स्थानीय और रिमोट के बीच क्लिपबोर्ड साझा मना कर सकने पर, और रीडायरेक्शन के डिफ़ॉल्ट अनुमति होने पर। ↩ ↩2
-
Microsoft Learn, Drag and Drop (COM). OLE ड्रैग एंड ड्रॉप के IDropSource (ड्रैग स्रोत), IDropTarget (ड्रॉप लक्ष्य), और DoDragDrop (OLE द्वारा दिया लूप) तीन से चलने पर; क्लिपबोर्ड कॉपी-एंड-पेस्ट जैसी वही कार्यक्षमता देने पर, जिससे पहले से कॉपी-एंड-पेस्ट लागू ऐप को केवल छोटा जोड़ चाहिए; और फ़ीडबैक के प्रकारों पर। ↩ ↩2 ↩3
-
Microsoft Learn, RegisterDragDrop function (ole2.h). ड्रॉप-लक्ष्य विंडो को IDropTarget से पंजीकृत करने पर; COM CoInitialize/CoInitializeEx से आरंभीकृत होने पर हमेशा E_OUTOFMEMORY से विफल होने, इसलिए OleInitialize आवश्यक होने पर; और कॉल करने वाले थ्रेड के मैसेज पंप न चलाने पर ड्रैग-स्रोत ऐप हैंग होने पर। ↩ ↩2 ↩3
-
Microsoft Learn, ChangeWindowMessageFilterEx function (winuser.h). UIPI के डिफ़ॉल्ट पर निम्न-अखंडता भेजने वाले से संदेश पाना रोकने वाले सुरक्षा तंत्र होने पर, और मैसेज फ़िल्टर (MSGFLT_ALLOW) से प्रति विंडो विशिष्ट संदेश अनुमति देने पर। ↩ ↩2 ↩3
-
Microsoft Learn, How to add data to the Clipboard (Windows Forms). DataObject और Clipboard.SetDataObject से एक साथ कई फ़ॉर्मेट में डेटा रखने पर; अन्य ऐप पहचान सकें इसलिए कई फ़ॉर्मेट जोड़ने पर; और Clipboard वर्ग के केवल STA थ्रेड से उपयोग योग्य होने, इसलिए [STAThread] आवश्यक होने पर। ↩ ↩2
संबंधित लेख
निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।
"Not Responding" वास्तव में क्या है — Windows ऐप के हैंग का निर्णय कैसे करता है, और न हैंग करने वाले ऐप कैसे डिज़ाइन करें
Windows का "Not Responding" वह तंत्र है जिसमें OS तय करता है कि विंडो ने 5 सेकंड संदेश नहीं लिया और उसे घोस्ट विंडो से बदल देता है। यह ले...
Win32 Thread Pool API — CreateThreadpoolWork से थ्रेड बनाए बिना समवर्तिता
क्या आपके नेटिव कोड में CreateThread कॉल बिखरी पड़ी हैं? यह लेख Vista में पुनर्डिज़ाइन की गई Win32 थ्रेड पूल API — work, timer, wait और i...
Named Pipes व्यवहार में — डिज़ाइन से सुरक्षा तक, Windows की मानक IPC
Named pipes — Windows की मानक इंटर-प्रोसेस कम्युनिकेशन — की व्यावहारिक मार्गदर्शिका। यह लेख प्राथमिक स्रोतों से बाइट और मैसेज मोड का चुना...
स्लीप से रिज़्यूम पर टूटने वाले ऐप — Windows पावर इवेंट कैसे काम करते हैं और उनसे बचने वाले व्यावसायिक ऐप कैसे बनाएँ
लैपटॉप खोला और व्यावसायिक ऐप के कनेक्शन मर चुके थे — कारण वह डिज़ाइन है जिसने स्लीप का हिसाब ही नहीं रखा। यह लेख WM_POWERBROADCAST सूचना ...
DllMain और Loader Lock — DLL आरंभीकरण में "कुछ न करें" कहे जाने का वास्तविक कारण
DllMain से LoadLibrary क्यों न बुलाएँ या दूसरे थ्रेड से सिंक्रोनाइज़ न करें। प्राथमिक स्रोतों से यह लेख समझाता है कि लोडर लॉक हर DLL सूचन...
संबंधित विषय
ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।
Windows के तकनीकी विषय
Windows विकास, बग जाँच और मौजूदा संपत्तियों के उपयोग का प्रवेश-द्वार।
ActiveX माइग्रेशन
COM / ActiveX / OCX कॉम्पोनेन्ट रखने, रैप करने या बदलने के निर्णय।
UI थ्रेड और टाइमर
WPF / WinForms का UI थ्रेड, असिंक्रोनस प्रवाह, Dispatcher और टाइमर डिज़ाइन।
इस विषय से जुड़ी सेवाएँ
यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।
Windows ऐप विकास
व्यावसायिक ऐप, डिवाइस एकीकरण और संचार उपकरण, आवश्यकताओं से विकास तक।
मौजूदा संपत्तियों का पुनरुपयोग और माइग्रेशन
COM / ActiveX / OCX संपत्तियों और 32/64-बिट निर्भरताओं का पुनरुपयोग और माइग्रेशन।
अक्सर पूछे जाने वाले प्रश्न
इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।
- Excel से कॉपी की तालिका मेरे ऐप में चिपकाने पर फ़ॉर्मेटिंग क्यों बिखर जाती है?
- क्लिपबोर्ड "एक टुकड़ा डेटा" नहीं रखता। एक ही सामग्री कई फ़ॉर्मेट में एक साथ रखी जाती है (स्रोत ऐप का निजी फ़ॉर्मेट, HTML Format, CSV, यूनिकोड पाठ, आदि), और गंतव्य ऐप वह फ़ॉर्मेट चुनता है जिसे समझता है और उसे निकालता है। जब फ़ॉर्मेटिंग बिखरती है, विशिष्ट कारण है कि गंतव्य केवल सादा पाठ (CF_UNICODETEXT) पढ़ रहा है। यदि तालिका संरचना भी चाहिए, चिपकाने वाले पक्ष को HTML Format या CSV प्राथमिकता देने वाला लागू करें। इसके विपरीत, यदि चाहते हैं कि अन्य ऐप आपके ऐप से की गई कॉपी सही चिपकाएँ, कॉपी समय समृद्ध फ़ॉर्मेट और सादा फ़ॉर्मेट दोनों दें।
- जिस ऐप से कॉपी किया उसे बंद करने के बाद चिपकाना क्यों बंद हो जाता है?
- क्योंकि स्रोत विलंबित रेंडरिंग उपयोग कर रहा है। बड़े डेटा सँभालने वाले ऐप कॉपी समय पेलोड नहीं रखते; क्लिपबोर्ड पर केवल वादा पंजीकृत करते हैं कि "माँगे जाने पर बनाएँगे"। यदि स्रोत तब बिना WM_RENDERALLFORMATS का उत्तर दे डेटा मूर्त किए निकले, जो फ़ॉर्मेट अभी रेंडर नहीं हुए वे खो जाते हैं। OLE क्लिपबोर्ड (IDataObject) उपयोग करने वाला ऐप निकास पर OleFlushClipboard कॉल कर डेटा मूर्त करके निकास के बाद भी चिपकाना चालू रख सकता है।
- मेरा ऐप क्लिपबोर्ड परिवर्तन कैसे देख सकता है?
- वर्तमान अनुशंसित विधि है अपनी विंडो AddClipboardFormatListener से श्रोता पंजीकृत करना और हर बार सामग्री बदलने पर आने वाला WM_CLIPBOARDUPDATE संदेश सँभालना। टाइमर पर सामग्री पोल करना काम बर्बाद करता है और अपडेट चूक सकता है, और SetClipboardViewer पर आधारित पुरानी व्यूअर श्रृंखला केवल पिछड़ी संगतता के लिए रखी है, क्योंकि श्रृंखला के एक ऐप का बग पूरी श्रृंखला तोड़ देता है। ध्यान दें कि पढ़ने पर OpenClipboard विफल हो सकता है क्योंकि दूसरा प्रोसेस क्लिपबोर्ड पकड़े है, इसलिए स्थिर पढ़ना हो तो छोटी प्रतीक्षा वाला पुनः-प्रयास लागू करें।
- क्या पासवर्ड जैसे रहस्य क्लिपबोर्ड इतिहास (Win+V) से बाहर रखने का तरीका है?
- दो लीवर हैं, एक ऐप पक्ष पर और एक नीति पक्ष पर। ऐप पक्ष पर, कॉपी करते समय पंजीकृत फ़ॉर्मेट ExcludeClipboardContentFromMonitorProcessing भी रखें तो वह सामग्री न इतिहास में आती है न डिवाइस-पार सिंक में। प्रत्येक को स्वतंत्र नियंत्रित भी कर सकते हैं CanIncludeInClipboardHistory (केवल इतिहास) और CanUploadToCloudClipboard (केवल सिंक) से। यही तंत्र पासवर्ड मैनेजर उपयोग करते हैं। यदि पूरे संगठन के लिए बंद करना चाहें, Group Policy या Intune (Policy CSP) से AllowClipboardHistory और AllowCrossDeviceClipboard से इतिहास और क्लाउड सिंक स्वयं अक्षम कर सकते हैं।
- एडमिनिस्ट्रेटर के रूप में चल रहे ऐप पर फ़ाइल ड्रैग एंड ड्रॉप क्यों नहीं कर सकता?
- क्योंकि UIPI (User Interface Privilege Isolation) नामक सुरक्षा तंत्र निम्न-अखंडता प्रोसेस से उच्च-अखंडता विंडो तक संदेश पहुँचाना रोकता है। File Explorer साधारण विशेषाधिकार (मध्यम अखंडता) पर चलता है, इसलिए ड्रैग-एंड-ड्रॉप सूचनाएँ ऊँचे ऐप की विंडो तक पहुँचती ही नहीं। ChangeWindowMessageFilterEx से WM_DROPFILES जैसे संदेश व्यक्तिगत अनुमति देने वाला उपाय जाना-माना है, पर वह केवल पुरानी ड्रॉप सूचना पर लागू होता है। वास्तविक सुधार ऐप को हमेशा ऊँचा चलाने वाला डिज़ाइन छोड़ना है, और केवल ऊँचाई चाहिए वाला काम अलग प्रोसेस में अलग करना।