Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I just ran into this problem as I was adding printing to my app. I was using the PrintDialog class and it works great if it is compiled as a 32-bit app, but doesn't even pop up when compiled in 64-bit mode. No error messages, no nothing. The call to ShowDialog just returns immediately. (Note that I am running 64-bit Vista.)</p> <p>I tried using PrintDlg, but that has the same problem. I looked online and found a lot of people we're having similar problems though apparently not everybody who has 64-bit Vista sees this. Anyway, I finally decided to write my own version of PrintDialog (borrowing from code online), but this was a bit tricky (as some of the online code had bugs) and since I never did find a complete example online for this, I thought I would post my solution here.</p> <p>Note, my version leaves a few things out of the dialog, like the "Print range", "Copies", and "Print to file". This should be easy to add but my app didn't need them. I also couldn't figure out what the "Type:" field was displaying so I left it out as well.</p> <p>Here's what the dialog looks like:</p> <p><a href="http://www.geocities.com/deancooper2000/PrintDialog64.jpg" rel="nofollow noreferrer">alt text http://www.geocities.com/deancooper2000/PrintDialog64.jpg</a></p> <p>And here's my code (I've left the designer code out as it should be pretty easy to recreate):</p> <pre><code>using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.Printing; using System.Runtime.InteropServices; using System.Windows.Forms; using Zemetrics.Diagnostics; namespace Utils { /// &lt;summary&gt; /// The PrintDialog64 class replaces the standard PrintDialog with one that works in Vista x64 /// &lt;/summary&gt; public partial class PrintDialog64 : Form { #region Private members [DllImport("winspool.drv", EntryPoint="DocumentPropertiesW")] private static extern int DocumentProperties(IntPtr hWnd,IntPtr hPrinter,[MarshalAs(UnmanagedType.LPWStr)] string pDeviceName,IntPtr pDevMode,IntPtr devModeIn,int fMode); [DllImport("winspool.drv")] private static extern int OpenPrinter(string pPrinterName,out IntPtr hPrinter,IntPtr pDefault); [DllImport("winspool.drv")] private static extern int ClosePrinter(IntPtr phPrinter); [DllImport("kernel32.dll")] private static extern IntPtr GlobalLock(IntPtr hMem); [DllImport("kernel32.dll")] private static extern int GlobalUnlock(IntPtr hMem); [DllImport("kernel32.dll")] private static extern int GlobalFree(IntPtr hMem); private const int DM_PROMPT = 4; private const int DM_OUT_BUFFER = 2; private const int DM_IN_BUFFER = 8; private List&lt;PrinterItem&gt; printers; private string printerName; private string originalName; private IntPtr hDevMode = IntPtr.Zero; #endregion /// &lt;summary&gt; /// Gets or sets the printer that prints the document /// &lt;/summary&gt; public PrinterSettings PrinterSettings { get; set; } /// &lt;summary&gt; /// Gets or sets a value indicating the PrintDocument used to obtain PrinterSettings. /// &lt;/summary&gt; public PrintDocument Document { get; set; } /// &lt;summary&gt; /// Constructs a replacement for the standard PrintDialog with one that works in Vista x64 /// &lt;/summary&gt; public PrintDialog64() { InitializeComponent(); } #region PrinterItem class /// &lt;summary&gt; /// The PrinterItem class holds a reference to a PrintQueue and allows us to sort a list based on printer name /// &lt;/summary&gt; private class PrinterItem : IComparable&lt;PrinterItem&gt; { #region Private members private PrinterItem() {} #endregion /// &lt;summary&gt; /// Construct a PrinterItem by supplying a reference to the printer's PrintQueue class /// &lt;/summary&gt; /// /// \param[in] printer Reference to PrintQueue class for this printer public PrinterItem(PrintQueue printer) { Printer = printer; } /// &lt;summary&gt; /// Reference to PrintQueue class for this printer /// &lt;/summary&gt; public PrintQueue Printer { get; set; } /// &lt;summary&gt; /// The string for this class is simply the FullName of the printer /// &lt;/summary&gt; public override string ToString() { return Printer.FullName; } #region IComparable&lt;PrinterItem&gt; Members /// &lt;summary&gt; /// Implements IComparable interface to allow sorting of PrinterItem classes (based on printer name) /// &lt;/summary&gt; /// /// \param[in] other The other PrinterItem class that we are to compare this one to public int CompareTo(PrinterItem other) { return other.Printer.FullName.CompareTo(this.Printer.FullName); } #endregion } #endregion private List&lt;PrinterItem&gt; GetPrinters() { List&lt;PrinterItem&gt; printers = new List&lt;PrinterItem&gt;(); EnumeratedPrintQueueTypes[] Queue_types = {EnumeratedPrintQueueTypes.Local,EnumeratedPrintQueueTypes.Connections}; try { using (LocalPrintServer server = new LocalPrintServer()) foreach (PrintQueue printer in server.GetPrintQueues(Queue_types)) printers.Add(new PrinterItem(printer)); } catch {} printers.Sort(); return printers; } private void PrintDialog64_Shown(object sender, EventArgs e) { originalName = Document.PrinterSettings.PrinterName; printers = GetPrinters(); int index=0, i=0; foreach(PrinterItem printer in printers) { nameComboBox.Items.Add(printer.ToString()); if (printer.ToString() == originalName) index = i; i++; } nameComboBox.SelectedIndex = index; } private void nameComboBox_Leave(object sender, EventArgs e) { string text = nameComboBox.Text; foreach(Object field in nameComboBox.Items) if (((string) field).ToLower().StartsWith(text.ToLower())) nameComboBox.SelectedItem = field; if (nameComboBox.SelectedIndex &lt; 0) nameComboBox.SelectedIndex = 0; } private void nameComboBox_SelectedIndexChanged(object sender, EventArgs e) { PrintQueue printer = printers[nameComboBox.SelectedIndex].Printer; if (hDevMode!=IntPtr.Zero) GlobalFree(hDevMode); PrinterSettings.PrinterName = printerName = printer.FullName; hDevMode = PrinterSettings.GetHdevmode(Document.DefaultPageSettings); statusValue .Text = printer.QueueStatus.ToString()=="None" ? "Ready" : printer.QueueStatus.ToString(); whereValue .Text = printer.Location=="" ? printer.QueuePort.Name : printer.Location; commentValue.Text = printer.Comment; } private void propertiesButton_Click(object sender, EventArgs e) { IntPtr handle; OpenPrinter(printerName, out handle, IntPtr.Zero); IntPtr pDevMode = GlobalLock( hDevMode ); DocumentProperties(this.Handle, handle, printerName, pDevMode, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER); GlobalUnlock( hDevMode ); PrinterSettings.SetHdevmode( hDevMode ); PrinterSettings.DefaultPageSettings.SetHdevmode( hDevMode ); ClosePrinter(handle); } private void pageDefaultsButton_Click(object sender, EventArgs e) { PageSetupDialog setup = new PageSetupDialog(); setup.PageSettings = Document.DefaultPageSettings; if (setup.ShowDialog() == DialogResult.OK) { if (hDevMode!=IntPtr.Zero) GlobalFree(hDevMode); hDevMode = PrinterSettings.GetHdevmode( Document.DefaultPageSettings = setup.PageSettings ); } } private void okButton_Click(object sender, EventArgs e) { if (hDevMode!=IntPtr.Zero) GlobalFree(hDevMode); } private void cancelButton_Click(object sender, EventArgs e) { if (hDevMode!=IntPtr.Zero) GlobalFree(hDevMode); PrinterSettings.PrinterName = originalName; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload