初心者なもので、どうしても分かりません。
リソースのビットマップを印刷したいと思っています。
ダイアログに、ボタンを貼り付けて、そのボタンクリックで印刷をしたいと思っています。
(将来的にはファイルを指定して印刷したいのですが、
まずは手始めという事でリソースから想定しています。)
CDC doc;
doc.StartPage();
doc.EndPage();
doc.EndDoc();
という構文の中で、StartPageとEndPageの中に何をどう入れれば良いのか、
しかもどういう手順で入れれば良いのか検討がつきません。
VisualC++の参考書見ても、ビットマップをダイアログベースで印刷
というのは載っていませんでした。(X_X;)
環境はWinXPHomeとVisualC++6.0
ビットマップの印刷の前に、ビットマップがリソースから読めるのでしょうか
それにあなたの示されたコードの概略がどのメッセージに対する応答なのか
少しも説明がありませんし、EndDoc() があるのに StartDoc() が無いのは
不思議に思いませんか?
CDialog ではなく CFormView なら DOC/VIEW が使えるらしいので、
CView での印刷の手順と同じになるのではないでしょうか?
島さんへ
せっかく回答して頂いたにもかかわらず返信が遅れてしまい誠に申し訳ありません。
(休暇を取っていました。)
今はテスト作成なので、ダイアログベースのアプリにただ1つのボタンを貼り付け、
OnButton1()の関数の中で、以下の様なコードを書いています。
また、将来的にダイアログベースでアプリを作っていきたい為、CViewではなく、
CDialogで作りたいと思っています。
1.ビットマップを表示するためのメモリデバイスコンテキストを作る
2.ビットマップリソースを読み込む
3.旧ビットマップを待避しておき、読み込んだビットマップを
メモリデバイスコンテキストに関連づける
4.メモリデバイスコンテキスト→現在のデバイスコンテキストに転送する
5.ビットマップを元に戻す
という考え方で間違っておりませんでしょうか?
また、AppWizardでは、ダイアログベースを選択し、後の項目は特に変更せずそのまま次へを
押してスケルトンを作りましたが、何か特別なオプションを設定すべきなのでしょうか?
よろしくお願いいたします。
// プリンタダイアログを表示する
CPrintDialog PrtDlg(FALSE);
int nRet;
nRet = PrtDlg.DoModal();
if(nRet != IDOK) return; // 処理中止
HDC myPtDC;
CDC myDC;
DOCINFO myDocInfo;
// プリンタデバイスコンテキストを取得する
myPtDC = PrintDlg.GetPrinterDC();
myDC.Attach(myPtDC);
// 新しいプリントジョブを開始する
memset(&myDocInfo, 0, sizeof(myDocInfo) );
myDocInfo.cbSize = sizeof(myDocInfo);
myDocInfo.lpszDocName = Test;
myDocInfo.lpszOutput = NULL;
myDocInfo.lpszDatatype = NULL;
myDocInfo.fwType = 0;
myDC.StartDoc(&myDocInfo);
// 印刷開始
myDC.StartPage();
// リソースからビットマップを読み込む
CBitmap myBMP;
myBMP.LoadBitmap(IDB_BITMAP1);
// 現在のデバイスコンテキストと互換のあるメモリデバイスコンテキストを作る
CDC myBMPDC;
myBMPDC.CreateCompatibleDC(&myDC);
// 旧ビットマップの保存と、myBMPを選択する
CBitmap* oldBMP = myDC.SelectObject(&myBMP);
myDC.BitBlt(10,10,100,100,&myBMPDC,0,0,SRCCOPY);
// 元のビットマップに戻す
myDC.SelectObject(oldBMP);
// 印刷終了
myDC.EndPage();
myDC.EndDoc();
// プリンタデバイスコンテキストの解放
::DeleteDC(myPtDC);
たびたびすみません、このコードではコンパイルは通りますが、
肝心のビットマップは印刷されません。
また、ビットマップを操作している箇所で、
myDC.TextOut(0,0,あいうえお);
では、テキストは正しく印刷する事ができました。
ここがいけません
>// プリンタデバイスコンテキストを取得する
>myPtDC = PrintDlg.GetPrinterDC();
>myDC.Attach(myPtDC);
>
>
>// 現在のデバイスコンテキストと互換のあるメモリデバイスコンテキストを作る
>CDC myBMPDC;
>myBMPDC.CreateCompatibleDC(&myDC);
LoadBitmap() では画面DCに互換なビットマップ(DDB)が出来ますが、
このビットマップはプリンターDCとは互換なビットマップでは無いので
myBMPDC には選択できないのです(選択に失敗します)
画面DCにコンパチブルなメモリーDCを作ってそれに選択するかDIBとして
画像を読み込んでプリンターDCに StretchDIBits などで描画してください
DIB として画像を扱う方が印刷するときは便利です(DDB の制限がないから)
島さんへ
ご指導ありがとうございます。
StretchDIBitsについて過去ログを調べてみましたが…、
まだまだ初心者の今の自分には、折角のご指導にも関わらず理解できない所があります。
>画面DCにコンパチブルなメモリーDCを作ってそれに選択する
>DIBとして画像を読み込んでプリンターDCに StretchDIBits などで描画
この2通りがあるという事でしょうか?
過去ログを参照して、メモリデバイスコンテキストを作る箇所を以下の様に修正しました。
// 指定されたデバイスコンテキストを取得して、互換性のあるビットマップを作成
HDC PrtDC = myDC.GetSafeHdc();
HBITMAP myBMPDC = CreateCompatibleBitmap(PrtDC,100,100);
StretchDIBitsについてですが、これが全然理解できません。
http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_DIB.html
等を参照しましたが、ファイルから読み込んでいるのでしょうか。
file.readしていました。
また、charやBYTE等、DIM形式について色々と知っていなければ、
ダメなような印象を受けました。
また、冒頭のAttachですが、これもなぜダメなのかが良く分かりません。
# ダイアログベースから印刷する事は、やはり初心者の自分ではハードルが高いのでしょう
か…。
>この2通りがあるという事でしょうか?
二通りあるのではなく、やり方を二つ挙げたのですが、何がおききになりたいのでしょうか?
>また、冒頭のAttachですが、これもなぜダメなのかが良く分かりません。
>>LoadBitmap() では画面DCに互換なビットマップ(DDB)が出来ますが、
>>このビットマップはプリンターDCとは互換なビットマップでは無いので
>>myBMPDC には選択できないのです(選択に失敗します)
この前回の説明のどこがわかり難いのですか?
Attach しようとしている元のDCはプリンターDCですね?
ですから myDC もプリンターDCですね?
ところが myDC に選択した myBMP は画面DCに互換な DDB ですから、プリンターDC
には選択に失敗するのではないかと思うのですがどうですか?
選択に成功したかどうかは CDC::SelectObject() の戻り値で判断できませんか?
DIB の取り扱いが判らないのなら無理に DIB に今、挑むことは無いでしょう
DDB では印刷が出来ない等の制限のあるプリンター(正確にはプリンタードライバー)が
あることを知っているので、私は印刷なさるのなら DDB ではなく DIB を勧めています
DDB でも印刷できないと決まっているわけではないので、先ず、GetDeviceCaps() で
描画能力を確かめてみると良いでしょう(特に RASTERCAPS で判ることが重要かな)
>ダイアログベースから印刷する事は、やはり初心者の自分ではハードルが高いのでしょう
か…。
いいえ、印刷は誰にでも簡単というものではないと思います(特に Windows は?)
印刷に関しては、プリンタドライバーの出来によって大幅に左右されるので
画面への描画と違ってかなり面倒である事は確かですね。
場合によってはドライバの不具合をこっちで補うはめになる事もありますし。
Windowsの実装では、表示と印刷は特に区別があるわけではなくて
描画対象が画面のDCなのかプリンタのDCなのかで分かれています。
ですから、うまくやれば描画部分に関しては一本化する事も可能だったりします。
この辺りの仕組みをうまくやっているのがCViewクラスということだと思います。
通常はプリンタへの出力の場合は、ヘッダやらフッタの処理が入ったり
印刷特有の処理が入ったりするので画面描画とは分けて考えますが、
コアの描画部分は基本的に同じなので後は出力先のDCによって処理を変えたり、
座標計算時のパラメータを変えたりする部分が理解できればそこまで複雑と言う
訳ではないと思います。
基本的な印刷の流れは、HELPに書いてあります。
//この辺に印刷ダイアログの表示やらプリントDCの取得が入る。
//印刷の開始
StartDoc
//一ページ分の処理の開始
StartPage
//一ページ分の描画処理をここでやる
//一ページ分の処理の終了
EndPage
//印刷の終了
EndDoc
複数ページの処理に関しては、StartPageからEndPageまでページ数分繰り返します。
描画の場合はStartPageとEndPageの間にある部分の処理だけですんでしまう点が
違うだけです。
(まあ、印刷の場合は、解像度とか色数の関係で処理が増えますけどね)