- ベストアンサー
BitBltについて。
どなたか経験のある方、わかる方居られましたら教えてください。 プリンタのデバイスコンテキストからメモリDCに描画してビットマップを作成したいと思っているのですが、プリンタDCからメモリDCへのBitBltがうまくいっていないのか、完成イメージが真っ黒になります。 hMemDC = CreateCompatibleDC(hPrinterDC); hBitmap = CreateCompatibleBitmap(hPrinterDC,lnWidth,lnHeight); Obj = (HBITMAP)SelectObject(hMemDC,hBitmap); iRet = GetDeviceCaps(hMemDC,RASTERCAPS); // iRet の戻り値は 28313(10進)でした。 // コピー iRet = BitBlt(hMemDC,0,0,lnWidth,lnHeight,hPrinterDC,0,0,SRCCOPY); // iRet の戻り値は 1 になってました。 本来は lnHeight の値が BitBlt の戻り値になるのかと思いますがうまくいきません。 hPrinterDC はもともと印刷用の関数で使用しているものなので、そこには問題が無いのではないかと自分では思っていますが、わかる方居られましたら教えていただけませんでしょうか?
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
★Toyochan8 さんへ ・随分と苦戦していますね。 ・過去に同じような質問を 3 つしていますが、解決していないようですね。 ・私は『プリンタ・デバイス』を操作した経験はありませんが、気になった点を4つアドバイスします。 ●1つ目 ・まず『BitBlt』の戻り値ですが、MSDN のマニュアルでは BOOL 型になっていて正常終了すると TRUE を 返します。エラーが起きた場合は FALSE を返します。→『lnHeight』の値は戻り値に戻りません。 ●2つ目 ・GetDeviceCaps の行は、 『iRet = GetDeviceCaps(hMemDC,(RASTERCAPS|RC_BITBLT));』と 『iRet = GetDeviceCaps(hPrinterDC,(RASTERCAPS|RC_BITBLT));』の 2つを調べます。 戻り値を調べ『if (iRet & RC_BITBLT)』が真ならば BitBlt 関数を利用できます。 ●3つ目 ・『BitBlt』関数で上手くコピーできないならば、『StretchBlt』関数で長方形をコピーします。 つまり、 『BOOL bRet = StretchBlt(hMemDC,0,0,lnWidth,lnHeight,hPrinterDC,0,0,lnWidth,lnHeight,SRCCOPY);』 として転送します。このとき、StretchBlt 関数をサポートしているかどうかを 『iRet = GetDeviceCaps(hMemDC,(RASTERCAPS|RC_STRETCHBLT));』と 『iRet = GetDeviceCaps(hPrinterDC,(RASTERCAPS|RC_STRETCHBLT));』で 問い合わせます。戻り値を調べ『if (iRet & RC_STRETCHBLT)』が真ならば StretchBlt 関数を利用できます。 ●4つ目 ・フルカラーならビットマップのヘッダの『biBitCount = 16;』ではなく『biBitCount = 24;』とすべきです。 ・さらに横方向のピクセル値は 4 バイト単位で揃えます。→横幅が 125 ピクセルならば、128 ピクセルとして 黒色データを 3 ピクセル余分に出力します。ここに注意して『.bmp』ファイルへ出力します。 ・あと分かりやすく『biCompression = BI_RGB;』という定数にしましょう。 最後に: ・一度、メモリDC のビットマップ・データをウインドウへ描画して、コピーが正常かどうかを目で 確認してみて下さい。その後にファイルへビットマップを出力します。 ・それとビットマップ・ファイルにパレットは使っていませんよね?もし使っていたら、パレットデータも正しく 出力しないと『真っ黒』になりますよ。→『RGBQUAD』構造体を参照 ・あと VC++ Ver.15.1 を使っているようですが、『CreateFile』、『WriteFile』、『CloseHandle』の関数が 使えないのですか? 下に『_lwrite』関数を書き直した部分を載せます。→for文の方が分かりやすいですよ。 lCount = (long)LtpBitmapFH.bfSize - sizeof( BITMAPFILEHEADER ); for ( lBuffCnt = 0 ; lBuffCnt >= lCount ; lBuffCnt++ ){ Liret = _lwrite( hF, &szBuffer[lBuffCnt], 1 ); } ・以上。おわり。
その他の回答 (1)
- tettsu
- ベストアンサー率30% (4/13)
とりあえず、3つのプリンタデバイスで実験してみました。 プリンタDCに画像を描画した直後に画像を取り出してみましたが、単色のビットマップイメージしか取り出せませんでした。 エプソンPM-890C:黒 PDF:黒 Dellのレーザプリンタ:白 プリンタによっては、画像が取り出せるかもしれませんが、通常はできないと思ったほうがよいと思われます。 ところで、どういう意図でプリンタDCからビットマップを取り出したいのでしょうか?
補足
tettsuさん、いつもアドバイス有難うございます。 わざわざ試していただき申しわけ有りません感謝します、単色だと取り出せる事もあるんですね。 その場合ヘッダ情報のBitCount を1にすればいいだけなのでしょうか? 通常出来ないと思ったほうが良いということなので、新規フォームを作成してそこに描画したイメージをビットマップにすることにしました。 残された時間も少なくなってきて、少し行き詰まってますがもうちょっと考えてみたいと思います。 プリンタDCから取り出したいと思ったのは印刷用のDLLがあったのでそれの終了時のDCから取り出せば早いのかなと思ったからです。
お礼
Oh-Orangeさん、アドバイス有り難うございます。 『BitBlt』の戻り値の件は自分がGetDIBitsと勘違いしていました申し訳ありません。 GetDeviceCapsの件ですが教えて頂いたとおり書いてみましたがアクティブウインドウでも戻り値が0でした。自分の使い方まずかったんでしょうか・・。下のように使用しました。 iRet = GetDeviceCaps(hMemDC,(RASTERCAPS|RC_STRETCHBLT)); if (iRet & RC_STRETCHBLT) { // TRUEの時の処理 ここは通りませんでした。 } BMPのサイズの横幅は 560 なのでその点は大丈夫だと思います。 仕方なくプリンタのDCは中止してフォームを1つ作成してそこに描画したものをメモリDCにコピーさせることにしました、しかしこれも又うまくいかず・・。真っ黒にはならなかったのですが、フォーム上部の×ボタン、最大、最小化ボタンがあるエリアの左部分のアイコンのあたりが指定サイズのビットマップに拡大されて作成されてしまいました。取得データをフォームに描画しても同じ画像だったのでうまくメモリDCに受け取れていないと思います、有り難うございました。