8

プリンターのプロパティ ウィンドウを表示せずに、プリンターのプロパティを変更できるようにしたいのですが...

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 を次に示します。現在は機能していません - コピーなどの他のメモリを変更し、「基になる」用紙サイズの変更に成功しません。変更を行うには、アウト バッファ フラグを指定するだけでよいと思いましたか?

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: ドキュメントが間違っているというマイクロソフトのページを見つけました。MSDN では、幅と高さを指定する場合は dmPaperSize を 0 に設定するように指示されていますが、Microsoft サポートの修正では DMPAPER_USER に設定するように指示されています。http://support.microsoft.com/kb/108924

4

1 に答える 1

2

DEVMODE で用紙サイズを指定する方法には 2 つの問題があります。

(1) DM_PAPERWIDTH または DM_PAPERLENGTH またはその両方を指定する場合、DM_PAPERSIZE ビットも設定してはなりません。プリンター ドライバーによって異なりますが、多くのドライバーは上記のコードの DM_PAPERLENGTH/WIDTH を無視します。

(2) 多くのドライバは DM_PAPERLENGTH/WIDTH をまったくサポートしていません。このようなドライバーでは、上記のように用紙サイズを設定することはできません。定義済みの dmPaperSizes の 1 つだけを選択できます。

DeviceCapabilities(DC_FIELDS) を使用して、ドライバーが DM_PAPERLENGTH/WIDTH をサポートしているかどうかを判断できます。

DeviceCapabilities(DC_PAPERS) を使用して、許容される dmPaperSizes を列挙できます。

于 2010-04-02T11:18:27.557 に答える