人生总是在赶着一个又一个的期限,直到最后的大限。
近来基本没更新过博客,实在是准备雅思看英语加上调节老看英语后的烦躁心情闹的。本来以为考完研就与大考再也不见了,这种想法实在是 Too young,Too naive。之前做过一个项目,是关于在Windows平台下用C++实现PDF文档制作的相关操作的,今天有点心情拿来总结下。
关于PDF的库其实有不少,本人因为一开始用神器搜到的是PDFlib,就用这个库做了。这就是所谓的缘分吧。
PDFlib并非是开源库,要使用需要付费,否则会有一个让人不要不要的水印在页面的后头。当然,我大天朝从来无需理会这些,有压迫的地方就总会有雷锋站出来搞个破解版,该库也不例外,有需要可以到这位雷锋的博客地点去下载。如果实在是懒也可以下载本人的DEMO工程,里面已经配置好了该库,不过由于本人本着折腾到死的心态做程序员,该工程的环境是最新的VS2015,如果你的版本不是最新的,下载了请自己默哀,十分我是不会还回去的哈哈。
PDFlib是一个标准的动态链接库,跟其他的动态链接库的配置方法一样,把pdflib.lib、pdflib.dll和pdflib.h放到工程目录下并放入pdflib.lib这个附加依赖项,在工程中包含pdflib.h这个现有项就算完成配置了。接下来就是如何去用这个库了,一开始在文件中包含pdflib.h头文件这事应该都是了然的。
具体的使用,网上有一些现成的例子,然而没有见过能解决好中英文交杂在一起的问题的。因为网上百分之八九十都是建议用PDFlib自带的字库,而很遗憾的是这些字库对中文支持的都不怎么好且字体也就那么几种,在一般情况下能分开去调用中英文也就算了,然而在一些中英文同时出现的情况下单单是排版的间隙问题就给跪了,要写程序去遍历里面的字符再区分出来对待,劳民伤财,要死要活。这个工作本人是做了的,后来无意间发现某些博客偶然提及的可以调用本地字库,于是决心尝试一番。真是不试不知道,一试一口老血差点吐出来,本地字库完美支持中英文不说,字体也是要什么有什么。。。有时一些博客真是误导死人。。。所以本人在此强烈建议要用这个库的程序猿直接去C:\Windows\Fonts这个路径下找到你喜欢的字体弄出来,然后放到你的工程目录下拿来调用,什么自带字体完全是坑爹的!!!下面直接上代码,输出一个页面上是《将进酒》的PDF文件。(建一个win32控制台空白工程并配置好环境后把下面这串代码拷进去理论上来说你也是可以运行的。)
#include "pdflib.h" #include <afx.h> void String2text(PDF *p, int &TextFlow, CString &mPagenameAndDate, int fontsize) { char characteristic_cn[100]; int mPagenameAndDateSize = mPagenameAndDate.GetLength();//字符串长度 PDF_set_parameter(p, "FontOutline", "a=./font/STXINGKA.TTF");//这里的“./font/STXINGKA.TTF”为字体文件的存放路径,也就是说需要将字库文件放到相应的位置,不然会造成错误 sprintf_s(characteristic_cn, "fontname=a:0 fontsize = %d encoding = unicode textlen = %d", fontsize, mPagenameAndDateSize * 2);//中文字符 PDF_add_textflow(p, TextFlow, (char *)(mPagenameAndDate).AllocSysString(), mPagenameAndDateSize * 2, characteristic_cn);//添加字符段内容 } void OutputStringToPDF(PDF *p, CString &mPagenameAndDate, int Left, int &Top, int Right, int Reduction, int fontsize)//数据输出 { //该函数输出数据到PDF中,需要注意的是在输出到页未的时候会自行进行换页 if (Top<130) { Top = 740; PDF_end_page_ext(p, ""); // 关闭页面并开启新的页面 PDF_begin_page_ext(p, a4_width, a4_height, ""); } int TextFlow = PDF_create_textflow(p, "", 0, "");//创建字符段 String2text(p, TextFlow, mPagenameAndDate, fontsize); while (true) { const char *returnstring = PDF_fit_textflow(p, TextFlow, Left, Top, Right, Top - Reduction, ""); Top -= Reduction; if (strcmp(returnstring, "_boxfull") != 0)//对象满了 { break; } if (Top<130) { Top = 740; PDF_end_page_ext(p, ""); // 关闭页面并开启新的页面 PDF_begin_page_ext(p, a4_width, a4_height, ""); } } PDF_delete_textflow(p, TextFlow);//释放字符串对象 } void main() { PDF *p = NULL; int Left = 85, Top = 740, Right = a4_width - 85; //pdf对象创建 if ((p = PDF_new()) == (PDF *)0) { printf("Couldn't create PDFlib object (out of memory)!n"); } PDF_TRY(p) { //先创建PDF文档,名为outout.pdf if (PDF_begin_document(p, "output.pdf", 0, "") == -1) { printf("Error: %sn", PDF_get_errmsg(p)); } //再创建PDF文档里面的页面,并填入页面的内容,这里本人将其封装成了两个函数 PDF_begin_page_ext(p, a4_width, a4_height, ""); CString mPagenameAndDate = L"君不见黄河之水天上来 奔流到海不复回\n"; mPagenameAndDate += L"君不见高堂明镜悲白发 朝如青丝暮成雪\n"; mPagenameAndDate += L"人生得意须尽欢 莫使金樽空对月\n"; mPagenameAndDate += L"天生我材必有用 千金散尽还复来\n"; mPagenameAndDate += L"烹羊宰牛且为乐 会须一饮三百杯\n"; mPagenameAndDate += L"岑夫子 丹丘生 将进酒 杯莫停\n"; mPagenameAndDate += L"与君歌一曲 请君为我倾耳听\n"; mPagenameAndDate += L"钟鼓馔玉不足贵 但愿长醉不复醒\n"; mPagenameAndDate += L"古来圣贤皆寂寞 惟有饮者留其名\n"; mPagenameAndDate += L"陈王昔时宴平乐 斗酒十千恣欢谑\n"; mPagenameAndDate += L"主人何为言少钱 径须沽取对君酌\n"; mPagenameAndDate += L"五花马 千金裘\n"; mPagenameAndDate += L"呼儿将出换美酒 与尔同销万古愁\n"; //将文字输出到PDF,第三个参数为输出的左边距,第四个参数为输出的高度,第五个参数为输出的右边距,第六个参数为行距,第七个则是字体的大小 OutputStringToPDF(p, mPagenameAndDate, Left, Top, Right, 45, 24); //页结束 PDF_end_page_ext(p, ""); //文档结束 PDF_end_document(p, ""); } PDF_CATCH(p)//错误信息输出 { printf("[%d] %s: %sn",PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p)); PDF_delete(p); } PDF_delete(p); //打开pdf system("output.pdf"); }
效果如下:
由于本人做工程只用到了输出PDF文件的那个部分,所以关于读取PDF文件的部分是没有写的,以后如果有做到则会放上来。至于更多的细节,则可以参考PDFlib的手册,这个手册我也会跟我的demo一起打包起来,这是demo地址。
版权声明:本文为博主原创文章,未经博主允许不得转载。