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

両面印刷でうまく両面に印刷してくれない

環境/言語:[Windows 7/Vista MS2010 C# Winアプリ]
分類:[.NET]

お世話になります。

両面印刷使しようと思い下記のようにコードを書きましたが、「プレビューを生成しています」のダイアログが1ページ単位で出て裏表に印刷しません。
予定では、10枚印刷なら「プレビューを生成しています」で表示するページは、1でなく10になるはずですね。

結果でいうと印刷処理がまとめてでなく1ページ単位で呼ばれているのでしょうが、どこでそのようにコードを書けばいいでしょうか?

アドバイスください。よろしくお願いします。

コード
for (int i = 0; i < _prints.Count; ++i)
{
print = _prints[i];

printDoc.BeginPrint += new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
printDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);

if (ppvw.ShowDialog() != DialogResult.OK)
{
printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);
}

// Printing the Documnet
// printDoc.Print();
// printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
// printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);
}

private static void PrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
:
: // 実際の印刷処理
:
// e.HasMorePages = true; 有効にすると無限ループになってしまう
}

上記のforループの_prints[i];は、1ページごとの印刷する文が入っています。
_prints.Countが実際印刷したいページ数、両面なのでこの半分の数ですが。

両面の設定は、
// DevMode にセットする
private static void PrinterSetDevmode(PrintDocument pd
{
IntPtr hMem = pd.PrinterSettings.GetHdevmode(pd.DefaultPageSettings); // ハンドル取得
IntPtr devmodePtr = GlobalLock(hMem); // ロック・ハンドルからポインタを取得
DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(devmodePtr, typeof(DEVMODE)); // ポインタから構造体にコピー

//dm.dmCopies = 10; // 印刷部数を10部に設定
//dm.dmCollate = 1; // 部単位で印刷
dm.dmDuplex = 2;    <- 多分これであっていると思います
Marshal.WriteByte(devmodePtr, dm.dmSize + 720, 0); // ドライバ固定の720Byte目を0
Marshal.StructureToPtr(dm, devmodePtr, true); // 構造体からポインタにコピー

GlobalUnlock(hMem); // ロックを解放
pd.PrinterSettings.SetHdevmode(hMem); // PriterSetteingsにコピー
GlobalFree(hMem); // ハンドルを解放
}
2013/11/20(Wed) 15:16:18 編集(投稿者)

■No31925に返信(hiroさんの記事)

> // e.HasMorePages = true; 有効にすると無限ループになってしまう
HasMorePageの判定処理がないからだと思います。

クラス内の変数indexとかを設け

BeginPrint で
  indexを0にして

PrintPageで
_prints[index]を処理して
index++して
  indexが配列の範囲内ならHasMorePage=TrueそうでなければFalseとする

こんな感じにして提示コード上の方のForループを1回のPrintだけにする。


VB.NETですが
VisualBasic中学校に同じような投稿がありましたのでリンクしておきます。
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=11422
どうも、お世話になります。

printDoc.BeginPrint += new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
printDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);

// Printing the Documnet
printDoc.Print();
printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);


private static void PrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
:
try
{
for (int i = 0; i < _prints.Count; ++i)
{
print = _prints[i];

印刷処理

       if (_prints.Count > i)
e.HasMorePages = true;
}
e.HasMorePages = false;
  }

こんな感じでやってみましたが、印刷は、1ページのみ(_prints.Countは、10件で試してます)で内容分の10行を1ページ内に表示して終了します。

うまくいかないようですが、私に何か、勘違いがありますか?

どうぞ、教えてください。
■No31928に返信(hiroさんの記事)
>
> うまくいかないようですが、私に何か、勘違いがありますか?
>
> どうぞ、教えてください。
再度書きます。
for文を書かなくていいんです。
配列のインデックス用の変数はPrintPage内で定義するのではなく
クラス内の変数として定義してください。BeginPrintでインデックス用変数を
0に初期化します。インデックス用変数はPrintPageで1だけ増やしてください。
インデックス用変数が配列のインデックス値を超えたらHasMorePagesをFalse
そうでないときはTrueにします。
ループ処理はHasMorePagesがTrueなら勝手にやってくれるのでループ処理を
どこかに書こうとか思わなくていいです。
前回答と同じ内容ですが分かりますでしょうか?

PrintPageイベントの理解が足りないように感じたため
補足させていただきます。
※理解していたらごめんなさい。

PrintPageイベントは、1ページ分の印刷を
行うイベントになります。
よって10ページ分の印刷をしたいならば、
PrintPageイベントは10回発生することになります。

ではどうしてOSは10回のイベントを発生することができるのでしょうか?
これの答えがHasMorePagesです。
HasMorePagesをtrueにして、PrintPageイベントを終了すれば、
OSが次のページの印刷のためにPrintPageイベントを発生させてくれます。
HasMorePagesをfalseにすれば次のページは無いということになりますので
イベントは発生しません。
shu様、kiku様、ありがとうございます。


おかげさまで、両面印刷してくれました。

forループで印刷するという先入観で勘違いしていたようです。

HasMorePagesをtrueでループするんでしたね。

お世話になりました。
解決済み!

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