c# - 使用命令将 BMP 文件打印到打印机

标签 c# c++ pinvoke

我需要使用命令将 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图像打印命令部分:enter image description here

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 [输出] 指向接收有效写入设备的字节数的变量的指针。

lpOverlapped [输入/输出] 指向 OVERLAPPED 结构的可选指针,用于异步操作。如果指定此参数,Usb_WritePort 会立即返回,并在操作完成时发出该事件信号。

返回值: 如果写入操作成功则为 TRUE,否则为 FALSE。如果为 FALSE,用户可以调用 GetLastError() 来获取其他信息

打印机不打印任何内容。 请帮我解决这个问题。

最佳答案

    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 创建一个,从非常小的东西开始,然后使用“文件 + 另存为”,将“保存类型”设置更改为“单色位图(*.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");
    }

关于c# - 使用命令将 BMP 文件打印到打印机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28317815/

相关文章:

c# - 如何使用 Asp.Net WebAPI 进行路由?

c# - 是否可以使用 Obsolete 属性标记 .net 函数

c# - Entity Framework 4.0 批量操作的性能

C++ - 通过 ref 将对象传递给 CreateThread()

c++ - 不能出现在常量表达式中

来自 C DLL 回调的 C# 跨线程 UI 操作

c# - 为什么在尝试 Assembly.ReflectionOnlyLoad 时没有执行 ReflectionOnlyAssemblyResolve?

c++ - 未解析的外部符号“公共(public) : __thiscall

c# - 在 C# 中查看非托管 dll 上的导出表

C# 等效于另一个进程的postthreadmessage