實現從 WordPad、瀏覽器等外部應用拖選文字,拖放到應用程式 TMemo 控件指定光標位置,自動插入文本。
TMyDropTarget 類別繼承 IDropTarget COM 介面,封裝 OLE 拖放目標邏輯,提供三大事件屬性:
OnGetFormat:檢查資料格式、決定拖放效果OnProcessData:處理通用 IDataObjectOnProcessText:專門處理純文字(CF_TEXT)#include "UnitTMyDropTarget.h"
class TForm1 : public TForm {
private:
TMyDropTarget* DropMemo1;
void __fastcall DropMemo1Text(IDropTarget* Sender, AnsiString AText, DWORD KeyState, TPoint pt);
public:
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
OleInitialize(NULL); // 初始化 OLE
DropMemo1 = new TMyDropTarget(Memo1); // 綁定目標控件
DropMemo1->OnProcessText = DropMemo1Text; // 綁定文字處理事件
}
__fastcall TForm1::~TForm1() {
DropMemo1->Release(); // 釋放 COM 物件(非 delete)
OleUninitialize();
}
void __fastcall TForm1::DropMemo1Text(IDropTarget* Sender, AnsiString AText, DWORD KeyState, TPoint pt) {
// 將螢幕座標轉換為 Memo 字符位置
POINTS p = {pt.x, pt.y};
*(long*)&p = SendMessage(Memo1->Handle, EM_CHARFROMPOS, 0, *(long*)&p);
Memo1->SelStart = p.x; // 設定選取起始位置
Memo1->SelLength = 0; // 無選取範圍
Memo1->SelText = AText; // 插入文字
}
TMyDropTarget 核心實現要點QueryInterface:支援 IUnknown、IDropTargetAddRef/Release:引用計數管理,Release 歸零時 delete thisDragEnter/DragOver/DragLeave/Drop:標準拖放流程FDataFormatOK
bool __fastcall TMyDropTarget::FDataFormatOK(DWORD KeyState, POINTL pt, DWORD& dpe) {
FORMATETC fetc = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
bool bOK = _lpDataObj->QueryGetData(&fetc) == S_OK;
dpe = bOK ? DROPEFFECT_COPY : DROPEFFECT_NONE;
if (_FGetFormat) { /* 觸發用戶事件 */ }
return bOK;
}
FProcessData
void __fastcall TMyDropTarget::FProcessData(DWORD KeyState, POINTL pt) {
if (_FProcessData) { /* 觸發通用事件 */ }
else if (_FProcessText) {
STGMEDIUM smed;
FORMATETC fetc = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (_lpDataObj->GetData(&fetc, &smed) == S_OK) {
HGLOBAL hData = GlobalLock(smed.hGlobal);
if (hData) {
TPoint point(pt.x, pt.y);
::ScreenToClient(_OwnerControl->Handle, &point);
_FProcessText(this, (char*)hData, KeyState, point);
GlobalUnlock(hData);
}
ReleaseStgMedium(&smed); // 釋放儲存介質
}
}
}
ScreenToClient 轉換為控件客戶區座標。GlobalLock/Unlock 存取 HGLOBAL,ReleaseStgMedium 釋放 STGMEDIUM。OleInitialize/OleUninitialize。RegisterDragDrop,解構函數 RevokeDragDrop。同樣架構可輕鬆擴展支援:
CF_HDROP)CF_BITMAP/CF_DIB)RegisterClipboardFormat)封裝 IDropTarget 為 TMyDropTarget 元件,讓 C++Builder 應用輕鬆獲得專業級 OLE 拖放體驗,提升使用者操作直覺性。