数回、ここで質問して、解決させて戴いてもらっている者です。
前回のここの質問でもBITMAPが
「『プレビュー』には表示できるがPrintOutできない!!!」
という質問がありました。
今回も同じ質問になりますが・・・
前回の回答は、「=GetDC()」がよいと言うことでしたが
それでもできませんでした。
また、その『プレビュー』も表示されるにはされるのですが
縮尺が小さすぎます。
・OnDrawには、BitBlt関数を仕様しています。
・アクティブウィンドウにも設定しております。
(いま、PrintBegin,PrintEend,PrintPrepareを
そのクラスにてオーバーロードしています
・・ていうか、
AppWizardにて「印刷、・・・」を設定した
単純なモデルソフトにても同じでした。)
どなたか教えて戴けませんか?
(APIはできるだけ使いたくない[好みです]のですが・・)
(VC++6:MFC)です
//MyView.h
class CMyView : public CScrollView
{
...
// インプリメンテーション
public:
protected:
BOOL bPrinting ;
char* m_BmpImage ;
LPBITMAPINFO m_BmpInfo ;
BITMAPFILEHEADER m_BmpFileHdr ;
LONG biWidth;
LONG biHeight;
...
}
//MyView.cpp
CMyView::CMyView()
{
// TODO: この場所に構築用のコードを追加してください。
bPrinting = FALSE ;
}
void CMyView::OnDraw(CDC* pDC)
{
CMapViewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この場所にネイティブ データ用の描画コードを追加します。
HBITMAP myDIB ;
HBITMAP oldDIB ;
HDC hDC ;
HDC hCompatiDC ;
//すでにビットマップ情報を取得済とする
hDC = pDC->GetSafeHdc () ;
hCompatiDC = ::CreateCompatibleDC (hDC) ;
myDIB = CreateDIBitmap (hDC, &m_BmpInfo->bmiHeader, CBM_INIT, m_BmpImage,
m_BmpInfo, DIB_RGB_COLORS) ;
oldDIB = (HBITMAP)::SelectObject (hCompatiDC, myDIB) ;
//表示を大きくする[10倍]
StretchBlt (hDC, // handle to destination device context
0,
0,
biWidth * 10, // width of destination rectangle
biHeight * 10, // height of destination rectangle
hCompatiDC, // HDC hdcSrc, // handle to source device context
0,
0,
biWidth, // width of source rectangle
biHeight, // height of source rectangle
SRCCOPY // raster operation code
) ;
//あるいは
//biWidth * 10,
//biHeight * 10,の変わりに
//プリンターデバイスコンテキストの幅、高さを指定してもいい
//if (bPrinting) {
//プリンター出力
//} else {
//画面出力
//}
//BitBlt を使うのならMM_TEXT以外のマップモードでは?
if (bPrinting) { //プリンターデバイス出力を終了する為に必要
pDC->EndPage () ;
pDC->EndDoc () ;
}
::SelectObject (hCompatiDC, oldDIB) ;
::DeleteObject (myDIB) ;
::DeleteObject (hCompatiDC) ;
::ReleaseDC (m_hWnd, hDC) ;
}
void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 印刷前の特別な初期化処理を追加してください。
bPrinting = TRUE ;
}
void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 印刷後の後処理を追加してください。
bPrinting = FALSE ;
}
MFC サンプルの DRAWCLI が参考になると思います。
このサンプルでは、CDrawView::OnDraw で、BltBlt による描画、印刷を行っています。
何やらビューポートをいじっているようなので、そのあたりを調べてみてください。
私も印刷に関してはあまり詳しくないので、申し訳ないのですが、ここでは回答できないです。
Kさん、TADさん
有難うございます。
教えていただいた事をもとに
挑戦してみます。
できなかったら、また
お聞きするかもわかりませんが
そのときは、よろしくお願いいたします。
Kさん、TADさん
やはり出来ませんでした。
Printer(Canon-BJF-6100)なのですが、印刷動作はするのですが、
結果として、印刷されません。
BitBltが可能かどうかも
GetDeviceCaps 関数を呼び出して RC_BITBLT にてチェック
したところ、ビット1(RC_BITBLT )が立っていて、OKでした。
プログラムの印刷(描画)部分は下記の通ですが、なにか不足しているのでしょうか?
これ以外にも、
CPrintDialog dl(FALSE);
AfxGetApp()->GetPrinterDeviceDefaults(&dl.m_pd);
HDC hDC = dl.CreatePrinterDC();
にて、プリンターのHDCを取得(したつもり・・)して
そのHDCにBitBltしても、結果は同じでした。
ご指南ください。
以下、ソフトです。
考え方は、
Docにて、ファイルの読み込み。
OnUpdateにて、メンバー変数のm_CBitにデータ-保存して、OnDraw準備。
OnDrawにてメンバー変数のm_CBitを再描画
void CpPreView::OnDraw(CDC* pDC)
{
CpImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この位置に描画用のコードを追加してください
CSize sz = GetTotalSize();
CDC pcDC; //バックグラウンド用DCポインターを設定
pcDC.CreateCompatibleDC(pDC);//バックグラウンド用DCポインターを標準DCに設定
pcDC.SelectObject(m_CBit);
pDC->BitBlt(0, 0, sz.cx,sz.cy, &pcDC, 0, 0, SRCCOPY);
pcDC.DeleteDC();
}
void CpPreView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CpImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
CSize sizeTotal;
CPictureHolder pH;
LPDISPATCH ld;
OLE_HANDLE phandle;
HBITMAP hbm;
BITMAP bm;
CBitmap cbm;
CString FileName=pDoc->m_FileName;
CDC* pDC=GetDC(); // 標準DCポインターを取得
CDC pcDC; // バックグラウンド用DCポインターを設定
HDC hcDC,hccDC; // バックグラウンド用DCハンドルを設定
pcDC.CreateCompatibleDC(pDC);//バックグラウンド用DCを標準DCフォーマットに設定
if(FileName != "){
if(FAILED(::OleLoadPictureFile(COleVarian
(FileName),&ld))) return;// FALSE;
pH.SetPictureDispatch((LPPICTUREDISP)ld);
if(pH.GetType() != PICTYPE_BITMAP) return;// FALSE;
pH.m_pPict->get_Handle(&phandle); /// GDIハンドル取得。
hbm=(HBITMAP)phandle; /// GDIハンドルをBITMAPハンドルに変換。
GetObject(hbm,sizeof(BITMAP),&bm);// GDI(BITMAP)Objectを取得。
sizeTotal.cx = bm.bmWidth; /// BITMAPの幅。
sizeTotal.cy = bm.bmHeight; /// BITMAPの高さ。
if(m_CBit.m_hObject!=NULL){
m_CBit.DeleteObject();
}
m_CBit.CreateCompatibleBitmap(pDC, bm.bmWidth, bm.bmHeight);
pcDC.SelectObject(&m_CBit); /// CBitmap m_CBit; にてメンバー変数
// pcDC.FillSolidRect(CRect(0, 0, m_Width, m_Height),RGB
(255,255,255));
hcDC=pcDC.GetSafeHdc();
hccDC=CreateCompatibleDC(hcDC);// バックグラウンド用DCハンドルを標準DC
フォーマットに設定
SelectObject(hccDC,hbm);
BitBlt(hcDC,0,0,bm.bmWidth, bm.bmHeight,hccDC,0,0,SRCCOPY);
DeleteObject(hccDC);
DeleteObject(hcDC);
DeleteObject(hbm);
pcDC.DeleteDC();
Invalidate();
}
else{
sizeTotal.cx = sizeTotal.cy = 100;
}
SetScrollSizes(MM_TEXT, sizeTotal);
}
こちらから質問ですが、DRAWCLI サンプルでは正しく印刷できますか?
もし印刷できないとなると、プログラム上の問題ではなく、Windows側(プリンタドライバ)に問題
があるのかもしれません。
印刷できれば、少しは希望が持てますね。
TADさん
以前、『スプリッタ-ウィンドウに、ToolBarを表示したい』
という私の悩みを解決して頂いたものです。
そのときは、有難うございました。
「DRAWCLI サンプル」ですが、わたしのパソコン上
で、『動作』しませんでした。
(わたしのは、Windows Me』で、95ではないため!!
と勝手に解釈したのですが・・・
でも、そのサンプルのプログラムリストをみて、
さきほどの、『きっと、プリンタードライバーのHDC』が
設定されていなかったために、印刷できないんだ!!
と思いました。(すみません、サンプルのすべてを
解読したわけではありません)
そこで、そのサンプル内のHDCを入手する(と思った・・・)、
CPrintDialog dl(FALSE);
AfxGetApp()->GetPrinterDeviceDefaults(&dl.m_pd);
HDC hDC = dl.CreatePrinterDC();
らの手法も試みました。
でも、結果は・・・・・
もうすこし、『サンプル』の解読を試みます。
いつもながら、早急で、新設なお答えに
感謝しております。
すみません。
補足ですが、
TextOut(・・・);
では、テキストはちゃんと印刷してくれるし
Windows付属の、『ペイント』などでは
BITMAPをちゃんと印刷してくれるので
ドライバーの問題でなく
わたしのソフトの問題と考えております。
(トホホ・・・・)
DDBをそのままプリンタに転送してもだめです。
(何しろデバイスに依存したビットマップなので)
というわけでDIBに変換してからStretchDIBitsを使って転送するとよいです。
kazumaさん
ありがとうございます。
さっそく、チャレンジしてみます。
void CpPreView::OnDraw(CDC* pDC)
{
CpImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この位置に描画用のコードを追加してください
CSize sz = GetTotalSize();
CDC pcDC; //バックグラウンド用DCポインターを設定
pDC.CreateCompatibleDC(pDC);//バックグラウンド用DCポインターを標準DCに設定
pDC.SelectObject(m_CBit);
pDC->BitBlt(0, 0, sz.cx,sz.cy, &pcDC, 0, 0, SRCCOPY);
//次の2行を追加して試してください。
pDC->EndPage () ;
pDC->EndDoc () ;
//Kの環境ではプリンターにビットマップが印刷されるようになりました。
pDC.DeleteDC();
}
修正します。
Kの2回目では確かに印刷されません。
CDCクラスに
myDIB = CreateDIBitmap (hDC, &m_BmpInfo->bmiHeader, CBM_INIT, m_BmpImage,
m_BmpInfo, DIB_RGB_COLORS) ;
のようなAPIが無い?ので
(APIはできるだけ使いたくない[好みです]のですが・・)
では無理かも知れません。
プログラミングVisualC++6.0[日経BPソフトプレス 11章 248P]
に記載されていました。
Kの環境ではAPIを使いました。[Kの1回目のスレッド]
そのとき次の行を省くと
if (bPrinting) { //プリンターデバイス出力を終了する為に必要
pDC->EndPage () ;
pDC->EndDoc () ;
}
Kの環境でも
「『プレビュー』には表示できるがPrintOutできない!!!」
現象が起きました。
Kさん、TADさん、Kazumaさん
ご親切に、大変有難うございました。
結局、APIを使って解決しました。
(意思薄弱で申し訳ありません)
いかに、解決したプログラム掲載します。
[まだ、印刷のサイズ設定までは至っておりませんが・・・・]
(私の気ままな[好み]のため、皆さんに
ご迷惑かけましたこと、平にお詫び致します。)
考え方は、以前と同じで、
メンバー変数は、
BYTE* m_Images;
BITMAPINFO *m_bi;
です。
void CpPreView::OnDraw(CDC* pDC)
{
CpImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この位置に描画用のコードを追加してください
CSize sz = GetTotalSize();
CDC pcDC; //バックグラウンド用DCポインターを設定
HDC hDC,hcDC;
HBITMAP hnBMP,hoBMP;
hDC=pDC->GetSafeHdc();
hcDC=::CreateCompatibleDC(hDC);
hnBMP=CreateDIBitmap(hDC, &m_bi-
>bmiHeader,CBM_INIT,m_Images,m_bi,DIB_RGB_COLORS);
hoBMP=(HBITMAP)::SelectObject(hcDC,hnBMP);
BitBlt(hDC,0,0,sz.cx,sz.cy,hcDC,0,0,SRCCOPY);
// StretchBlt(hDC,0,0,sz.cx,sz.cy,hcDC,0,0,sz.cx,sz.cy,SRCCOPY);
/////////結果としては、BitBlt でも StretchBlt でもOKでした//////////////
// SelectObject(hcDC, hoBMP);
pcDC.DeleteDC();
DeleteObject(hcDC);
DeleteObject(hnBMP);
DeleteObject(hoBMP);
pcDC.DeleteDC();
::ReleaseDC(m_hWnd, hDC);
::ReleaseDC(m_hWnd, hcDC);
}
void CpPreView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CpImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
CSize sizeTotal;
CPictureHolder pH;
LPDISPATCH ld;
OLE_HANDLE phandle;
HBITMAP hbm;
DIBSECTION ds;
CString FileName=pDoc->m_FileName;
CDC* pDC=GetDC(); // 標準DCポインターを取得
HDC hDC = pDC->GetSafeHdc(); // バックグラウンド用DCハンドルを設定
if(m_bi != NULL) delete[] m_bi;
if(m_Images != NULL) delete[] m_Images;
if(FileName != "){
if(FAILED(::OleLoadPictureFile(COleVariant(FileName),&ld)))
return;// FALSE;
pH.SetPictureDispatch((LPPICTUREDISP)ld);
if(pH.GetType() != PICTYPE_BITMAP) return;// FALSE;
pH.m_pPict->get_Handle(&phandle); /// GDIハンドル取得。
hbm=(HBITMAP)phandle; /// GDIハンドルをBITMAPハンドルに変換。
// (未使用)--> GetObject(hbm,sizeof(BITMAP),&bm);// GDI(BITMAP)Objectを取得。
GetObject(hbm,sizeof(DIBSECTION),&ds);//GDI(BITMAP)Objectを取
得。
sizeTotal.cx = ds.dsBm.bmWidth; /// BITMAPの幅。
sizeTotal.cy = ds.dsBm.bmHeight; /// BITMAPの高さ。
m_bi=(BITMAPINFO*)new BYTE [sizeof(BITMAPINFO)];
m_bi->bmiHeader=ds.dsBmih;
int hhh=GetDIBits(hDC,hbm,0,0,NULL,m_bi,DIB_RGB_COLORS);
m_Images=new BYTE[m_bi->bmiHeader.biSizeImage];
hhh=GetDIBits(hDC,hbm,0,m_bi-
>bmiHeader.biHeight,m_Images,m_bi,DIB_RGB_COLORS);
pH.m_pPict->Release(); /// IPictureの開放。
DeleteObject(hbm); /// hbmの開放。
ReleaseDC(pDC); /// pDCの開放。
::ReleaseDC(m_hWnd, hDC); /// hDCの開放。
Invalidate();
}
else{
sizeTotal.cx = sizeTotal.cy = 100;
}
SetScrollSizes(MM_TEXT, sizeTotal);
}
----------------------------------------------------------
あと、上の表示で
hhh=GetDIBits(hDC,hbm,0,m_bi-
>bmiHeader.biHeight,m_Images,m_bi,DIB_RGB_COLORS);
など、かってに二段になってしまうのですが、ここに、表示する場合
どうしたら、一段に表示できるのでしょうか??