DOBON.NET DOBON.NETプログラミング掲示板過去ログ

印刷ダイアログのカスタマイズ

環境/言語:[C#]
分類:[.NET]

フォームの中に印刷ダイアログの機能を盛り込み、カスタマイズされた印刷ダイアログを
表示しようと思います。
コモンダイアログのプリンタの「プロパティ」ボタンをクリックするイベントを、
カスタマイズした印刷ダイアログの中に記述したいのですが、
どのようにしたら良いかわかりません。
どなたかご存知の方、教えてください。

以下、作成中のソースです

↓-------------------------

//印刷ダイアログボックス
private void printdlg_Load(object sender, System.EventArgs e)
{
  DialogResult res;
  printDialog1.PrinterSettings
    = new System.Drawing.Printing.PrinterSettings();

  //プリンタ名を表示する
  comboBox1.Text = printDialog1.PrinterSettings.PrinterName;
}
//プリンタのプロパティボタンをクリックしたときのイベント
private void button1_Click(object sender, System.EventArgs e)
{
  //ここにプリンタのプロパティ画面を表示する処理を入れたい

}
ポンは、こんな感じでWin32APIのDocumentProperties を使って表示しています。
_PD のところは、printDialog1 に置き換えればいいと思います。
申し訳ありませんが、ポンは C#はわからないので、いまあるVBのコードのままのせておきます、
まだらねこさんのコードに合うように改造してください。


'Win32API
Private Declare Auto Function OpenPrinter Lib "winspool.drv" ( _
<MarshalAs(UnmanagedType.LPTStr)> ByVal pPrinterName As String, _
ByRef phPrinter As IntPtr, _
ByVal pDefault As IntPtr) As Int32

Private Declare Auto Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As IntPtr) As Int32

Private Declare Auto Function DocumentProperties Lib "winspool.drv" ( _
ByVal hwnd As IntPtr, _
ByVal hPrinter As IntPtr, _
<MarshalAs(UnmanagedType.LPTStr)> ByVal pDeviceNameg As String, _
ByVal pDevModeOutput As IntPtr, _
ByVal pDevModeInput As IntPtr, _
ByVal fMode As Integer) As Int32

Private Declare Auto Function GlobalLock Lib "kernel32" (ByVal hmem As IntPtr) As IntPtr
Private Declare Auto Function GlobalFree Lib "kernel32" (ByVal hmem As IntPtr) As Int32
Private Declare Auto Function GlobalUnlock Lib "kernel32" (ByVal hMem As IntPtr) As Int32

'DocumentProperties Use
Private Const DM_OUT_BUFFER As Short = 2
Private Const DM_PROMPT As Short = 4
Private Const DM_IN_PROMPT As Short = DM_PROMPT
Private Const DM_IN_BUFFER As Short = 8

Private _PD As New Printing.PrintDocument

'プリンタのプロパティダイアログ表示
Public Function ShowPrinterProperties(ByVal hwnd As IntPtr) As Integer
Dim ret As Integer
Dim hPrinter As IntPtr
Dim PtrDMOut As IntPtr
Dim PtrDMIn As IntPtr
Dim _PrinterName As String = _PD.PrinterSettings.PrinterName

PtrDMIn = _PD.PrinterSettings.GetHdevmode(_PD.PrinterSettings.DefaultPageSettings)
PtrDMOut = _PD.PrinterSettings.GetHdevmode(_PD.PrinterSettings.DefaultPageSettings)

Dim globalDevIn As IntPtr = GlobalLock(PtrDMIn)
Dim globalDevOut As IntPtr = GlobalLock(PtrDMOut)

Try
'プリンタのハンドルを取得
ret = OpenPrinter(_PrinterName, hPrinter, IntPtr.Zero)
If ret = 0 Or hPrinter.Equals(IntPtr.Zero) Then
Return 0
End If

'DialogBox 表示
ret = DocumentProperties(hwnd, hPrinter, _PrinterName, globalDevOut, globalDevIn, DM_IN_PROMPT Or DM_IN_BUFFER Or DM_OUT_BUFFER)

If PtrDMOut.Equals(IntPtr.Zero) Then
Return 0
End If
'DialogBoxでOKがクリックされた場合に設定内容を反映させる。
If ret = 1 Then
_PD.PrinterSettings.SetHdevmode(globalDevOut)
End If

Return ret

Catch ex As Exception
'エラー処理
Finally
GlobalUnlock(PtrDMIn)
GlobalFree(PtrDMIn)
GlobalUnlock(PtrDMOut)
GlobalFree(PtrDMOut)

If Not hPrinter.Equals(IntPtr.Zero) Then
ClosePrinter(hPrinter)
End If
End Try

End Function
ポンさん、早速のご解答ありがとうございます。
ポンの教えてくださったVBのソースをC#に書き換えたのですが、
DocumentPropertiesがダイアログを表示してくれません。
デバックするとプリンタ名は入っています。
プリンタのハンドルが正しく取れていないのか、
単に、DocumentPropertiesの第6パラメータ(モード)が間違っているのか。。。

以下書き換えたソースです。
どなたかお分かりになる方は教えてください〜。

↓−−−−−−−−
private void button1_Click(object sender, System.EventArgs e)
{
int ret;
IntPtr hwnd = this.Handle;
IntPtr hPrt = System.IntPtr.Zero;
IntPtr PtrDMIn =
printDialog1.PrinterSettings.GetHdevmode(printDialog1.PrinterSettings.DefaultPageSettings);
IntPtr PtrDMOut =
printDialog1.PrinterSettings.GetHdevmode(printDialog1.PrinterSettings.DefaultPageSettings);

string prName = printDialog1.PrinterSettings.PrinterName;
IntPtr glDevIn = GlobalLock(PtrDMIn);
IntPtr glDevOut = GlobalLock(PtrDMOut);

try
{
//プリンタのハンドルを取得
if(OpenPrinter(prName, out hPrt, IntPtr.Zero) == false)
{
return;
}
else if(hPrt.ToInt32() == 0)
{
return;
}
//ダイアログボックスの表示
ret = DocumentProperties(hwnd, hPrt, prName, glDevOut, glDevIn, 0);
if( PtrDMOut.ToInt32() == 0 )
{
return;
}
//DialogBoxでOKがクリックされた場合に設定内容を反映させる。
if(ret != 0)
{
printDialog1.PrinterSettings.SetHdevmode(glDevOut);
return;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
finally
{
GlobalUnlock(PtrDMIn);
GlobalFree(PtrDMIn);
GlobalUnlock(PtrDMOut);
GlobalFree(PtrDMOut);
ClosePrinter(hPrt);
}
}
> //ダイアログボックスの表示
> ret = DocumentProperties(hwnd, hPrt, prName, glDevOut, glDevIn, 0);

最後の引数を 0 ではなく、DM_IN_PROMPT Or DM_IN_BUFFER Or DM_OUT_BUFFER
にしてみてください。

# Imports System.Runtime.InteropServices が抜けていました。
いま試してみたところ、PrintDocument を printDialog1 としても表示できました。
また、メモリのロックと解放は、APIを使わなくても、.net の Marshalクラスの
AllocHGlobal,FreeHGlobalでできるので、次のようにしたほうがいいかもしれません。

'ロック
Dim globalDevIn As IntPtr = Marshal.AllocHGlobal(PtrDMIn)
Dim globalDevOut As IntPtr = Marshal.AllocHGlobal(PtrDMOut)
'解放
Marshal.FreeHGlobal(PtrDMIn)
Marshal.FreeHGlobal(PtrDMOut)
ポンさん、アドバイスありがとうございます。
DM_IN_PROMPT と DM_IN_BUFFER と DM_OUT_BUFFER
の定義を忘れていたので、追加し、パラメータにしたら
うまくできました。
ほんとに助かりました。
ありがとうございました。

DOBON.NET | プログラミング道 | プログラミング掲示板