OnPrepareDC() の実行回数 – プログラミング – Home

通知
すべてクリア

OnPrepareDC() の実行回数

固定ページ 1 / 2

テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

VS2010, MFC, SDI で印刷アプリを作っています。

複数ページの印刷で、何ページから何ページまで印刷したかを記録する必要があり、印刷
したページ番号を、配列 m_nPrintedPage[] に格納してみました。

CMyProjView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pDC->IsPrinting())
{
m_nPrintedPage[m_nPPAray] = pInfo->m_nCurPage;
m_nPPAray++; // 印刷開始前に m_nPPAray = 0; としています。
...(印刷のためのコード)...
}
}

結果を OnEndPrinting() 関数内で調べたところ、同じページ番号が2回ずつ格納されて
いました。
例:(3~5ページを印刷した場合) m_nPrintedPage[] = {3, 3, 4, 4, 5, 5, 0, 0...}

この動作は正しいでしょうか?
OnPrepareDC() はページ毎に2回ずつ実行されると考えていいでしょうか?
(印刷は正常に行われています。)

解説を見てもそのようなことは書かれていません。
例:マルチページドキュメント
https://msdn.microsoft.com/ja-jp/library/vstudio/w7wzay73(v=vs.110).aspx

ご存じの方がいらっしゃいましたらご教授ください。
よろしくお願いいたします。


引用解決済
トピックタグ
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーーん

ここに書いてあります。
https://msdn.microsoft.com/ja-jp/library/sk4fs3es(v=vs.100).aspx


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

ITO 様、有り難うございます。

教えて戴いたページは、CPrintInfo::m_nCurPage の説明です。
「フレームワークは、ドキュメントのページごとにこのメンバーに異なる値を指定して、
CView::OnPrepareDC と CView::OnPrint を呼び出します。」と書いてあります。

これが、『フレームワークは・・・ CView::OnPrepareDC を2度呼び出す』と書いてあれ
ば納得なのですが・・・


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>CMyProjView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
失礼しました。
ここで実際に処理していたのですね。
>OnPrepareDC() はページ毎に2回ずつ実行されると考えていいでしょうか?
うーーん、
たまたま2回だったということはないでしょうか?

https://technet.microsoft.com/en-us/lync/aa248127(v=vs.60)
ここでは、「OnPrint()」で処理するように書いてありますね。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

OnPaint() の中で、印刷したページ番号を格納しました。

CMyProjView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pDC->IsPrinting())
{
m_nPrintedPage[m_nPPAray] = pInfo->m_nCurPage;
m_nPPAray++; // 印刷開始前に m_nPPAray = 0; としています。
...(印刷のためのコード)...
}
}

結果:(3~5ページを印刷した場合) m_nPrintedPage[] = {3, 4, 5, 0, 0, 0, 0, 0...}

これで解決です。
ありがとうございました。


返信引用
K
 K
(@K)
ゲスト
結合: 23年前
投稿: 98
 

解決したようなので今さらですが。

VS2008 ですが MFC のソースを見てみると
viewprnt.cpp の CView::OnFilePrint() で OnPrepareDC() を
ページごとに 2 回呼び出しているように読めます。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

K様、有り難うございます。
やはりそうですか。
OnPrepareDC() が2回呼び出されるのは異常ではないと、安心しました。

OnPrint() の中で、印刷したページ番号を取得できたとして解決としましたが、その後、
例えば3ページ印刷しようとして用紙が1枚しかセットされておらず、印刷が中断した場
合でも、OnPaint() は3ページ分動作してしまうことが判りました。
これでは目的に合わないので、最初から考え直すことにしました。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

> viewprnt.cpp の CView::OnFilePrint() で OnPrepareDC() を
> ページごとに 2 回呼び出しているように読めます。
なるほど、フォロー助かります。

>例えば3ページ印刷しようとして用紙が1枚しかセットされておらず、印刷が中断した
>場合でも、OnPaint() は3ページ分動作してしまうことが判りました。

おそらくもうテッパンさんの 印刷処理は終了しています。

https://msdn.microsoft.com/ja-jp/library/cc428280.aspx
ここの、ジョブ/スプールの処理になっていると思います。
http://support.microsoft.com/kb/160129/JA
これもかな?

キャンセルされたかどうかを調べるのは難しいと思います。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

教えて戴いた印刷ジョブ/スプールを理解しようと努力しましたが、プリンタ側で何ペー
ジまで印刷できて何ページから印刷できていないかの情報を取得するのは至難の業と、諦
めることにしました。
皆様、ありがとうございました。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーーん、
プリンタ側は、何ページからは関係ないですね。
そこは、
>結果:(3~5ページを印刷した場合) m_nPrintedPage[] = {3, 4, 5, 0, 0, 0, 0, 0...}
この値を信用するしかないと思います。
あとは、実際に印刷されたページ数(途中キャンセルの有無)をチェックすればいいと思
いますが、どうでしょうか?


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

あきらめるな!、と励まして戴いて有り難うございます。
実際に印刷されたページ数を取得しようと、コードを一応書いてみたのですが、始めのと
ころでつまづいています。

CMyProjView::EndPrinting(CDC* /*pDC*/, CPrintInfo* pInfo)
{
DWORD cByteNeeded;
PRINTER_INFO_2 *pPrinterInfo = NULL;
GetPrinter(pInfo->m_pPD, 2, NULL, 0, &cByteNeeded);  ←この行でエラー
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
・・・以下、GetPrinter()、EnumJobs() まで
}

pInfo->m_pPD がいけないかと、OpenPrinter() でハンドルを取得してみても同じです。
HANDLE hPrinter;
OpenPrinter(_T(EPSON EP-301), &hPrinter, NULL); ←この関数は成功
GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded);  ←この行でエラー

コードを OnPrint() の中に書いても、GetPrinter() がエラーは同じです。
お気づきのことがありましたらご教授ください。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

GetPrinter() のエラーコードは、6番、ERROR_INVALID_HANDLE となっています。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

失礼しました。訂正します。エラーコードは、

GetPrinter(pInfo->m_pPD,... のとき、ERROR_INVALID_HANDLE です。

OpenPrinter(_T(EPSON EP-301), &hPrinter, NULL);
GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded);
のとき、122番、ERROR_INSUFFICIENT_BUFFER になります。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded);
の戻りが ERROR_INSUFFICIENT_BUFFER であるのは予定の結果なんですね。

お手本「プリンタと印刷ジョブの状態の取得方法」
http://support.microsoft.com/kb/160129/JA
の中の
GetPrinter(hPrinter, 2, (LPSTR)pPrinterInfo, cByteNeeded, &cByteUsed)
3番目の引数が (LPSTR) は誤記で、(LPBYTE) が正みたい。

EnumJobs() のあと、PagesPrinted を取得するところで奮戦中です。


返信引用
テッパン
 テッパン
(@テッパン)
ゲスト
結合: 10年前
投稿: 13
Topic starter  

EnumJobs() のあとに、次のコードを入れてやってみましたが、何ページ印刷しても、結
果は 0 ページとなります。

DWORD result = pJobStorage->PagesPrinted;
wchar_t test[16];
_itow_s(result, test, 16, 10);
MessageBox(CString(test));

印刷が終わる前に結果が表示されてしまいます。
ちなみに、result = pJobStorage->TotalPages; をやると、印刷するトータル枚数が正し
く表示されます。

EndPrinting() の中にコードを書いていますが、これがいけないのでしょうか。
ネットを検索すると、”PagesPrinted は not reliable”という記事が出ています。
当方、Windows 8.1 です。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました