簡體   English   中英

PrinterSettings.GetHdevmode()是否有錯誤?

[英]Does PrinterSettings.GetHdevmode() have a bug?

我希望能夠在不打開打印機屬性窗口的情況下更改打印機屬性。

到目前為止,使用DocumentProperties(從winspool.drv導入)功能失敗,因為雖然很容易抑制對話框的顯示,但似乎PrinterSettings.GetHdevmode()返回的值並不反映正在調用它的PrinterSettings。 ,但是來自先前打印機屬性的值將返回OK。 例如,這給了我上次調用屬性時的先前(錯誤)值,而不是它應從PrinterSettings對象獲得的值:

IntPtr hdevmode = PrinterSettings.GetHdevmode(PrinterSettings.DefaultPageSettings);
PrinterSettings.SetHdevmode(hdevmode);
PrinterSettings.DefaultPageSettings.SetHdevmode(hdevmode);

那么GetHdevmode是否有錯誤,或者這是應該做的嗎? 是否有C#可以解決此問題,或者是否有人對此有任何信息? 甚至很難找到有關該主題的信息。

預先感謝您的任何見解。

編輯:我不想讓這個問題過於個人化,但希望在這種情況下擁有所有信息也可以提供一個答案,這對於其他人也是有用的解決方案。

這是我為了解決此問題而編寫的C ++ DLL。 它當前不起作用-它會更改其他內存(例如副本),並且無法成功更改“基礎”紙張尺寸。 我以為我需要做的就是指定out buffer標志以進行更改?

extern "C" __declspec(dllexport) DEVMODE* __stdcall GetRealHDevMode(int width, int height, char *printerName, DEVMODE* inDevMode)
    {
//declare handles and variables
HANDLE printerHandle;
LPHANDLE printerHandlePointer(&printerHandle);

//get printer handle pointer
OpenPrinter((LPWSTR)printerName, printerHandlePointer, NULL);

//Get size needed for public and private devmode data and declare devmode structure
size_t devmodeSize = DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, NULL, NULL, 0);
DEVMODE* devmode = reinterpret_cast<DEVMODE*>(new char[devmodeSize + sizeof(DEVMODE) + sizeof(inDevMode->dmDriverExtra)]);

//lock memory
GlobalLock(devmode);

//fill the out buffer
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, NULL, DM_OUT_BUFFER);

//change the values as required
devmode->dmPaperWidth = width;
devmode->dmPaperLength = height;
devmode->dmPaperSize = DMPAPER_USER;

devmode->dmFields &= ~DM_PAPERSIZE;
devmode->dmFields &= ~DM_PAPERLENGTH;
devmode->dmFields &= ~DM_PAPERWIDTH;
devmode->dmFields |= (DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH);

//input flag on now to put the changes back in
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER);

//unlock memory
GlobalUnlock(devmode);

//return the devmode that was used to alter the settings
return devmode;
    }

我認為C ++代碼足以更改設置,因此我在C#中所做的就是:

public PrinterSettings ChangePrinterProperties(PrinterSettings inPrinterSettings)
    {
        IntPtr TemphDevMode = inPrinterSettings.GetHdevmode(inPrinterSettings.DefaultPageSettings);
        IntPtr hDevMode = GetRealHDevMode((int)(inPrinterSettings.DefaultPageSettings.PaperSize.Width * 2.54F),
            (int)(inPrinterSettings.DefaultPageSettings.PaperSize.Height * 2.54F),
            inPrinterSettings.PrinterName, TemphDevMode);
        GlobalFree(hDevMode);
        return inPrinterSettings;
    }

更新:使用dmPaperSize和dmFields稍微改變了順序。 改善結果; 還不在那里。

更新2:好的,我找到了一個Microsoft頁面,該頁面指出文檔錯誤。 MSDN表示要指定寬度和高度時將dmPaperSize設置為0,而Microsoft支持更正則表示將其設置為DMPAPER_USER。 http://support.microsoft.com/kb/108924

在DEVMODE中指定紙張尺寸的方式有兩個問題:

(1)如果您指定DM_PAPERWIDTH或DM_PAPERLENGTH或兩者都指定,則不得同時設置DM_PAPERSIZE位。 它取決於打印機驅動程序,但是許多驅動程序將忽略上述代碼中的DM_PAPERLENGTH / WIDTH。

(2)許多驅動程序根本不支持DM_PAPERLENGTH / WIDTH。 使用此類驅動程序,您根本無法像上面嘗試的那樣設置紙張尺寸。 您只能選擇預定義的dmPaperSizes之一。

您可以使用DeviceCapabilities(DC_FIELDS)確定驅動程序是否支持DM_PAPERLENGTH / WIDTH。

您可以使用DeviceCapabilities(DC_PAPERS)枚舉允許的dmPaperSizes。

暫無
暫無

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

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