今回、私が直面している問題は、
void Draw_Char( HDC hdc, int char_num, int pos, int dir )
@param
[tab=30]hdc[tab=30]表示したいデバイスコンテキストのHDC
[tab=30]char_num[tab=30]読み込む画像の変更用変数
[tab=30]pos[tab=30]画像を表示する位置の変更用変数
[tab=30]dir[tab=30]画像を表示する際の非ミラー・ミラー変更用の変数
のような、画像を表示する関数の中身として
① LoadImage()で外部ファイルからBITMAPイメージ読み込む。
② dir の値がミラーを求める場合、仮のメモリデバイスコンテキスト hdc_mem2 を作成して、まずはここに SelectObject()で読み込んだイメージを割り当てる。
③ StretchBlt()で仮のメモリデバイスコンテキスト hdc_mem2 に割り当てられたイメージを、ミラーして本命のメモリデバイスコンテキスト hdc_mem に転送。
④この時点で、不要になったと思われる仮のメモリデバイスコンテキストは DeleteDC() で破棄。
⑤ TransparentBlt() で hdc_mem に転送されているはずのイメージを、背景透過色を指定して、表示用のデバイスコンテキスト hdc に転送。
このような流れを想定してDraw_Char()を組み立ててみたところ、非ミラー時には正常に画像が表示されるのですが、ミラー時には画像が表示されません。
おそらくミラー時に挟んでいる StretchBlt() を使ったイメージの転送が正しくないのだと思いますが、現状この代替となるイメージのミラー方法を私は知りません。
今回はDxLib等を使用せずに、生のWindowsAPIの組み合わせで解決することに興味があること。
また、透過用のマスクイメージを用意、または自動作成して、論理的に透過するといった仕組み以外での解決を希望しています。
現在の進展・・・YuO様からご指摘いただいた、ミラー時にビットマップが明示的に割り当てられていないという点について検討した結果、問題を解決することが出来ました。本当にありがとうございました!
以下、現在の問題の関数部分です。
/*
画像の表示関数
@param hdc 画像を表示するHDC
char_num 画像の識別番号
pos 画像の表示位置
dir 画像の表示方向
*/
void Draw_Char( HDC hdc, int char_num, int pos, int dir )
{
static int bmpw, bmph, pos_x, pos_y;
static HDC hdc_mem;
static HBITMAP hBmp;
BITMAP bmp_info;
switch( char_num )
{
case 1:
hBmp = ( HBITMAP )LoadImage( hInst, // インスタンスハンドル
TEXT("otama1.bmp"), // イメージの名前
IMAGE_BITMAP, // イメージタイプ
0, // 幅
0, // 高さ
LR_LOADFROMFILE ); // 読み込みオプション
break;
case 2:
hBmp = ( HBITMAP )LoadImage( hInst, // インスタンスハンドル
TEXT("otama2.bmp"), // イメージの名前
IMAGE_BITMAP, // イメージタイプ
0, // 幅
0, // 高さ
LR_LOADFROMFILE ); // 読み込みオプション
break;
default:
break;
}
GetObject( hBmp, ( int )sizeof( bmp_info ), &bmp_info );
bmpw = bmp_info.bmWidth;
bmph = bmp_info.bmHeight;
hdc_mem = CreateCompatibleDC( NULL );
if( dir == 1 )
{
SelectObject( hdc_mem, hBmp );
}
/*
質問解決に関わる修正部分。(修正後を後述します)
ここから~
*/
else if( dir == 2 )
{
static HDC hdc_mem2;
hdc_mem2 = CreateCompatibleDC( NULL );
SelectObject( hdc_mem2, hBmp );
// 仮のメモリDC(hdc_mem2)に割り当てたイメージを
// 本命のメモリDC(hdc_mem)に転送 (しているつもりです。おそらくこれが正しくない)
StretchBlt( hdc_mem, // 転送先
bmpw, // 転送先x座標
0, // 転送先y座標
(-bmpw), // 転送先長方形の幅
bmph, // 転送先長方形の高さ
hdc_mem2, // 転送元
0, // 転送元x座標
0, // 転送元y座標
bmpw,
bmph,
SRCCOPY ); // ラスタオペレーションコード
DeleteDC( hdc_mem2 );
}
/*
~ここまで、修正部分
*/
switch( pos )
{
case 1:
pos_x = 0;
pos_y = 0;
break;
case 2:
pos_x = 150;
pos_y = 0;
break;
case 3:
pos_x = 300;
pos_y = 0;
break;
default:
break;
}
TransparentBlt( hdc, // 転送先
pos_x, // 転送先x座標
pos_y, // 転送先y座標
bmpw, // 転送先長方形の幅
bmph, // 転送先長方形の高さ
hdc_mem, // 転送元
0, // 転送元x座標
0, // 転送元y座標
bmpw,
bmph,
RGB( 200, 10, 10 ) ); // ラスタオペレーションコード
DeleteDC( hdc_mem );
DeleteObject( hBmp );
}
else if( dir == 2 )
{
HBITMAP hBmp2; // hdc_mem2と互換性のあるビットマップ用
HDC hdc_mem2;
hdc_mem2 = CreateCompatibleDC( NULL );
SelectObject( hdc_mem2, hBmp );
hBmp2 = CreateCompatibleBitmap( hdc_mem2, bmpw, bmph ); // hdc_mem2と互換性のあるビットマップの作成
SelectObject( hdc_mem, hBmp2 ); // hdc_memにhBmp2を割り当て
StretchBlt( hdc_mem, // 転送先
(bmpw - 1), // 転送先x座標
0, // 転送先y座標
(- bmpw), // 転送先長方形の幅
bmph, // 転送先長方形の高さ
hdc_mem2, // 転送元
0, // 転送元x座標
0, // 転送元y座標
bmpw,
bmph,
SRCCOPY ); // ラスタオペレーションコード
DeleteDC( hdc_mem2 );
DeleteObject( hBmp2 ); // hBmp2の破棄
}
softya様
マルチポストとなってしまった件、配慮と確認に欠けてしまい、本当に申し訳ありません。
現状、あちらは追記ができない状態で相互リンクが不可能であるため、大変身勝手な行いとなってしまいますが、あちらの質問を削除させていただきます。