类似于windows的复制、剪切、粘贴操作、我们也可以使用剪切板来实现这样的功能。
下面通过一个例子来演示:点击 “复制” 按钮,可以把"D:\temp"文件夹放到剪切板, 右键选择粘贴,可以把该文件夹放到硬盘目录下。点击 “粘贴” 按钮,可以把"D:\temp"这个路径名显示到文本框中。
程序运行界面如下:
复制按钮响应过程:
先建立一个自定义剪切板,用来存放复制或者剪切操作标识符号,判断是哪一种操作;
然后建立一个文件夹剪切板,头部存放一个DROPFILES结构大小内容,之后的空间用来存放文件夹列表
1 void CMyDlg::OnBtnCopy()
2 {
3 // TODO: Add your control notification handler code here
4
5 //要复制剪切的文档或者文件夹
6 char *lpBuffer = "D:\\Temp";
7 UINT uBufLen = strlen(lpBuffer);
8
9 //true拷贝,false剪切
10 bool bCopy = true;
11
12 UINT uDropEffect = 0;
13 DROPFILES dropFiles = {0};
14 UINT uGblLen = 0;
15 UINT uDropFilesLen = 0;
16 HGLOBAL hGblFiles;
17 HGLOBAL hGblEffect;
18 char * szData = NULL;
19 char * szFileList = NULL;
20 DWORD * dwDropEffect = NULL;
21
22 ///////////////////////////自定义剪切板,用来设置标识(复制还是剪切)/////////////////////////
23
24 uDropEffect = RegisterClipboardFormat("Preferred DropEffect"); //参数随便填
25
26 hGblEffect = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(DWORD));
27 dwDropEffect = (DWORD*)GlobalLock(hGblEffect);
28
29 //设置自定义剪切板的内容为复制或者剪切标识
30 if(bCopy)
31 {
32 *dwDropEffect = DROPEFFECT_COPY;
33 }
34 else
35 {
36 *dwDropEffect = DROPEFFECT_MOVE;
37 }
38
39 GlobalUnlock(hGblEffect);
40
41 ///////////////////////////文件剪切板,用来存放文件列表/////////////////////////
42
43 uDropFilesLen = sizeof(DROPFILES);
44 //DROPFILES结构的大小
45 dropFiles.pFiles = uDropFilesLen;
46 dropFiles.pt.x = 0;
47 dropFiles.pt.y = 0;
48 dropFiles.fNC =FALSE;
49 //true: UNICODE, false: ascii
50 dropFiles.fWide =TRUE;
51
52 //uBufLen * 2表示的是宽字符大小, 加8表示文件末尾需要2个空指针结尾,每个指针占4个字节大小
53 uGblLen = uDropFilesLen + uBufLen * 2 + 8;
54 hGblFiles = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, uGblLen);
55
56 szData = (char * )GlobalLock(hGblFiles);
57
58 //把DROPFILES结构大小的内容放到szData剪切板空间的最开始
59 memcpy(szData, (LPVOID)(&dropFiles), uDropFilesLen);
60
61 //szFileList指向需要放入文件的那个空间,前面存放了DROPFILES结构大小的空间
62 szFileList = szData + uDropFilesLen;
63
64 //把文件列表转为宽字符,并存放到szFileList指向的那片空间
65 MultiByteToWideChar(CP_ACP,MB_COMPOSITE,
66 lpBuffer,uBufLen,(WCHAR *)szFileList,uBufLen);
67
68 GlobalUnlock(hGblFiles);
69
70 if( ::OpenClipboard(NULL) )
71 {
72 EmptyClipboard();
73
74 //可以设置剪切板内容为拖动文件
75 SetClipboardData( CF_HDROP, hGblFiles );
76
77 //可以设置剪切板内容为复制或者剪切标识
78 SetClipboardData(uDropEffect,hGblEffect);
79
80 //关闭剪切板
81 CloseClipboard();
82 }
83 }
执行复制操作的时候,程序相当于建立了两个剪切板, 但是想要执行粘贴操作,又该选择哪一个剪切板呢?
执行粘贴操作的时候,我们可以先判断文件夹剪切板格式是否存在,如果存在,则判断自定义剪切板格式是否存在,自定义剪切板格式存在,则判断是执行复制还是剪切操作。之后就是查询所有的文件类表了。当然如果剪切板格式不存在就不进行处理了。
粘贴操作响应函数代码:
1 void CMyDlg::OnBtnPaste()
2 {
3 // TODO: Add your control notification handler code here
4
5 //自定义剪切板,名称要和复制注册的名称一样
6 UINT uDropEffect = RegisterClipboardFormat("Preferred DropEffect");
7 UINT cFiles = 0;
8 DWORD dwEffect = 0;
9 DWORD * dw = NULL;
10
11 if( ::OpenClipboard(this->m_hWnd) )
12 {
13 //获取CF_HDROP剪切板的内容
14 HDROP hDrop = HDROP( GetClipboardData( CF_HDROP));
15
16 //判断文件夹剪切板是否存在,如果存在,在判断自定义剪切板格式是否存在
17 //如果自定义剪切板格式存在,则判断是复制操作还是剪切操作
18 if( hDrop)
19 {
20 //获取自定义剪切板的内容
21 dw = (DWORD*)(GetClipboardData( uDropEffect));
22
23 if(dw==NULL)
24 {
25 dwEffect = DROPEFFECT_COPY;
26 }
27 else
28 {
29 dwEffect = *dw;
30 }
31
32 //查询获取到的文件或文档
33 cFiles = DragQueryFile( hDrop, (UINT) -1, NULL, 0);
34 char szFile[ MAX_PATH] = {'\0'};
35 char lpBuffer[ MAX_PATH] = {'\0'};
36
37 //查询所有的文件列表,并把路径显示到文本框中
38 for( UINT count = 0; count < cFiles; count++ )
39 {
40 DragQueryFile( hDrop, count, szFile, sizeof( szFile));
41
42 lstrcat(lpBuffer,szFile);
43 lstrcat(lpBuffer,"\r\n");
44
45 //把文件显示到文本框
46 SetDlgItemText(IDC_EDIT_DISPLAY, lpBuffer);
47 }
48 }
49
50 CloseClipboard();
51 }
52
53 if(cFiles==0)
54 {
55 return ;
56 }
57 }