アプリ版:「スタンプのみでお礼する」機能のリリースについて

ABの4.23.00を使用しています

今回、マスク画像を自動的に作成して、ビットマップ画像を透過して表示させる方法を考えているのですが、なかなかうまくいきません。
皆さんの知識をお貸しください。

とりあえず、グローバルで変数を用意しました。
Dim hMemDC As HDC
Dim hMemBmp As HBITMAP

Dim hIconDC As HDC
Dim hIconBmp As HBITMAP

BITMAPリソースに適当な画像を入れて、クリエイトイベントで変数に読み込みました。
※ビットマップの大きさは、32*32の物を使用してみました。
Dim hDC As HDC
hDC=GetDC(hMainWnd)

hIconDC=CreateCompatibleDC(hDC)
hMemDC=CreateCompatibleDC(hDC)
hIconBmp=LoadBitmap(GetModuleHandle(0),IDB_BITMAP1)
hMemBmp=CreateCompatibleBitmap(hDC,300,300)

SelectObject(hIconDC,hIconBmp)
SelectObject(hMemDC,hMemBmp)

背景の色を指定しました
SetBkColor(hIconDC,GetPixel(hIconDC,0,0))

とりあえず、hMemDCに画像をコピーしました。
BitBlt(hMemDC,0,0,32,32,hIconDC,0,0,SRCCOPY)
ReleaseDC(hMainWnd,hDC)


次に、再描写の処理のときに、マスク画像を用意する処理を入れてみたのですが、うまくいきません。
Dim hMaskDC As HDC
Dim hMaskBmp As HBITMAP
Dim hTempDC As HDC
Dim hTempBmp As HBITMAP

hMaskDC=CreateCompatibleDC(hMemDC)
hMaskBmp=CreateBitmap(32,32,1,1,0)

SelectObject(hMaskDC,hMaskBmp)
BitBlt(hMaskDC,0,0,32,32,hIconDC,0,0,SRCCOPY)

hTempDC=CreateCompatibleDC(hDC)
hTempBmp=CreateCompatibleBitmap(hMemBmp,32,32)

SelectObject(hTempDC,hTempBmp)
BitBlt(hTempDC,0,0,32,32,hMaskDC,0,0,NOTSRCCOPY)
BitBlt(hTempDC,0,0,32,32,hIconDC,0,0,SRCAND)


BitBlt(hMemDC,0,0,32,32,hMaskDC,0,0,SRCAND)
BitBlt(hMemDC,0,0,32,32,hTempDC,0,0,SRCPAINT)

DeleteDC(hMaskDC)
DeleteObject(hMaskBmp)
DeleteDC(hTempDC)
DeleteObject(hTempBmp)

BitBlt(hDC,0,0,32,32,hMemDC,0,0,SRCCOPY)

このような感じで書いてみました
すみませんが、添削をお願いします

A 回答 (3件)

どこまで意図したとおりの画像になっているのかを確認してみましょう



1) オリジナル画像のビットマップ
2) 背景部分が白、マスク部分が黒の白黒ビットマップ
3) 背景部分が黒、マスク部分が白の白黒ビットマップ
4) 1と3のANDを取った 背景が黒のビットマップ
の4種類が必要になります

実際の描画に必要なのは 2と4ですが ・・・

dim hBmpORG as HBITMAP, hOrgDC as HDC ' オリジナル用
dim hBmpMsk as HBITMAP, hMskDC as HDC ' マスク用
dim hBmpInv as HBITMAP, hInvDC as HDC ' 反転用
dim hBmpImg as HBITMAP, hImgDC as HDC ' 描画用
dim hBmp(3) as HBITMAP
dim cl as DWord, clOld as DWord

' オリジナル
hBmpOrg = LoadBitmap( GetModuleHandle(0), IDB_BITMAP1 )
hOrgDC = CreateCompatibleDC( hDC )
hBmp(0) = SelectObject( hOrgDC, hBmpOrg )
' デバッグ
BitBlt( hDC, 33*1, 0, 32, 32, hOrgDC, 0, 0, SRCCOPY )

' マスク用
hBmpMsk = CreateBitmap( 32, 32, 1, 1, 0 )
hMskDC = CreateCompatibleDC( hDC )
hBmp(1) = SelectObject( hMskDC, hBmpMsk )
cl = GetPixel( hOrgDC, 0, 0 )
clOld = SetBkColor( hOrgDC, cl )
BitBlt( hMskDC, 0, 0, 32, 32, hOrgDC, 0, 0, SRCCOPY )
SetBkColor( hOrgDC, clOld )
' デバッグ
BitBlt( hDC, 33*2, 0, 32, 32, hMskDC, 0, 0, SRCCOPY )

' 反転用
hBmpInv = CreateBitmap( 32, 32, 1, 1, 0 )
hInvDC = CreateCompatibleDC( hDC )
hBmp(2) = SelectObject( hInvDC, hBmpInv )
BitBlt( hInvDC, 0, 0, 32, 32, hMskDC, 0, 0, NOTSRCCOPY )
' デバッグ
BitBlt( hDC, 33*3, 0, 32, 32, hInvDC, 0, 0, SRCCOPY )

' 描画用
hBmpImg = CreateCompatibleBitmap( hBmpOrg, 32, 32 )
hImgDC = CreateCompatibleDC( hDC )
hBmp(3) = SelectObject( hImgDC, hBmpImg )
BitBlt( hImgDC, 0, 0, 32, 32, hOrgDC, 0, 0, SRCCOPY )
BitBlt( hImgDC, 0, 0, 32, 32, hInvDC, 0, 0, SRCAND )
' デバッグ
BitBlt( hDC, 33*4, 0, 32, 32, hImgDC, 0, 0, SRCCOPY )

' 画面への描画
' マスク用で 画像部分だけ黒抜きにする
BitBlt( hDC, 0, 0, 32, 32, hMskDC, 0, 0, SRCAND )
' 描画用で 画像部分だけを追加する
BitBlt( hDC, 0, 0, 32, 32, hImgDC, 0, 0, SRCPAINT )

' 後始末
SelectObject( hOrgDC, hBmp(0) )
SelectObject( hMskDC, hBmp(1) )
SelectObject( hInvDC, hBmp(2) )
SelectObject( hImgDC, hBmp(3) )

DeleteDC( hOrgDC )
DeleteDC( hMskDC )
DeleteDC( hInvDC )
DeleteDC( hImgDC )

DeleteObject( hBmpOrg )
DeleteObject( hBmpMsk )
DeleteObject( hBmpInv )
DeleteObject( hBmpImg )

といった具合で ・・・
    • good
    • 0
この回答へのお礼

完璧なご回答ありがとうございます!

もうひとつ、教えていただきたいのですが、
最後の部分でhDCに画像をコピーしていますが、
ここを変数に格納するにはどのようにすればいいのでしょうか?

透過した画像を常に別の変数に入れておき、
いつでもBitBltでコピーできたらな・・・と思います。
ゲームを作っていますので、処理が追いつかないと、
時々ちらちらとモノクロ部分が浮き出てしまいますので・・・

よろしくお願いします

お礼日時:2009/09/03 19:28

バッファ画面が必要なら HDCとHBITMAPを質問のように構築しておきます


HDCにHBITMAPをSelectObjectで接続しておきます

先の回答の最後のhDCへの描画部分を 上記で生成したHDCに対して行えばいいでしょう

私なら hMskDC,hImgDC, hBmpMsk,hBmpImgと接続復元のためのHBITMAP2個を外部変数などにしておいて
Createイベントで生成、接続
Destroyイベントで後始末
として構築するでしょうね ・・・
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

質問の書き方が悪かったです。
関数のような感じにして、画像を取り出したいのです。
最後にhDCにコピーしたものを関数の戻り値に引き渡して、
使ってみたのですが、無理でした。
やはり、ビットマップとDCを作っておかないといけないみたいですね・・・

この場合、やり方などは存在するのでしょうか。
透過処理を施したイメージをそのまま使いまわせるように・・・
というのは、無理でしょうか。

関数で、描写したもの(DC)を引き渡して使う以外に
方法などがあれば、教えていただけないでしょうか
お願いします

お礼日時:2009/09/04 16:34

ひとつの関数の戻り値として複数のオブジェクトを返すといった仕様はあまり好ましくないかも知れません



DCやBITMAPをメンバーに持つ構造体として返すのであれば可能かもしれませんが ・・・

さほど大きくないシステムであればグローバル変数でとってしまう方が管理がしやすいかもしれませんよ

今回の場合なら オリジナルからマスクを生成する関数と
マスクとオリジナルから背景を抜いた描画用を生成する関数に分けたほうがいいかもしれませんね

Function MakeMask( ByVal hBmp as HBITMAP ) as HBITMAP
  dim hDC as HDC, hTemp As HDC, hDest as HDC
  dim hBmpTemp as HBITMAP, dummy(1) as HBITMAP
  dim bmp as BITMAP
  hDC = GetDC( NULL )
  hTemp = CreateCompatibleDC( hDC )
  hDest = CreateCompatibleDC( hDC )
  ReleaseDC( NULL, hDC )
  ' 元画像の情報の取得
  GetObject( hBmp, len( bmp ), bmp )
  ' モノクロBITMAPの生成
  hBmpTemp = CreateCompatibleBitmap( hDest, bmp.bmWidth, bmp.bmHeight )
  dummy( 0 ) = SelectObject( hTemp, hBmp )
  dummy( 1 ) = SelectObject( hDest, hBmpTemp )
  SetBkColor( hTemp, GetPixel( hTemp, 0, 0 ) )
  ' 背景マスクの生成
  BitBlt( hDest, 0, 0, bmp.bmWidth, bmp.bmHeight、hTemp, 0, 0, SRCCOPY )
  ' HBITMAPの切り離し
  SelectObject( hTemp, dummy(0) )
  SelectObject( hDest, dummy(1) )
  ' HDCの後始末
  DeleteDC( hTemp )
  DeleteDC( hDest )
  ' 呼び出し元への返り値
  MakeMask = hBmpTemp
End Function
といった具合で HBITMAPを取得するようにすればいいと思います

呼び出し側では
Dim hBmpMask as HBITMAP
Dim hBmp as HBITMAP
hBmp = LoadBitmap( GetModuleHandle( 0 ), IDB_BITMAP1 )
hBmpMask = MakeMask( hBmp )
といった具合です

後始末などは
DeleteObject( hBmpMask )

同様に 描画用のイメージも作成できますよ
マスクと反転用をDC選択し NOTSRCCOPYで反転コピー
オリジナルと戻り値用をDCに選択して SRCCOPY
戻り値用と反転を選択して SRCAND
といった具合でしょう ・・・
    • good
    • 0
この回答へのお礼

それです!
ありがとうございました!!
無事出来ました。
勉強になりました

お礼日時:2009/09/05 19:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!