一直想开始写自己的博客,之前都是在学习业内大牛们的博客,目前这点渣技术也是从大牛们的博客中汲取消化而来的,但是由于各种事儿比较多(就是懒),也苦于找不到一个感兴趣又写的来的话题,就拖到了现在,刚好最近接了个私活儿,客户的需求简单来说就是一个局域网的收银软件,需要打印小票(58mm),并且每个月末需要打印出每个客户本月的所有订单(A4),之前也写过类似的收银软件,但是这次跟以前的都不一样,这次首先是需要局域网使用,所以首先就得选择合适的数据库,平时为了方便,大小软件都用SQLITE,因为实在是太方便了,不用编译库,不用安装额外的数据库,轻量级…貌似有点儿跑题了(←_←),言归正传,其实一开始也是想用SQLITE的,也可以支持局域网操作,当然,SQLITE本身是不支持局域网访问的,但是可以通过共享文件夹来使得局域网电脑可以访问到文件,当然也就可以访问到数据库了,网上查了半天资料,又发现一个严重的问题,多用户操作数据库时,可能会同时访问到数据库文件,而由于SQLITE本身特有的工作原理,每次执行SQL语句时都会有打开和关闭文件的过程,so,如果多用户访问的话可能会出问题,于是想了半天,准备用守护进程+消息队列这种模式来解决这个问题,于是准备先写个在放数据库的主机上的守护进程,写啊写,写了半天,突然惊醒,想给自己一巴掌,这特么还用自己写么?你丫SB了吧!直接装个MySQL不就行了,人家把这些都帮你做好了,你还在这自己写个毛啊,能有人家专业的写的效率高不成,就这样,本着不浪费资源的精神,前面所做的工作归零,又从头开始,首先是下载MySQL,选择合适的版本下载安装,具体的安装过程可以参见mysql 5.6安装图解,版本不同可能会略有差异,不过这都不重要,具体安装过程就不多说了,各位碰到问题的话可以再找找资料,我的安装过程也是比较坎坷,安装卸载了好几次,后来发现其实第一次已经装好了…
装完以后,还得配置下,使得MySQL可以在局域网中访问,具体过程见《如何设置mysql在局域网中访问》,这个配置完了以后,MySQL就可以先放下了,然后就开始coding,几个小时后,除了打印账单,打印小票,界面这些(貌似也没有其他的了吧(←←),其他的已经写好了,然后由于之前没有接触过小票打印机,最多是在超市买东西见过。。。,上某宝买了个小票打印机(后来客户给报销了,某宝果然方便了我等屌丝),几天后收完快递搬回宿舍,宿舍的弟兄们都惊呆了,纷纷以为我要开超市,我赶紧解释我不开超市><,玛德我倒是想开,你给我赞助啊,然后每次有人来宿舍我就得解释下(T_T),说多了都是泪,不说这些了,说下后面遇到的主要问题以及解决方案吧,小票打印机回来后,装完驱动,小本本上就多了个新设备,然后就可以愉快的打印小票了,操作起来和一般的打印机并没有什么区别,打印小票也和平时在word里边打印文档没有什么区别,重要的是自己写软件使用小票打印机打印时,文档的大小尤其是宽度一定得设置合适了,具体见下面代码,
`
/*
**由于软件中会使用到两种打印机(票据打印机&普通打印机)
**所以不能都使用默认打印机来打印,我设置普通打印机为默认打印机
**然后在Qt中创建printer对象的时候,对应的打印机其实是默认的
**普通打印机,于是我加了个配置文件,用户在初次使用软件打印小票
**时,会弹出一个界面,让用户选择小票打印机,然后将这个打印机的
**名字存到setting.ini文件中,之后运行时就从文件中读取小票打印机
**的名称,这样就可以愉快的使用两种打印机了
**
*/
QPrinter printer(QPrinter::HighResolution);
//如果是首次运行程序,先选择小票打印机,并生成配置文件
if(printer_name_58.isEmpty()||paper_name_58.isEmpty())
{
QPrintDialog d(this);
if(QDialog::Rejected==d.exec())
return;
printer_name_58=d.printer()->printerName();
paper_name_58=d.printer()->paperName();
QFile file("setting.ini");
file.open(QIODevice::WriteOnly|QIODevice::Text);
file.write((printer_name_58+"&&"+paper_name_58).toLatin1());
file.close();
}
//选择小票打印机
printer.setPrinterName(printer_name_58);
//由于默认打印机不是小票打印机,所以纸张大小在设置了打印机后
//还是A4,就会导致打印出来边距什么的都不正确,随便设置一个小
//票打印机不支持的纸张大小,printer就会自动的选择小票打印机
//默认的纸张大小,这样打印出来边距就正常了,这应该是Qt的一个Bug
printer.setPaperName(paper_name_58);
//貌似没什么用,不过我还是设置了下
printer.setFullPage(true);
//计算在打印机的DPI下,58mm对应的点数
int dpi=printer.logicalDpiX();
int width=58*(dpi*1.0/25.4);//58mm
//我一般打印什么的喜欢用html来布局,因为Qt自带的QDocument
//效果感觉一般,而且也不如html好控制
//使用QWebPage来解析并输出解析后的文档到打印机
QWebPage page;
page.mainFrame()->setHtml(html);
QWebFrame *frame=page.mainFrame();
frame->setTextSizeMultiplier(1.4);
//设置网页视口大小,因为我在html文档中用相对大小布局的
page.setViewportSize(QSize(width,frame->findFirstElement("table").geometry().height()));
//将网页通过painter打印出来
QPainter painter(&printer);
frame->render(&painter);
`上面就是小票打印部分的代码,具体的html代码就不贴了
说完了小票打印,再来说说客户账单的打印,这个跟上面的不太一样,因为涉及到分页什么的,而我又懒得自己处理复杂的分页,所以在此本着充分使用已有软件功能的精神,使用COM接口调用word来帮我实现这个功能,其实说来也简单,上面也说了,我一般喜欢使用html来进行布局,所以,在这里也是不例外,依然是用html table来控制报表格式,最后输出到一个html文档,直接用word打开这个html文件,就可以愉快的看着强大的word帮我们处理好分页信息了,然后在调用word的打印功能就OK了(PS:偷懒真是人类进步的阶梯啊(^_^))下面上代码:
//软件启动时
word=new QAxObject("Word.Application");
此处略去1w行代码...
//下面是打印函数
QAxObject *docs = word->querySubObject("Documents");
//filename就是生成的html文件名,注意得用**绝对路径**!!
docs->dynamicCall("Open (const QString&)", filename);
word->dynamicCall("PrintOut ()");
docs->dynamicCall("Close (Boolean)", false);
//打印函数结束
//记得退出软件时调用接口关闭winword进程
word->dynamicCall("Quit (void)");
绝对简单,绝对靠谱!当然具体的html文件还是得自己来生成了,格式什么的都不在话下,一切都由你掌控!