需要用 IDropTarget 来实现文字拖放。
• 选择菜单 File → New → Unit
• 或者选择 File → New → Other 在打开的对话框里面选择 C++ Builder Files → Unit
新建一个 Unit,例如新建的是 Unit2,那么包含 Unit2.h 和 Unit2.cpp 两个文件。
其中 Unit2.h 的内如如下,是一个从 IDropTarget 继承的 TMyDropTarget 类:
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <vcl.h>
//---------------------------------------------------------------------------
class TMyDropTarget: public IDropTarget
{
public:
typedef void __fastcall (__closure *TOnGetFormat)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt, DWORD &dpe, bool &bDataOK);
typedef void __fastcall (__closure *TOnProcessData)(IDropTarget *Sender, IDataObject *DataObject, DWORD KeyState, TPoint pt);
typedef void __fastcall (__closure *TOnProcessText)(IDropTarget *Sender, UnicodeString AText, DWORD KeyState, TPoint pt);
__property TOnGetFormat OnGetFormat = { read = _lpfnGetFormat , write = _lpfnGetFormat };
__property TOnProcessData OnProcessData = { read = _lpfnProcessData , write = _lpfnProcessData };
__property TOnProcessText OnProcessText = { read = _lpfnProcessText , write = _lpfnProcessText };
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);
TMyDropTarget(TWinControl *AOwner);
~TMyDropTarget();
private:
ULONG _iRefCount;
IDataObject *_lpDataObj;
TWinControl *_OwnerControl;
TOnGetFormat _lpfnGetFormat;
TOnProcessData _lpfnProcessData;
TOnProcessText _lpfnProcessText;
bool __fastcall _DataFormatOK(DWORD KeyState, POINTL pt, DWORD &dpe);
void __fastcall _ProcessData(DWORD KeyState, POINTL pt);
};
//---------------------------------------------------------------------------
#endif
//--------------------------------------------------------------------------- |
Unit2.cpp 是 TMyDropTarget 的实现部分:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
TMyDropTarget::TMyDropTarget(TWinControl *AOwner)
{
_OwnerControl = AOwner;
_iRefCount = 0;
_lpDataObj = NULL;
_lpfnGetFormat = NULL;
_lpfnProcessData = NULL;
_lpfnProcessText = 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;
_DataFormatOK(grfKeyState, pt, *pdwEffect);
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall TMyDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
_DataFormatOK(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(_DataFormatOK(grfKeyState, pt, *pdwEffect))
_ProcessData(grfKeyState, pt);
return S_OK;
}
//---------------------------------------------------------------------------
bool __fastcall TMyDropTarget::_DataFormatOK(DWORD KeyState, POINTL pt, DWORD &dpe)
{
FORMATETC fetc={ CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, DWORD(-1) };
bool bOK=_lpDataObj->QueryGetData(&fetc)==S_OK;
dpe = bOK ? DROPEFFECT_COPY : DROPEFFECT_NONE;
if(_lpfnGetFormat)
{
TPoint point(pt.x, pt.y);
::ScreenToClient(_OwnerControl->Handle, &point);
_lpfnGetFormat(this, _lpDataObj, KeyState, point, dpe, bOK);
}
return bOK;
}
//---------------------------------------------------------------------------
void __fastcall TMyDropTarget::_ProcessData(DWORD KeyState, POINTL pt)
{
if(_lpfnProcessData)
{
TPoint point(pt.x,pt.y);
::ScreenToClient(_OwnerControl->Handle, &point);
_lpfnProcessData(this, _lpDataObj, KeyState, point);
}
else if(_lpfnProcessText)
{
STGMEDIUM smed;
FORMATETC fetc={ CF_UNICODETEXT, 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);
_lpfnProcessText(this, (wchar_t*)hData, KeyState, point);
GlobalUnlock(hData);
GlobalFree(hData);
}
}
}
}
//--------------------------------------------------------------------------- |
在主窗口里面添加拖放文字功能:
• 在主窗口上放一个 TMemo 控件 Memo1
• 在主窗口的 .h 文件,例如 Unit1.h 里面,在 TForm1 类的 private 部分里面添加刚才写的 TMyDropTarget 类声明的变量和 DropMemo1Text 函数,如下代码所示:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
private: // User declarations
TMyDropTarget *DropMemo1; //自定义的拖放目标类
void __fastcall DropMemo1Text(IDropTarget *Sender, UnicodeString AText, DWORD KeyState, TPoint pt); //拖放事件
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif |
在主窗口的 .cpp 文件 Unit1.cpp 里面添加拖放的实现部分,完成的代码如下:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__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, UnicodeString AText, DWORD KeyState, TPoint pt)
{
POINTS p;
p.x = pt.x;
p.y = pt.y;
*(long*)&p = SendMessage(Memo1->Handle, EM_CHARFROMPOS, 0, *(long*)&p);
Memo1->SelStart = p.x;
Memo1->SelLength = 0;
Memo1->SelText = AText;
}
//--------------------------------------------------------------------------- |
相关链接:把文件拖拽到窗口里面,获取文件名列表并且显示出来
|