win32 C++ 将字符串打印到打印机

2023-12-07

经过几天的网络搜索,了解如何在 Windows 上将任意字符串打印到任意打印机上,我终于想出了这段代码。

LPBYTE pPrinterEnum;
DWORD pcbNeeded, pcbReturned;
PRINTER_INFO_2 *piTwo = NULL;
HDC printer;
EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,NULL,0,&pcbNeeded,&pcbReturned);
pPrinterEnum = new BYTE[pcbNeeded];
if (!EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,pPrinterEnum,pcbNeeded,&pcbNeeded,&pcbReturned)) {
    qDebug() << "In Print, could not enumerate printers";
} else {
    piTwo = ((PRINTER_INFO_2*)pPrinterEnum);
    for (int i = 0; i < pcbReturned; i++) {
        QString name = QString::fromWCharArray(piTwo[i].pPrinterName);
        if (this->m_printer_path == name) {
            const WCHAR * driver = L"WINSPOOL\0";
            printer = CreateDC(NULL,piTwo[i].pPrinterName,NULL,NULL);
        }
    }
}
if (printer == 0) {
    qDebug() << "No Printer HDC";
    return;
} else {
    qDebug() << "Printer seems okay!";
}

qDebug() << "Starting Document";
DOCINFO di;
memset( &di, 0, sizeof( di ) );
di.cbSize = sizeof( di );
WCHAR * text = new WCHAR[ba.length()];
QString(ba).toWCharArray(text);
StartDoc(printer,&di);
    qDebug() << "Writing text";
    TextOut(printer,0, 0, text, ba.length());
    qDebug() << "Text Written";
EndPage(printer);
qDebug() << "Page ended";
DeleteDC(printer);
qDebug() << "DC Deleted";

一些基本注意事项:

1) 我无法使用 QPrinter。我需要写原始文本,没有附言。 2)在用户设置打印机之前我不知道打印机的名称,并且在用户创建它之前我不知道要打印的字符串的大小。

附加信息:

a) 打印机工作正常,我可以从记事本、Chrome 打印几乎所有内容到我想要的打印机。 b) 我愿意实施任何 hack。像将其写入文本文件并发出复制命令之类的方法似乎不起作用,也就是说,我收到无法初始化设备错误。

这有效: 记事本/P文档/test_print.txt 这不起作用: 复制 Documents\test_print.txt /D:EPSON_TM_T20 copy Documents\test_print.txt /D \MYCOMPUTER\epson_tm_t20(导致访问被拒绝,打印机被共享) 打印 Documents\test_print.txt (无法初始化设备)

我已经尝试了几乎所有推荐的从命令行打印文本文件的方法,但不起作用。我已经安装、重新安装了驱动程序、添加了打印机、弄乱了端口,然后又重新完成了这一切。

显然,由于缺乏经验,我缺少一些有关 Windows 打印的简单内容。

我想要完成的是:

1)最佳场景(直接将文本写入打印机) 2)第二个最佳方案(将文本写入文件,然后执行一些程序为我打印它)记事本在打印输出的底部添加了令人讨厌的空间,浪费纸张。

由于该程序是针对最终用户的,因此我必须找到一种方法来自动为他们执行此操作,因此我不能指望他们在从 powershell 运行命令obscur_configuration 后单击选项卡 36 中的复选框 a。

任何帮助将不胜感激。

/Jason

UPDATE

这是工作代码,在我稍微修改一下之前,它将 QByteArray 的内容打印到热敏打印机上。

qDebug() << "Executing windows code";
BOOL     bStatus = FALSE;
DOC_INFO_1 DocInfo;
DWORD      dwJob = 0L;
DWORD      dwBytesWritten = 0L;
HANDLE     hPrinter;
wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;
qDebug() << "opening printer";
bStatus = OpenPrinter(name,&hPrinter, NULL);

if (bStatus) {
    qDebug() << "Printer opened";
    DocInfo.pDocName = L"My Document";
    DocInfo.pOutputFile = NULL;
    DocInfo.pDatatype = L"RAW";
    dwJob = StartDocPrinter( hPrinter, 1, (LPBYTE)&DocInfo );
    if (dwJob > 0) {
        qDebug() << "Job is set.";
        bStatus = StartPagePrinter(hPrinter);
        if (bStatus) {
            qDebug() << "Writing text to printer";
            bStatus = WritePrinter(hPrinter,ba.data(),ba.length(),&dwBytesWritten);
            EndPagePrinter(hPrinter);
        } else {
            qDebug() << "could not start printer";
        }
        EndDocPrinter(hPrinter);
        qDebug() << "closing doc";
    } else {
        qDebug() << "Couldn't create job";
    }
    ClosePrinter(hPrinter);
    qDebug() << "closing printer";
} else {
    qDebug() << "Could not open printer";
}
if (dwBytesWritten != ba.length()) {
    qDebug() << "Wrong number of bytes";
} else {
    qDebug() << "bytes written is correct " << QString::number(ba.length()) ;
}

Note:我确实要向 Skizz 道歉,他写的内容实际上对调试根本问题很有帮助。 QByteArray 中的字符是专门为打印机预先格式化的,问题是,它们包含几个 NULL 字节。当尝试将它们发送到打印机时,这会导致 TextOut 截断文本,仅打印前几行。按照答案中的建议,使用 WritePrinter 会忽略空字节并接受 void * 和长度,然后将其全部放在那里。

此外,他建议使用 PrintDlg 的回复确实有助于获取正确的打印机 HDC,问题是,用户首先选择打印机一次,然后不需要每次打印时都选择它,因为他们将打印很多(这是一个销售点)。

从字符串名称获取打印机 HDC 的问题是由于没有将所有重要的 NULL 字节添加到 wchar_* 中,这是通过以下方式解决的:

wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;

在上面,m_printer_path 是从打印管理器获取的打印机名称的字符串表示形式。

由于字符串具有打印机所需的所有格式,因此无需担心换行或任何格式。

这个问题的所有三个答案实际上对实现最终的工作解决方案都非常有帮助,我对每个答案都投了票,我很感谢每个人花时间做出回应。


大多数现代打印机不会对所提供的数据执行任何形式的布局处理。因此,将字符序列发送到打印机最多只能以某种默认字体打印页面侧面的一行文本。回车符也可能有效。

现代打印机通常做的是使用打印机理解的预处理数据来打印页面,并定义打印内容、打印位置以及打印方式。所有这些预处理都在主机上完成,并将结果发送到打印机。这就是您通常安装打印机驱动程序的原因 - 这些驱动程序获取用户数据(无论是简单的文本文件还是 DTP 页面)并将其转换为打印机可以理解的语言。

这样做的结果是,将原始文本发送到打印机可能不起作用。

那么您就会遇到拥有多台具有不同属性和语言的打印机的问题。

因此,在 Windows 中,所有这些都被抽象到打印机设备上下文对象中。它与图形设备上下文具有相同的接口,但创建方式不同。

Win32 API 有一个通用对话框让用户选择打印机。使用打印DlgEx功能允许用户选择打印机。然后使用返回的DC将文本绘制到页面上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

win32 C++ 将字符串打印到打印机 的相关文章

  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 在现代 C++ 中,临时生命周期延长何时有用?

    在 C 中 您可以将函数的返回值 返回值 而不是引用 绑定到 const 引用 并且代码仍然有效 因为该临时对象的生命周期将延长到作用域末尾 例如 std string get string return abc void f const
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 需要提取字符串中点后的最后一个数字,如“7.8.9.1.5.1.100”

    我需要提取 C 字符串中最后一个点后面的最后一个数字 例如 7 8 9 1 5 1 100 并将其存储在整数中 Added 该字符串也可以是 7 8 9 1 5 1 1 或 7 8 9 1 5 1 0 我还想验证它在最后一个点之前恰好是 7
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include
  • LINQ 中的“from..where”或“FirstOrDefault”

    传统上 当我尝试从数据库中获取用户的数据时 我使用了以下方法 在某种程度上 DbUsers curUser context DbUsers FirstOrDefault x gt x u LoginName id string name c
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • 来自 3rd 方库的链接器错误 LNK2019

    我正在将旧的 vc 6 0 应用程序移植到 vs2005 我收到以下链接器错误 我花了几天时间试图找到解决方案 错误LNK2019 无法解析的外部符号 imp 创建AwnService 52 在函数 public int thiscall
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan

随机推荐

  • 使用 BinaryFormatter 反序列化加密数据时出现问题

    这是我的代码 public static void Save
  • 控制 C 或 C++ 中的 shell 命令行通配符扩展

    我正在用 C 编写一个程序 foo 它通常在命令行上调用 如下所示 foo txt My main 以正常方式接收参数 在许多系统上 argv 1 从字面上看是 txt 并且我必须调用系统例程来进行通配符扩展 然而 在 Unix 系统上 s
  • 如何将 Handbrake 输出同时输出到屏幕和文件?

    因此 我一直在使用 Handbrake 命令行对我的视频收藏进行编码以存储在我的 NAS 上 这样我就可以在我的 HTPC 上使用它 我一直在寻找一种既可以输出到屏幕的方法 这样我就可以在编码时观察它的输出 也可以输出到文件 这样我就可以返
  • 非递归快速排序

    我很想知道我的非递归快速排序算法的实现是否存在一些缺点或隐藏的问题 为了优化它应该修改什么 以我的方式比较两个对象时可能会发生什么问题 public class QuickSort
  • MS Access 中出现“操作必须使用可更新查询”错误

    当我尝试运行 SQL 时 收到一条错误消息 操作必须使用可更新查询 据我了解 当 MS Access 中的更新 删除查询中使用联接时 就会发生这种情况 然而 我有点困惑 因为我的数据库中有另一个几乎相同的查询 它工作得很好 这是我的麻烦查询
  • Hadoop java.io.IOException:Mkdirs 无法创建 /some/path

    当我尝试运行我的作业时 出现以下异常 Exception in thread main java io IOException Mkdirs failed to create some path at org apache hadoop u
  • 如何使用 PHP 从 JSON 访问另一个对象内部的类成员

    我有一个像这样的 JSON 字符串 test var1 null var3 null status code 150 message blah blah 我想访问函数中的状态代码 这就是我尝试过的 responseObj jsonServi
  • UNIX 将 LARGE csv 导入 SQLite

    我有一个 5gig csv 文件 也可以作为 sas 数据文件 如果会更容易的话 我需要将其放入 sql 数据库中 以便我可以在 R 中使用它 变量名称全部包含在第一观察行中并用双引号引起来 有 1000 多个变量 其中一些是数字 另一些是
  • 向 UTL_MAIL.SEND 提供凭据以绕过 ORA-29278

    我正在尝试使用 UTL MAIL Send 打包过程从 PL SQL 程序发送电子邮件 但我收到以下错误 ORA 29278 SMTP 瞬时错误 421 服务不可用 我在网上搜索了一下 发现出现这个错误是因为运行我的Oracle数据库的主机
  • UIPickerView 用于具有不同数组的每个文本字段(Swift/Firebase)

    我正在尝试创建一个表单 其中每个文本字段都有一个 UIPickerView 用户可以使用它来选择所需的选项 我需要为每个文本字段使用不同的信息数组 但我似乎无法让它工作 而且我已经坚持了很长一段时间了 我有一个可能有效的方法 但由于每个字段
  • SVG 数据图像不能用作伪元素中的背景图像

    我将 SVG 设置为background image对于伪元素 content position absolute right 0 bottom 0 left 0 width 100 height 12px background image
  • ZXing - 使用通用类型 BarcodeWriter 需要 1 个类型参数 ZXing.NET.Mobile

    我一直在尝试使用 ZXing Net Mobile 和 ZXing Net Mobile Forms 生成 QRCode https github com Redth ZXing Net Mobile并遇到以下错误 严重性代码描述项目文件行
  • 使用接口变量

    我仍在努力更好地理解接口 我知道它们是什么以及如何在课堂上实现它们 我不明白的是 当您创建一个接口类型之一的变量时 IMyInterface somevariable 你为什么要这样做 我不明白如何像类一样使用 IMyInterface 例
  • 如何从 Java 调用 .NET dll

    我有这段代码来创建一个简单的 NET dll 它只返回一个int 但是 它在 Java 中不起作用 using System using System Collections Generic using System Linq using
  • Jquery:点击菜单外部后下拉菜单不会消失

    我是 jquery 的新手 我正在查看 google 的代码来创建他们的 更多 按钮 我已经可以使用自动取款机了 但让下拉菜单消失的唯一方法是再次单击 更多 按钮 我可以添加一种方法来更改此设置 以便下拉菜单本身之外的任何单击都会将其关闭吗
  • Flask-Admin 多对多字段显示

    I develop an application using Flask I use Postgres db psycop2 SQLAlchemy and Flask Admin for admin interface And I got
  • NSDate 在一个月的第一天返回错误的日期

    我的应用程序使用 NSDate date 函数来获取当前日期 其他日子工作正常 除了每月 1 日上午 即按照以下步骤操作 将系统日期设置为 2011 年 6 月 1 日 时间为午夜 00 00 至凌晨 5 59 使用以下代码 NSLog C
  • Moment.js 在 Firefox 中给出无效日期

    我需要在 moment js 中转换日期时间 但它在 Chrome 和 Firefox 中给了我不同的结果 在 Google Chrome 中 它给出正确的结果 但在 Mozilla firefox 中给出 无效日期 谷歌浏览器 momen
  • 为什么 LEFT JOIN 比 INNER JOIN 慢?

    我有两个查询 第一个 内连接 非常快 第二个 左连接 非常慢 如何使第二个查询更快 EXPLAIN SELECT saved email FROM saved INNER JOIN finished ON finished email sa
  • win32 C++ 将字符串打印到打印机

    经过几天的网络搜索 了解如何在 Windows 上将任意字符串打印到任意打印机上 我终于想出了这段代码 LPBYTE pPrinterEnum DWORD pcbNeeded pcbReturned PRINTER INFO 2 piTwo