Advanced Printer Properties Dialog in WPF

I'm trying to get the advanced printer properties dialog to display on the push of a button.  It should display the same thing as the Preferences button on the PrintDialog.ShowDialog window.  Is there a supplied class to do this in the .NET Framework?  If not, how is this done considering the Window API wants a DEVMODE and WPF printing uses a PrintTicket?  I seen examples of how to do this using Windows Forms, but haven't seen any examples for getting this same functionality in WPF.  Which is why I'm thinking I'm missing something.

Any help would be appreciated


5 Answers Found


Answer 1

It is the same as in WindowsForms.....

You need to add the referance System.Windows.Forms

and than


PrivateSub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click


Dim dlg AsNew System.Windows.Forms.PrintDialog





Answer 2

I'm looking to display the advanced printer settings, not the printer dialog.  Run your code above and hit the preferences button on the window that is displayed.  That is the window I want/need without having to get there from the print dialog.

Answer 3

I think I may be making some headway, but I need some assistance on one issue.  The print settings are flowing out of the dialog, but not in.  For example, if the PrintTicket is set to Landscape when entering the dialog, the dialog still shows Portrait.  But if the orientation is changed while it is open, it does show this change on the retrieved PrintTicket.  How do I fix this one issue?

EDIT:  Had a ref keyword on the pDevModeInput parameter.  Removed it and it works as expected.  So below is a working solution.  If there is a better way or if I'm doing something incorrectly, please let me know.

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

			PrintTicketConverter ptc = new PrintTicketConverter(SelectedPrintQueue.Name, SelectedPrintQueue.ClientPrintSchemaVersion);
			IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;

			byte[] myDevMode = ptc.ConvertPrintTicketToDevMode(SelectedPrintQueuePrintTicket, BaseDevModeType.UserDefault);
			GCHandle pinnedDevMode = GCHandle.Alloc(myDevMode, GCHandleType.Pinned);
			IntPtr pDevMode = pinnedDevMode.AddrOfPinnedObject();
			DocumentProperties(mainWindowPtr, IntPtr.Zero, SelectedPrintQueue.Name, pDevMode, pDevMode, 14);
			SelectedPrintQueuePrintTicket = ptc.ConvertDevModeToPrintTicket(myDevMode);

Answer 4

Be careful. For network printers you will need to use the SelectedPrintQueuePrintTicket.FullName property instead of the Name property!

Answer 5

Thank you,

I was trying to do this myself and you saved me a lot of trouble.

I especially like your usage of pinning the GCHandle as I was going the route of Marshal.AllocHGlobal, with the code looking a lot less clean and unnecessary copying.


<< Previous      Next >>

Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter