--- lang: ja-jp breaks: true --- # Crystal Reports `PrintToPrinter` の内部処理 ※特定のプリンタで給紙トレイの設定が正しく反映されない事象の調査 2023-03-14 ## 対象のバージョン ![](https://i.imgur.com/QcsWPvy.png) ## `iLSpy`を使用して内部の処理を解析 ### `PaperSize` の設定処理 ※ CrystalDecisions.CrystalReports.Engine.PrintOptions.CopyTo(PrinterSettings printer, PageSettings page) ```csharp= private System.Drawing.Printing.PaperSize FindPaperSize( PrinterSettings printer, CrystalDecisions.Shared.PaperSize size ) { try { if (size == CrystalDecisions.Shared.PaperSize.DefaultPaperSize) { return printer.DefaultPageSettings.PaperSize; } PaperKind paperKind = PrintingConverter.PaperSizeToPaperKind(size); foreach (System.Drawing.Printing.PaperSize paperSize in printer.PaperSizes) { if (paperSize.Kind == paperKind) { return paperSize; } } } catch (NotSupportedException) { } return null; } ``` :::info 用紙サイズを検索する処理にて、`Kind` が参照されており、`RawKind` が使用されていない為、ユーザ定義用紙を使用した特殊な用紙では `null` が返却される。 ::: ```csharp= System.Drawing.Printing.PaperSize paperSize = FindPaperSize(printer, PaperSize); if (paperSize == null) { IntPtr hdevmode = printer.GetHdevmode(page); if (hdevmode != IntPtr.Zero) { IntPtr intPtr = GlobalLock(hdevmode); if (intPtr != IntPtr.Zero) { DEVMODE structure = (DEVMODE)Marshal.PtrToStructure(intPtr, typeof(DEVMODE)); structure.dmPaperSize = (short)PaperSize; Marshal.StructureToPtr(structure, intPtr, fDeleteOld: true); GlobalUnlock(hdevmode); printer.SetHdevmode(hdevmode); } GlobalFree(hdevmode); } } else { page.PaperSize = paperSize; } ``` :::info `paperSize`に`null`が返却されてきた場合、その後は `DEVMODE`構造体の`dmPaperSize`メンバに `RawKind`相当の値を設定することが可能な為、おそらく正常に動作する。 ::: ### `PaperSource` の設定処理 ※ CrystalDecisions.CrystalReports.Engine.PrintOptions.CopyTo(PrinterSettings printer, PageSettings page) ```csharp= private System.Drawing.Printing.PaperSource FindPaperSource( PrinterSettings printer, CrystalDecisions.Shared.PaperSource source ) { try { PaperSourceKind paperSourceKind = PrintingConverter.PaperSourceToPaperSourceKind(source); foreach (System.Drawing.Printing.PaperSource paperSource in printer.PaperSources) { if (paperSource.Kind == paperSourceKind) { return paperSource; } } } catch (NotSupportedException) { } return null; } ``` :::info 上記の処理で、給紙トレイの設定を `Kind` を使用して探し出している為、オプショントレイを指定した場合にプリンタによっては正しく取得出来ずに、`null` が返却される。 以下のように、全ての給紙トレイで同じ値が取得されるプリンタの場合に想定する給紙トレイを探し出すことが出来ずに不具合が発生する。 ```= - PaperSources ----------------------------- 自動選択 RawKind=[7] Kind=[AutomaticFeed][7] 手差しトレイ RawKind=[261] Kind=[Custom][257] 用紙カセット1 RawKind=[258] Kind=[Custom][257] 用紙カセット2 RawKind=[259] Kind=[Custom][257] 用紙カセット3 RawKind=[260] Kind=[Custom][257] 用紙カセット4 RawKind=[268] Kind=[Custom][257] ``` 上記の処理でも正常に動作するプリンタは以下のような値を返す。 ※`Kind`の値が、給紙トレイ毎に異なる為正常に動作する。 ```= - PaperSources ----------------------------- プリンターの設定に従う RawKind=[15] Kind=[FormSource][15] 自動 RawKind=[7] Kind=[AutomaticFeed][7] トレイ1 RawKind=[1] Kind=[Upper][1] トレイ2 RawKind=[3] Kind=[Middle][3] トレイ3 RawKind=[2] Kind=[Lower][2] トレイ4 RawKind=[257] Kind=[Custom][257] トレイ5(手差し) RawKind=[4] Kind=[Manual][4] ``` ::: ```csharp= if (CustomPaperSource == null) { page.PaperSource = FindPaperSource(printer, PaperSource); } else { page.PaperSource = CustomPaperSource; } ``` :::info オプショントレイを指定した場合に、プリンタによっては、`FindPaperSource` が `null` を返す為、給紙方法を正しく設定することが出来ない。 ::: :::danger 給紙方法が正しく反映されない場合は、`CustomPaperSource` プロパティを使用して明示的に `RawKind` の値を指定する必要がある。 ::: ###### tags: `Crystal Reports` `PrintToPrinter` `iLSpy`