使用命令将 BMP 文件打印到打印机
Posted
技术标签:
【中文标题】使用命令将 BMP 文件打印到打印机【英文标题】:Print a BMP file to Printer using command 【发布时间】:2015-02-04 09:28:26 【问题描述】:我需要使用命令将 BMP 文件打印到 USB 打印机。
C++ 签名是
USB_API BOOL Usb_WritePort(BOOL bUseBulkEndp, LPCVOID lpBuffer, DWORD dwNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
这是我的 C# 签名
[DllImport("usbRtb.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean Usb_WritePort(bool bUseBulkEndp, IntPtr lpBuffer, UInt32 nNumberOfBytesToWrite,
out UInt32 lpNumberOfBytesWritten, [In] ref NativeOverlapped lpOverlapped);
我试过了
update = Usb_UpdateConnection(0, ref out1, ref out2);
char[] files = System.Text.Encoding.ASCII.GetString(File.ReadAllBytes(@"D:\\mailman.BMP")).ToCharArray();
update = Usb_UpdateConnection(0, ref out1, ref out2);
byte[] pr = Encoding.BigEndianUnicode.GetBytes(files);
intpt = Marshal.StringToCoTaskMemAnsi("\x1F\x42\x4D\x50" + ASCIIEncoding.ASCII.GetString(pr));
count = (UInt32)pr.Count() + 4;
var read = Usb_WritePort(true, intpt, count, out written, ref natOverlap0);
附加打印机手册BMP图像打印命令部分:
C++ SDK 文档: Usb_WritePort
语法:
BOOL Usb_WritePort (BOOL bUseBulkEndp,
LPCVOID lpBuffer,
DWORD dwNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
目的: 通过指定的输出端点将数据写入当前选定的设备。 需要首先使用 Usb_UpdateConnection() API 建立连接。 操作类似于在结构重叠的同步和异步模式下使用 WriteFile()。
参数:
bUseBulkEndp [in] 将参数设置为 TRUE 以将数据写入 BULK OUT 端点,设置为 FALSE 以写入 INTERRUPT OUT 端点
lpBuffer [in] 指向包含要写入设备的数据的缓冲区的指针。
dwNumberOfBytesToWrite [in] 要写入设备的字节数。此数字必须小于或等于数据缓冲区的大小(以字节为单位)
lpNumberOfBytesWritten [out] 指向接收有效写入设备的字节数的变量的指针。
lpOverlapped [输入/输出] 指向 OVERLAPPED 结构的可选指针,用于异步操作。如果指定此参数,Usb_WritePort 会立即返回,并在操作完成时发出事件信号。
返回值: 如果写入操作成功,则为 TRUE,否则为 FALSE。如果为 FALSE,用户可以调用 GetLastError() 来获取更多信息
打印机不打印。 请帮我解决这个问题。
【问题讨论】:
请注意,数据字符串中的前四个斜线不是字面的,对吗? \x1F\x42\x4D\x50 这是命令 我不太了解打印机和 USB,但是 USB 打印机可以访问“D:\mailman.bmp”吗?我想你必须在某个时候发送位图数据。 很难看出这是如何工作的。 USB电缆另一端的那个东西看不到您的文件系统。看起来你是在编造这个。当然,您需要了解有关打印机的一些详细信息。但无论如何,你为什么要在这台打印机上喷出原始数据?你不是像其他人一样只使用打印机驱动程序打印吗? 所以我猜你需要阅读打印机手册并进行编码 【参考方案1】: Marshal.StringToCoTaskMemAnsi("\x1F\x42\x4D\x50" + ASCIIEncoding.ASCII.GetString(pr));
您的代码并不接近正确,使用 ASCIIEncoding 是非常错误的。位图包含不能用 ASCII 表示的字节值。您需要做的第一件事是更改 pinvoke 声明,第二个参数需要是 byte[] 并且您应该避免重叠 I/O,因为这需要更多的 pinvoke。所以:
[DllImport("usbRtb.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean Usb_WritePort(
bool bUseBulkEndp,
byte[] lpBuffer,
int nNumberOfBytesToWrite,
out int lpNumberOfBytesWritten,
IntPtr lpOverlapped
);
接下来你需要做的是密切关注实际的位图。手册要求这是一个单色位图,这在现在并不容易。但是您仍然可以使用 MSPaint 创建一个,从非常小的东西开始,然后使用 File + Save As,将“Save as type”设置更改为“Monochrome Bitmap (*.bmp, *.dib)”。
接下来,您需要在调用函数之前创建正确的 byte[]。它需要类似于:
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
byte[] inpt = new byte[fs.Length + 1];
inpt[0] = 0x1f;
fs.Read(inpt, 1, (int)fs.Length);
int written;
bool ok = Usb_WritePort(true, inpt, inpt.Length, out written, IntPtr.Zero);
if (!ok || written != inpt.Length) throw new Exception("USB write failed");
【讨论】:
以上是关于使用命令将 BMP 文件打印到打印机的主要内容,如果未能解决你的问题,请参考以下文章