【问题标题】:Using PrintDlg on Vista x64 does not work, works fine on 32 bit and XP在 Vista x64 上使用 PrintDlg 不起作用,在 32 位和 XP 上工作正常
【发布时间】:2023-03-11 11:59:01
【问题描述】:

我们有一个带有一些旧打印机“设置”代码的应用程序,我们仍在使用@987654321@。我们使用自定义模板允许用户选择用于各种类型打印任务(例如报告或图纸)的打印机以及方向和纸张大小/来源。

它适用于 XP 和 32 位 Vista,但在 Vista x64 上它通过CommDlgExtendedError() 获得CDERR_MEMLOCKFAILURE。我尝试只使用PRINTDLG 结构中的基本输入来运行它,但如果参数包括PD_PRINTSETUPPD_RETURNDEFAULT,我会收到该错误。

由于打印机选择/页面设置已拆分为 @987654322@@987654323@,因此如果不更改大量代码和/或完全更改我们向用户呈现打印和打印机设置的方式,就没有明显的简单转换.

有没有人在 64 位 Vista 上看到过这个问题,您是否找到了任何解决方法?

注意事项:
由于其他限制,应用程序以管理员身份运行

【问题讨论】:

    标签: c++ visual-studio-2008 printing vista64


    【解决方案1】:

    我在微软论坛上找到了一个相关的帖子:On Vista x64, DocumentProperties fails from UAC-elevated process

    我已经用一个示例程序验证了 PrintDlg 以非管理员身份运行。

    【讨论】:

      【解决方案2】:

      我在 Quicken 社区论坛上找到了一个帖子:Solution to Printing Problems Vista 64 Quicken 2008,以及相关的常见问题解答:What if I'm unable to print, or receive "Error communicating with printer"?,以及使用仿真打印机的建议。

      【讨论】:

        【解决方案3】:

        我刚刚在我的应用程序中添加打印时遇到了这个问题。我正在使用 PrintDialog 类,如果它被编译为 32 位应用程序,它工作得很好,但在 64 位模式下编译时甚至不会弹出。没有错误消息,什么都没有。对 ShowDialog 的调用立即返回。 (请注意,我运行的是 64 位 Vista。)

        我尝试使用 PrintDlg,但也有同样的问题。我在网上查了一下,发现很多人都遇到了类似的问题,但显然不是每个拥有 64 位 Vista 的人都能看到这一点。无论如何,我最终决定编写自己的 PrintDialog 版本(借用在线代码),但这有点棘手(因为一些在线代码有错误),因为我从来没有在网上找到一个完整的例子,我想我会在这里发布我的解决方案。

        请注意,我的版本在对话框中留下了一些内容,例如“打印范围”、“份数”和“打印到文件”。这应该很容易添加,但我的应用不需要它们。我也无法弄清楚“类型:”字段显示的内容,所以我也将其省略了。

        对话框如下所示:

        alt text 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;
            }
        }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-28
          • 2014-12-31
          • 1970-01-01
          • 1970-01-01
          • 2014-11-24
          • 1970-01-01
          相关资源
          最近更新 更多