告别Word和PDF!用Python win32ui库直接驱动打印机,搞定标签贴打印(附完整代码)
Python直连打印机实战:高效标签打印解决方案
在办公自动化和生产流程中,打印标签、票据等特殊格式文档是常见需求。传统方法依赖Word或PDF作为中间媒介,不仅效率低下,还常遇到格式错乱、字体丢失等问题。本文将介绍如何利用Python的win32ui库直接与打印机对话,实现高效精准的打印控制。
1. 传统打印方式的痛点分析
日常工作中,我们习惯通过Word或PDF文档进行打印,这种方式看似方便,实则存在诸多限制:
- 效率瓶颈:每次打印都会启动相关软件(如Word或Acrobat),消耗额外系统资源
- 格式失控:文档在不同设备上打开可能出现版式错乱,特别是包含特殊字体时
- 自动化困难:难以集成到自动化流程中,需要人工干预点击打印按钮
- 精度不足:对于标签、票据等需要精确定位的打印任务,传统方式难以满足毫米级定位要求
# 传统打印流程示意代码 import os os.startfile("document.docx") # 会启动Word应用程序相比之下,直接驱动打印机的方式可以:
- 完全绕过中间软件,提升打印速度
- 精确控制每个字符的位置和样式
- 轻松集成到自动化系统中
- 减少系统资源占用
2. Windows打印系统架构解析
要理解直接打印的原理,需要先了解Windows的打印子系统架构:
| 组件 | 功能 | Python对应接口 |
|---|---|---|
| GDI (图形设备接口) | 提供基本的绘图功能 | win32ui.CreateDC() |
| 打印机驱动 | 转换GDI指令为打印机语言 | CreatePrinterDC() |
| 假脱机服务 | 管理打印队列 | StartDoc/EndDoc |
| 物理打印机 | 最终输出设备 | 通过驱动程序通信 |
关键对象关系:
- 设备上下文(DC):绘图操作的画布
- 字体对象:控制文本显示样式
- 绘图指令:文本、线条、形状等
import win32ui import win32con # 创建打印设备上下文 hdc = win32ui.CreateDC() hdc.CreatePrinterDC(win32ui.GetDefaultPrinter()) # 连接默认打印机3. 核心API实战详解
3.1 初始化打印任务
完整的打印流程包含以下步骤:
- 创建设备上下文(DC)
- 创建打印机DC(指定具体打印机)
- 开始文档任务(StartDoc)
- 开始页面(StartPage)
- 执行绘图操作
- 结束页面(EndPage)
- 结束文档任务(EndDoc)
def init_print_job(printer_name=None): """初始化打印任务""" hdc = win32ui.CreateDC() printer_name = printer_name or win32ui.GetDefaultPrinter() hdc.CreatePrinterDC(printer_name) hdc.StartDoc("Python打印任务") hdc.StartPage() return hdc3.2 字体控制技巧
win32ui.CreateFont()提供了精细的字体控制能力,主要参数包括:
| 参数 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| height | int | 字体高度(像素) | 24 |
| width | int | 字体宽度(像素) | 0(自动) |
| escapement | int | 文本行倾斜(0.1度) | 900(90度) |
| weight | int | 粗细(0-1000) | 400常规,700粗体 |
| italic | bool | 斜体 | True/False |
| underline | bool | 下划线 | True/False |
| charset | int | 字符集 | win32con.GB2312_CHARSET |
# 创建特殊字体示例 special_font = { 'name': '黑体', 'height': 36, 'weight': 700, # 加粗 'italic': True, 'underline': True, 'charset': win32con.GB2312_CHARSET } font = win32ui.CreateFont(special_font) hdc.SelectObject(font) hdc.TextOut(100, 100, "特殊样式文本")3.3 文本定位与绘制
精确控制文本位置是标签打印的关键:
- 获取打印机可打印区域尺寸
- 计算每个元素的绝对坐标
- 处理多行文本自动换行
# 获取打印机可打印区域 printable_width = hdc.GetDeviceCaps(8) # 可打印宽度(像素) printable_height = hdc.GetDeviceCaps(10) # 可打印高度(像素) # 文本定位示例 def print_text(hdc, text, x, y, font_spec): font = win32ui.CreateFont(font_spec) hdc.SelectObject(font) hdc.TextOut(x, y, text)4. 标签打印完整解决方案
4.1 标签打印机配置要点
使用标签打印机时需要特别注意:
- 纸张设置:必须在打印机属性中正确配置标签尺寸
- 打印方向:根据标签布局选择横向或纵向
- DPI设置:高DPI可获得更精细的打印效果
- 测试打印:先用普通纸测试,确认无误再用标签纸
# 打印机配置检查函数 def check_printer_settings(printer_name): from win32print import GetPrinter hprinter = win32print.OpenPrinter(printer_name) attributes = win32print.GetPrinter(hprinter, 2) # 获取打印机属性 print(f"当前纸张尺寸: {attributes['pDevMode'].PaperSize}") print(f"打印方向: {'纵向' if attributes['pDevMode'].Orientation == 1 else '横向'}")4.2 标签打印模块实现
下面是一个完整的标签打印类实现:
class LabelPrinter: def __init__(self, printer_name=None): self.hdc = win32ui.CreateDC() self.printer_name = printer_name or win32ui.GetDefaultPrinter() self.hdc.CreatePrinterDC(self.printer_name) def print_label(self, items, job_name="标签打印"): """打印标签内容 items: [(x, y, text, font_spec), ...] """ self.hdc.StartDoc(job_name) try: self.hdc.StartPage() for x, y, text, font_spec in items: font = win32ui.CreateFont(font_spec) self.hdc.SelectObject(font) self.hdc.TextOut(x, y, text) self.hdc.EndPage() finally: self.hdc.EndDoc() def __del__(self): if hasattr(self, 'hdc'): del self.hdc4.3 高级功能扩展
除了基本文本打印,还可以实现:
- 条形码/二维码打印:使用第三方库生成图像后绘制
- 表格绘制:组合LineTo和Rectangle函数
- 图形打印:通过Dib对象绘制位图
# 打印二维码示例 def print_qrcode(hdc, content, x, y, size): import qrcode from PIL import ImageWin qr = qrcode.QRCode(version=1, box_size=10, border=4) qr.add_data(content) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") dib = ImageWin.Dib(img) dib.draw(hdc.GetHandleOutput(), (x, y, x+size, y+size))5. 实战案例:医疗标本标签系统
假设我们需要为医院开发一个标本标签打印系统,主要需求包括:
- 打印患者基本信息(姓名、性别、年龄)
- 打印标本编号和采集时间
- 包含条形码用于扫描识别
- 使用特殊字体突出关键信息
def print_specimen_label(patient_info, specimen_id): printer = LabelPrinter("标签打印机名称") # 定义字体样式 font_large = {'name': '黑体', 'height': 36, 'weight': 700} font_normal = {'name': '宋体', 'height': 24} font_small = {'name': '宋体', 'height': 18} # 准备打印内容 from datetime import datetime items = [ (50, 20, "医疗标本标签", font_large), (50, 70, f"姓名: {patient_info['name']}", font_normal), (50, 110, f"性别: {patient_info['gender']} 年龄: {patient_info['age']}", font_normal), (50, 150, f"标本ID: {specimen_id}", font_normal), (50, 190, f"采集时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}", font_small), ] # 打印标签 printer.print_label(items) # 打印条形码(需要额外空间) printer.hdc.StartPage() print_barcode(printer.hdc, specimen_id, 50, 230, 300) printer.hdc.EndPage()实际部署时,这个方案比传统Word打印方式效率提升约3-5倍,且完全避免了格式错乱问题。系统可以轻松集成到医院HIS系统中,实现标本采集、检验、报告的全程自动化。
