I have been dabbling with winapi crate for printing international characters. For some reason the thermal printer seems to be printing garbage.
I have tried to encode using utf8 encoding of data but with no luck.
Has anyone been able to print international charset using winapi on a thermal printer?
Here is the 3 step code snippet of what I have tried:
Step 1: Open Printer
--------------------
let printer_name = "MY_PRINTER_NAME";
let mut printer_name_wide: Vec<u16> = printer_name.encode_utf16().chain(std::iter::once(0)).collect();
let mut printer_handle: winapi::um::winnt::HANDLE = std::ptr::null_mut();
let datatype: &str = "RAW"; // XPS_PASS, EMF,
let datatype_wide: Vec<u16> = datatype.encode_utf16().chain(std::iter::once(0)).collect();
let mut defaults = PRINTER_DEFAULTSW {
pDataType: datatype_wide.as_ptr() as *mut u16,
pDevMode: ptr::null_mut(),
DesiredAccess: 0x40000000, //GENERIC_WRITE
};
let result = unsafe {
OpenPrinter2W(
printer_name_wide.as_mut_ptr(),
&mut printer_handle,
&mut defaults,
std::ptr::null_mut(),
)
};
Step 2: Start Doc Printer
-------------------------
let job_name = "PrintJob";
let utf16_job_name: Vec<u16> = job_name.encode_utf16().collect();
let datatype: &str = "RAW"; // XPS_PASS, EMF,
let mut datatype_utf16: Vec<u16> = datatype.encode_utf16().chain(std::iter::once(0)).collect();
let docinfo1w = DOC_INFO_1W {
pDocName: utf16_job_name.as_ptr() as *mut u16,
pOutputFile: ptr::null_mut(),
pDatatype: datatype_utf16.as_mut_ptr(), // This works
};
fn struct_to_bytes<T>(data: &T) -> Vec<u8> {
unsafe {
let size = std::mem::size_of::<T>();
let ptr = data as *const T as *const u8;
std::slice::from_raw_parts(ptr, size).to_vec()
}
}
let struct_bytes: Vec<u8> = struct_to_bytes(&docinfo1w);
let result = StartDocPrinterW (
printer_handle,
1, // Number of copies
struct_bytes.as_ptr() as *mut u8);
println!("Failed to start page. Error code: {}", unsafe {
winapi::um::errhandlingapi::GetLastError()
});
Step 3: Print using WritePrinter
--------------------------------
let page_result = unsafe { StartPagePrinter(printer_handle) };
println!("Page started successfully!");
let text_to_print = "Zażółć gęślą jaźń";
let utf16_text: Vec<u16> = text_to_print.encode_utf16().chain(std::iter::once(0)).collect();
let mut bytes_written: u32 = 0;
let write_result = unsafe {
WritePrinter(
printer_handle,
utf16_text.as_ptr() as *mut winapi::ctypes::c_void,
utf16_text.len().try_into().unwrap(),
&mut bytes_written,
)
};
Points to Highlight:
- Used RAW as datatype
- As for as possible, have used unicode version of functions, that ends with W than A
- Encoded, data using encode_utf16