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

プリンタ選択ダイアログの部数印刷について

分類:[.NET]

管理人さん、みなさん、こんにちは。
VB.NETについての質問です。

プリンタ選択ダイアログで部数を指定して印刷をしたいのですが、

.NET Tipsの
「プリンタ選択ダイアログを表示して印刷する」

を参考に、
以下のようなソースを書いてみたのですが、
部数を何部に指定しても1部しかプリントアウトされません。

部数印刷を実現させる方法をご存じの方いらしたら、教えて下さい。

--------------------------------------------------------

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'印刷する文字列と位置を設定する
printingText = TextBox1.Text
printingPosition = 0
'印刷に使うフォントを指定する
printFont = New Font("MS Pゴシック", 10)
'PrintDocumentオブジェクトの作成
Dim pd As New System.Drawing.Printing.PrintDocument()
'PrintPageイベントハンドラの追加
AddHandler pd.PrintPage, AddressOf pd_PrintPage
'PrintDialogクラスの作成
Dim pdlg As New PrintDialog()
'PrintDocumentを指定
pdlg.Document = pd

Dim busu As Integer ' 部数

'印刷の選択ダイアログを表示する
If pdlg.ShowDialog() = DialogResult.OK Then
'OKがクリックされた時は印刷する
For busu = 1 To pdlg.PrinterSettings.Copies ' 指定された部数分だけ印刷
pd.Print()
Next
End If
End Sub
■No1405に返信(のぶさんの記事)
> プリンタ選択ダイアログで部数を指定して印刷をしたいのですが、
>
> .NET Tipsの
> 「プリンタ選択ダイアログを表示して印刷する」
>
> を参考に、
> 以下のようなソースを書いてみたのですが、
> 部数を何部に指定しても1部しかプリントアウトされません。

多分 No1393 の投稿と同じ問題なのではないかと思います。 No1393 の回答(No1398)を試してみてください。

また、
' 指定された部数分だけ印刷
のループは必要ありません。下手をするとすごい数印刷されてしまいます。
■No1414に返信(管理人さんの記事)

管理人さん、お返事ありがとうございます。

> 多分 No1393 の投稿と同じ問題なのではないかと思います。 No1393 の回答(No1398)を試してみてください。

PrintDocument1_PrintPage
の中に
printingPosition = 0
を追加するというご回答ですよね?
これは対応しています。

> また、
> ' 指定された部数分だけ印刷
> のループは必要ありません。下手をするとすごい数印刷されてしまいます。

部数印刷に関する記述をわざわざしなくても、印刷ダイアログの部数欄に
部数を指定すれば、普通は部数印刷ができるという事でしょうか?

ちなみに、プリンタ選択ダイアログのチェックボックス「部単位で印刷」をチェックし、
印刷部数を指定して印刷すると、部数分印刷されるのですが、
チェックを外して印刷すると、部数をいくつにしても、1枚しか印刷されません。
「部単位で印刷」のチェックの有無に関わらず、部数印刷ができるようにするには、
どうしたらいいのでしょうか?
■No1420に返信(のぶさんの記事)
> 部数印刷に関する記述をわざわざしなくても、印刷ダイアログの部数欄に
> 部数を指定すれば、普通は部数印刷ができるという事でしょうか?

その通りです。

> ちなみに、プリンタ選択ダイアログのチェックボックス「部単位で印刷」をチェックし、
> 印刷部数を指定して印刷すると、部数分印刷されるのですが、
> チェックを外して印刷すると、部数をいくつにしても、1枚しか印刷されません。
> 「部単位で印刷」のチェックの有無に関わらず、部数印刷ができるようにするには、
> どうしたらいいのでしょうか?

試してみたところ、私のところでは「部単位で印刷」のチェックの有無に関わらずうまく行きました。何か別の問題があるのでしょうか...。
■No1427に返信(管理人さんの記事)

管理人さん、お返事ありがとうございます。

> 試してみたところ、私のところでは「部単位で印刷」のチェックの有無に関わらずうまく行きました。何か別の問題があるのでしょうか...。

そうですかぁ。以下のような単純なプログラムにしても、ダメでした。なぜでしょう…。
ちなみに、印刷内容が1ページに収まる物の場合も複数ページ物の場合も同じです。

「部単位で印刷」のチェックを固定(チェックオンのままユーザーは変更できない)にする事は可能でしょうか?
デフォルトでチェックオンにする事はできたのですが(↓)、部数を入力するとチェックボックスが有効になりチェックの有無の変更が可能になってしまうので。
 PrintDialog1.PrinterSettings.Collate = True

---------------------------------------------------------
Private printingText As String
Private printingPosition As Integer
Private printFont As Font

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'印刷する文字列と位置を設定する
printingText = TextBox1.Text
printingPosition = 0
'印刷に使うフォントを指定する
printFont = New Font("MS Pゴシック", 10)
'PrintDocumentオブジェクトの作成
Dim pd As New System.Drawing.Printing.PrintDocument()
'PrintPageイベントハンドラの追加
AddHandler pd.PrintPage, AddressOf pd_PrintPage
'PrintDialogクラスの作成
Dim pdlg As New PrintDialog()
'PrintDocumentを指定
pdlg.Document = pd

'* 次の行を追加してみました(「部単位で印刷」チェックをオンにする)
PrintDialog1.PrinterSettings.Collate = True

'印刷の選択ダイアログを表示する
If pdlg.ShowDialog() = DialogResult.OK Then
'OKがクリックされた時は印刷する
pd.Print()
End If
End Sub

Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
If printingPosition = 0 Then
'改行記号を'\n'に統一する
printingText = printingText.Replace(vbCrLf, vbLf)
printingText = printingText.Replace(vbCr, vbLf)
End If

'印刷する初期位置を決定
Dim x As Integer = e.MarginBounds.Left
Dim y As Integer = e.MarginBounds.Top

e.Graphics.DrawString("タイトル", printFont, Brushes.Black, x, y)

'1ページに収まらなくなるまでループ
While e.MarginBounds.Height > y + printFont.Height * 3
Dim line As String = ""

While True
'印刷する文字がなくなるか、
'改行の時はループから抜けて印刷する
If printingPosition >= printingText.Length OrElse _
printingText.Chars(printingPosition) = vbLf Then
printingPosition += 1
Exit While
End If
'一文字追加し、印刷幅を超えるか調べる
line += printingText.Chars(printingPosition)
If e.Graphics.MeasureString(line, printFont).Width _
> e.MarginBounds.Width Then
'印刷幅を超えたため、折り返す
line = line.Substring(0, line.Length - 1)
Exit While
End If
'印刷文字位置を次へ
printingPosition += 1
End While
'一行書き出す
e.Graphics.DrawString(line, printFont, Brushes.Black, x, y + printFont.Height)
'次の行の印刷位置を計算
y += printFont.GetHeight(e.Graphics)
End While

e.Graphics.DrawString("ページ", printFont, Brushes.Black, e.MarginBounds.Width / 2, e.MarginBounds.Height)

'次のページがあるか調べる
If printingPosition >= printingText.Length Then
printingPosition = 0
e.HasMorePages = False
Else
e.HasMorePages = True
End If
End Sub
■No1437に返信(のぶさんの記事)
> そうですかぁ。以下のような単純なプログラムにしても、ダメでした。なぜでしょう…。

試してみましたが、私のところでは「部単位で印刷」が無効になっている時でもうまく行きました。

> 「部単位で印刷」のチェックを固定(チェックオンのままユーザーは変更できない)にする事は可能でしょうか?

申し訳ありませんが、ちょっと分からないです。

> デフォルトでチェックオンにする事はできたのですが(↓)、部数を入力するとチェックボックスが有効になりチェックの有無の変更が可能になってしまうので。
>  PrintDialog1.PrinterSettings.Collate = True

最悪の場合、印刷の直前でCollateをTrueにすることになるでしょうか...。
■No1447に返信(管理人さんの記事)

> 試してみましたが、私のところでは「部単位で印刷」が無効になっている時でもうまく行きました。

そうですか。私は他のマシンでも試してみましたが、うまくいきませんでした…。
管理人さんと何が違うのでしょう?バージョンでしょうか?
私のバージョンは、
Microsoft Development Environment 2002 Version 7.0.9486
Microsoft .NET Framework 1.0 Version 1.0.3705
なのですが。

> 最悪の場合、印刷の直前でCollateをTrueにすることになるでしょうか...。

印刷の直前というのはどの部分になるでしょうか?
以下のように、
pd.Print()
の前に入れてみましたがダメでした。

--------------------------------------------------------
If pdlg.ShowDialog() = DialogResult.OK Then
pdlg.PrinterSettings.Collate = True
pd.Print()
End If
■No1464に返信(のぶさんの記事)
> Microsoft Development Environment 2002 Version 7.0.9486
> Microsoft .NET Framework 1.0 Version 1.0.3705

私のところの.NET Frameworkのバージョンは、1.1です。1.0の環境がないため、1.0ではちょっと試すことができません。(試せるようでしたら、試してみますが...。)

>>最悪の場合、印刷の直前でCollateをTrueにすることになるでしょうか...。
>
> 印刷の直前というのはどの部分になるでしょうか?
> 以下のように、
> pd.Print()
> の前に入れてみましたがダメでした。

これはつまり、ダイアログを表示する前にCollateの値を入れてもその後設定を変えられてしまう可能性があるため、強制的にCollateをTrueにするという意味です。根本的な問題の解決にはなりませんから、無視してください。
■No1477に返信(管理人さんの記事)

> 私のところの.NET Frameworkのバージョンは、1.1です。1.0の環境がないため、1.0ではちょっと試すことができません。(試せるようでしたら、試してみますが...。)

ならば、バージョンを1.1にしてみようと思い、調べてみたら以下の事が判明しました。

Visual Studio.NETを起動して、バージョン情報を確かめると以下のとおり。
Microsoft .NET Framework 1.0 Version 1.0.3705

コントロールパネルの「アプリケーションの追加と削除」を見ると、以下の記述が。
Microsoft .NET Framework (JPN) v1.0.3705
Microsoft .NET Framework 1.1
Microsoft .NET Framework 1.1 Japanese Language

これは1.0と1.1両方が入っているという事でしょうか???

> これはつまり、ダイアログを表示する前にCollateの値を入れてもその後設定を変えられてしまう可能性があるため、強制的にCollateをTrueにするという意味です。根本的な問題の解決にはなりませんから、無視してください。

分かりました。

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