簡體   English   中英

如何顯示打印機屬性/首選項對話框並保存更改?

[英]How to show printer properties/preferences dialog and save changes?

編輯:我的錯! 我希望在實際上只更改PrinterSettings的本地實例時,將更改寫回默認的打印機設置。 - 以下代碼似乎按預期工作

我試圖顯示給定打印機的自定義打印機屬性。 我需要這個作為我想寫的自定義PrintDialog的一部分。

我在網上找到的大多數示例都設法顯示對話框,但用戶可能做出的任何更改都會丟失,這使得它無用。

示例: http//www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx

(關於上面的頁面:我試圖改變BartJoy建議的代碼(在頁面上)但是沒有修復它)

我也嘗試過pinvoke.net頁面上的示例和建議,但它仍然不起作用:

http://www.pinvoke.net/default.aspx/winspool.documentproperties

從上面的網站我假設問題可能只在64位Windows上和/或如果打印機名稱超過32個字符。

我不知道接下來應該嘗試什么...我感謝任何建議和意見!

編輯:這是我嘗試過的:

[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesW", SetLastError = true,
 ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter,
        [MarshalAs(UnmanagedType.LPWStr)] string pDeviceName,
        IntPtr pDevModeOutput, IntPtr pDevModeInput, 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")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalFree(IntPtr hMem);

private const int DM_PROMPT = 4;
private const int DM_OUT_BUFFER = 2;
private const int DM_IN_BUFFER = 8;

private void OpenPrinterPropertiesDialog()
{
    var printerSettings = new System.Drawing.Printing.PrinterSettings();
    var printerName = printerSettings.PrinterName;

    IntPtr handle;
    OpenPrinter(printerName, out handle, IntPtr.Zero);

    IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
    IntPtr pDevMode = GlobalLock(hDevMode);
    int sizeNeeded = DocumentProperties(this.Handle, handle, printerName, pDevMode, pDevMode, 0);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
    DocumentProperties(this.Handle, handle, printerName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER);

    ClosePrinter(handle);
    GlobalUnlock(hDevMode);

    printerSettings.SetHdevmode(devModeData);
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData);

    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
}

我試圖使用OpenPrinter和ClosePrinter方法並在第二次調用中將devModeData作為輸出參數傳遞,因為我發現奇怪的是pinvoke.net的原始代碼沒有這樣做。 (但我承認,我不知道我在做什么 - 這只是反復試驗)。

以下是pinvoke網站的原始代碼:

private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings)
{
    IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
    IntPtr pDevMode = GlobalLock(hDevMode);
    int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, 0);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
    DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 14);
    GlobalUnlock(hDevMode);
    printerSettings.SetHdevmode(devModeData);
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
}

如果你定位x86編譯並從x64機器運行,那么來自Jeff Roe的代碼將不起作用:在分配devModeDataDocumentPropreties將始終失敗並返回sizeNeeded為-1,其LastError代碼為13。

要解決此問題,請確保將目標設為AnyCPU,或者只是將對DocumentPropreties的調用更改為以下內容:

int sizeNeeded = DocumentProperties(pHandle, 
                                    IntPtr.Zero, 
                                    printerSettings.PrinterName, 
                                    IntPtr.Zero, // This solves it
                                    pDevMode, 
                                    fMode);

使用IntPtr.Zero而不是指向DevMode結構的正確指針看起來是錯誤的,但是對DocumentProperties的第一次調用不會嘗試修改該位置的內存。 調用返回的唯一數據是存儲表示打印驅動程序內部參數的設備模式數據所需的內存大小。

參考:

即使答案最終解決了問題,我認為以下內容為原始問題提供了更好的答案,

(1)因為如果用戶取消,它顯然不會修改傳入的PrinterSettings。

(2)因為它返回一個DialogResult,調用者可能會對此感興趣。

[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalFree(IntPtr hMem);
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesW", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPWStr)] string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);

private const int DM_PROMPT = 4;
private const int DM_OUT_BUFFER = 2;
private const int DM_IN_BUFFER = 8;

private DialogResult EditPrinterSettings(PrinterSettings printerSettings)
{
    DialogResult myReturnValue = DialogResult.Cancel;
    IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
    IntPtr pDevMode = GlobalLock(hDevMode);
    int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, 0);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
    long userChoice = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER);
    long IDOK = (long)DialogResult.OK;
    if (userChoice == IDOK)
    {
        myReturnValue = DialogResult.OK;
        printerSettings.SetHdevmode(devModeData);
        printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
    }
    GlobalUnlock(hDevMode);
    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
    return myReturnValue;
}
  • 當您的應用程序啟動時:
    • 你有沒有在分配它之前查詢打印機驅動程序的DEVMODE結構的正確大小?
    • 你有沒有要求設備驅動程序在分配后用默認設置初始化DEVMODE緩沖區?
  • 當您的應用程序彈出打印機對話框時:
    • 你有沒有將fMode參數中的DM_IN_BUFFERDM_OUT_BUFFER標志(除了DM_IN_PROMPTfModeDocumentProperties
    • 你有沒有將pDevModeInputpDevModeOutput指向你在應用程序啟動時初始化的DEVMODE緩沖區?
    • 是在調用DocumentProperties(... DM_IN_PROMPT ...)之前正確設置的DEVMODE緩沖區中的dmFields
    • 你是否在對DocumentProperties(... DM_IN_PROMPT ...)調用之間保留了DEVMODE緩沖區的內容?

看到:

此外,如果您想使用WPF類(PrintQueue,PrintTicket)執行此操作,此頁面將指向正確的方向:

http://social.msdn.microsoft.com/Forums/en/wpf/thread/0dc695c1-578d-4da5-8f68-b2a257846c02

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM