1. 前言
老板让在相机控制程序中加入一个功能, 将采集的图片移动到相应的目录下去。于是想到了 CopyFileExA。
相关参考文档:
1. CopyFileEx function
2.CopyProgressRoutine callback function
我们需要做的就是将这个函数调用封装一下, 使他更加贴近我们熟悉的方式进行调用。
2. 基本思路
核心是使用 CopyFileEx, 不过这个函数可以传入一个回调函数。我们可以通过封装这个过程, 将接口简化成我们自定义的形式, 默认覆盖目标目录下的同名文件
static bool copyToNewDir(const std::string & filename, const std::string & newfileName, FUNC func, void * data);
3. 具体实现
Utils.h
#pragma once
#include <string>
typedef int (*FUNC)(void * params);
class CUtils
{
private:
static DWORD CALLBACK CopyProgressRoutine(
_In_ LARGE_INTEGER TotalFileSize,
_In_ LARGE_INTEGER TotalBytesTransferred,
_In_ LARGE_INTEGER StreamSize,
_In_ LARGE_INTEGER StreamBytesTransferred,
_In_ DWORD dwStreamNumber,
_In_ DWORD dwCallbackReason,
_In_ HANDLE hSourceFile,
_In_ HANDLE hDestinationFile,
_In_opt_ LPVOID lpData
);
public:
static bool copyToNewDir(const std::string & filename, const std::string & newfileName, FUNC func, void * data);
};
Utils.cpp
#include "stdafx.h"
#include "Utils.h"
#include <windows.h>
#include <iostream>
using namespace std;
struct DATA{
FUNC func;
void * data;
DATA(FUNC func, void * data) :func(func), data(data){}
};
DWORD CALLBACK CUtils::CopyProgressRoutine(
_In_ LARGE_INTEGER TotalFileSize,
_In_ LARGE_INTEGER TotalBytesTransferred,
_In_ LARGE_INTEGER StreamSize,
_In_ LARGE_INTEGER StreamBytesTransferred,
_In_ DWORD dwStreamNumber,
_In_ DWORD dwCallbackReason,
_In_ HANDLE hSourceFile,
_In_ HANDLE hDestinationFile,
_In_opt_ LPVOID lpData
){
if (TotalBytesTransferred.HighPart == TotalFileSize.HighPart
&& TotalBytesTransferred.LowPart == TotalFileSize.LowPart){
//cout << "拷贝文件完成" << endl;
// TODO:
if (lpData){
DATA data = *(DATA*)lpData;
if (data.func)
data.func(data.data);
}
}
return PROGRESS_CONTINUE;
}
bool CUtils::copyToNewDir(const std::string & filename, const std::string & newfileName, FUNC func, void * data)
{
DATA Data(func, data);
int ret = CopyFileExA(filename.c_str(), newfileName.c_str(), CopyProgressRoutine, (void *)&Data, nullptr, 0);
if (ret == 0){
//cout << "error occurred: " << GetLastError() << endl;
return false;
}
return true;
}