C++怎么调用打印机_C++打印控制教程【外设】

5次阅读

windows 用 printdlg 弹出标准打印对话框需初始化 printdlg、获取 hdc 并设 pd_returndc;gdi 打印须完整执行 startdoc/startpage/endpage/enddoc;unicode 打印必须用 textoutw 配合 multibytetowidechar 转码。

C++怎么调用打印机_C++打印控制教程【外设】

Windows 上用 PrintDlg 弹出标准打印对话框

Windows API 提供的 PrintDlg 是最轻量、最兼容的起点,它不负责实际渲染,只帮你拿到用户选的打印机、页数、份数等配置。直接调用它,比自己拼 GDI 打印逻辑安全得多。

常见错误是传入空或未初始化的 PRINTDLG 结构体——必须先 memset 为 0,再设 lStructSizehDevMode/hDevNames(可用 GlobalAlloc 配合 DocumentProperties 获取)。

  • 必须在调用前调用 GetPrinterDCCreateDC 获取设备上下文(HDC),否则对话框可能崩溃或静默失败
  • PD_RETURNDC 标志要设上,否则返回的 hDC 无效;但别忘了后续用完后调用 DeleteDC
  • 如果程序是线程的,PrintDlg 必须在 ui 线程调用,否则对话框不显示或卡死

StartDoc + StartPage + GDI 绘制真实内容

拿到 HDC 后,得走完整 GDI 打印流程:启动文档 → 启动页面 → 绘图 → 结束页面 → 结束文档。跳过任意一步,输出可能为空、错页或触发驱动报错。

典型现象是“打印任务进队列但没纸出来”,大概率是漏了 EndPageEndDoc;而“文字模糊/缩放异常”往往因为没查 GetDeviceCapsLOGPIXELSX/Y,直接按屏幕 DPI 渲染。

立即学习C++免费学习笔记(深入)”;

  • 每次 StartPage 后必须配对 EndPage,即使只打一页
  • 文本绘制优先用 TextOutDrawText,避免 SetTextColor 后忘记 SetBkMode 导致背景遮盖
  • 打印时禁用双缓冲(WM_PRINT 不适用),所有绘图必须直写到打印 HDC

linux/macos 没有统一 API,得走 CUPS 或系统命令

c++ 在非 Windows 平台没有内建打印抽象层。硬连 CUPS 库(libcups.so)太重,更现实的做法是生成 PDF 或文本,再调 lp 命令交给系统处理。

常见坑是路径含空格或中文时,system("lp file.pdf") 直接失败;还有默认打印机变更后,lpstat -d 返回空导致程序误判。

  • popen 替代 system,能捕获 lp 的 stderr 输出(比如 lp: No such file or Directory
  • 生成 PDF 推荐用轻量库如 libharu 或直接写简单 PDF 结构(仅文本+字体+页面尺寸),别依赖 qt / GTK
  • macOS 可用 lpr,但需注意默认队列名(lpstat -p 查),且某些 M1 机器需加 -o printer-is-shared=false

Unicode 文本打印容易乱码的根源

不是字体问题,而是 GDI 打印 HDC 默认用 OEM 字符集(CP_OEMCP)。哪怕你传的是 UTF-8 字符串TextOut 也会按本地 ANSI 编码解释,中文直接变问号或方块。

解决方法不是换字体,是显式用宽字符接口 + 正确编码转换:

  • 必须用 TextOutW(不是 TextOutA),且字符串是 wchar_t*
  • UTF-8 输入需先用 MultiByteToWideChar(CP_UTF8, ...) 转,别用 mbstowcs(locale 依赖,不可靠)
  • 打印 HDC 的字体建议用 CreateFont 指定 DEFAULT_CHARSET,而非 GB2312_CHARSET(后者在部分打印机驱动里不识别)

真正麻烦的是:同一段代码,在不同品牌打印机上,对 TrueType 字体的支持程度天差地别。有些只认点阵字体,有些拒收嵌入子集——这没法靠代码绕过,只能实机测。

text=ZqhQzanResources