ビットマップの背景を透過して描画するには
ビットマップの背景を透過するには、マスク処理を行います。
背景の上にスプライトを描画したい際の、お決まりの処理です。
わたしの目的はオーナードローコントロール作成時の基底クラスとしての作成でした。
背景を透過するには、
(1) マスクを作成。
(2) 背景色を黒にしたビットマップ作成。
(3) マスクをSRCANDで、背景黒ビットマップをSRCPAINTで重ねて描画。
という処理を行います。詳細はコメントも記載していますので、描画クラス TTransparentBitmap のソースコードをご参照ください。
サンプルは下記になります。"C:\Windows\winnt.bmp"の背景を透過してデスクトップに描画します。
■■■ transparent_bmp プロジェクト
■ stdafx.h
#ifndef _H_YUSU_STDAFX
#define _H_YUSU_STDAFX
#include <windows.h>
#include <tchar.h>
#include "myassert.h"
#endif
|
■ myassert.h
//----------------------------------------------------------------------
// ASSERT マクロと実装
//----------------------------------------------------------------------
#ifndef _H_YUSU_ASSERT
#define _H_YUSU_ASSERT
//----------------------------------------------------------------------
// ASSERT マクロ定義
#ifndef ASSERT
#ifdef _DEBUG
#include <crtdbg.h>
#define ASSERT(f) \
_ASSERTE(f)
#else
#define ASSERT(f) \
NULL
#endif
#endif
//----------------------------------------------------------------------
#endif
|
■ transparent_bmp.h
//----------------------------------------------------------------------
// 透過ビットマップ 描画クラス
//----------------------------------------------------------------------
#ifndef _H_YUSU_TRANSPARENT_BITMAP
#define _H_YUSU_TRANSPARENT_BITMAP
//----------------------------------------------------------------------
class TTransparentBitmap
{
protected:
// ウィンドウハンドル
HWND m_hOwnerWnd;
// ビットマップハンドル
HBITMAP m_hBitmap;
// 透過色
COLORREF m_clrBackground;
// マスク作成
HBITMAP CreateMask ( HBITMAP hBitmap );
// 背景色を黒にしたビットマップ作成
HBITMAP CreateBlackBackgroundBitmap ( HBITMAP hSrcBitmap,
HBITMAP hMaskBitmap );
// 背景色を黒にしたビットマップ と マスクの組み合わせ描画
BOOL InternalDraw ( HDC hdc,
long nX,
long nY,
HBITMAP hMaskBitmap,
HBITMAP hBlackBkgndBitmap,
DWORD dwMaskRop = SRCAND,
DWORD dwBlackBkgndRop = SRCPAINT );
// 背景色を黒にしたビットマップ と マスクの組み合わせ伸縮描画
BOOL InternalDrawStretch ( HDC hdc,
long nX,
long nY,
long nWidth,
long nHeight,
HBITMAP hMaskBitmap,
HBITMAP hBlackBkgndBitmap,
DWORD dwMaskRop = SRCAND,
DWORD dwBlackBkgndRop = SRCPAINT );
// コピーコンストラクタ 補助関数
virtual void InternalCopyConstructor ( void *pvObj );
// 代入演算子 補助関数
virtual void InternalSubstitutionOperator ( void *pvObj );
public:
// コンストラクタ ( m_hOwnerWnd は NULL 許可 )
TTransparentBitmap ();
TTransparentBitmap ( HWND hOwnerWnd );
TTransparentBitmap ( HWND hOwnerWnd, HBITMAP hBitmap, COLORREF clrBackground );
// デストラクタ
virtual ~TTransparentBitmap ();
// コピーコンストラクタ
TTransparentBitmap ( const TTransparentBitmap &obj );
// 代入演算子
TTransparentBitmap operator = ( const TTransparentBitmap obj );
// ウィンドウハンドル変更
void SetWindowHandle ( HWND hOwnerWnd );
// ウィンドウハンドル取得
HWND GetWindowHandle () const;
// ビットマップハンドル アタッチ
HBITMAP Attach ( HBITMAP hBitmap );
// ビットマップハンドル デタッチ
HBITMAP Detach ();
// 透過色指定
void SetBackgroundColor ( COLORREF clrBackground );
// 透過色取得
COLORREF GetBackgroundColor () const;
// 描画
virtual BOOL Draw ( long nX, long nY );
// DC指定描画
virtual BOOL Draw ( HDC hdc, long nX, long nY );
// 伸縮描画
virtual BOOL DrawStretch ( long nX, long nY, long nWidth, long nHeight );
// DC指定伸縮描画
virtual BOOL DrawStretch ( HDC hdc, long nX, long nY, long nWidth, long nHeight );
};
//----------------------------------------------------------------------
#endif
|
■ transparent_bmp.cpp
#include "stdafx.h"
#include "transparent_bmp.h"
//----------------------------------------------------------------------
// protected メンバ
//----------------------------------------------------------------------
// マスク作成
HBITMAP TTransparentBitmap::CreateMask ( HBITMAP hBitmap )
{
ASSERT ( hBitmap != NULL );
HBITMAP hMask;
HDC hSrcDc;
HDC hDstDc;
HBITMAP hSrcDcPrevBitmap;
HBITMAP hDstDcPrevBitmap;
// マスク用ビットマップ入れ物 作成
BITMAP bm;
HDC hClientDC = GetDC ( m_hOwnerWnd );
GetObject ( hBitmap, sizeof ( BITMAP ), &bm );
hMask = CreateBitmap ( bm.bmWidth,
bm.bmHeight,
1,
1,
NULL );
ASSERT ( hMask != NULL );
// 下準備
hSrcDc = CreateCompatibleDC ( hClientDC );
hSrcDcPrevBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hSrcDc, hBitmap ) );
hDstDc = CreateCompatibleDC ( hClientDC );
hDstDcPrevBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hDstDc, hMask ) );
// 作成
SetBkColor ( hSrcDc, m_clrBackground );
BitBlt ( hDstDc,
0,
0,
bm.bmWidth,
bm.bmHeight,
hSrcDc,
0,
0,
SRCCOPY );
// 後始末
SelectObject ( hSrcDc, hSrcDcPrevBitmap );
DeleteDC ( hSrcDc );
SelectObject ( hDstDc, hDstDcPrevBitmap );
DeleteDC ( hDstDc );
ReleaseDC ( m_hOwnerWnd, hClientDC );
return hMask;
}
// 背景色を黒にしたビットマップ作成
HBITMAP TTransparentBitmap::CreateBlackBackgroundBitmap ( HBITMAP hSrcBitmap,
HBITMAP hMaskBitmap )
{
HDC hdc = GetDC ( m_hOwnerWnd );
HDC hMaskDC = CreateCompatibleDC ( hdc );
HBITMAP hOldMaskBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hMaskDC, hMaskBitmap ) );
BITMAP maskBitmap;
GetObject ( hMaskBitmap, sizeof ( BITMAP ), &maskBitmap );
BitBlt ( hMaskDC,
0,
0,
maskBitmap.bmWidth,
maskBitmap.bmHeight,
hMaskDC,
0,
0,
NOTSRCCOPY );// マスクを反転します(背景が黒になる)
HDC hSrcMemDC = CreateCompatibleDC ( hdc );
HBITMAP hOldSrcBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hSrcMemDC, hSrcBitmap ) );
// hSrcBitmap をコピーした 作業用 HBITMAP である hBitmap を作成
HDC hMemDC = CreateCompatibleDC ( hdc );
HBITMAP hBitmap = CreateCompatibleBitmap ( hdc,
maskBitmap.bmWidth,
maskBitmap.bmHeight );
HBITMAP hOldBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hMemDC, hBitmap ) );
BitBlt ( hMemDC,
0,
0,
maskBitmap.bmWidth,
maskBitmap.bmHeight,
hSrcMemDC,
0,
0,
SRCCOPY );
// hSrcBitmap 関連を削除 ( hSrcBitmap 以外 )
SelectObject ( hSrcMemDC, hOldSrcBitmap );
DeleteDC ( hSrcMemDC );
// マスク部分黒になるSprite作成
BitBlt ( hMemDC,
0,
0,
maskBitmap.bmWidth,
maskBitmap.bmHeight,
hMaskDC,
0,
0,
SRCAND );
// マスクを反転します(背景が黒になる)
BitBlt ( hMaskDC,
0,
0,
maskBitmap.bmWidth,
maskBitmap.bmHeight,
hMaskDC,
0,
0,
NOTSRCCOPY );
SelectObject ( hMaskDC, hOldMaskBitmap );
SelectObject ( hMemDC, hOldBitmap );
DeleteDC ( hMaskDC );
DeleteDC ( hMemDC );
ReleaseDC ( m_hOwnerWnd, hdc );
return hBitmap;
}
// 背景色を黒にしたビットマップ と マスクの組み合わせ描画
BOOL TTransparentBitmap::InternalDraw ( HDC hdc,
long nX,
long nY,
HBITMAP hMaskBitmap,
HBITMAP hBlackBkgndBitmap,
DWORD dwMaskRop,
DWORD dwBlackBkgndRop )
{
ASSERT ( hMaskBitmap != NULL );
ASSERT ( hBlackBkgndBitmap != NULL );
if ( hMaskBitmap == NULL || hBlackBkgndBitmap == NULL )
return FALSE;
// ビットマップの幅、高さ取得
BITMAP bm;
int nResult = GetObject ( hMaskBitmap, sizeof ( BITMAP ), &bm );
ASSERT ( nResult != 0 );
if ( nResult == 0 )
return FALSE;
// 作業用として メモリデバイスコンテキスト 作成
HDC hMemDC = CreateCompatibleDC ( hdc );
HBITMAP hOldMemBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hMemDC, hMaskBitmap ) );
BitBlt ( hdc,
nX,
nY,
bm.bmWidth,
bm.bmHeight,
hMemDC,
0,
0,
dwMaskRop );
SelectObject ( hMemDC, hBlackBkgndBitmap );
BitBlt ( hdc,
nX,
nY,
bm.bmWidth,
bm.bmHeight,
hMemDC,
0,
0,
dwBlackBkgndRop );
SelectObject ( hMemDC, hOldMemBitmap );
// 削除
DeleteDC ( hMemDC );
return TRUE;
}
// 背景色を黒にしたビットマップ と マスクの組み合わせ伸縮描画
BOOL TTransparentBitmap::InternalDrawStretch ( HDC hdc,
long nX,
long nY,
long nWidth,
long nHeight,
HBITMAP hMaskBitmap,
HBITMAP hBlackBkgndBitmap,
DWORD dwMaskRop,
DWORD dwBlackBkgndRop )
{
ASSERT ( hMaskBitmap != NULL );
ASSERT ( hBlackBkgndBitmap != NULL );
if ( hMaskBitmap == NULL || hBlackBkgndBitmap == NULL )
return FALSE;
// ビットマップの幅、高さ取得
BITMAP bm;
int nResult = GetObject ( hMaskBitmap, sizeof ( BITMAP ), &bm );
ASSERT ( nResult != 0 );
if ( nResult == 0 )
return FALSE;
// 作業用として メモリデバイスコンテキスト 作成
HDC hMemDC = CreateCompatibleDC ( hdc );
HBITMAP hOldMemBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hMemDC, hMaskBitmap ) );
StretchBlt ( hdc,
nX,
nY,
nWidth,
nHeight,
hMemDC,
0,
0,
bm.bmWidth,
bm.bmHeight,
dwMaskRop );
SelectObject ( hMemDC, hBlackBkgndBitmap );
StretchBlt ( hdc,
nX,
nY,
nWidth,
nHeight,
hMemDC,
0,
0,
bm.bmWidth,
bm.bmHeight,
dwBlackBkgndRop );
SelectObject ( hMemDC, hOldMemBitmap );
// 削除
DeleteDC ( hMemDC );
return TRUE;
}
// コピーコンストラクタ 補助関数
void TTransparentBitmap::InternalCopyConstructor ( void *pvObj )
{
TTransparentBitmap *pObj = static_cast < TTransparentBitmap * > ( pvObj );
m_hOwnerWnd = pObj->m_hOwnerWnd;
m_clrBackground = pObj->m_clrBackground;
// hBitmap が NULL でないとき、同じイメージを作成する
if ( pObj->m_hBitmap != NULL )
{
HDC hdc = GetDC ( m_hOwnerWnd );
// 元
HDC hSrcMemDC = CreateCompatibleDC ( hdc );
HBITMAP hOldSrcBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hSrcMemDC, pObj->m_hBitmap ) );
// 先
BITMAP bm;
GetObject ( pObj->m_hBitmap, sizeof ( BITMAP ), &bm );
HDC hMemDC = CreateCompatibleDC ( hdc );
m_hBitmap = CreateCompatibleBitmap ( hdc,
bm.bmWidth,
bm.bmHeight );
HBITMAP hOldBitmap = reinterpret_cast < HBITMAP > ( SelectObject ( hMemDC, m_hBitmap ) );
// 描画
BitBlt ( hMemDC,
0,
0,
bm.bmWidth,
bm.bmHeight,
hSrcMemDC,
0,
0,
SRCCOPY );
SelectObject ( hSrcMemDC, hOldSrcBitmap );
SelectObject ( hMemDC, hOldBitmap );
// 先 関連 削除
DeleteDC ( hMemDC );
// 元 関連 削除
DeleteDC ( hSrcMemDC );
ReleaseDC ( m_hOwnerWnd, hdc );
}
else
m_hBitmap = NULL;
}
// 代入演算子 補助関数
void TTransparentBitmap::InternalSubstitutionOperator ( void *pvObj )
{
TTransparentBitmap *pObj = static_cast < TTransparentBitmap * > ( pvObj );
// すでに hBitmap があるときは 削除
if ( m_hBitmap != NULL )
DeleteObject ( m_hBitmap );
// あとはコピーコンストラクタと同じ
InternalCopyConstructor ( pObj );
}
//----------------------------------------------------------------------
// public メンバ
//----------------------------------------------------------------------
// コンストラクタ ( m_hOwnerWnd は NULL 許可 )
TTransparentBitmap::TTransparentBitmap ()
: m_hOwnerWnd ( NULL ),
m_hBitmap ( NULL ),
m_clrBackground ( 0 )
{
}
TTransparentBitmap::TTransparentBitmap ( HWND hOwnerWnd )
: m_hOwnerWnd ( hOwnerWnd ),
m_hBitmap ( NULL ),
m_clrBackground ( 0 )
{
}
TTransparentBitmap::TTransparentBitmap ( HWND hOwnerWnd, HBITMAP hBitmap, COLORREF clrBackground )
: m_hOwnerWnd ( hOwnerWnd ),
m_hBitmap ( hBitmap ),
m_clrBackground ( clrBackground )
{
ASSERT ( m_hBitmap != NULL );
}
// コピーコンストラクタ
TTransparentBitmap::TTransparentBitmap ( const TTransparentBitmap &obj )
{
InternalCopyConstructor ( const_cast < TTransparentBitmap * > ( &obj ) );
}
// 代入演算子
TTransparentBitmap TTransparentBitmap::operator = ( const TTransparentBitmap obj )
{
InternalSubstitutionOperator ( const_cast < TTransparentBitmap * > ( &obj ) );
return *this;
}
// デストラクタ
TTransparentBitmap::~TTransparentBitmap ()
{
if ( m_hBitmap != NULL )
DeleteObject ( m_hBitmap );
}
// ウィンドウハンドル変更
void TTransparentBitmap::SetWindowHandle ( HWND hOwnerWnd )
{
m_hOwnerWnd = hOwnerWnd;
}
// ウィンドウハンドル取得
HWND TTransparentBitmap::GetWindowHandle () const
{
return m_hOwnerWnd;
}
// ビットマップハンドル アタッチ
HBITMAP TTransparentBitmap::Attach ( HBITMAP hBitmap )
{
HBITMAP hBitmapBuffer = m_hBitmap;
m_hBitmap = hBitmap;
return hBitmapBuffer;
}
// ビットマップハンドル デタッチ
HBITMAP TTransparentBitmap::Detach ()
{
m_hBitmap = NULL;
return m_hBitmap;
}
// 透過色指定
void TTransparentBitmap::SetBackgroundColor ( COLORREF clrBackground )
{
m_clrBackground = clrBackground;
}
// 透過色取得
COLORREF TTransparentBitmap::GetBackgroundColor () const
{
return m_clrBackground;
}
// 描画
BOOL TTransparentBitmap::Draw ( long nX, long nY )
{
HDC hdc = GetDC ( m_hOwnerWnd );
BOOL bResult = Draw ( hdc, nX, nY );
ReleaseDC ( m_hOwnerWnd, hdc );
return bResult;
}
// DC指定描画
BOOL TTransparentBitmap::Draw ( HDC hdc, long nX, long nY )
{
ASSERT ( m_hBitmap != NULL );
if ( m_hBitmap == NULL )
return FALSE;
// ビットマップ情報取得
BITMAP bm;
GetObject ( m_hBitmap, sizeof ( BITMAP ), &bm );
// マスク作成
HBITMAP hMaskBitmap = CreateMask ( m_hBitmap );
ASSERT ( hMaskBitmap != NULL );
if ( hMaskBitmap == NULL )
return FALSE;
// 背景色が黒のビットマップ作成
HBITMAP hBlackBkgndBitmap = CreateBlackBackgroundBitmap ( m_hBitmap, hMaskBitmap );
ASSERT ( hBlackBkgndBitmap != NULL );
if ( hBlackBkgndBitmap == NULL )
{
DeleteObject ( hMaskBitmap );
return FALSE;
}
// 描画
BOOL bResult = InternalDraw ( hdc,
nX,
nY,
hMaskBitmap,
hBlackBkgndBitmap );
// 削除
DeleteObject ( hBlackBkgndBitmap );
DeleteObject ( hMaskBitmap );
return bResult;
}
// 伸縮描画
BOOL TTransparentBitmap::DrawStretch ( long nX, long nY, long nWidth, long nHeight )
{
HDC hdc = GetDC ( m_hOwnerWnd );
BOOL bResult = DrawStretch ( hdc,
nX,
nY,
nWidth,
nHeight );
ReleaseDC ( m_hOwnerWnd, hdc );
return bResult;
}
// DC指定伸縮描画
BOOL TTransparentBitmap::DrawStretch ( HDC hdc, long nX, long nY, long nWidth, long nHeight )
{
ASSERT ( m_hBitmap != NULL );
if ( m_hBitmap == NULL )
return FALSE;
// ビットマップ情報取得
BITMAP bm;
GetObject ( m_hBitmap, sizeof ( BITMAP ), &bm );
// マスク作成
HBITMAP hMaskBitmap = CreateMask ( m_hBitmap );
ASSERT ( hMaskBitmap != NULL );
if ( hMaskBitmap == NULL )
return FALSE;
// 背景色が黒のビットマップ作成
HBITMAP hBlackBkgndBitmap = CreateBlackBackgroundBitmap ( m_hBitmap, hMaskBitmap );
ASSERT ( hBlackBkgndBitmap != NULL );
if ( hBlackBkgndBitmap == NULL )
{
DeleteObject ( hMaskBitmap );
return FALSE;
}
// 描画
BOOL bResult = InternalDrawStretch ( hdc,
nX,
nY,
nWidth,
nHeight,
hMaskBitmap,
hBlackBkgndBitmap );
// 削除
DeleteObject ( hBlackBkgndBitmap );
DeleteObject ( hMaskBitmap );
return bResult;
}
|
■ main.cpp
#include "stdafx.h"
#include "transparent_bmp.h"
int WINAPI _tWinMain ( HINSTANCE hThisInstance,
HINSTANCE,
_TCHAR *,
int )
{
// "C:\\Windows\\winnt.bmp" を読み込む
HBITMAP hBitmap;
hBitmap = reinterpret_cast < HBITMAP > ( LoadImage ( hThisInstance,
_TEXT ( "C:\\Windows\\winnt.bmp" ),
IMAGE_BITMAP,
0,
0,
LR_DEFAULTSIZE | LR_LOADFROMFILE ) );
TTransparentBitmap transparentBitmap;
// 透過色を黒にする
COLORREF clrrefTransparent = 0x00000000;
transparentBitmap.SetBackgroundColor ( clrrefTransparent );
// hBitmapを設定
transparentBitmap.Attach ( hBitmap );
// デスクトップのDC取得
HDC hDesktopDC;
hDesktopDC = GetDC ( NULL );
// デスクトップに描画
transparentBitmap.Draw ( hDesktopDC, 0, 0 );
// デスクトップのDC解放
ReleaseDC ( NULL, hDesktopDC );
// hBitmapはTTransparentBitmapのデストラクタで自動削除
return 0;
}
|
|