ক্লিপবোর্ড ও ড্র্যাগ অ্যান্ড ড্রপ কীভাবে কাজ করে — ব্যবসায়িক অ্যাপে OLE ডেটা ট্রান্সফার সঠিকভাবে সামলানো
· Go Komura · Windows, ক্লিপবোর্ড, ড্র্যাগ অ্যান্ড ড্রপ, OLE, COM, Windows ডেভেলপমেন্ট, WinForms, WPF
“Excel থেকে কপি করা টেবিল পেস্ট করলে ফরম্যাটিং ভেঙে যায়। টেবিল হিসেবে পেস্ট চাই।” “আমাদের অ্যাপে কপি করা বিষয়বস্তু Word-এ পেস্ট করলে অদ্ভুত কিছু হয়ে যায়।” “ফাইল ড্র্যাগ অ্যান্ড ড্রপ করে নিতে চাই।” — ব্যবসায়িক-অ্যাপ বদলের পরামর্শ আলোচনায় কপি-অ্যান্ড-পেস্ট ও ড্র্যাগ অ্যান্ড ড্রপ (D&D) ঘিরে অনুরোধ নিয়মিত।
ঠিক কারণ এগুলো “সবাই স্বাভাবিক ধরে নেওয়া ফিচার”, আসলে কীভাবে কাজ করে তা আশ্চর্যজনকভাবে কম জানা। ক্লিপবোর্ডকে “এক টুকরো ডেটা রাখার বাক্স” ভাবলে ব্যাখ্যা করা যায় না কেন একই কপি পেস্ট কোথায় তার উপর আলাদা ফল দেয়, অথবা সোর্স অ্যাপ বন্ধ করার পর পেস্ট কেন থেমে যায়। আসল ক্লিপবোর্ড এমন যন্ত্র যা একই বিষয়বস্তু একসঙ্গে একাধিক ফরম্যাটে রাখে, আর পেস্ট পাশকে যে ফরম্যাট বোঝে সেটা বেছে নিতে দেয়।
আর ড্র্যাগ অ্যান্ড ড্রপ, তলায়, OLE ডেটা ট্রান্সফার যা ক্লিপবোর্ডের ঠিক একই ডেটা উপস্থাপন (IDataObject) COM ইন্টারফেস দিয়ে হস্তান্তর করে। অর্থাৎ কপি-অ্যান্ড-পেস্ট ও D&D ভাইবোন: একটা সঠিকভাবে বুঝলে অন্যটা সেখানেই।
এই নিবন্ধ ক্ষুদ্র ও মাঝারি কোম্পানির IT কর্মী ও Windows অ্যাপ ডেভেলপারদের লক্ষ্য করে। ক্লিপবোর্ড ফরম্যাট কীভাবে কাজ করে, পেস্ট পাশ ও কপি পাশের অনুশীলন, ক্লিপবোর্ড দেখার সঠিক উপায়, ক্লিপবোর্ড ইতিহাস, ক্লাউড সিঙ্ক ও RDP-এর প্রশাসনিক নীতি, আর OLE ড্র্যাগ অ্যান্ড ড্রপের কাঠামো ও ফাঁদ — এক ছবিতে বেঁধে দেয়।
১. আগে উপসংহার
- ক্লিপবোর্ড একই ডেস্কটপের (উইন্ডো স্টেশন) অ্যাপগুলোর শেয়ার করা একটি এলাকা, আর সেখানে যা বসে তা “এক টুকরো ডেটা” নয় বরং একই বিষয়বস্তু একসঙ্গে একাধিক ফরম্যাটে। RDP-এর মতো আলাদা সেশনের আসলে আলাদা ক্লিপবোর্ড; রিডাইরেকশন ফিচার দুটোকে সেতু করে। গন্তব্য যে ফরম্যাট বোঝে সেটা বেছে নেয় বলে একই কপি পেস্ট কোথায় তার উপর আলাদা ফল দেয়।12
- টেক্সটের জন্য CF_UNICODETEXT ব্যবহার করুন। CF_TEXT ANSI ও কোড-পেজ নির্ভর, আর জাপানি সিস্টেমে মজিবাকে-এর প্রজননক্ষেত্র। সিস্টেম দুটোর মধ্যে অন্তর্নিহিতভাবে রূপান্তর করে, কিন্তু ক্যানোনিকাল পাশ ইউনিকোড।3
- ফাইল যায় CF_HDROP হিসেবে (পাথের ডাবল-NUL-টার্মিনেটেড অ্যারে), আর ফরম্যাটেড টেক্সট রেজিস্টার্ড ফরম্যাট “HTML Format” ব্যবহার করে। HTML Format-এর অস্বাভাবিক কাঠামো: বাইট অফসেটের হেডারসহ UTF-8 টেক্সট।45
- “সোর্স অ্যাপ বন্ধ করে আর পেস্ট করা যায় না”-এর আসল কারণ ডিলেড রেন্ডারিং। এটি পেলোড নয়, শুধু “চাইলে তৈরি করব” প্রতিশ্রুতি রাখার যন্ত্র; এক্সিটে মূর্ত করা বাদ দিলে (WM_RENDERALLFORMATS-এ সাড়া, অথবা OLE-এর জন্য OleFlushClipboard) পেস্ট থেমে যায়।26
- পেস্ট করা ডেটাকে বাইরের অবিশ্বস্ত ইনপুট ধরুন। Microsoft নিজে স্পষ্ট বলে “clipboard data is not trusted. Parse it carefully”।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
নিচে ক্লিপবোর্ডের ভিত্তি থেকে এটি ঘুরে দেখা।
২. ক্লিপবোর্ড আসলে কী — “এক টুকরো ডেটা” নয়, “একই বিষয়বস্তু একাধিক ফরম্যাটে”
ক্লিপবোর্ড সাধারণ ডেটা-শেয়ারিং যন্ত্র যা একই ডেস্কটপ শেয়ার করা প্রতিটি অ্যাপ পৌঁছাতে পারে (আরও সঠিকভাবে, উইন্ডো স্টেশনপ্রতি: আলাদা ব্যবহারকারী সেশন বা RDP সেশনের নিজস্ব ক্লিপবোর্ড। RDP-এ কপি-অ্যান্ড-পেস্ট চলে কারণ রিডাইরেকশন ফিচার দুটোকে সেতু করে — অধ্যায় ৭)। প্রথম নীতি ব্যবহারকারী-চালিত: অফিসিয়াল ডিজাইন অবস্থান ব্যবহারকারীর পেছনে ডেটা রাখা বা তোলা নয়।1
গুরুত্বপূর্ণ বিষয় একটি কপি “এক টুকরো ডেটা” রাখে না। যে উইন্ডো কপি করে ক্লিপবোর্ড খালি করে তারপর একই বিষয়বস্তু আরও সক্ষম ফরম্যাট থেকে কম সক্ষম ফরম্যাটে কয়েকটি ফরম্যাট সারিতে রাখে।2 উদাহরণস্বরূপ, স্প্রেডশিটে টেবিল কপি করলে ধারণাগতভাবে নিচের মতো কিছু একসঙ্গে ক্লিপবোর্ডে থাকে।
| অগ্রাধিকার | ফরম্যাট | বিষয়বস্তু |
|---|---|---|
| 1 | অ্যাপ-প্রাইভেট ফরম্যাট | ফর্মুলা ও ফরম্যাটিংসহ সম্পূর্ণ অভ্যন্তরীণ উপস্থাপন (একই অ্যাপে ফিরে পেস্টের জন্য) |
| 2 | HTML Format | টেবিল কাঠামো ও ফরম্যাটিং রাখা HTML খণ্ড |
| 3 | CSV | সেল-বিভক্ত টেক্সট |
| 4 | CF_UNICODETEXT | ট্যাব-বিভক্ত প্লেইন টেক্সট |
| 5 | ইমেজ ফরম্যাট | টেবিল দেখতে যেমন তার বিটম্যাপ |
পেস্ট পাশ এই তালিকা থেকে যে ফরম্যাট বোঝে সেটা বেছে তোলে। Word-এ পেস্ট করলে ফরম্যাটেড টেবিল পান; নোটপ্যাডে পেস্ট করলে ট্যাব-বিভক্ত টেক্সট — কারণ দুটো আলাদা ফরম্যাট বেছেছে। “পেস্ট কোথায় তার উপর ফল নির্ভর করে” বাগ নয়; এই ডিজাইনের স্বাভাবিক পরিণতি।
flowchart TB
accTitle: একই কপি পেস্ট কোথায় তার উপর আলাদা ফল দেয় কেন
accDescr: কপি পাশ একই বিষয়বস্তু ক্লিপবোর্ডে একাধিক ফরম্যাটে রাখে, আর পেস্ট পাশ যে ফরম্যাট বোঝে সেটা বেছে নেয়, তাই Word ফরম্যাটেড টেবিল পায় আর নোটপ্যাড ট্যাব-বিভক্ত টেক্সট পায়
copy["কপি: স্প্রেডশিট"] --> cb["ক্লিপবোর্ড (অনেক ফরম্যাট)"]
cb --> rich["আরও সমৃদ্ধ ফরম্যাট"]
cb --> plain["আরও সরল ফরম্যাট"]
rich --> f1["অ্যাপ-প্রাইভেট"]
rich --> f2["HTML Format"]
plain --> f3["CSV"]
plain --> f4["CF_UNICODETEXT"]
f2 -->|"Word"| word["ফরম্যাটেড টেবিল"]
f4 -->|"নোটপ্যাড"| notepad["ট্যাব-বিভক্ত টেক্সট"]
চিত্র ১: একই কপি গন্তব্য যে ফরম্যাট বেছে নেয় তার উপর আলাদা ফল দেয়; “ভেঙে যায়” প্রায়ই ফরম্যাট পছন্দের সমস্যা।
উল্টো করে বললে, শুরুর অভিযোগ — “ফরম্যাটিং ভেঙে যায়”, “অদ্ভুত কিছু পেস্ট হয়” — প্রায় সব এক পাশ ফরম্যাট কীভাবে বেছে নেয়, অথবা অন্য পাশ কীভাবে দেয় সেই সমস্যায় নেমে আসে। অধ্যায় ৪ পেস্ট পাশ; অধ্যায় ৫ কপি পাশ।
৩. মানক ফরম্যাট ও রেজিস্টার্ড ফরম্যাট — CF_UNICODETEXT, CF_HDROP, HTML Format
৩.১. মানক ফরম্যাট — টেক্সটের জন্য ইউনিকোড পাশ ব্যবহার করুন
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["প্রকাশযোগ্য নয় এমন অক্ষর পড়ে যায়"]
চিত্র ২: অ্যাপ ইউনিকোড পাশে একীভূত করুক; ANSI রূপান্তর সিস্টেমের, আর সেখানে অক্ষর হারানো যায়।
৩.২. 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[] হিসেবে পাওয়া যায়। “যা যায় শুধু পাথ, ফাইল নিজে নয়” এই তথ্য অধ্যায় ৮ ও ৯-এর 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["শুধু পাথ যায়, ফাইল নয়"]
চিত্র ৩: CF_HDROP ফাইল বহন করে না; পাথের তালিকা বহন করে। ইমপোর্টের আগে পাথ যাচাই অধ্যায় ৯।
৩.৩. রেজিস্টার্ড ফরম্যাট — 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>
প্রতিটি অফসেট হেডারসহ ডেটার শুরু থেকে বাইট অবস্থান; সাধারণ অনুশীলন স্থির প্রস্থ (যেমন ১০ অঙ্ক) সংরক্ষণ করে বডি গড়ার পর মাপা মান ফিরিয়ে লেখা। 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-এর পর বাইট"]
চিত্র ৪: HTML Format অফসেট অক্ষর নয় বাইট; UTF-8-এ এনকোডের পর মাপুন, নাহলে পেস্ট কেটে যায়।
টেবুলার ডেটার জন্য CSVও (.NET-এ DataFormats.CommaSeparatedValue) সাধারণত ব্যবহৃত। Excel-এর সাথে ইন্টারঅপের জন্য HTML Format (ফরম্যাটিংসহ), CSV (শুধু মান) ও CF_UNICODETEXT (ট্যাব-বিভক্ত) একসঙ্গে দিলে একটি পেস্ট গন্তব্য বেছে নিতে হয় না।
৪. পেস্ট পাশের অনুশীলন — ফরম্যাট অগ্রাধিকার ও যাচাই
৪.১. সমৃদ্ধ ফরম্যাট থেকে নিচে দেখুন
ক্লিপবোর্ডের ফরম্যাট কপি পাশ যে ক্রমে রেখেছে সেই ক্রমে সারবদ্ধ (অর্থাৎ আরও প্রকাশক্ষম থেকে কম)। পেস্ট পাশের বেসলাইন সামলাতে পারেন এমন ফরম্যাটের মধ্যে সবচেয়ে বেশি তথ্য আছে সেখান থেকে দেখা। 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["প্রত্যাখ্যান"]
চিত্র ৫: পেস্ট পাশ সমৃদ্ধ থেকে সরলে দেখে; শুধু প্লেইন টেক্সট পড়লে টেবিল কাঠামো কখনো আসে না।
৪.২. পেস্ট করা ডেটা বাইরের ইনপুট
সহজে মিস হয়, কিন্তু ক্লিপবোর্ড বিষয়বস্তু বাইরের ডেটা, আর কোন অ্যাপ রেখেছে জানা নেই। Microsoftও OLE ক্লিপবোর্ড ডকুমেন্টেশনে সতর্ক করে “clipboard data is not trusted. Parse it carefully before you use it in the app”।7
- HTML Format হেডার অফসেট বাফারের বাইরে নির্দেশ করে না যাচাই করুন (ভাঙা হেডার দেওয়া অ্যাপ আছে)।
- সংখ্যা, তারিখ বা কোড হিসেবে ইমপোর্ট করা মান স্ক্রিন ইনপুটের মতোই যাচাই পার করুক।
- বিশাল ডেটার বিরুদ্ধে প্রতিরক্ষা রাখুন। কেউ কয়েকশ মেগাবাইট ইমেজ বা লক্ষ লাইন টেক্সট পেস্ট করলেও UI ব্লক করবেন না, আর সীমা অতিক্রম করলে প্রত্যাখ্যান করুন। সতর্কতা: .NET-এর GetData, ডাকার মুহূর্তেই পুরো পেলোড ম্যানেজড স্ট্রিংয়ে মূর্ত করে (আর ডিলেড রেন্ডারিং তার অংশ হিসেবে চলে), তাই GetData-এর পর আকার যাচাই প্রতিরক্ষা নয়। Win32-এ GetClipboardData যে HGLOBAL ফেরায় তার GlobalSize যাচাই “ম্যানেজড স্ট্রিং হিসেবে রূপান্তর ও পার্সিংয়ে এগোবেন না” পর্যায়ে প্রতিরক্ষা দেয়, কিন্তু ডিলেড-রেন্ডারিং ফরম্যাটে GetClipboardData নিজেই রেন্ডারিং শুরু করে, তাই কপি-সোর্স পাশে মূর্তকরণ আটকানো যায় না। UI জমতে না দিতে তোলা UI থ্রেড থেকে সরান (তবুও, .NET-এর Clipboard STA চায় বলে Task.Run থ্রেড-পুল থ্রেডে (MTA) নয়, STA সেট করা নিবেদিত থ্রেডে করুন — ধারা ৫.১)।
“বাইরে থেকে যে পথেই আসুক মান ব্যবহারের আগে যাচাই” ধারণা “QR কোডের ডিকোড করা মান কখনোই যেমন আছে তেমন ব্যবহার করবেন না“-এও সাজানো। পেস্ট ব্যবহারকারীর কাজ বলে নিরাপদ ধরে নেওয়াই দুর্ঘটনার শুরু।
flowchart TB
accTitle: পেস্ট করা ডেটা ব্যবহারের আগে যাচাই করুন
accDescr: ক্লিপবোর্ড থেকে নেওয়া ডেটা ফরম্যাট-আছে, পেলোড-টাইপ, আকার-সীমা ও বিষয়বস্তু যাচাই এই ক্রমে পার করে; যেকোনোটা ব্যর্থ হলে প্রত্যাখ্যান বা পরের প্রার্থী ফরম্যাটে পড়ুন
present["ফরম্যাট আছে?"] --> type["পেলোড টাইপ ঠিক?"]
type --> size["আকার সীমার ভেতরে?"]
size --> content["বিষয়বস্তু যাচাই"]
content --> ok["ইমপোর্ট"]
type -.->|"ভুল টাইপ"| rej["প্রত্যাখ্যান / পরের ফরম্যাট"]
size -.->|"অতিরিক্ত বড়"| rej
content -.->|"অবৈধ"| rej
চিত্র ৬: পেস্ট বাইরের ইনপুট; ফরম্যাট, টাইপ, আকার ও বিষয়বস্তু যাচাই পার না হলে গ্রহণ করবেন না।
৫. কপি পাশের অনুশীলন — একসঙ্গে একাধিক ফরম্যাট দেওয়া, আর ডিলেড রেন্ডারিং
৫.১. একসঙ্গে একাধিক ফরম্যাট রাখুন
কপি পাশের অনুশীলন ৪.১-এর উল্টো: সমৃদ্ধ ফরম্যাট ও প্লেইন ফরম্যাট একসঙ্গে দিন। 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 কী মানে পরের উপধারার ডিলেড রেন্ডারিংয়ের সাথে বাঁধা।
৫.২. ডিলেড রেন্ডারিং — “সোর্স বন্ধ করলে আর পেস্ট করা যায় না” কেন
বড় পেলোড অনেক ফরম্যাটে প্রতিবার গড়া অপচয়, তাই ক্লিপবোর্ডে ডিলেড রেন্ডারিং নামের যন্ত্র আছে। 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["বন্ধের পর ফরম্যাট হারায়"]
চিত্র ৭: ডিলেড রেন্ডারিং প্রতিশ্রুতি রাখে; এক্সিটে মূর্তকরণ বাদ দিলে পেস্ট মরে যায়।
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?” ঠিক এই মূর্তকরণ (ফ্লাশ) চালাবেন কি না তার নিশ্চিতকরণ। নিজের অ্যাপে ডিলেড রেন্ডারিং ব্যবহার করলে মনে রাখুন এক্সিট-সময় মূর্তকরণ একই সেটের অংশ। ডিলেড রেন্ডারিং পারফরম্যান্স অপটিমাইজেশন, আর রেন্ডার অনুরোধ মেসেজ প্রক্রিয়ার ভেতরে সিঙ্ক্রোনাসভাবে চলে বলে তৈরি হতে দীর্ঘ সময় লাগে এমন ডেটার ট্রেড-অফ UI জমানো।2
৬. ক্লিপবোর্ড দেখার অনুশীলন — লিসনার, পুনঃচেষ্টা ও ইতিহাস বাদ
৬.১. 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["পুনঃচেষ্টা দিয়ে পড়া (৬.২)"]
readtry --> wait
destroyed["RemoveClipboardFormatListener"] -.->|"নিবন্ধন তোলা"| created
চিত্র ৮: ক্লিপবোর্ড দেখা লিসনার + পুনঃচেষ্টা; পোলিং ও পুরোনো ভিউয়ার চেইন ব্যবহার করবেন না।
// 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);
}
}
৬.২. খুলতে না পারলে পুনঃচেষ্টা
এক সময়ে শুধু একটি উইন্ডো ক্লিপবোর্ড খুলতে পারে; অন্য প্রক্রিয়া খোলা রাখলে OpenClipboard ব্যর্থ হয়।2 WM_CLIPBOARDUPDATE-এর ঠিক পরে কপি সোর্স বা অন্য ওয়াচার প্রায়ই এখনও কাজ করছে, তাই অস্থায়ী পড়া ব্যর্থতা স্বাভাবিক ইভেন্ট। সংক্ষিপ্ত অপেক্ষা (কয়েক দশ মিলিসেকেন্ড) মাঝে রেখে সবসময় কয়েকটি পুনঃচেষ্টা রাখুন। লক্ষ করুন, .NET Clipboard যে ওভারলোড পুনঃচেষ্টা সংখ্যা ও অন্তর নির্দিষ্ট করতে দেয় সেগুলো শুধু লেখার পাশে, SetDataObject। পড়ার পাশে (GetDataObject ও বন্ধুরা) সমতুল্য নেই, তাই ক্যাচ-অপেক্ষা-পুনঃচেষ্টা নিজে লিখুন — WinForms-এ ExternalException, WPF-এ COMException।
flowchart TB
accTitle: ক্লিপবোর্ড-পড়া পুনঃচেষ্টার প্রবাহ
accDescr: এক সময়ে শুধু একটি উইন্ডো ক্লিপবোর্ড খুলতে পারে, তাই বদল নোটিফিকেশনের ঠিক পরে পড়া অন্য প্রক্রিয়ার সাথে রেসে ব্যর্থ হতে পারে। এক্সেপশনে কয়েক দশ ms অপেক্ষা করে পুনঃচেষ্টা; সীমায় পৌঁছালে এবার ছেড়ে পরের আপডেটে তুলুন
upd["WM_CLIPBOARDUPDATE"] --> tryread["পড়া চেষ্টা"]
tryread -->|"সফল"| useok["ইমপোর্ট (অধ্যায় ৪ যাচাই)"]
tryread -->|"ব্যবহৃত"| waitretry["কয়েক দশ ms অপেক্ষা"]
waitretry -->|"পুনঃচেষ্টা"| tryread
waitretry -->|"সীমা"| giveup2["এবার ছেড়ে দিন"]
চিত্র ৯: নোটিফিকেশনের ঠিক পরে পড়া ব্যর্থ হওয়া স্বাভাবিক; সংক্ষিপ্ত অপেক্ষাসহ পুনঃচেষ্টা রাখুন।
৬.৩. ইতিহাস ও সিঙ্ক থেকে বাইরে রাখুন — গোপন সামলানো কপি ফিচারের যত্ন
Windows-এ ক্লিপবোর্ড ইতিহাস (Win+V) ও ক্রস-ডিভাইস সিঙ্ক (ক্লাউড ক্লিপবোর্ড) আছে, আর অ্যাপ যা রাখে তা ডিফল্টে দুটোরই পরিসরে। পাসওয়ার্ড বা অ্যাকাউন্ট নম্বরের মতো গোপন কপি ফিচারে রাখা অ্যাপ ইতিহাস ও সিঙ্ক থেকে বিষয়বস্তু বাদ দেওয়া রেজিস্টার্ড ফরম্যাটও রাখে।1
- ExcludeClipboardContentFromMonitorProcessing: এটি রাখলে সেই কপির বিষয়বস্তু ইতিহাসেও সিঙ্কেও যায় না।
- CanIncludeInClipboardHistory (DWORD 0): শুধু ইতিহাস দমন।
- CanUploadToCloudClipboard (DWORD 0): শুধু ক্রস-ডিভাইস সিঙ্ক দমন।
পাসওয়ার্ড ম্যানেজার যে পাসওয়ার্ড কপি করে Win+V-তে থাকে না তার কারণ এই যন্ত্র। নাম RegisterClipboardFormat-এ দিয়ে ফরম্যাট ID পান আর সাধারণ ডেটার পাশে সেট করুন, তাই গোপন সামলানো যেকোনো ব্যবসায়িক অ্যাপে বাস্তবায়ন করা মূল্যবান।
৭. 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["অ্যাপ বাদ-দেওয়া ফরম্যাট (৬.৩)"]
চিত্র ১০: ইতিহাস, ক্লাউড সিঙ্ক ও RDP ডিফল্টে খোলা; গোপন সামলানো পরিবেশে ইচ্ছাকৃতভাবে ঠিক করুন।
৮. ড্র্যাগ অ্যান্ড ড্রপ COM — IDataObject + IDropSource + IDropTarget
৮.১. ক্লিপবোর্ডের একই ডেটা, বহনের আলাদা উপায়
OLE ড্র্যাগ অ্যান্ড ড্রপ নিচের তিন ভূমিকায় চলে।12
| ভূমিকা | কে বাস্তবায়ন করে | কাজ |
|---|---|---|
| IDataObject | ড্র্যাগ সোর্স | যে পেলোড বহন করা হচ্ছে। ক্লিপবোর্ডের একই বহু-ফরম্যাট ডেটা অবজেক্ট |
| IDropSource | ড্র্যাগ সোর্স | ড্র্যাগ চলবে নাকি বাতিল, আর কার্সার ফিডব্যাক ঠিক করা |
| IDropTarget | ড্রপ টার্গেট | DragEnter/DragOver/DragLeave/Drop-এ গ্রহণ/প্রত্যাখ্যান ঘোষণা, আর ড্রপ গ্রহণ |
ড্র্যাগ সোর্স DoDragDrop ডাকে, ড্র্যাগ লুপ শুরু হয়, আর মাউস ড্রপ-টার্গেট উইন্ডোতে ঢুকলে IDropTarget জানানো হয়; ড্রপে IDataObject হস্তান্তর হয়। অফিসিয়াল ডকুমেন্টেশনও বলে “D&D ক্লিপবোর্ড কপি-অ্যান্ড-পেস্টের ঠিক একই কার্যকারিতা দেয়। অ্যাপ ইতিমধ্যে কপি-অ্যান্ড-পেস্ট বাস্তবায়ন করলে যোগ ছোট”।12 অর্থাৎ অধ্যায় ২ থেকে ৫-এ যে বহু-ফরম্যাট 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["ফরম্যাট বেছে তোলা"]
চিত্র ১১: D&D ক্লিপবোর্ডের একই IDataObject বহন করে; কপি-অ্যান্ড-পেস্ট থাকলে যোগ ছোট।
৮.২. 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 প্রথা; বাদ দিলে বাগ হয় যেখানে কার্সার “অনুমোদিত নয়”-এ থেকে যায় আর বদলায় না।
৯. D&D-এর ফাঁদ — এলিভেশন, মুভ ও পাথ যাচাই
৯.১. অ্যাডমিনিস্ট্রেটর হিসেবে এলিভেটেড অ্যাপে ড্রপ করা যায় না
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["আলাদা এলিভেটেড প্রক্রিয়া"]
চিত্র ১২: এলিভেটেড অ্যাপে ড্রপ UIPI আটকায়; UI সাধারণ সুবিধায় রাখলে ড্রপ আসে।
ChangeWindowMessageFilterEx দিয়ে WM_DROPFILES-এর মতো নির্দিষ্ট মেসেজ আলাদা অনুমোদন করার ওয়ার্কঅ্যারাউন্ড সুপরিচিত,14 কিন্তু যা পার করে দেয় তা পুরোনো (WM_DROPFILES) ড্রপ নোটিফিকেশন; OLE D&D সামগ্রিকভাবে সমাধান করে না। ব্যবহারিক নির্দেশনা স্পষ্ট: অ্যাপকে সবসময় এলিভেটেড চালানো ডিজাইন বন্ধ করুন। শুধু এলিভেশন দরকার এমন কাজ আলাদা প্রক্রিয়ায় আলাদা করুন, আর UI নিজে সাধারণ সুবিধায় থেকে D&D পেতে পারে (আলাদাকরণ ডিজাইন “Windows অ্যাপে "শুধু যে কাজগুলোর অ্যাডমিনিস্ট্রেটর সুবিধা দরকার" কংক্রিটভাবে কীভাবে আলাদা করবেন“-এ বিস্তারিত)।
৯.২. 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["সোর্স ফাইল মুছে দেয়"]
চিত্র ১৩: ইমপোর্টে গ্রহণ পাশ Copy বলুক; Move আসল ফাইল মুছে দেওয়ার চুক্তি।
৯.৩. ড্রপ করা পাথ যাচাই
CF_HDROP/FileDrop-এ যা যায় শুধু পাথ (ধারা ৩.২)। ইমপোর্টের আগে পেস্টের মতোই অবিশ্বস্ত-ইনপুট যাচাই পার করান।
- ফাইল নাকি ফোল্ডার: পুরো ফোল্ডার ড্রপ হলে কী হয় স্পেক হিসেবে ঠিক করুন (রিকার্স করে ইমপোর্ট, নাকি প্রত্যাখ্যান)।
- OneDrive প্লেসহোল্ডার: পাথ থাকতে পারে অথচ ফাইল বডি স্থানীয় নয় — অন-ডিমান্ড ফাইল। খোলার মুহূর্তে ডাউনলোড শুরু হয়, আর অফলাইনে ব্যর্থ হয়। আচরণ ও প্রতিরোধ “OneDrive "Files On-Demand" ও ব্যবসায়িক অ্যাপ“-এ।
- দীর্ঘ পাথ ও অস্বাভাবিক পাথ: MAX_PATH-এর উপর পাথ, নেটওয়ার্ক (UNC) পাথ ও রিমুভেবল মিডিয়ার পাথ ডাউনস্ট্রিম প্রক্রিয়া সামলাতে পারে নিশ্চিত করার পরই গ্রহণ করুন।
- সংখ্যা ও মোট আকার: হাজার হাজার ফাইল ড্রপ করলে UI যাতে না জমে, ইমপোর্ট অ্যাসিঙ্ক্রোনাস করুন আর সীমা ও অগ্রগতি ডিসপ্লে রাখুন।
১০. সারসংক্ষেপ
- ক্লিপবোর্ড একই ডেস্কটপের (উইন্ডো স্টেশন) শেয়ার করা একটি এলাকায় একই বিষয়বস্তু একসঙ্গে একাধিক ফরম্যাটে রাখার যন্ত্র। পেস্ট পাশ ফরম্যাট বেছে নেয়, তাই একই কপি আলাদা ফল দেয়।
- টেক্সট CF_UNICODETEXT, ফাইল CF_HDROP, আর ফরম্যাটেড টেক্সট রেজিস্টার্ড ফরম্যাট HTML Format (বাইট-অফসেট হেডার + UTF-8)।
- পেস্ট পাশ সমৃদ্ধ থেকে সরলে দেখে আর পেলোডকে বাইরের ইনপুট ধরে। কপি পাশ একসঙ্গে একাধিক ফরম্যাট দেয়, আর ডিলেড রেন্ডারিং ব্যবহার করলে এক্সিট-সময় মূর্তকরণও (WM_RENDERALLFORMATS / OleFlushClipboard) বাস্তবায়ন করে।
- দেখা AddClipboardFormatListener + WM_CLIPBOARDUPDATE। OpenClipboard রেসের জন্য পুনঃচেষ্টা প্রস্তুত রাখুন, আর ExcludeClipboardContentFromMonitorProcessing ও বন্ধুরা দিয়ে গোপন ইতিহাস ও সিঙ্ক থেকে বাইরে রাখুন।
- IT GPO / Intune দিয়ে ক্লিপবোর্ড ইতিহাস, ক্লাউড সিঙ্ক ও RDP রিডাইরেকশন নিয়ন্ত্রণ করতে পারে। সবগুলোর ডিফল্ট অনুমোদিত, তাই গোপন সামলানো পরিবেশে ইচ্ছাকৃতভাবে ঠিক করুন।
- 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-এর নিচের স্তর জড়িত কেস উপসর্গ আলাদা করা থেকে শুরু করলেও স্বাগত।
- Windows অ্যাপ্লিকেশন ডেভেলপমেন্ট
- COM কম্পোনেন্ট ডেভেলপমেন্ট
- টেকনিক্যাল কনসালটিং ও ডিজাইন রিভিউ
- যোগাযোগ করুন
তথ্যসূত্র
-
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_LOCALE-এর সাথে যুক্ত কোড পেজ ব্যবহার করে CF_TEXT ও CF_UNICODETEXT অন্তর্নিহিতভাবে রূপান্তর করা সম্পর্কে। ↩ ↩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 বিচার করে উইন্ডো ৫ সেকেন্ড মেসেজ তোলেনি আর তাকে ঘোস্ট উইন্ডো দিয়ে বদলায়। এই নিবন্ধ সেই...
Win32 থ্রেড পুল API — CreateThreadpoolWork দিয়ে থ্রেড তৈরি না করে কনকারেন্সি
নেটিভ কোডে চারদিকে CreateThread ডাকছেন? এই নিবন্ধ Vista-তে নতুন করে সাজানো Win32 থ্রেড পুল API ব্যাখ্যা করে — work, timer, wait ও io চারট...
নেমড পাইপ ব্যবহারিকভাবে — ডিজাইন থেকে নিরাপত্তা পর্যন্ত Windows-এর মানক IPC
Windows-এর মানক আন্তঃপ্রক্রিয়া যোগাযোগ নেমড পাইপের ব্যবহারিক গাইড। প্রাথমিক উৎস থেকে এই নিবন্ধ বাইট ও মেসেজ মোডের পছন্দ, একাধিক ক্লায়েন...
ঘুম থেকে জাগলে ভাঙে যে অ্যাপ — Windows পাওয়ার ইভেন্টের কাজ ও যে ব্যবসায়িক অ্যাপ তা সহ্য করে
ল্যাপটপ খুললেন আর ব্যবসায়িক অ্যাপের সংযোগ মৃত — কারণ ঘুম ধরে না নেওয়া ডিজাইন। এই নিবন্ধ WM_POWERBROADCAST নোটিফিকেশন প্রবাহ, Modern Sta...
DllMain ও লোডার লক — DLL ইনিশিয়ালাইজেশনে "কিছুই করবেন না" বলা হয় তার আসল কারণ
DllMain থেকে LoadLibrary ডাকা বা অন্য থ্রেডের সাথে সিঙ্ক্রোনাইজ করা যায় না কেন। প্রাথমিক উৎস থেকে এই নিবন্ধ ব্যাখ্যা করে লোডার লক প্রতিট...
সম্পর্কিত বিষয়
এই পৃষ্ঠাগুলো বিষয়টিকে সেবা ও সিদ্ধান্তের বৃহত্তর প্রেক্ষাপটে স্থাপন করে।
Windows-এর প্রযুক্তিগত বিষয়
Windows ডেভেলপমেন্ট, বাগ তদন্ত ও বিদ্যমান সম্পদ ব্যবহারের প্রবেশদ্বার।
ActiveX মাইগ্রেশন
COM / ActiveX / OCX কম্পোনেন্ট রাখা, র্যাপ করা বা প্রতিস্থাপনের সিদ্ধান্ত।
UI থ্রেড ও টাইমার
WPF / WinForms-এর UI থ্রেড, অ্যাসিনক্রোনাস প্রবাহ, Dispatcher ও টাইমার ডিজাইন।
এই বিষয়ের সাথে সম্পর্কিত সেবা
নিবন্ধটি নিচের সেবাগুলোর সাথে সরাসরি সম্পর্কিত।
Windows অ্যাপ ডেভেলপমেন্ট
ব্যবসায়িক অ্যাপ, ডিভাইস ইন্টিগ্রেশন ও যোগাযোগ টুল, চাহিদা থেকে ডেভেলপমেন্ট পর্যন্ত।
বিদ্যমান সম্পদের পুনর্ব্যবহার ও মাইগ্রেশন
COM / ActiveX / OCX সম্পদ এবং ৩২/৬৪-বিট নির্ভরতার পুনর্ব্যবহার ও মাইগ্রেশন।
প্রায়শ জিজ্ঞাসিত প্রশ্ন
এই নিবন্ধের বিষয়ে পরামর্শে প্রায়ই আসা প্রশ্ন।
- 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-এর মতো মেসেজ আলাদা অনুমোদন করার ওয়ার্কঅ্যারাউন্ড সুপরিচিত, কিন্তু তা শুধু পুরোনো ড্রপ নোটিফিকেশনে প্রযোজ্য। আসল সমাধান অ্যাপকে সবসময় এলিভেটেড চালানো ডিজাইন বন্ধ করা, আর শুধু এলিভেশন দরকার এমন কাজ আলাদা প্রক্রিয়ায় আলাদা করা।