代码写了两个小时,速度太慢(包括学习文档的时间)。
我接到一个同学的求助,她需要将 389 个图片文件按照文件名分组,每一组再扫描成PDF。图片文件大概长这样:
D:\pic2pdf>dir *.jpg
驱动器 D 中的卷是 Data
卷的序列号是 ####-####
D:\pic2pdf 的目录
2025/02/19 09:34 388,171 2025####J02_回函扫描件_01.jpg
2025/02/19 09:34 416,678 2025####J02_回函扫描件_02.jpg
2025/02/19 09:34 414,120 2025####J02_回函扫描件_03.jpg
2025/02/19 09:34 380,703 2025####J02_回函扫描件_04.jpg
2025/02/19 09:34 216,506 2025####J02_回函扫描件_05.jpg
2025/02/19 09:34 243,285 2025####J02_回函扫描件_06.jpg
2025/02/19 09:34 216,857 2025####J02_回函扫描件_07.jpg
2025/02/19 09:34 388,839 2025####A01_回函扫描件_01.jpg
2025/02/19 09:34 384,575 2025####A01_回函扫描件_02.jpg
省略其余的输出. . .
389 个文件 119,463,114 字节
0 个目录 1,361,840,406,528 可用字节
D:\pic2pdf>
最终想要的输出类似于:
2025####J02.pdf
2025####A01.pdf
它们分别有 7 页、2 页。
我第一反应就是,Windows 系统默认不是有个虚拟的打印机嘛?名叫 “Microsoft Print to PDF”。所以我就想以编程的方式,使用 strchr 函数,识别文件名中的下划线,然后切分出序列号部分。由于所有页码都以固定的 2 位编码,所以顺序遍历目录下的图片文件即可。识别序列号后,发现和之前的序列号不一致,或者扫描结束,都应该输出一份文档(EndDoc)。
#include <stdio.h>
#include <Windows.h>
#include <gdiplus.h>
#include <string.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
enum {
IDLEN=30,
FNAME=IDLEN+5,//.pdf
};
int main(void) {
GdiplusStartupInput gsi;
ULONG_PTR tok;
GdiplusStartup(&tok,&gsi,nullptr);
HDC print=CreateDCA("WINSPOOL","Microsoft Print to PDF",nullptr,nullptr);
SetCurrentDirectoryA("D:\\pic2pdf");
WIN32_FIND_DATAW fd;
HANDLE hf=FindFirstFileW(L"*.jpg",&fd);
if (hf) {
puts("找到了jpg文件");
wchar_t f[FNAME];
wchar_t* p=wcschr(fd.cFileName,L'_');
wcsncpy(f,fd.cFileName,p-fd.cFileName);
wcscpy(p-fd.cFileName+f,L".pdf");
DOCINFOW doc{};
doc.cbSize=sizeof doc;
doc.lpszDocName=doc.lpszOutput=f;
StartDocW(print,&doc);
StartPage(print);
Graphics g(print);
while (true) {
Image img(fd.cFileName);
g.DrawImage(&img,0,0);
EndPage(print);
if (FindNextFileW(hf,&fd)) {
wchar_t f1[FNAME];
p=wcschr(fd.cFileName,L'_');
wcsncpy(f1,fd.cFileName,p-fd.cFileName);
wcscpy(p-fd.cFileName+f1,L".pdf");
if (wcscmp(f,f1)) {
EndDoc(print);
wprintf(L"%s\n",f);
wcscpy(f,f1);
StartDocW(print,&doc);
}
} else {
EndDoc(print);
wprintf(L"%s\n",f);
break;
}
};
}
return 0;
}
参考资料:
将 GDI+ 输出发送到打印机 - Win32 apps | Microsoft Learn