ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Delphi 调 Bartender 打印环境搭建与避坑指南

Delphi 调 Bartender 打印环境搭建与避坑指南

简介:这份资源面向使用 Delphi 进行桌面应用开发、并需要集成标签打印功能的开发者,重点解决在 Delphi 环境下调用 Bartender 实现标签设计与打印的问题。资源包内共 1 个 doc 文档,压缩后约 392KB,内容围绕 Bartender 的 ActiveX 控件调用展开,涵盖控件安装、项目创建、控件引入、API 调用及功能测试等关键环节,同时介绍了 Bartender 在标签设计、打印输出和数据库管理方面的主要能力。文档还结合条码打印、票据打印等实际场景,说明如何借助 Delphi 的灵活性与 Bartender 的打印能力提升工作效率、降低开发与硬件成本。目前已有 389 人学习,适合希望快速掌握 Delphi 与 Bartender 集成思路、需要一份可参照操作说明的开发者查阅。

1. Delphi 调 Bartender:从 ActiveX 控件到打印跑通,一次讲清环境怎么搭

接手一个老产线的标签打印模块时,我第一反应是这活儿应该不复杂——Delphi 调 Bartender,网上一搜一大把。真动手才发现,坑全在版本和注册表里。BarTender 从 9.x 到 2016 再到 2019,ActiveX 控件的注册方式、Pro 版和 Automation 版的授权差异、32 位 Delphi 与 64 位系统的兼容问题,每一个都能让你在“控件已注册但创建对象失败”的报错里卡一下午。这套环境在条码打印、仓储标签、产线赋码场景里非常常见,尤其是那些用 Delphi 维护了十几年的老系统,换不掉也不想重写。如果你正卡在“BarTender 装了但 Delphi 里调不通”这一步,下面这套流程是我踩过坑之后固定下来的顺序,照着走能少走弯路。

2. 装之前先把版本和授权理清楚:BarTender 与 Delphi 的匹配关系

2.1 BarTender 版本选择:Automation 版才是能调用的那个

很多人装完 BarTender 发现 Delphi 的 Import Component 里找不到类型库,根本原因就是装错了版本。BarTender 分 Professional、Automation、Enterprise 几个层级,只有 Automation 及以上才开放 ActiveX 自动化接口。Professional 版能设计能打印,但外部程序调不了它的 API。

我一般会先确认两件事:一是安装的是 BarTender Automation 版,二是安装时勾选了“ActiveX 自动化支持”组件。2016 和 2019 版本在安装向导里这个选项藏得比较深,在自定义安装的“附加组件”里,默认是不勾的。9.4 和 10.x 老版本相对直接,装完就有。

版本对照上,Delphi 7 到 Delphi 2007 这类老 IDE 配 BarTender 9.4 或 10.1 最稳,因为类型库的接口定义没怎么变。Delphi 2010 以后的版本配 BarTender 2016 或 2019 更合适,Unicode 支持完整,不会出现中文标签内容乱码。如果你用的是 Delphi XE 系列,BarTender 2016 是分水岭,之前的版本在字符串传递上要用 WideString 手动转,之后的版本直接传 string 就行。

提示:BarTender 安装路径里不要带中文和空格,默认的C:\Program Files\Seagull\BarTender Suite就很好。我见过装在D:\标签打印\BarTender下面,结果 ActiveX 注册表项路径解析出错的案例。

2.2 Delphi 环境准备:32 位编译目标不能忘

BarTender 的 ActiveX 控件是 32 位的,哪怕你系统是 64 位 Windows,Delphi 的编译目标也必须设成 32-bit Windows。Delphi 10.4 以后默认可能是 64 位,这里要手动切回来。

检查步骤很简单:在 Delphi IDE 里打开 Project Manager,右键 Target Platforms,确认只有 Win32 被激活。如果 64-bit Windows 也在列表里且被选中,编译出来的 exe 创建 BarTender 对象时会直接报“类未注册”的错,因为 64 位进程找不到 32 位的 COM 组件。

另外,Delphi 的“Import Component”功能依赖类型库文件。BarTender 安装后会注册BarTend.tlb,位置一般在C:\Program Files (x86)\Seagull\BarTender Suite\下面。如果 Delphi 的 Import Component 对话框里看不到 BarTender 的类型库,说明注册没成功,需要手动用regtlib或regasm重新注册一下。

:: 以管理员身份运行 CMD,手动注册 BarTender 类型库 cd C:\Program Files (x86)\Seagull\BarTender Suite regtlib.exe BarTend.tlb

regtlib.exe是 Delphi 自带的类型库注册工具,在 Delphi 安装目录的 Bin 文件夹里也能找到。执行完没有报错就说明注册成功,重新打开 Delphi 的 Import Component 就能看到BarTender 2016 ActiveX Automation Library之类的条目。

3. 在 Delphi 里导入 ActiveX 控件并生成调用单元

3.1 用 Import Component 生成 BarTender 接口单元

Delphi 调用 COM 组件的标准做法是通过 IDE 的 Import Component 向导,把类型库转成 Pascal 接口文件。步骤是:菜单栏 Component → Import Component → 选 Import a Type Library → 在列表里找到 BarTender 对应的类型库 → 勾选需要的接口 → 指定生成单元的名称,比如BarTender_TLB。

生成出来的单元里会包含IBarTender接口定义、TBarTender组件类,以及CoBarTender这个 CoClass 的 GUID。这个单元不要手动改,BarTender 升级后重新生成一遍覆盖就行。

我一般会把生成的单元单独放在一个Lib文件夹里,项目引用路径加上去,这样多个项目共用一份接口定义,升级的时候只改一个地方。

3.2 创建 BarTender 对象的两种写法

生成接口单元之后,创建 BarTender 对象有两种方式。一种是直接用CoBarTender.Create,另一种是通过CreateOleObject动态创建。前者编译期检查强,后者灵活但容易写错方法名。

uses BarTender_TLB, ComObj, ActiveX; procedure TForm1.PrintLabel; var btApp: IBarTender; btFormat: IBTFormat; begin // 初始化 COM 库,Delphi 主线程里通常已经初始化过 CoInitialize(nil); try // 方式一:通过 CoClass 创建,推荐 btApp := CoBarTender.Create; // 打开已经设计好的标签格式文件 btFormat := btApp.Formats.Open('D:\Labels\product_label.btw', False, True); // 设置数据库字段,这里对应标签里绑定的数据库列 btFormat.SetNamedSubStringValue('ProductName', '测试产品A'); btFormat.SetNamedSubStringValue('BatchNo', '20250101-001'); // 打印一份到默认打印机 btFormat.PrintOut(False, False); // 关闭格式文件,不保存修改 btFormat.Close(btSaveChangesNo); finally btApp := nil; CoUninitialize; end; end;

这段代码里几个关键点:Formats.Open的第二个参数是“是否以只读方式打开”,第三个参数是“是否显示打印对话框”,一般设 False 和 True 组合,让用户能看到打印预览。SetNamedSubStringValue是给标签里的“命名子串”赋值,这些子串需要在 BarTender 设计器里提前用“数据源 → 命名数据源”定义好。PrintOut的第一个参数控制是否弹出打印机选择框,第二个参数控制是否打印到文件。

注意:CoInitialize和CoUninitialize必须成对出现。在 Delphi 的 VCL 主线程里,Application.Initialize 已经调过 CoInitialize,重复调用不会报错但引用计数会乱。稳妥做法是在单元初始化段调用一次,在 finalization 段释放。

3.3 数据库字段绑定的参数传递

BarTender 标签里绑定的数据库字段,在 Delphi 这边是通过SetNamedSubStringValue或者SetNamedSubStringValue来传值的。如果标签里用的是“数据库字段”而不是“命名子串”,那就要用btFormat.Database.SetFieldValue方法。

// 假设标签里绑定了一个名为 "OrderNo" 的数据库字段 btFormat.Database.SetFieldValue('OrderNo', 'SO-2025-0001'); // 批量打印时,可以循环赋值后调用 PrintOut for i := 1 to 10 do begin btFormat.SetNamedSubStringValue('SerialNo', Format('SN%04d', [i])); btFormat.PrintOut(False, False); end;

这里有个性能上的取舍:每次PrintOut都会走一遍打印队列,如果标签数量大,建议用 BarTender 的“打印任务”模式,把所有数据一次性传给 BarTender,由它内部排队。不过 Delphi 这边调PrintOut简单直接,几百张以内感觉不到差异。

4. 避坑与排查:Delphi 调 BarTender 最常见的五个翻车点

4.1 创建对象报“类未注册”或“OLE 错误 80040154”

现象是CoBarTender.Create直接抛异常,错误码 80040154。原因通常是 BarTender 的 ActiveX 组件没有正确注册,或者 Delphi 编译目标是 64 位。解决方法是先用管理员权限运行 BarTender 安装目录下的BarTend.exe /regserver,强制重新注册所有 COM 组件。然后确认 Delphi 的 Target 是 Win32。如果还不行,检查注册表HKEY_CLASSES_ROOT\BarTender.Application是否存在,不存在就说明注册失败,需要修复安装 BarTender。

4.2 打印出来中文变成问号或乱码

这个坑在 Delphi 2007 及更早版本配 BarTender 9.x 时特别常见。原因是 Delphi 的string是 AnsiString,传给 COM 的 BSTR 时编码转换丢了。解决办法是在传递中文之前用WideString包一层,或者升级到 Delphi 2010 以上版本,原生 Unicode 就没这个问题。另一个可能是 BarTender 标签里用的字体不支持中文,换成宋体或微软雅黑。

4.3 标签格式文件打开失败,报“文件被占用”

Formats.Open返回 nil 或者抛异常,提示文件被其他进程锁定。BarTender 的 .btw 文件在打开时会生成一个临时锁文件,如果上一次打印异常退出没释放,下次就打不开。我一般会在打开之前先检查文件是否存在,然后用btApp.Formats.Open的第三个参数设成 True,让 BarTender 以独占方式打开,避免多个 Delphi 进程同时抢一个格式文件。如果还是不行,重启 BarTender 的后台服务BarTender Print Scheduler能解决大部分锁文件问题。

4.4 打印速度慢,每张标签间隔好几秒

默认情况下 BarTender 每次PrintOut都会重新初始化打印引擎,标签数量多的时候累积延迟很明显。优化方法是把btApp.Formats.Open放在循环外面,循环里只做SetNamedSubStringValue和PrintOut,打完再Close。另外在 BarTender 的打印设置里把“打印前重新计算”关掉,能省掉每次的数据校验时间。

4.5 换机器部署后找不到 ActiveX 控件

开发机上跑得好好的,部署到产线机器就报错。原因是目标机器只装了 BarTender 的打印驱动,没装 Automation 版。部署清单里必须包含:BarTender Automation 完整安装、类型库注册、以及 Delphi 程序目录下的BarTend.tlb文件(如果用了动态创建)。我习惯在安装脚本里加一句regtlib.exe BarTend.tlb,确保 COM 注册表项在部署后是完整的。

5. 装完怎么验证:从设计器到 Delphi 的完整链路测试

5.1 先用 BarTender 设计器做一张最小标签

在 Delphi 里写代码之前,先在 BarTender 设计器里建一个最简单的标签:一个文本对象,内容绑定到命名子串TestField,打印机选一个虚拟 PDF 打印机或者实际标签机。保存为test_label.btw。然后手动打印一次,确认设计器本身能正常输出。这一步是排除 BarTender 安装和打印机驱动的问题,把变量控制在 Delphi 之外。

5.2 用 Delphi 写一个最小调用程序验证

新建一个 Delphi VCL 项目,放一个按钮,把前面生成的BarTender_TLB单元加进 uses,按钮事件里写创建对象、打开标签、赋值、打印、关闭的完整流程。编译成 32 位 exe,运行。如果打印出正确的标签,说明 ActiveX 调用链路通了。

procedure TForm1.btnTestClick(Sender: TObject); var btApp: IBarTender; btFormat: IBTFormat; begin btApp := CoBarTender.Create; try btFormat := btApp.Formats.Open('D:\Labels\test_label.btw', False, True); btFormat.SetNamedSubStringValue('TestField', 'Delphi调用测试 ' + DateTimeToStr(Now)); btFormat.PrintOut(False, False); btFormat.Close(btSaveChangesNo); ShowMessage('打印任务已发送'); except on E: Exception do ShowMessage('调用失败:' + E.Message); end; btApp := nil; end;

这段代码里try...except是必须的,COM 调用失败会抛 EOleSysError,不捕获的话程序直接崩。btApp := nil放在最后是释放 COM 引用,让 BarTender 进程能正常退出。

5.3 验证清单和参数速查

跑通最小程序之后,按下面这张表逐项确认,基本能覆盖 90% 的部署问题。

检查项正确状态常见错误
BarTender 版本Automation 或 EnterpriseProfessional 版无 ActiveX
Delphi 编译目标32-bit Windows64 位下类未注册
类型库注册注册表有 BarTender.Application需 regtlib 手动注册
标签文件路径纯英文无空格中文路径打开失败
命名子串设计器里已定义未定义则赋值无效
打印机驱动系统默认打印机可用驱动缺失导致挂起

我自己的习惯是,每次部署到新机器,先跑一遍这个最小程序,确认打印出纸了,再把正式的业务代码放上去。从那以后我每次配 Delphi 调 BarTender 的环境,都强制走一遍“设计器手动打印 → 最小 Delphi 程序 → 业务代码”这三步,不再跳步。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进