flutterdartwinapithermal-printer

How can I read Boca Printer status using Win32 package of Flutter Dart


Description

Here I need to achieve a two way communication between Printer and app.

  1. Write
  2. Read

So far I'm able to write in the Printer using func writePrinter of winspool API. Issue that I am facing is for the readPrinter.

Code to open a Printer

   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');
   }

Code to send command to printer

   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');
    }

Code to read Printer

  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();

In the above code block the ReadPrinter is not getting executed as well no error is thrown.

Winspool Dart API Reference


Solution

  • // 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() {
        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();
        }
    }
    

    In the above code:

    This code demonstrates how to achieve two-way communication between your application and the printer in Dart using the winspool API.