باستخدام PrintDlg على ويندوز فيستا x64 لا يعمل بشكل جيد على 32 بت و XP

StackOverflow https://stackoverflow.com/questions/285482

سؤال

لدينا التطبيق مع بعض تراث الطابعة "الإعداد" رمز ونحن لا تزال تستخدم PrintDlg ل.نستخدم قالب مخصص للسماح للمستخدم باختيار الطابعة التي تستخدم لأنواع مختلفة من مهام الطباعة (مثل التقارير أو الرسومات) جنبا إلى جنب مع التوجه حجم الورق/المصدر.

يعمل على XP 32-bit Vista, ولكن على ويندوز فيستا x64 فإنه يحصل على CDERR_MEMLOCKFAILURE عبر CommDlgExtendedError().لقد حاولت تشغيله مع مجرد البدائي الإدخال في PRINTDLG هيكل, ولكن إذا كانت تشمل المعلمات PD_PRINTSETUP أو PD_RETURNDEFAULT, أنا الحصول على هذا الخطأ.

منذ اختيار الطابعة / إعداد الصفحة وقد تم تقسيمها إلى PageSetupDlg و PrintDlgEx, لا يوجد واضح من السهل الانتقال من دون تغيير كمية عادلة من رمز و/أو تغيير تماما كيف نقدم الطباعة إعداد الطابعة المستخدم.

وقد أي شخص ينظر إلى هذه المشكلة على 64 بت ويندوز فيستا و هل وجدت أي العمل-احترف?

ملاحظات:
تشغيل التطبيق كمسؤول بسبب قيود أخرى

هل كانت مفيدة؟

المحلول

لقد وجدت وظيفة ذات الصلة على موقع Microsoft المنتديات: على Vista x64, DocumentProperties فشل من UAC-مرتفعة عملية

لقد تم التحقق منها مع عينة البرنامج الذي PrintDlg يعمل في غير المشرف يعمل.

نصائح أخرى

لقد وجدت وظيفة على تسريع منتدى المجتمع: حل مشاكل الطباعة Vista 64 سرع 2008, و ذات التعليمات: ماذا لو كنت غير قادر على الطباعة ، أو تلقي "خطأ التواصل مع الطابعة"? والتوصية إلى استخدام مضاهاة الطابعة.

لقد واجهت هذه المشكلة كما كنت إضافة الطباعة إلى بلدي التطبيق.كنت تستخدم PrintDialog الدرجة ويعمل كبيرة إذا جمعت 32 بت التطبيق ، ولكن حتى لا يطفو على السطح عندما جمعت في وضع 64 بت.لا توجد رسائل خطأ ، لا شيء.الدعوة إلى ShowDialog فقط يعود فورا.(ملاحظة أنني تشغيل 64 بت ويندوز فيستا.)

حاولت استخدام PrintDlg ، ولكن لديها نفس المشكلة.بحثت على الانترنت وجدت الكثير من الناس نحن من مشاكل مماثلة على ما يبدو ليس كل شخص لديه 64 بت فيستا يرى هذا.على أي حال, قررت أخيرا أن أكتب نسختي الخاصة من PrintDialog (الاقتراض من رمز الانترنت) ، ولكن هذا كان صعبا قليلا (مثل بعض رمز الانترنت قد البق) وبما أنني لم أجد كاملة سبيل المثال على الانترنت لهذا فكرت في أن ما الحل هنا.

ملاحظة نسختي يترك بعض الأشياء من الحوار ، مثل "نطاق الطباعة" ، "نسخ" و "طباعة إلى ملف".هذا ينبغي أن يكون من السهل لإضافة لكن التطبيق لم يكن في حاجة إليها.أنا أيضا لم أستطع معرفة ما نوع":" حقل تم عرض لذلك تركت الأمر كذلك.

هنا ما الحوار تبدو مثل:

النص البديل http://www.geocities.com/deancooper2000/PrintDialog64.jpg

وهنا لي رمز (لقد تركت مصمم رمز كما ينبغي أن يكون من السهل جدا إعادة):

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;
    }
}
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top