DragSource Lib for BCB使用说明

来源:互联网 发布:java 转换json 编辑:程序博客网 时间:2024/05/13 06:21

如果你想让你的软件可以象WinRAR/WinZip一样支持把文件拖曳到资源管理器里, 或者把图片, 文字拖出到Word里,以增强用户体验, 偶的DragSource Lib 是你很好的选择(怎么有点象广告词?).

在你的线程(注意不是进程)使用DragSource Lib函数之前,都要先调用OleInitialize初始化OLE.


函数:
TDropResult DoDragDrop(char *szText,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE); 
开始拖出文本
 szText      指向一个以NULL结尾的字符串
 dwOKEffect  支持哪些操作(默认支持拷贝和移动),可以是以下几种值的组合:
  DROPEFFECT_NONE     什么都不支持
      DROPEFFECT_COPY     支持拷贝
  DROPEFFECT_MOVE     支持移动
  DROPEFFECT_LINK     支持链接
  DROPEFFECT_SCROLL   表示拖放目标窗口正在/将要滚动
 返回值:     拖动结果(TDropResult::Result)和最终拖动类型(TDropResult::Effect)

TDropResult DoDragDropURL(char *URL,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK);
开始拖出网址URL
 URL         网页地址,一个以NULL结尾的字符串.
 dwOKEffect  同上, 默认支持(默认支持拷贝,移动,链接)
 返回值:     同上

TDropResult DoDragDrop(wchar_t *wszText,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE); 
//Drag Unicode Text
开始拖出Unicode文本
 wszText     以NULL结尾的宽字符串.
 dwOKEffect  同上, 默认支持(默认支持拷贝,移动)
 返回值:     同上

TDropResult DoDragDrop(HBITMAP hBitmap,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE); 
//Drag Bitmap
开始拖出BMP图片
 hBitmap     HBITMAP类型,你应该知道是什么.
 dwOKEffect  同上, 默认支持(默认支持拷贝,移动)
 返回值:     同上

TDropResult DoDragDrop(const THDROP_Files &files,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK); 
开始拖出文件
 files       THDROP_Files类型, 存放要被拖出的文件名
 dwOKEffect  同上, 默认支持(默认支持拷贝,移动,链接)
 返回值:     同上

TDropResult DoDragDrop(FORMATETC *fmtetc, STGMEDIUM *stgmeds,UINT count=1,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE); 
用于同时拖出多种格式,比如拖到资源管理器里表现为文件拖动,拖到Word里表现为文字
 fmtetc      FORMATETC数组(定义查MSDN),指出每个数据的格式类型  
 stgmeds     STGMEDIUM数组(定义查MSDN),存储数据指针
 count       格式种类数,也就是FORMATETC数组和STGMEDIUM数组的大小.
 dwOKEffect  同上.
 返回值:     同上

TDropResult DoDragDrop(CLIPFORMAT ctFormat,DWORD tymed,void *hStorage,
  DWORD dwOKEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE); 
拖出一个自定义格式数据
 ctFormat    CLIPFORMAT(还得查MSDN),CLIPFORMAT常用于表示剪切板里的数据类型.
 tymed       存储媒介类型,是在内存里的还是文件里的? 也可以查MSDN(关键字:TYMED)
 hStorage    存储媒介指针,实际上它是STGMEDIUM里的hGlobal/hBitmap/lpszFileName...项,注意调用后hStorage里的数据将被自动释放
 dwOKEffect  同上.
 返回值:     同上

HANDLE MemToHandle (void *pMem, int nSize);
生成适用于DoDragDrop(CLIPFORMAT ctFormat,DWORD tymed,void *hStorage,dwOKEffect)中hGlobal(hStorage)的内存数据.

类:
TDataObject
IDataObject的实现,主要成员函数:
 void Add(FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count);   添加多个数据类型,参考DoDragDrop的定义
 void Add(CLIPFORMAT ctFormat,DWORD tymed,void *hStorage);      添加一个数据类型,参考DoDragDrop的定义
 size_t size();             类型种类数
 bool empty();              是否为空
 void Clear();              清空数据
 void ClearAndRelease();    清空并释放数据
 

TDropSource
IDropSource的实现

TDataObject和TDropSource用于和WINAPI DoDragDrop合作.

THDROP_Files
文件列表类,继承自std::vector<std::string>,用于DoDragDrop(const THDROP_Files &files,dwOKEffect)函数,主要成员函数:
 void *Create_HDROP() const;   根据文件列表生成HDROP数据类型(这可以偶花了一下午时间摸索出来的,偶在MSDN里没查到相关资料,好在比较简单)

 例:
BCB6里新建一工程:

 Form1的OnCreate和OnDestroy分别调用OleInitialize(NULL)和OleUninitialize().
 Form1->OnMouseDown:
 {
  Tag=1;  // Tag=1用来表示鼠标已按下
 }
 Form1->OnMouseUp:
 {
  Tag=0;  // Tag=0用来表示鼠标已松开
 }
 Form1->OnMouseMove:
 {
  if(Tag)
  {
   DoDragDrop("Hello EveryOne!");
   Tag=0;
  }
 } 
编译执行,按住Form1(不是标题栏,是客户区)拖动鼠标到WordPad里试试.

然后把
 DoDragDrop("Hello EveryOne!");
改成:
 DoDragDropURL("http://www.csdn.net");
再拖到IE里试试


再改成
  Graphics::TBitmap *bmp=new Graphics::TBitmap;
                bmp->Width  = Form1->ClientWidth;
                bmp->Height = Form1->ClientHeight;
                Form1->PaintTo(bmp->Canvas,0,0);
                DoDragDrop(bmp->Handle);
  delete bmp;
再拖动到WordPad里试试?


再改一把:
        THDROP_Files files;
        files.push_back(Application->ExeName.c_str());
        files.push_back(ChangeFileExt(Application->ExeName,".cpp").c_str());
     DoDragDrop(files,DROPEFFECT_COPY);
这次请拖到桌面上试试,是不是多了什么? :)


最后再试一个复杂点的(同时支持多种格式):
     TDataObject DataObject;
        TDropSource DropSource;

        THDROP_Files files;
        files.push_back(Application->ExeName.c_str());
        files.push_back(ChangeFileExt(Application->ExeName,".cpp").c_str());

        DataObject.Add(CF_TEXT,TYMED_HGLOBAL,MemToHandle("Hahahaha",8));
        DataObject.Add(CF_HDROP,TYMED_HGLOBAL,files.Create_HDROP());

        DWORD dwEffect;
        DoDragDrop(&DataObject, &DropSource, DROPEFFECT_COPY , &dwEffect);

        DataObject.ClearAndRelease();   //帮我们把MemToHandle和files.Create_HDROP()生成的内存给清理掉

这次要用Word试了, WordPad有时会先处理我们拖进去的文件, 晕~~. 试完Word再试桌面:)

如有更多细节问题或BUG请在Blog上留言.