主页C++ Builder 资料C++ Builder 编程技巧界面处理其他程序文字拖拽到Memo里
C++ Builder 串口控件
C++ Builder 编程技巧
字符串及文字处理
多媒体处理
图片处理
文件处理
界面处理
 • 使用 Action 控件
 • 其他程序文字拖拽到Memo里
 • 把文件拖拽到窗口里面
 • 枚举控件的属性、事件、成员函数和变量
C++ Builder 操作指南
C++ Builder 参考手册
网友留言/技术支持
把其他程序(网页或文字编辑等)里面的文字拖拽到 Memo 编辑框里面

需要用 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;
}
//---------------------------------------------------------------------------

 

相关链接:把文件拖拽到窗口里面,获取文件名列表并且显示出来

◤上一页:使用 Action 控件下一页:把文件拖拽到窗口里面

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