4

DEVMODE標準およびデバイス固有の設定を渡すために、現在の印刷タスクのプリンターを変更する必要があります。私は次のことを行います:

PrintDocument d = new PrintDocument();
d.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"; // example printer name           
byte[] devmode_data; // contains a valid value that is obtained from registry
IntPtr devmode = IntPtr.Zero;
GCHandle handle = GCHandle.Alloc(devmode_data, GCHandleType.Pinned);
try
{
    devmode = handle.AddrOfPinnedObject();
    if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);
}
finally
{
    if (handle.IsAllocated) handle.Free();
}

意味のあるエラー情報なしで実行しようとPrinterSettings.SetHdevmodeすると失敗します。null でない場合、メソッド内で例外がスローされます。 だから私の質問は:何が間違っているのですか?キャストするのは間違っていますか?たぶん、配列以外のものを期待していますか?NullReferenceExceptiond.PrinterSettingsPrinterSettings.SetHdevmode
byte[]IntPtrSetHdevmodebyte[]

byte[] devmode_dataレジストリから配列を取得します。これは有効な値であり、現在のプリンター設定で使用されている値と同じです。

4

2 に答える 2

1

有効なデータがないため、次のようにコードを変更しましたdevmode_data

devmode = d.PrinterSettings.GetHdevmode();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);

そして今、ここでも例外はありません。

devmode_data有効かどうかにかかわらず、データを提供するか、自分のデータを確認してください。

于 2011-11-27T00:28:40.010 に答える
1

SetHdevmodeを期待しHGLOBALます。HGLOBAL経由で .Net からを取得できますMarshal.AllocHGlobal。次に、を使用Marshal.Copy(byte[], int, IntPtr, int)して、マネージド バイト配列からHGLOBAL. 下記参照:

var pDevMode = Marshal.AllocHGlobal(devmode_data.Length);
Marshal.Copy(devmode_data, 0, pDevMode, devmode_data.Length);

d.PrinterSettings.SetHdevmode(pDevMode);
Marshal.FreeHGlobal(pDevMode);

バイト配列は部分的に構造体として扱うことができますが、それにはp/Invoke の定義が必要になります。ただし、PrinterSettingsクラスは構造体を受け入れないため、この場合は必要ありません。さらに、このDEVMODE構造体は、プリンタ ドライバが不透明なデータを追加できるように可変長であるため、データを失うことなく変換することはできません。

「PrinterSettings」を保存および復元するにはどうすればよいですか? を参照してください。多くのための。

于 2015-01-18T06:08:20.700 に答える