我正在使用WPF并且需要让用户设置一些与打印相关的选项,例如打印机和打印机属性(例如,papertray,横向/纵向,双面打印等)。我知道PrintDialog类可以获取PrintQueue和PrintTicket对象。但是,我需要创建自定义解决方案,无法显示PrintDialog。 我设法获得可用的PrintQueue对象,并让用户选择一台打印机。我正在努力打印机属性。 我的问题是:如何显示用户可以为所选PrintQueue设置打印机属性的对话框(当用户单击WPF PrintDialog中的“属性”按钮时显示的对话框)。
答案 0 :(得分:4)
找到以下代码 here (减去Window_Loaded
事件)。我测试了它,它看起来像一个魅力。显然,在显示对话框之前,您必须在PrinterSettings
对象中设置打印机名称。
希望这适合你:
[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalFree(IntPtr hMem);
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesW", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPWStr)] string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);
private const Int32 DM_OUT_BUFFER = 14;
public void OpenPrinterPropertiesDialog(PrinterSettings printerSettings, System.IntPtr pHandle) {
IntPtr hDevMode = printerSettings.GetHdevmode();
IntPtr pDevMode = GlobalLock(hDevMode);
Int32 fMode = 0;
int sizeNeeded = DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, fMode);
IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
fMode = DM_OUT_BUFFER;
DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, fMode);
GlobalUnlock(hDevMode);
printerSettings.SetHdevmode(devModeData);
printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
GlobalFree(hDevMode);
Marshal.FreeHGlobal(devModeData);
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
OpenPrinterPropertiesDialog(new PrinterSettings(), new WindowInteropHelper(this).Handle);
}
答案 1 :(得分:3)
如果您定位x86编译并从x64机器运行,则Pwninstein的代码将无效:分配devModeData
时,DocumentPropreties
将始终失败并返回sizeNeeded
-1 ,使用LastError
代码13。
要解决此问题,请确保定位 AnyCPU 或仅将DocumentPropreties
的呼叫更改为以下内容:
int sizeNeeded = DocumentProperties(pHandle,
IntPtr.Zero,
printerSettings.PrinterName,
IntPtr.Zero, // This solves it
pDevMode,
fMode);
使用IntPtr.Zero
而不是指向DevMode结构的正确指针看起来不对,但是第一次调用DocumentProperties并不会尝试修改该位置的内存。调用返回的唯一数据是存储表示打印驱动程序内部参数的设备模式数据所需的内存大小。
参考: