Frage

Wir haben eine App mit einigem Legacy-Drucker „setup“ Code bekommen, dass wir noch PrintDlg verwenden für. Wir verwenden ein eigenes Template dem Benutzer zu ermöglichen, auszuwählen, welche Drucker für verschiedene Arten von Druckaufgaben zu verwenden (wie Berichte oder Zeichnungen) zusammen mit Orientierung und Papierformat / Quelle.

Es funktioniert auf XP und 32-Bit-Vista, aber auf Vista x64 es wird ein CDERR_MEMLOCKFAILURE über CommDlgExtendedError(). Ich habe versucht, es nur mit dem nackten Knochen Eingang in der PRINTDLG Struktur ausgeführt wird, aber wenn die Parameter PD_PRINTSETUP oder PD_RETURNDEFAULT umfassen, bekomme ich diesen Fehler.

Da der Druckerauswahl / Seite-Setup wird in PageSetupDlg und PrintDlgEx aufgeteilt worden ist, ist es kein offensichtlicher einfacher Übergang ohne eine angemessene Menge an Code zu ändern und / oder zu ändern vollständig, wie wir präsentieren Drucke und Druckerkonfiguration für den Benutzer.

Hat jemand dieses Problem auf 64-Bit-Vista gesehen, und haben festgestellt, Sie Workarounds?

Weitere Informationen:
Anwendung läuft als Administrator aufgrund anderer Einschränkungen

War es hilfreich?

Lösung

Ich fand einen ähnlichen Beitrag auf den Microsoft-Foren: auf Vista x64 , DocumentProperties nicht von UAC-Prozess erhöht

ich mit einem Beispielprogramm überprüft habe, die PrintDlg als Nicht-Admin-Arbeiten ausgeführt werden.

Andere Tipps

fand ich einen Beitrag auf dem Quicken Community-Forum: Lösung zu Druckproblemen Vista 64 Quicken 2008 , und die damit verbundenen FAQ: Was passiert, wenn ich nicht in der Lage zu drucken, oder empfangen "Fehler mit dem Drucker zu kommunizieren"? und die Empfehlung einen Emulationsdrucker verwendet werden.

Ich lief in dieses Problem, da ich den Druck meiner app Zugabe wurde. Ich wurde mit der Printdialog Klasse und es funktioniert super, wenn sie als 32-Bit-Anwendung kompiliert wird, ist aber nicht einmal Pop-up, wenn sie in 64-Bit-Modus kompiliert. Keine Fehlermeldungen, kein gar nichts. Der Aufruf von Showdialog gibt nur sofort. (Beachten Sie, dass ich 64-Bit-Vista leite.)

Ich habe versucht PrintDlg verwenden, aber das hat das gleiche Problem. Ich sah online und eine Menge Leute fanden wir ähnliche Probleme haben, wenn auch offenbar nicht jeder, der diese 64-Bit-Vista sieht hat. Wie dem auch sei, entschied ich mich schließlich meine eigene Version von Printdialog (Anleihen von Code online) zu schreiben, aber das war ein bisschen schwierig (wie einige der Online-Code Bugs hatte) und da ich nie ein vollständiges Beispiel online diese gefunden haben, dachte ich, ich würde meine Lösung hier posten.

Beachten Sie, meine Version läßt ein paar Dinge aus dem Dialog, wie der „Druckbereich“, „Kopien“ und „Print to file“. Dies sollte einfach hinzufügen, aber meine app habe sie nicht brauchen. Ich kann auch nicht herausfinden, was der „Typ:“. Feld anzeigte, damit ich es auch weggelassen

Hier ist, was der Dialog wie folgt aussieht:

alt text http://www.geocities.com/deancooper2000/PrintDialog64.jpg

Und hier ist mein Code (ich den Designer-Code verlassen haben, wie es recht einfach sein sollte, neu):

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
{
/// <summary>
/// The PrintDialog64 class replaces the standard PrintDialog with one that works in Vista x64
/// </summary>
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<PrinterItem> printers;
    private string            printerName;
    private string            originalName;
    private IntPtr            hDevMode = IntPtr.Zero;
    #endregion

    /// <summary>
    /// Gets or sets the printer that prints the document       
    /// </summary>
    public PrinterSettings PrinterSettings { get; set; }

    /// <summary>
    /// Gets or sets a value indicating the PrintDocument used to obtain PrinterSettings.       
    /// </summary>
    public PrintDocument Document { get; set; }

    /// <summary>
    /// Constructs a replacement for the standard PrintDialog with one that works in Vista x64
    /// </summary>
    public PrintDialog64()
    {
        InitializeComponent();
    }

    #region PrinterItem class
    /// <summary>
    /// The PrinterItem class holds a reference to a PrintQueue and allows us to sort a list based on printer name
    /// </summary>
    private class PrinterItem : IComparable<PrinterItem>
    {
        #region Private members
        private PrinterItem() {}
        #endregion

        /// <summary>
        /// Construct a PrinterItem by supplying a reference to the printer's PrintQueue class
        /// </summary>
        ///
        /// \param[in]  printer Reference to PrintQueue class for this printer
        public PrinterItem(PrintQueue printer)
        {
            Printer = printer;
        }

        /// <summary>
        /// Reference to PrintQueue class for this printer
        /// </summary>
        public PrintQueue Printer { get; set; }

        /// <summary>
        /// The string for this class is simply the FullName of the printer
        /// </summary>
        public override string ToString()
        {
            return Printer.FullName;
        }

        #region IComparable<PrinterItem> Members
        /// <summary>
        /// Implements IComparable interface to allow sorting of PrinterItem classes (based on printer name)
        /// </summary>
        ///
        /// \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<PrinterItem> GetPrinters()
    {
        List<PrinterItem> printers = new List<PrinterItem>();

        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 < 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;
    }
}
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top