当前位置:首页 > 芯闻号 > 充电吧
[导读]如何与资源管理器互动剪切/拷贝/粘贴文件 2016-06-06一.本文将向读者介绍下面两个问题的解决方案:1,用户在资源管理器(Windows Explorer)中剪切/拷贝(Cut/Copy)文件,

如何与资源管理器互动剪切/拷贝/粘贴文件 2016-06-06

一.本文将向读者介绍下面两个问题的解决方案:

1,用户在资源管理器(Windows Explorer)中剪切/拷贝(Cut/Copy)文件,然后在自己的应用程序中进行粘贴(Paste)操作;

2.用户在自己的应用程序中剪切/拷贝文件,在资源管理其中粘贴操作。

二.本文中的代码编写工具及测试环境:

1,VC6.0, Platform SDK(无须MFC);

2.Windows 2000。

三.概述

我们知道,在Windows中可以通过剪贴板(Clipboard)来共享和传递数据,比如在资源管理器(Windows Explorer)中可以剪切/拷贝/粘贴文件。同样我们也可以在自己的应用程序中通过剪贴板来完成这些工作,从而提高我们自己的应用程序与Windows操作系统之间的互操作性。但我们如何才能与资源管理器之类的应用程序共享和传递数据呢?本文提供的方法是:使用Windows本身提供的一些数据结构和API,通过剪贴板来实现数据共享和传递。

四.实现方法

首先,Windows在剪切/拷贝文件时并不是把文件名称写入剪贴板,而是在剪贴板中放入了一个DragAndDrop文件对象,并写入了一个状态值来标识操作类型(移动/拷贝,剪切其实就是移动,如果你剪切之后并没有粘贴,那么该文件依然存在而不会被删除)。依据这个知识,我们首先来看看在应用程序中如何识别出Windows 资源管理器的剪切/拷贝动作。

在使用剪贴板前,我们首先要打开它:

1 2BOOL OpenClipboard(HWND hWnd);参数 hWnd 是打开剪贴板的窗口句柄,成功返回TRUE,失败返回FALSE。

之后,可以用GetClipboardData来得到剪贴板中的数据:

1HANDLEGetClipboardData(UINTuFormat);

uFormat是所需要数据的格式,例如本文拖放对象的格式为CF_HDROP。而表明该拖放对象类型(Move/Copy)的数据格式并不是Windows标准的剪贴板数据结构,而是一个简单的DWORD指针。我们可以通过下面的语句来注册一下数据类型 :

1UINT uDropEffect=RegisterClipboardFormat("Preferred DropEffect");

这里返回的uDropEffect就是我们将要代入GetClipboardData函数的该数据结构的代码,GetClipboardData函数返回是一个句柄,这只是Windows为了统一性而做的工作,我们可以根据需要来转换成相应的数据形式,比如我们的uDropEffect就是一个DWORD指针。

前面我已经说过在剪贴板中放的是一个拖放对象,因此我们可以通过如下语句得到该对象:

1HDROP hDrop = HDROP( GetClipboardData( CF_HDROP));

如果确实存在一个hDrop对象,我们应该取得uDropEffect的数据,以便我们处理后面的文件:

1DWORD dwEffect=*((DWORD*)(GetClipboardData( uDropEffcet)));

关于这个值的含义,我们只要包含一下"OLEIDL.H"头文件即可,在该头文件中5种状态的定义而本文只关注:

1 2#define DROPEFFECT_COPY ( 1 )#define DROPEFFECT_MOVE ( 2 )

因此,我们可以通过

1 2 3 4if(dwEffect & DROPEFFECT_COPY)  CopyFile(....);else (dwEffect & DROPEFFECT_MOVE)  MoveFile(...);

来完成剪切/拷贝操作。

在我们取得uDropEffect状态之后,我们需要得到文件列表,得到拖放对象中的文件列表可以通过DragQueryFile来实现:

1UINT DragQueryFile(HDROP hDrop, UINT iFile,LPTSTRlpszFile,UINTcch);

第二个参数是文件序列号,可以通过将iFile置为-1的方法来得到文件数量。

最后我们给出完整的例子:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37#include < Shellapi.h >#include < oleidl.h > ....   UINTuDropEffect=RegisterClipboardFormat("Preferred DropEffect");     if( OpenClipboard( hWnd)) {        HDROPhDrop = HDROP( GetClipboardData( CF_HDROP));        if( hDrop) {            DWORDdwEffect,*dw;            dw=(DWORD*)(GetClipboardData( uDropEffect));            if(dw==NULL)                dwEffect=DROPEFFECT_COPY;            else                dwEffect=*dw;                     charBuf[4096];            Buf[0] = 0;            UINTcFiles = DragQueryFile( hDrop, (UINT) -1, NULL, 0);            POINT Point;            charszFile[ MAX_PATH];            for(UINT count = 0; count < cFiles; count++ ) {                DragQueryFile( hDrop, count, szFile,sizeof( szFile));                lstrcat(Buf,szFile);                lstrcat(Buf,"n");            }                 if(dwEffect & DROPEFFECT_MOVE) {                MessageBox(NULL,Buf,"Move Files",MB_OK);            }else  if(dwEffect & DROPEFFECT_COPY) {                    MessageBox(NULL,Buf,"Copy Files",MB_OK);            }             CloseClipboard();        }    }

在这个例子中,我并没有进行文件操作,只是简单的显示一个消息框,实际应用时,需要使用MoveFile和CopyFile函数来完成,本文不做讨论。 

知道如何识别其他程序的剪切/拷贝 文件的动作后,我们对该操作的数据结构已经很了解了,要想让其他程序能识别我们的剪切/拷贝 文件动作其实就是将以上数据结构放入剪贴板的过程。

在我们这个例子中,往剪贴板中放的数据必须是内存对象:HGLOBAL。这个对象可以通过GlobalAlloc来生成。然后使用GlobalLock就可以得到该对象的内存地址,继而往里面写 数据。实际上在Win32中由于进程拥有独立的内存空间,因而常规的内存分配已经不需要GlobalLock了,看看MSDN就知道该函数主要就是为DDE和剪贴板服务的。 

根据前面的知识,要想让其他程序识别出我们的剪切/拷贝动作我们必须往剪贴板中放两项数据,现在就让我们来为DropEffect准备数据吧,同样我们需要先注册该数据格式:

1uDropEffect=RegisterClipboardFormat("Preferred DropEffect");

然后分配内存对象并得到指针:

1 2hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(DWORD));dwDropEffect=(DWORD*)GlobalLock(hGblEffect);

注意往剪贴板中放的数据必须使用GMEM_MOVEABLE标志,最后我们设置数据并解除锁定:

1 2 3 4 5if(COPY)  *dwDropEffect=DROPEFFECT_COPY;else *dwDropEffect=DROPEFFECT_MOVE;GlobalUnlock(hGblEffect);

这样我就为DropEffect准备还数据了,等一会儿我们连同文件拖放对象一起放入剪贴板。建立文件拖放对象的方法与DropEffect基本相同,只是文件拖放对象有特殊的数据结构 而不象DropEffect那样简单,该对象数据结构如下:

1 2 3+----------------------------+|  DROPFILES  |  Files List  |+----------------------------+

DROPFILES是拖放对象的头数据,该结构在shlobj.h中定义:

1 2 3 4 5 6typedefstruct _DROPFILES {    DWORDpFiles;     POINT pt;    BOOLfNC;     BOOLfWide; } DROPFILES, FAR * LPDROPFILES;

 pFiles指针是以对象首地址为参照的文件列表(上图中的Files List项)的offset量。通常该值等于DROPFILES结构的长度(我还没见过例外);pt表明文件拖放的位置坐标,在这个例子里我们忽略为0; fNC表明pt值是否为客户区坐标(FALSE表明是屏幕坐标);fWide表明Files List是否包含unicode,作为中国人,我们当然要设其为TRUE。DROPFILES结构之后紧跟Files List,Files List是一组宽字符串,之间以0相隔,比如:"文件1文件2..."

我们可以通过MultiByteToWideChar函数将常规的字符串转换成宽字符串。下面就是生成拖放对象的代码:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22uDropFilesLen=sizeof(DROPFILES);dropFiles.pFiles =uDropFilesLen;dropFiles.pt.x=0;dropFiles.pt.y=0;dropFiles.fNC =FALSE;dropFiles.fWide =TRUE; uGblLen=uDropFilesLen+uBufLen<<1+8;//uBufLen是文件名字符传组的长度,由于要转换成宽字符,因此长度要乘2 hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen);szData=(char*)GlobalLock(hGblFiles);memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen);//将DROPFILES copy到头部 szFileList=szData+uDropFilesLen;//得到存放文件列表的首地址 MultiByteToWideChar(CP_ACP,MB_COMPOSITE,    lpBuffer,uBufLen,(WCHAR*)szFileList,uBufLen);     GlobalUnlock(hGblFiles);

现在我们就可以将上面两组数据放入剪贴板中了,注意在写数据前应先清空剪贴板。为了方便大家使用,下面我给出实现此功能的独立的函数:

1VOID CutOrCopyFiles(char * lpBuffer,UINT uBufLen,BOOL bCopy)

lpBuffer是包括所有准备剪切/拷贝的文件名称的缓冲区;uBufLen是lpBuffer的长度;bCopy决定该操作是Copy还是Cut,TRUE为Copy,FALSE为Cut。例如我们可以这样调用该函数:

1 2char szFiles[]="c:\1.txtc:\2.txt";CutOrCopyFiles(szFiles,sizeof(szFiles),FALSE);

来剪切文件,或者使用:

1CutOrCopyFiles(szFiles,sizeof(szFiles),TRUE);

来拷贝文件。

1 2 3#include < Shellapi.h >#include < Shlobj.h >#include < oleidl.h >1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47...... VOID CutOrCopyFiles(char *lpBuffer,UINT uBufLen,BOOL bCopy){    UINTuDropEffect;    DROPFILES dropFiles;    UINTuGblLen,uDropFilesLen;    HGLOBALhGblFiles,hGblEffect;    char*szData,*szFileList;     DWORD*dwDropEffect;     uDropEffect=RegisterClipboardFormat("Preferred DropEffect");    hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(DWORD));    dwDropEffect=(DWORD*)GlobalLock(hGblEffect);    if(bCopy)        *dwDropEffect=DROPEFFECT_COPY;    else        *dwDropEffect=DROPEFFECT_MOVE;    GlobalUnlock(hGblEffect);     uDropFilesLen=sizeof(DROPFILES);    dropFiles.pFiles =uDropFilesLen;    dropFiles.pt.x=0;    dropFiles.pt.y=0;    dropFiles.fNC =FALSE;    dropFiles.fWide =TRUE;     uGblLen=uDropFilesLen+uBufLen*2+8;    hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen);    szData=(char*)GlobalLock(hGblFiles);    memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen);    szFileList=szData+uDropFilesLen;     MultiByteToWideChar(CP_ACP,MB_COMPOSITE,            lpBuffer,uBufLen,(WCHAR*)szFileList,uBufLen);         GlobalUnlock(hGblFiles);     if( OpenClipboard(NULL) )    {        EmptyClipboard();        SetClipboardData( CF_HDROP, hGblFiles );        SetClipboardData(uDropEffect,hGblEffect);        CloseClipboard();    }}

希望以上内容对你有所帮助。 

本文附上一个Demo工程,编译后生成CutCopy.exe程序,该程序的使用方法如下: 

启动程序后,可使用Windows 资源管理器等程序剪切/拷贝文件,然后点程序中的[CheckClipboard],Demo程序将分析剪贴板中的内容,并弹出消息框告知是Copy Files还是Cut Files,并给出文件列表.用户点[OK]关闭消息框后,文件列表 将被放入文本框中,此时用户可以通过[Cut]/[Copy]按钮来改变剪贴板中的属性。 

同时,用户可以通过[Browser]来选择若干文件到文本框中,然后点[Cut]/[Copy]进行操作,之后,用户既可以通过[CheckClipboard]检查剪贴板中的内容也可以通过在Windows 资源管理器等程序中进行粘贴(Paste)来检查其是否正确。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭