ページ 1 / 1
BitBltについて
Posted: 2006年9月29日(金) 23:00
by BingoMan
学校の文化祭も終わり、部活を引退したところで久しぶりの投稿です。
BitBlt関数がメモリ内デバイスコンテキストのビットマップのビット配列を別のデバイスコンテキストのビットマップのビット配列にコピーするメカニズムが知りたくなっていろいろ調べたのですが、結局きちんと解説されているページが見つからなかったのでここで質問させていただきます。具体的には
コード: 全て選択
Dim hOrgDC As HDC
Dim hOrgBmp As HBITMAP
をコピー元メモリ内デバイスコンテキストとビットマップのハンドルとして、
コード: 全て選択
Dim hCpyDC As HDC
Dim hCpyBmp As HBITMAP
にコピーすることを考えています。
自分なりに考えてみたのですが、
- 1.コピー元ビット配列のアドレスを調べる
2.コピー先ビット配列のアドレスを調べる
3.コピー元ビット配列にアクセスする
4.コピー先ビット配列に書き込む
という方向で考えています。現在は
3がうまくいかないので、おそらく
1から失敗しているのではないかと思います。
というわけで、デバイスコンテキストのハンドルからそのデバイスコンテキストに関連付けられたビットマップの、ビット配列のアドレスを取得する方法を教えてください。
長くてわかりにくい質問で申し訳ございません...
Re: BitBltについて
Posted: 2006年9月29日(金) 23:22
by イグトランス
> 1.コピー元ビット配列のアドレスを調べる
> 2.コピー先ビット配列のアドレスを調べる
> 3.コピー元ビット配列にアクセスする
> 4.コピー先ビット配列に書き込む
Windowsが内部でやっていることはおそらくこうでしょう。
GetObjectすればBITMAP構造体のbmBitsには内部のビットマップへのポインタが入っています。
しかし,一体なぜ3がうまくいかないと言うのでしょうか。
どういうコードを書いて,どうなったからそうだと結論付けたというのを是非書いてください。
実は別のことがうまくいっていなかったということがあるかもしれませんよ。
Posted: 2006年9月30日(土) 00:13
by BingoMan
イグトランス様、早速のご返事ありがとうございます。
具体的なコードを出していなかったのでここに掲載します。
まず先頭で次のグローバル変数を定義しています。
コード: 全て選択
' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Dim hOrgDC As HDC
Dim hOrgBmp As HBITMAP
Dim hCpyDC As HDC
Dim hCpyBmp As HBITMAP
'GetObject関数で取得する情報を格納するための変数
Dim OrgBitmap As BITMAP
Dim OrgBits As BytePtr
Dim CpyBitmap As BITMAP
Dim CpyBits As BytePtr
そしてウィンドウ生成時に次の処理を行っています。
コード: 全て選択
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
Dim hDC As HDC
Dim i As Long,j As Long
hDC=GetDC(hMainWnd)
hCpyDC=CreateCompatibleDC(hDC)
hCpyBmp=CreateCompatibleBitmap(hDC,200,200)
SelectObject(hCpyDC,hCpyBmp)
hOrgDC=CreateCompatibleDC(hDC)
hOrgBmp=LoadImage(GetModuleHandle(0),XXX_BMP1,IMAGE_BITMAP,200,200,LR_DEFAULTCOLOR)
SelectObject(hOrgDC,hOrgBmp)
ReleaseDC(hMainWnd,hDC)
GetObject(hOrgBmp,SizeOf(BITMAP),OrgBitmap)
OrgBits=OrgBitmap.bmBits'bit配列の先頭アドレスをBytePtr型変数に格納
GetObject(hCpyBmp,SizeOf(BITMAP),CpyBitmap)
CpyBits=CpyBitmap.bmBits'bit配列の先頭アドレスをBytePtr型変数に格納
/*デバッグ時にここの部分でエラーが発生
For i=0 To 199
For j=0 To 199
SetByte(CpyBits+i*200+j,GetByte(OrgBits+i*200+j))
Next
Next
*/
'代わりにGetObjectで取得したbit配列の先頭アドレスを表示
MessageBox(hMainWnd,Hex$(OrgBits),"",MB_OK)
End Sub
このプログラムを実行したところ、表示されるアドレスが常に0でした。
つまり先ほど質問した内容の
1の時点でうまくいっていないようです。
このプログラムの間違いを教えてください。よろしくお願い致します。
Posted: 2006年9月30日(土) 09:04
by マティ
動作確認等は行っていません!!!
APIを見ただけの印象でお答えします。(赤字の部分)
hDC=GetDC(hMainWnd)
hCpyDC=CreateCompatibleDC(hDC)
hCpyBmp=CreateCompatibleBitmap(hCpyDC,200,200)
//SelectObject(hCpyDC,hCpyBmp) //hCpyDCで作成すると必要ない
hOrgDC=CreateCompatibleDC(hDC)
hOrgBmp=LoadImage(GetModuleHandle(0),XXX_BMP1,IMAGE_BITMAP,200,200,LR_DEFAULTCOLOR)
SelectObject(hOrgDC,hOrgBmp)
ReleaseDC(hMainWnd,hDC) //※hDCを開放すると、hDCで作成したビットマップは使えない!
依存関係のあるオブジェクトは、生成した順番が新しい物から開放してください。
メモリーリークや不思議な動きをする原因になります。
Posted: 2006年9月30日(土) 11:04
by イグトランス
元のビットマップがLoadImageやCreateCompatibleBitmapで作成しているからだと思います。
bmBitsは,CreateBitmapやCreateBitmapIndirectで作成し(そこでビットマップへのポインタを指定し)たときしか使えなかった気がします。
それ以外の方法でビットマップを作るとビットマップのメモリはシステムが管理するのでユーザにはこうして見せてくれないというのではないでしょうか。
なお,CreateCompatibleBitmapの引数にメモリデバイスコンテキストであるhCpyDCを渡すのは良くないです。
http://msdn.microsoft.com/library/ja/jp ... bitmap.asp
またメモリDCから互換ビットマップを作ればSelectObjectの必要がないということは,記述されていません。
またそこでhDCをReleaseDCによって返しても問題ないです。
メモリDCを作るための情報を得るためだけに使われており,
作ってしまえばメモリDCは元のDCがReleaseDCされても問題無いはずです。