描述
这里我需要实现打印机和应用程序之间的双向通信。
到目前为止,我可以使用winspool API 的func writePrinter 在打印机中进行写入。我面临的问题是针对 readPrinter。
打开打印机的代码
final alloc = Arena();
final pPrinterName = printerName.toNativeUtf16(allocator: alloc);
final pWritePrinterHandle = alloc<HANDLE>();
final pDefault = alloc<PRINTER_DEFAULTS>()
..ref.pDatatype = nullptr
..ref.pDevMode = nullptr
..ref.DesiredAccess = PRINTER_ALL_ACCESS;
// Open Printer
var fSuccess = OpenPrinter(pPrinterName, pWritePrinterHandle, pDefault);
if (fSuccess == 0) {
final error = GetLastError();
throw Exception('OpenPrint error, status: $fSuccess, error: $error');
}
向打印机发送命令的代码
final pDocInfo = alloc<DOC_INFO_1>()
..ref.pDocName =
'Boca Systems Communicator'.toNativeUtf16(allocator: alloc)
..ref.pDatatype =
'RAW'.toNativeUtf16(allocator: alloc) // RAW, TEXT or XPS_PASS
..ref.pOutputFile = nullptr;
//https://learn.microsoft.com/windows/win32/printdocs/startdocprinter
var fStartDocJobId =
StartDocPrinter(pWritePrinterHandle.value, 1, pDocInfo);
if (fSuccess == 0) {
final error = GetLastError();
throw Exception(
'StartDocPrinter error, status: $fSuccess, error: $error');
}
var fStartPrintSuccess = StartPagePrinter(pWritePrinterHandle.value);
// Print Row Data
String dataToPrint = '<S92>';
final cWritten = alloc<DWORD>();
final data = dataToPrint.toNativeUtf8(allocator: alloc);
final writeSuccess = WritePrinter(
pWritePrinterHandle.value, data, dataToPrint.length, cWritten);
if (dataToPrint.length != cWritten.value) {
final error = GetLastError();
throw Exception(
'WritePrinter error, status: $writeSuccess, error: $error');
}
读取打印机的代码
final printerJobName = '$printerName, Job $fStartDocJobId';
final Completer<void> completer = Completer<void>();
final pReadPrinterHandle = alloc<HANDLE>();
final pReadDefault = alloc<PRINTER_DEFAULTS>()
..ref.pDatatype = nullptr
..ref.pDevMode = nullptr
..ref.DesiredAccess = PRINTER_USE_ACCESS;
final openPrinterDetailName = printerJobName.toNativeUtf16(allocator: alloc);
// Open Printer for Reading
var fReadOpenSuccess =
OpenPrinter(openPrinterDetailName, pReadPrinterHandle, pReadDefault);
if (fReadOpenSuccess == 0) {
final error = GetLastError();
throw Exception(
'Read OpenPrint error, status: $fReadOpenSuccess, error: $error, openPrinterDetailName $printerJobName');
}
final readBufferSize = 1024;
final pReadData = alloc<Uint8>(readBufferSize);
final bytesRead = alloc<Uint32>();
final readSuccess = ReadPrinter(
pReadPrinterHandle.value, pReadData, readBufferSize, bytesRead);
if (readSuccess == 0) {
final error = GetLastError();
throw Exception('ReadPrinter error, status: $readSuccess, error: $error');
}
// Process the read data
final readData = pReadData.cast<Utf8>().toDartString();
在上面的代码块中,ReadPrinter也没有被执行,也没有抛出错误。
// Open the printer for reading using the port name (e.g., "USB001, Port"), it is required to add the ", Port" keyword as a postfix.
int openReadPrinter() {
final Pointer<Utf16> pPortName = portName.toNativeUtf16();
final success = OpenPrinter(pPortName, readPrinterHandle, nullptr);
if (success == 0) {
final error = GetLastError();
throw Exception('OpenPrint Read error, status: $success, error: $error');
}
return success;
}
// Function to read from the printer
String readFromPrinter(Pointer readPrinterHandle) {
const readBufferSize = 1024;
final pReadData = alloc<Uint8>(readBufferSize);
final bytesRead = alloc<Uint32>();
final success =
ReadPrinter(readPrinterHandle, pReadData, readBufferSize, bytesRead);
if (success == 0) {
final error = GetLastError();
throw Exception("Read from printer failed. Error: $error");
} else {
return pReadData.cast<Utf8>().toDartString();
}
}
在上面的代码中:
openReadPrinter
功能打开打印机以使用指定的端口名称 (portName) 进行读取。如果成功,则返回一个非零值;否则,它会抛出带有错误详细信息的异常。ReadPrinter
无法从打印机读取数据的情况的错误处理,提供有关遇到的错误的信息。此代码演示了如何使用 winspool API 在 Dart 中实现应用程序和打印机之间的双向通信。