希望有人在这里可以帮助我,因为我正在撞墙试图让它发挥作用。基本上我需要使用winspool.Drv win32 API打印以将原始文本/ PCL命令发送到打印机。这很好,但是,您在打印机对话框/首选项中选择的打印机选项都没有做任何事情。
最终我想从对话框PrinterSettings中获取DEVMODE,并将其用于原始打印,但我甚至无法让它手动设置它。
我尝试在WritePrinter之前更改DEVMODE,或者在单独的打开/关闭打印机之前,我尝试仅使用DocumentProperties调用,并使用带有PRINTER_INFO_8结构的GetPrinter / SetPrinter,没有什么可说的。 DEVMODE结构似乎填写正确,我改变它,它似乎正确改变,但打印机始终打印相同的方式无论如何。
以下是我一直在使用的代码:
方法一:
public static bool SetPrinterSettings(PrinterSettings settings, IntPtr hPrinter)
{
IntPtr hDevMode; // a handle to our current DEVMODE
IntPtr pDevMode; // a pointer to our current DEVMODE
String sPrinterName; // normalized printer name
DEVMODE dm;
// Setup
sPrinterName = settings.PrinterName.Normalize();
// Obtain the current DEVMODE from the PrinterSettings
hDevMode = settings.GetHdevmode(settings.DefaultPageSettings);
// Obtain a lock on the handle and get an actual pointer so Windows won't move
// it around while we're futzing with it
pDevMode = GlobalLock(hDevMode);
// test
dm = (DEVMODE)Marshal.PtrToStructure(pDevMode, typeof(DEVMODE));
// Our DEVMODE is 188 bytes, but dmSize returns 220, does this matter?
// This code doesnt seem to work
//dm.dmSize = (short)Marshal.SizeOf(dm); // Set size to our implementation of DevMode
//int isize = GlobalSize(pDevMode).ToInt32() - (int)dm.dmSize; // Set the print drivers extra size
//dm.dmDriverExtra = Convert.ToInt16(isize);
// Change things
dm.dmFields = DM_FIELD_TYPE.DM_ORIENTATION;
dm.dmOrientation = 2;
// Load the structure back into the buffer
Marshal.StructureToPtr(dm, pDevMode, true);
//Tell the printer about the new property
int ret = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, pDevMode, pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));
if (ret <= 0)
{
return false;
}
// We're done futzing
GlobalUnlock(hDevMode);
// Tell our printer settings to use the one we just overwrote
//settings.SetHdevmode(hDevMode);
// It's copied to our printer settings, so we can free the OS-level one
GlobalFree(hDevMode);
//test
dm = (DEVMODE)Marshal.PtrToStructure(pDevMode, typeof(DEVMODE));
// ^^ this contains correct orientation
return true;
}
方法2:
public static bool SetLandscapeMode(PrinterSettings settings, IntPtr hPrinter)
{
// Setup
String sPrinterName = settings.PrinterName.Normalize();
// get current printer settings
int memNeeded = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, 0);
IntPtr pFullDevMode = Marshal.AllocHGlobal(memNeeded);
DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, pFullDevMode, IntPtr.Zero, DM_OUT_BUFFER);
DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(pFullDevMode, typeof(DEVMODE));
// change the settings
dm.dmFields = DM_FIELD_TYPE.DM_ORIENTATION;
dm.dmOrientation = 2;
Marshal.StructureToPtr(dm, pFullDevMode, true);
PRINTER_INFO_8 PI8 = new PRINTER_INFO_8();
PI8.pDevMode = pFullDevMode;
IntPtr pPI8 = Marshal.AllocHGlobal(Marshal.SizeOf(PI8));
Marshal.StructureToPtr(PI8, pPI8, true);
// save the printer settings
SetPrinter(hPrinter, 9, pPI8, 0);
Marshal.FreeHGlobal(pPI8);
return true;
}
测试打印的代码:
private void testPrint_Click(object sender, EventArgs e)
{
IntPtr hPrinter;
if (printDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
hPrinter = RawPrint.OpenRAWPrinter(printDialog1.PrinterSettings.PrinterName);
if (hPrinter == IntPtr.Zero)
{
MessageBox.Show("Error opening printer");
return;
}
if (!RawPrint.StartRAWDocument(hPrinter, "Test document"))
{
MessageBox.Show("Error starting raw document");
RawPrint.CloseRAWPrinter(hPrinter);
return;
}
// Start a page.
if (RawPrint.StartRawPage(hPrinter))
{
// Set the printers settings
//if (!RawPrint.SetPrinterSettings(printDialog1.PrinterSettings, hPrinter))
if(!RawPrint.SetLandscapeMode(printDialog1.PrinterSettings, hPrinter))
{
MessageBox.Show("Error setting printer settings");
RawPrint.CloseRAWPrinter(hPrinter);
return;
}
String test = "This is \r\n test print data";
byte[] buf = Encoding.Default.GetBytes(test);
GCHandle gch = GCHandle.Alloc(buf, GCHandleType.Pinned);
RawPrint.writeRAW(hPrinter, gch.AddrOfPinnedObject(), buf.Length);
gch.Free();
RawPrint.EndRawPage(hPrinter);
}
RawPrint.EndRAWDocument(hPrinter);
RawPrint.CloseRAWPrinter(hPrinter);
}
else
{
MessageBox.Show("Error starting raw page");
}
}
唯一奇怪的是Marshal.SizeOf(typeof(DEVMODE))或Marshal.SizeOf(dm)等于188,而返回到结构中的dmSize是220.我尝试修改此dmSize以匹配我们的结构,如图所示在注释掉的代码中,但似乎错误或不起作用,不确定是否重要。
此外,DevModes中返回的信息似乎都是正确且有效的。我可以在打印对话框中设置选项,并在PrinterSettings devmode中查看它们。在这些函数的最后,将pDevMode编组回结构体中的设置已更改。
然而,这一切似乎都没有对印刷产生任何影响。有什么东西我不见了吗?
编辑:测试函数中的RawPrint调用只是假脱机程序api调用的包装。页面打印正常,它只是始终以纵向模式打印,没有选项可用。
答案 0 :(得分:1)
不是通过使用WritePrinter绕过打印机驱动程序,而应该正常启动打印作业并使用ExtEscape()和PASSTHROUGH转义注入PCL。这将允许所有PrinterSettings值应用于作业。并非所有打印机驱动程序都支持PASSTHROUGH,但您可以通过使用QUERYESCSUPPORT调用ExtEscape()来检查驱动程序支持。