把其它措施(如网页等)的文字拖放到Memo里
需要用 COM 接口的 OLE 拖放方针, 措施新建一个支持拖放方针的UnitTMyDropTarget 单位, 在这个单位里建设一个 TMyDropTarget 类。
这个措施可以使从写字板可能网页等界说的文本块用鼠标拖动, 放到措施的 Memo 里, 插入到 Memo 的拖放的位置。
首先看看如何利用这个 TMyDropTarget 类:
在 Form 的头文件里 (譬喻 Unit1.h) 需要增加的内容(蓝色部门是新增内容):
#include "UnitTMyDropTarget.h"
class TForm1 : public TForm
{
private: // User declarations
TMyDropTarget *DropMemo1; //自界说的拖放方针类
void __fastcall DropMemo1Text(IDropTarget *Sender, AnsiString AText, DWORD KeyState, TPoint pt); //拖放事件
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
在 From 的 .cpp 文件里 (譬喻 Unit1.cpp), 需要增加的内容(蓝色部门是新增内容):
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
OleInitialize(NULL);
DropMemo1 = new TMyDropTarget(Memo1);
DropMemo1->OnProcessText = DropMemo1Text;
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
DropMemo1->Release();//delete DropMemo1;
OleUninitialize();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::DropMemo1Text(IDropTarget *Sender, AnsiString AText, DWORD KeyState, TPoint pt)
{
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 类的实现:
头文件 UnitTMyDropTarget.h 的内容:
//---------------------------------------------------------------------------
#ifndef UnitTMyDropTargetH
#define UnitTMyDropTargetH
//---------------------------------------------------------------------------
#include "oleidl.h"
#include "controls.hpp"
//---------------------------------------------------------------------------
class TMyDropTarget: public IDropTarget
{
public:
__property void __fastcall (__closure *OnGetFormat)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt, DWORD &dpe, bool &bDataOK) = { read=_FGetFormat, write=_FGetFormat };
__property void __fastcall (__closure *OnProcessData)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt) = { read=_FProcessData, write=_FProcessData };
__property void __fastcall (__closure *OnProcessText)(IDropTarget *Sender, AnsiString AText, DWORD KeyState, TPoint pt) = { read=_FProcessText, write=_FProcessText };
TMyDropTarget(TWinControl *AOwner);
~TMyDropTarget();
HRESULT __stdcall QueryInterface(const GUID &iid, void **ppv);
ULONG __stdcall AddRef(void) { return ++_iRefCount; }
ULONG __stdcall Release(void) { if(--_iRefCount==0){delete this;} return _iRefCount; }
HRESULT __stdcall DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT __stdcall DragLeave(void);
HRESULT __stdcall Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
private:
ULONG _iRefCount;
IDataObject *_lpDataObj;
TWinControl *_OwnerControl;
void __fastcall (__closure *_FGetFormat)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt, DWORD &dpe, bool &bDataOK);
void __fastcall (__closure *_FProcessData)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt);
void __fastcall (__closure *_FProcessText)(IDropTarget *Sender, AnsiString AText, DWORD KeyState, TPoint pt);
bool __fastcall FDataFormatOK(DWORD KeyState, POINTL pt, DWORD &dpe);
void __fastcall FProcessData(DWORD KeyState, POINTL pt);
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
UnitTMyDropTarget.cpp 的内容:
//---------------------------------------------------------------------------
#include "UnitTMyDropTarget.h"
//---------------------------------------------------------------------------
TMyDropTarget::TMyDropTarget(TWinControl *AOwner)
{
_OwnerControl = AOwner;
_iRefCount = 0;
_lpDataObj = NULL;
_FGetFormat = NULL;
_FProcessData = NULL;
_FProcessText = NULL;
RegisterDragDrop(_OwnerControl->Handle,this);
}
//---------------------------------------------------------------------------
TMyDropTarget::~TMyDropTarget()
{
RevokeDragDrop(_OwnerControl->Handle);
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::QueryInterface(const GUID &iid, void **ppv)
{
if((iid==IID_IUnknown)||(iid==IID_IDropTarget))
{
*ppv=this;
AddRef();
}
else
{
*ppv=NULL;
return E_NOINTERFACE;
}
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
_lpDataObj = pDataObject;
FDataFormatOK(grfKeyState,pt,*pdwEffect);
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
FDataFormatOK(grfKeyState,pt,*pdwEffect);
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::DragLeave(void)
{
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
{
_lpDataObj = pDataObject;
if(FDataFormatOK(grfKeyState,pt,*pdwEffect))
FProcessData(grfKeyState,pt);
return S_OK;
}
//---------------------------------------------------------------------------
bool __fastcall TMyDropTarget::FDataFormatOK(DWORD KeyState, POINTL pt, DWORD &dpe)
{
FORMATETC fetc={CF_TEXT,0,DVASPECT_CONTENT,-1,DWORD(-1)};
bool bOK=_lpDataObj->QueryGetData(&fetc)==S_OK;
dpe = bOK?DROPEFFECT_COPY:DROPEFFECT_NONE;
if(_FGetFormat)
{
TPoint point(pt.x,pt.y);
::ScreenToClient(_OwnerControl->Handle,&point);
_FGetFormat(this,_lpDataObj,KeyState,point,dpe,bOK);
}
return bOK;
}
//---------------------------------------------------------------------------
void __fastcall TMyDropTarget::FProcessData(DWORD KeyState, POINTL pt)
{
if(_FProcessData)
{
TPoint point(pt.x,pt.y);
::ScreenToClient(_OwnerControl->Handle,&point);
_FProcessData(this,_lpDataObj,KeyState,point);
}
else if(_FProcessText)
{
STGMEDIUM smed;
FORMATETC fetc={CF_TEXT,0,DVASPECT_CONTENT,-1,DWORD(-1)};
BOOL bValue=(_lpDataObj->GetData(&fetc,&smed)==S_OK);
if(bValue)
{
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);
GlobalFree(hData);
}
}
}
}
//---------------------------------------------------------------------------