CopyFile.h:
#pragma once
#include <list>
#include <map>
#include <string>
#include <xstring>
#include <concrt.h>
#include <ShlObj.h>
using namespace std;
class CCopyFilesOper
{
public:
CCopyFilesOper();
~CCopyFilesOper();
/**
* @brief 将文件拷贝到剪切板
* @param[in] std::list<wstring> FileList 需要拷贝的文件列表
* @param[in] DWORD DropEffect DROPEFFECT_COPY 表示复制, DROPEFFECT_MOVE 表示剪切
* @return 无
*/
bool CopyToClipboard(std::list<wstring> FileList, DWORD DropEffect);
void OpenCopyClipboard();
private:
/*
* @brief 计算需要分配内存的总长度
* @param[in] std::list<wstring> FileList 需要处理的列表
* @param[out] std::map<wstring, int> &MapFile 文件名对应长度列表
* @return int 总长度
*/
int CalFileListLen(std::list<wstring> FileList, std::map<wstring, int> &MapFile);
/*
* @brief 将文件列表拷贝到 DROPFILES 文件列表区域内存
* @param[in] std::map<wstring, int> &MapFile 文件列表
* @param[out] char* pData DROPFILES 文件列表区域内存首地址
* @return
*/
void CopyFileListIntoDropFiles(char* pData, std::map<wstring, int> &MapFile);
};
CopyFile.cpp
#include "stdafx.h"
#include <windows.h>
#include "CopyFiles.h"
CCopyFilesOper::CCopyFilesOper()
{
}
CCopyFilesOper::~CCopyFilesOper()
{
}
bool CCopyFilesOper::CopyToClipboard(std::list<wstring> FileList, DWORD DropEffect)
{
bool bRes = false;
std::map<wstring, int> MapFile;
UINT uBufLen = CalFileListLen(FileList, MapFile);//文件列表中所有文件的总长度
UINT uDropEffect = 0;
DROPFILES dropFiles = { 0 };//
UINT uGblLen = 0;//总长度
UINT uDropFilesLen = 0;
HGLOBAL hGblFiles;//
HGLOBAL hGblEffect;
char * pszData = NULL;
char * szFileList = NULL;
DWORD * dwDropEffect = NULL;
///自定义剪切板,用来设置标识(复制还是剪切)/
uDropEffect = RegisterClipboardFormat(L"Preferred DropEffect"); //参数随便填
hGblEffect = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DWORD));
dwDropEffect = (DWORD*)GlobalLock(hGblEffect);
//设置自定义剪切板的内容为复制或者剪切标识
*dwDropEffect = DropEffect;
GlobalUnlock(hGblEffect);
///文件剪切板,用来存放文件列表/
uDropFilesLen = sizeof(DROPFILES);
//DROPFILES结构的大小
dropFiles.pFiles = uDropFilesLen;
dropFiles.pt.x = 0;
dropFiles.pt.y = 0;
dropFiles.fNC = FALSE;
//true: UNICODE, false: ascii
dropFiles.fWide = TRUE;
//uBufLen * 2表示的是宽字符大小, 加8表示文件末尾需要2个空指针结尾,每个指针占4个字节大小
//uGblLen = uDropFilesLen + (uBufLen+1) * sizeof(TCHAR) + 8;
uGblLen = uDropFilesLen + uBufLen + 8;
hGblFiles = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, uGblLen);
pszData = (char *)GlobalLock(hGblFiles);
//把DROPFILES结构大小的内容放到szData剪切板空间的最开始
memmove(pszData, (LPVOID)(&dropFiles), uDropFilesLen);
//szFileList指向需要放入文件的那个空间,前面存放了DROPFILES结构大小的空间
szFileList = pszData + uDropFilesLen;
CopyFileListIntoDropFiles(szFileList, MapFile);
GlobalUnlock(hGblFiles);
if (::OpenClipboard(NULL))
{
EmptyClipboard();
//可以设置剪切板内容为拖动文件
SetClipboardData(CF_HDROP, hGblFiles);
//可以设置剪切板内容为复制或者剪切标识
SetClipboardData(uDropEffect, hGblEffect);
//关闭剪切板
CloseClipboard();
bRes = true;
// OpenCopyClipboard();
}
return bRes;
}
void CCopyFilesOper::OpenCopyClipboard()
{
UINT cFiles = 0;
DWORD dwEffect = 0;
DWORD * dw = NULL;
if (::OpenClipboard(NULL))
{
//获取CF_HDROP剪切板的内容
HDROP hDrop = HDROP(GetClipboardData(CF_HDROP));
//判断文件夹剪切板是否存在,如果存在,在判断自定义剪切板格式是否存在
//如果自定义剪切板格式存在,则判断是复制操作还是剪切操作
if (hDrop)
{
//查询获取到的文件或文档
cFiles = DragQueryFile(hDrop, (UINT)-1, NULL, 0);
TCHAR szFile[MAX_PATH] = { '\0' };
TCHAR lpBuffer[MAX_PATH] = { '\0' };
//查询所有的文件列表,并把路径显示到文本框中
for (UINT count = 0; count < cFiles; count++)
{
DragQueryFile(hDrop, count, szFile, sizeof(szFile));
lstrcat(lpBuffer, szFile);
lstrcat(lpBuffer, L"\r\n");
}
}
CloseClipboard();
}
if (cFiles == 0)
{
return;
}
}
int CCopyFilesOper::CalFileListLen(std::list<wstring> FileList, std::map<wstring, int> &MapFile)
{
int iLen = 0;
std::list<wstring>::iterator it = FileList.begin();
for ( ; it != FileList.end(); ++it)
{
wstring wstrFile = *it;
int iFileLen = (wstrFile.size() + 1) * sizeof(TCHAR);
if (0 == iFileLen)//文件长度为0 过滤
{
continue;
}
iLen = iLen + iFileLen;
MapFile.insert(make_pair(wstrFile, iFileLen));
}
return iLen;
}
void CCopyFilesOper::CopyFileListIntoDropFiles(char* pData, std::map<wstring, int> &MapFile)
{
std::map<wstring, int>::iterator it = MapFile.begin();
for (int i = 0; i < MapFile.size(); i++)
{
wstring wstrFile = it->first;
memmove(pData, wstrFile.c_str(), it->second);
pData = pData + it->second;
++it;
}
}
Main.h
#include "stdafx.h"
#include "CopyFiles.h"
int main()
{
std::list<wstring> FileList;
FileList.push_back(L"C:\\Users\\myPC\\Desktop\\C++ Primer Plus(第6版)_中文版_带书签_超清.pdf");
FileList.push_back(L"C:\\Users\\myPC\\Desktop\\文件");
CCopyFilesOper copy;
copy.CopyToClipboard(FileList, DROPEFFECT_COPY);//复制
copy.CopyToClipboard(FileList, DROPEFFECT_MOVE);//移动,剪切
return 0;
}