让窗体支持文件拖拽

来源:互联网 发布:淘宝开店怎么认证不了 编辑:程序博客网 时间:2024/05/22 06:19

一、基本概念

拖放,是指用鼠标拖动的方法,在不同程序的窗口之间、同一个程序的不同窗口之间或同一程序同一窗口的不同控件之间,进行移动、复制和粘贴等操作的技术。拖放操作是在操作系统的帮助下完成的。被拖动的对象首先向操作系统注册它使用的数据格式,并按指定的数据格式提供数据,拖放操作结束时,接收拖放的窗口按指定的数据格式提取有关数据,并根据提取的数据生成相应的对象。

二、两种拖放方式

拖放有两种类型:OLE拖放和文件管理器拖放。这两种方式是完全不同的机制。文件管理器拖放只能处理文件名,通过映射目的窗口的WM_DROPFILES消息,窗口就可以收到拖放进来的文件名。OLE拖放则更加通用一些,它允许你拖放可同时被保存在剪贴板上的任何数据。本文首先介绍文件管理器拖放,然后再介绍OLE拖放,最后给出一个用OLE实现的,支持文件拖放操作的增强列表控件CListCtrlEx

三、文件管理器拖放原理及实例

这种方式的实质就是产生一个消息WM_DROPFILES。技术上没有什么难点,主要用到下面几个API函数:DragQueryFileDragQueryPointDragFinish。它们的原型和注解分别如下:

UINT DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch)

本函数用来取得拖放的文件名。其中,hDrop是一个指向含有被拖放的文件名的结构体的句柄;iFiles是要查询的文件序号,因为一次可能同时拖动很多个文件;lpszFiles是出口缓冲区指针,保存iFiles指定序号的文件的路径名,cch指定该缓冲区的大小。有两点值得注意,第一,如果我们在调用该函数的时候,指定iFile0xFFFFFFFF,则DragQueryFile将忽略lpszFilecch参数,返回本次拖放操作的文件数目;第二,如果指定lpszFileNULL,则函数将返回实际所需的缓冲区长度。

BOOL DragQueryPoint(HDROP hDrop, LPPOINT lppt);

本函数用来获取,当拖放操作正在进行时,鼠标指针的位置。第二个参数lppt是一个指向POINT结构体的指针,用来保存文件放下时,鼠标指针的位置。窗口可以调用该函数以查询文件是否落在自己的窗口矩形中。

void DragFinish(HDROP hDrop);

当拖放操作处理完毕后需调用该函数释放系统分配来传输文件名的内存。

首先,建立一个对话框工程,确保选中对话框的Accept Files属性。如果不选,也可以在窗口创建的时候(譬如OnCreate函数中)调用DragAcceptFiles(TRUE),效果是一样的。

然后映射WM_DROPFILES消息。该消息处理函数原型如下:void OnDropFiles(HDROP hDrop),注意入口参数为HDROP型,它是一个结构体指针,所指向的结构体中包含了被拖放的文件的名称。接下来我们主要要完成两个动作:第一,通过调用DragQueryFile并指定其iFile参数为0xFFFFFFFF,得到本次拖放操作的文件数目;第二步,用一个循环依次取出各个文件名。示例如下:

void CListCtrlEx::OnDropFiles(HDROP hDrop)

{

        char   szFilePathName[_MAX_PATH+1] = {0};

UINT nNumOfFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); //得到文件个数

        for (UINT nIndex=0 ; nIndex< nFileCount; ++nIndex)

        {

            DragQueryFile(hDrop, nIndex, szFilePathName, _MAX_PATH); //得到文件名

        }

        DragFinish(hDrop);

}

 

原创粉丝点击