Vista x64에서 printdlg 사용은 작동하지 않으며 32 비트 및 XP에서 잘 작동합니다.

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

문제

우리는 여전히 사용중인 레거시 프린터 "설정"코드가있는 앱이 있습니다. printdlg 을 위한. 사용자가 사용자 정의 템플릿을 사용하여 사용자가 방향 및 용지 크기/소스와 함께 다양한 유형의 인쇄 작업 (예 : 보고서 또는 도면)에 사용할 프린터를 선택할 수 있습니다.

그것은 XP 및 32 비트 비스타에서 작동하지만 Vista X64에서는 CDERR_MEMLOCKFAILURE ~을 통해 CommDlgExtendedError(). 나는 베어 본 입력만으로 그것을 실행하려고 시도했다. PRINTDLG 구조이지만 매개 변수에 포함 된 경우 PD_PRINTSETUP 또는 PD_RETURNDEFAULT, 나는 그 오류가 발생합니다.

프린터 선택 / 페이지 설정이 분할되었으므로 pagesetupdlg 그리고 printdlgex, 상당한 양의 코드를 변경하거나 사용자에게 인쇄 및 프린터 설정을 제시하는 방법을 완전히 변경하지 않고는 명백한 쉬운 전환이 없습니다.

64 비트 비스타 에서이 문제를 본 사람이 있습니까?

메모:
응용 프로그램은 다른 제약으로 인해 관리자로 실행됩니다

도움이 되었습니까?

해결책

Microsoft 포럼에서 관련 게시물을 찾았습니다. Vista x64에서는 UAC가 발생하는 프로세스에서 DocumentProperties가 실패합니다

Admin이 아닌 작업으로 실행되는 PrintDLG가 샘플 프로그램으로 확인했습니다.

다른 팁

Quicken Community Forum에서 게시물을 찾았습니다. 인쇄 문제 Vista 64 Quicken 2008, 및 관련 FAQ : 인쇄 할 수 없거나 "프린터와 통신하는 오류"를받을 수 없다면 어떻게해야합니까? 그리고 에뮬레이션 프린터를 사용하는 것이 좋습니다.

앱에 인쇄를 추가 하면서이 문제를 해결했습니다. PrintDialog 클래스를 사용하고 있었고 32 비트 앱으로 컴파일되면 잘 작동하지만 64 비트 모드로 컴파일 될 때도 팝업되지 않습니다. 오류 메시지가없고 아무것도 없습니다. showdialog에 대한 호출은 즉시 돌아옵니다. (64 비트 비스타를 운영하고 있습니다.)

나는 printdlg를 사용하려고 시도했지만 같은 문제가 있습니다. 나는 온라인을보고 우리가 비슷한 문제를 겪고있는 많은 사람들을 발견했지만 64 비트 비스타가있는 모든 사람이 이것을 보는 것은 아닙니다. 어쨌든, 나는 마침내 내 자신의 버전의 PrintDialog (온라인으로 차용)을 작성하기로 결정했지만, 이것은 온라인 코드 중 일부에 버그가 있었기 때문에 약간 까다 롭습니다. 여기에 솔루션을 게시하겠습니다.

내 버전은 "인쇄 범위", "사본"및 "Print to File"과 같이 대화에서 몇 가지를 남겨 둡니다. 추가하기 쉽지만 내 앱은 필요하지 않았습니다. 또한 "Type :"필드가 표시되는 내용을 알 수 없었습니다.

대화 상자의 모습은 다음과 같습니다.

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;
    }
}
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top