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)
このような感じで書いてみました
すみませんが、添削をお願いします
No.1
- 回答日時:
どこまで意図したとおりの画像になっているのかを確認してみましょう
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 )
といった具合で ・・・
完璧なご回答ありがとうございます!
もうひとつ、教えていただきたいのですが、
最後の部分でhDCに画像をコピーしていますが、
ここを変数に格納するにはどのようにすればいいのでしょうか?
透過した画像を常に別の変数に入れておき、
いつでもBitBltでコピーできたらな・・・と思います。
ゲームを作っていますので、処理が追いつかないと、
時々ちらちらとモノクロ部分が浮き出てしまいますので・・・
よろしくお願いします
No.2
- 回答日時:
バッファ画面が必要なら HDCとHBITMAPを質問のように構築しておきます
HDCにHBITMAPをSelectObjectで接続しておきます
先の回答の最後のhDCへの描画部分を 上記で生成したHDCに対して行えばいいでしょう
私なら hMskDC,hImgDC, hBmpMsk,hBmpImgと接続復元のためのHBITMAP2個を外部変数などにしておいて
Createイベントで生成、接続
Destroyイベントで後始末
として構築するでしょうね ・・・
ご回答ありがとうございます。
質問の書き方が悪かったです。
関数のような感じにして、画像を取り出したいのです。
最後にhDCにコピーしたものを関数の戻り値に引き渡して、
使ってみたのですが、無理でした。
やはり、ビットマップとDCを作っておかないといけないみたいですね・・・
この場合、やり方などは存在するのでしょうか。
透過処理を施したイメージをそのまま使いまわせるように・・・
というのは、無理でしょうか。
関数で、描写したもの(DC)を引き渡して使う以外に
方法などがあれば、教えていただけないでしょうか
お願いします
No.3ベストアンサー
- 回答日時:
ひとつの関数の戻り値として複数のオブジェクトを返すといった仕様はあまり好ましくないかも知れません
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
といった具合でしょう ・・・
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- Visual Basic(VBA) EXCEL VBAにて動的にCheckBOXを複数作成し、同BOXにイベントを追加したい 1 2023/03/16 07:05
- Excel(エクセル) EXCELのグラフを画像(JPG形式)で保存、通常実行がうまく行かない。ステップインはうまく行く 3 2022/08/30 12:06
- Visual Basic(VBA) エクセルのマクロを使ってメールを送る方法について教えてください 2 2022/03/29 01:36
- Visual Basic(VBA) このVBAでExcelアプリケーションを作成は必要ですか? 3 2023/07/19 21:13
- Excel(エクセル) 【マクロ】スクショ印刷がうまく動かない件 5 2022/12/06 17:37
- Excel(エクセル) マクロで行を追加、削除すると行位置がずれますが、解決方法はありませんか?。 5 2022/05/28 16:03
- Visual Basic(VBA) VBAでoutlook365が起動しません。 4 2022/08/25 13:31
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
PCで「使用可能な場合はグラフ...
-
MFCのタイマーのつかい方を教え...
-
NVIDIAのシェーダーキャッシュ
-
[VB.net] DataGridViewの列ヘッ...
-
SHGetFileInfoでアイコンが取得...
-
C#のタブコントロールについて...
-
VBAにGDI+を参照させる方法
-
この二つの違いは・・・?
-
ウインドウサイズを変更しても...
-
アプリケーションのデザイン
-
VB6,リストボックスの特定行の...
-
最前面に無理やりフォームを持...
-
TextBoxに文字を書いても表示さ...
-
VB.netでのライン描画方法がわ...
-
OpenOffice Calcで株価チャート...
-
MFCでOnPaintのタイミング
-
ドローソフトのダブルバッファ...
-
CS_HREDRAW|CS_VREDRAWについて
-
ClistBoxでオーナードローがよ...
-
扇形などを描く方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VB6,リストボックスの特定行の...
-
[VB.net] DataGridViewの列ヘッ...
-
NVIDIAのシェーダーキャッシュ
-
MFCでOnPaintのタイミング
-
TextBoxに文字を書いても表示さ...
-
word
-
UpdateData( FALSE); による文...
-
VC++プログラムをつかったBMP画...
-
InvalidateRectの使い方について
-
OneNote 2010 文字と描画がずれる
-
StretchBlt関数について
-
C# ラバーバンドの描画を快適に...
-
エクセルでガンチャートを作成...
-
C++にて、塗りつぶされた円を描...
-
VBAにGDI+を参照させる方法
-
GDI+で高速な描画
-
MFC DrawText 背景色とフォント
-
FlexGridの一部のみ表示を更新...
-
MFCのタイマーのつかい方を教え...
-
Labelの文字をスクロールする際...
おすすめ情報