主页C++ Builder 源码把其它程序 (如网页等) 的文字拖放到 Memo 里
Victor 串口控件
 • 最新版本 (VCL/FMX)
 • 常见问题及解决方法
 • 以往版本串口控件
控件安装方法
 • XE6 ~ C10 (CX)
 • XE2 ~ XE5
 • 2007/2009/2010/XE
 • BCB5, BCB6
使用简介
串口控件详细说明
串口调试工具
C++ Builder 资料
C++ Builder 编程技巧
C++ Builder 操作指南
C++ Builder 参考手册
C++ Builder 资源
控件
SDK 开发库
源码
软件发布
更新动态
网站更新记录
网友留言/技术支持
把其它程序 (如网页等) 的文字拖放到 Memo 里

注:这是老版本 (BCB6 及之前版本) 的程序,
2009 之后的新版本 (解决字符编码问题) 请点击:新版文字拖放到 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);
            }
        }
    }
}
//---------------------------------------------------------------------------

相关链接:
2009之后新版本 (解决字符编码问题):把其他程序(网页或文字编辑等)里面的文字拖拽到 Memo 编辑框里面
把文件拖拽到窗口里面,获取文件列表并且显示出来


C++ 爱好者 -- Victor Chen 的个人网站 www.cppfans.com 辽ICP备11016859号