win32打印机控制,API打印操作

  1. #include <windows.h>  
  2. #include <stdio.h>  
  3.   
  4. //这个函数用于读取bmp图像文件,用于给打印机打印的时候使用  
  5. //info是位图信息结构  
  6. //file是文件名  
  7. //dib_ptr是位图rgb像素数据指针,输出用的,所以请提供一个void**  
  8. bool read_bmp(BITMAPINFO& info, const char* file, void** dib_ptr)  
  9. {  
  10.     BITMAPFILEHEADER file_handle;  
  11.     FILE* f = fopen(file, "rb");  
  12.     if(f == 0) return false;  
  13.   
  14.     memset(&info, 0, sizeof(info));  
  15.     fread(&file_handle, 1, sizeof(file_handle), f);  
  16.     fread(&info.bmiHeader, 1, sizeof(info.bmiHeader), f);  
  17.     fseek(f, file_handle.bfOffBits, SEEK_SET);  
  18.     void* dib = malloc(info.bmiHeader.biSizeImage);  
  19.     fread(dib, 1, info.bmiHeader.biSizeImage, f);  
  20.     fclose(f);  
  21.     *dib_ptr = dib;  
  22.     return true;  
  23. }  
  24.   
  25. //释放位图的数据指针,释放空间  
  26. void release_bmp(void** dib_ptr)  
  27. {  
  28.     if(dib_ptr != 0)  
  29.     {  
  30.         if(*dib_ptr != 0)  
  31.         {  
  32.             free(*dib_ptr);  
  33.             *dib_ptr = 0;  
  34.         }  
  35.     }  
  36. }  
  37.   
  38. int main(int argc, char* argv[])  
  39. {  
  40.     PRINTDLG printInfo = {0};  
  41.     printInfo.lStructSize = sizeof(printInfo);  
  42.     printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;  
  43.     //PD_RETURNDEFAULT 意味着直接返回当前系统默认的打印机设置,若没有这个标识,则会弹出对话框让用户自己选择  
  44.     //PD_RETURNDC 意味着返回的是dc而不是ic(information context)  
  45.     //PD_ALLPAGES 指定“全部”单选钮在初始时被选中(缺省标志)  
  46.     //对于错误的时候,若需要知道更多的错误消息,请执行CommDlgError来查看返回值  
  47.   
  48.     //PrintDlg目的是获取当前系统设置的默认打印机相关信息,供后面使用  
  49.     if(!PrintDlg(&printInfo))  
  50.     {  
  51.         printInfo.Flags = 0;    //清除标志,然后执行将会弹出对话框让用户选择打印机  
  52.         if(!PrintDlg(&printInfo))   
  53.         {  
  54.             printf("没有选择打印机。\n");  
  55.             return 0;  
  56.         }  
  57.     }  
  58.   
  59.     //获取打印的时候的dc,然后往这个dc上绘图就是打印出来的样子了  
  60.     HDC hPrintDC = printInfo.hDC;  
  61.   
  62.     //锁定全局对象,获取对象指针。 devmode是有关设备初始化和打印机环境的信息  
  63.     DEVMODE* devMode = (DEVMODE*)GlobalLock(printInfo.hDevMode);  
  64.     if(devMode == 0)  
  65.     {  
  66.         printf("获取打印机设置时发生了错误.\n");  
  67.         return 0;  
  68.     }  
  69.   
  70.     devMode->dmPaperSize = DMPAPER_A4;               //打印机纸张设置为A4。  
  71.     devMode->dmOrientation   = DMORIENT_PORTRAIT;        //打印方向设置成纵向打印  
  72.     //DMORIENT_LANDSCAPE 是横向打印  
  73.     //对打印方向的设置,会影响hPrintDC的大小,假设宽度为1024,高度为300  
  74.     //则在横向打印的时候dc大小会是宽1024 * 高300  
  75.     //而纵向打印的时候dc大小会是宽300 * 高1024  
  76.   
  77.     int printQuality = devMode->dmPrintQuality;          //获取打印机的打印质量  
  78.     //devMode->dmPrintQuality = DMRES_MEDIUM;  
  79.     //设置打印质量的,因为像素被打印到纸上的时候是有做转换的  
  80.     //单位是dpi,意为像素每英寸(dots per inch)。就是一英寸的纸张上  
  81.     //打印多少个像素点,意味着这个质量越高,打印结果越精细,越低,越粗糙  
  82.     //设置的质量可以是具体数值,也可以是宏DMRES_MEDIUM  
  83.     //一般我们选择300,或者600,DMRES_MEDIUM = 600dpi  
  84.   
  85.     //应用我们修改过后的设置.  
  86.     ResetDC(hPrintDC, devMode);  
  87.   
  88.     //解锁全局对象,对应GlobalLock  
  89.     GlobalUnlock(printInfo.hDevMode);  
  90.   
  91.     //设置绘图模式,以保证绘图可以不失真的绘制上去,因为StretchDIBits函数要求设置这个才能够不是失真的绘图  
  92.     //当你用StretchDIBits绘图往窗口显示的时候就会发现,24位图,若没有这个设置,是会失真的  
  93.     SetStretchBltMode(hPrintDC, HALFTONE);  
  94.   
  95.     //读取位图,待会画在hPrintDC上面去  
  96.     BITMAPINFO bmp_info;  
  97.     int image_width = 0, image_height = 0;  
  98.     void* dib_ptr = 0;  
  99.     if(!read_bmp(bmp_info, "miku.bmp", &dib_ptr))  
  100.     {  
  101.         printf("读取位图miku.bmp失败了.\n");  
  102.         return 0;  
  103.     }  
  104.     image_width = bmp_info.bmiHeader.biWidth;  
  105.     image_height = bmp_info.bmiHeader.biHeight;  
  106.     printf("位图大小:%d x %d\n", image_width, image_height);  
  107.   
  108.     //设置打印时候的字体  
  109.     LOGFONT lf;  
  110.     lf.lfHeight         = -printQuality * 1 / 2.54;   
  111.                                 //打印出来的字像素高度有n个,注意是像素高度,打印到纸上的时候是需要将  
  112.                                 //像素转换成实际尺寸单位,比如你需要在纸上打印高度为1cm的字,当你打印质量为600dpi的时候  
  113.                                 //这里就设置为 -236, -600dpi * 1cm / 2.54 = -236pix  
  114.     lf.lfWidth          = 0;  
  115.     lf.lfEscapement     = 0;  
  116.     lf.lfOrientation    = 0;  
  117.     lf.lfWeight         = 5;        //这里设置字体重量,意味着字体的厚度  
  118.     lf.lfItalic         = false;    //斜体  
  119.     lf.lfUnderline      = false;    //下划线  
  120.     lf.lfStrikeOut       = 0;  
  121.     lf.lfCharSet        = DEFAULT_CHARSET;  
  122.     lf.lfOutPrecision    = 0;  
  123.     lf.lfClipPrecision    = 0;  
  124.     lf.lfQuality         = PROOF_QUALITY;  
  125.     lf.lfPitchAndFamily  = 0;  
  126.     strcpy (lf.lfFaceName, "宋体");   //使用宋体进行打印  
  127.   
  128.     //实际上这一步并不是必须的,因为默认打印机设置已经配置好了,这里只是我们自己固定好字体  
  129.     HFONT hUseFont = CreateFontIndirect(&lf);                   //创建字体  
  130.     HFONT hOldFont = (HFONT)SelectObject(hPrintDC, hUseFont);   //选用创建的字体  
  131.       
  132.     //获取dc的大小,实际上还有一种HORZRES和VERTRES就是宽度和高度,但是我查得到的结果说计算下来准确的  
  133.     //HORZSIZE 是Horizontal size in millimeters,页面宽度(水平),单位毫米mm  
  134.     //VERTSIZE 是Vertical size in millimeters,页面高度(垂直),单位毫米mm  
  135.     //LOGPIXELSX 是Logical pixels/inch in X,x方向的逻辑像素每英寸.单位 pix / inch,像素每英寸  
  136.     //LOGPIXELSY 是Logical pixels/inch in Y,y方向的逻辑像素每英寸.单位 pix / inch,像素每英寸  
  137.     //不用管逻辑是个什么东西,不理会他,知道单位是pix / inch就行了  
  138.     //1 inch = 2.54 cm,所以这里是 mm / 25.4 * pix / inch,得到的结果就是dc大小像素数为单位  
  139.     int dc_page_width  = GetDeviceCaps(hPrintDC, HORZSIZE) / 25.4 * GetDeviceCaps(hPrintDC, LOGPIXELSX);  
  140.     int dc_page_height = GetDeviceCaps(hPrintDC, VERTSIZE) / 25.4 * GetDeviceCaps(hPrintDC, LOGPIXELSY);  
  141.   
  142.     //好了,可以开始打印了  
  143.     DOCINFO doc_info = {sizeof(DOCINFO), "测试打印机"};  
  144.     //cbSize  
  145.     //结构体的字节大小  
  146.     //lpszDocName  
  147.     //指明文档名的字符串指针,该字符串以null为尾。  
  148.     //lpszOutput  
  149.     //指明输出文件的名称的字符串指针,该字符串以null为尾。如果指针为null,那么输出将会发送至某个设备,该设备将由传递至 StartDoc 函数的‘设备上下文句柄’HDC来指明。  
  150.     //lpszDatatype  
  151.     //指针指向代表某种数据类型的字符串,而数据用于记录打印工作,该字符串以null为尾。合法值可通过调用函数 EnumPrintProcessorDatatypes 可得到,亦可为 NULL。  
  152.     //fwType  
  153.     //指明打印工作的其它信息。可为0或者以下值之一:  
  154.     //DI_APPBANDING  
  155.     //DI_ROPS_READ_DESTINATION  
  156.   
  157.     //开始一个档案,打印的时候是按照档案来区分的,返回作业编号(大于0的为正常)  
  158.     int doc_idd = StartDoc(hPrintDC, &doc_info);  
  159.     if(doc_idd <= 0)  
  160.     {  
  161.         printf("StartDoc 错误,错误代码:%d\n", GetLastError());  
  162.         goto last_code;  
  163.     }  
  164.     printf("作业编号:%d\n", doc_idd);  
  165.   
  166.     //开始一个打印页面,大于等于0为正确  
  167.     if(StartPage(hPrintDC) < 0)  
  168.     {  
  169.         printf("StartPage 错误\n");  
  170.         AbortDoc(hPrintDC); //结束doc打印  
  171.         goto last_code;  
  172.     }  
  173.   
  174.     //设定文字和图像绘制的区域  
  175.     RECT rcText = {0, 30, dc_page_width, 300};  
  176.     RECT rcImage = {30, 300, dc_page_width - 30, dc_page_height - 30};  
  177.   
  178.     //写下文字  
  179.     DrawText(hPrintDC, "miku,测试打印图片", -1, &rcText, DT_VCENTER | DT_SINGLELINE | DT_CENTER);  
  180.   
  181.     //将图片绘制到dc上,给打印机打印出来  
  182.     //这个函数带拉伸功能的,若dest的宽度高度和src不一致的时候他会拉伸  
  183.     StretchDIBits(hPrintDC, rcImage.left, rcImage.top, rcImage.right - rcImage.left,   
  184.         rcImage.bottom - rcImage.top, 0, 0, image_width, image_height,   
  185.         dib_ptr, &bmp_info, DIB_RGB_COLORS, SRCCOPY);  
  186.   
  187.     //结束这一页,其实可以循环的startpage、endpage,这样在一个文档中进行多个页面的打印  
  188.     EndPage(hPrintDC);  
  189.     EndDoc(hPrintDC);  
  190.     printf("打印顺利完成了. o(∩_∩)o \n");  
  191.   
  192. last_code:  
  193.     //选取旧的字体  
  194.     SelectObject(hPrintDC, hOldFont);  
  195.   
  196.     //删除gdi对象,释放内存  
  197.     DeleteObject(hUseFont);  
  198.   
  199.     //释放位图内存  
  200.     release_bmp(&dib_ptr);  
  201.     return 0;  
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值