Bra*_*ndi 8 c# printing printer-properties
我希望能够在不打开打印机属性窗口的情况下更改打印机属性...
到目前为止,使用DocumentProperties(从winspool.drv导入)函数失败了,因为虽然很容易抑制对话框显示,但似乎PrinterSettings.GetHdevmode()返回的值不反映调用它的PrinterSettings ,而是之前打印机属性的值返回OK.例如,这给了我上次调用属性的先前(错误)值,而不是它应该来自PrinterSettings对象的值:
IntPtr hdevmode = PrinterSettings.GetHdevmode(PrinterSettings.DefaultPageSettings);
PrinterSettings.SetHdevmode(hdevmode);
PrinterSettings.DefaultPageSettings.SetHdevmode(hdevmode);
Run Code Online (Sandbox Code Playgroud)
那么GetHdevmode有一个bug还是它应该做的呢?有没有C#可以解决这个问题,还是有人甚至没有任何相关信息?我甚至很难找到关于这个主题的信息.
提前感谢您的任何见解.
编辑:我不想让这个问题太个人化,但希望在这种情况下拥有所有信息可以提供一个对其他人也是有用的解决方案的答案.
这是我编写的C++ DLL,以便为此问题找到解决方法.它目前没有工作 - 它改变了其他内存,如副本,并没有成功改变"底层"纸张大小.我认为我需要做的就是指定out缓冲区标志以进行更改?
extern "C" __declspec(dllexport) DEVMODE* __stdcall GetRealHDevMode(int width, int height, char *printerName, DEVMODE* inDevMode)
{
//declare handles and variables
HANDLE printerHandle;
LPHANDLE printerHandlePointer(&printerHandle);
//get printer handle pointer
OpenPrinter((LPWSTR)printerName, printerHandlePointer, NULL);
//Get size needed for public and private devmode data and declare devmode structure
size_t devmodeSize = DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, NULL, NULL, 0);
DEVMODE* devmode = reinterpret_cast<DEVMODE*>(new char[devmodeSize + sizeof(DEVMODE) + sizeof(inDevMode->dmDriverExtra)]);
//lock memory
GlobalLock(devmode);
//fill the out buffer
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, NULL, DM_OUT_BUFFER);
//change the values as required
devmode->dmPaperWidth = width;
devmode->dmPaperLength = height;
devmode->dmPaperSize = DMPAPER_USER;
devmode->dmFields &= ~DM_PAPERSIZE;
devmode->dmFields &= ~DM_PAPERLENGTH;
devmode->dmFields &= ~DM_PAPERWIDTH;
devmode->dmFields |= (DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH);
//input flag on now to put the changes back in
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER);
//unlock memory
GlobalUnlock(devmode);
//return the devmode that was used to alter the settings
return devmode;
}
Run Code Online (Sandbox Code Playgroud)
我认为C++代码足以改变设置,所以我在C#中做的就是:
public PrinterSettings ChangePrinterProperties(PrinterSettings inPrinterSettings)
{
IntPtr TemphDevMode = inPrinterSettings.GetHdevmode(inPrinterSettings.DefaultPageSettings);
IntPtr hDevMode = GetRealHDevMode((int)(inPrinterSettings.DefaultPageSettings.PaperSize.Width * 2.54F),
(int)(inPrinterSettings.DefaultPageSettings.PaperSize.Height * 2.54F),
inPrinterSettings.PrinterName, TemphDevMode);
GlobalFree(hDevMode);
return inPrinterSettings;
}
Run Code Online (Sandbox Code Playgroud)
更新:使用dmPaperSize和dmFields稍微更改了订单.改善结果; 还没到那儿.
更新2:好的,我发现一个微软页面说文档错误.MSDN说要在指定宽度和高度时将dmPaperSize设置为0,而Microsoft支持更正表示将其设置为DMPAPER_USER.http://support.microsoft.com/kb/108924
在 DEVMODE 中指定纸张尺寸的方式存在两个问题:
(1) 如果指定 DM_PAPERWIDTH 或 DM_PAPERLENGTH 或两者,则不得同时设置 DM_PAPERSIZE 位。这取决于打印机驱动程序,但许多驱动程序会忽略上面代码中的 DM_PAPERLENGTH/WIDTH。
(2) 许多驱动程序根本不支持 DM_PAPERLENGTH/WIDTH。使用此类驱动程序,您根本无法像上面那样设置纸张尺寸。您只能选择预定义的 dmPaperSizes 之一。
您可以使用 DeviceCapability(DC_FIELDS) 来确定您的驱动程序是否支持 DM_PAPERLENGTH/WIDTH。
您可以使用 DeviceCapability(DC_PAPERS) 枚举允许的 dmPaperSizes。