2016-09-09 19 views
0

STM_IMAGEをビットマップでコントロールに送信してイメージを設定している静的コントロールがあります。これは正常に動作しますが、私はビットマップが透明な背景を持つことを望みます。 (これはそうSTM_SETIMAGEを使用する前のビットマップの透明度の設定

case WM_CREATE: 
{ 
    HWND newGameText = CreateWindowW(
     L"STATIC", 
     L"", 
     WS_VISIBLE | WS_CHILD | SS_BITMAP | SS_NOTIFY, // Styles 
     150,   // x position 
     150,   // y position 
     74,  // width 
     24,  // height 
     hWnd,  // Parent window 
     (HMENU)ID_BUTTONNEWGAME, 
     (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
     NULL);  // Pointer not needed. 
} 
break; 

私がコントロールの特定の位置にビットマップをコピーする必要があります:

case WM_PAINT: 
{ 
    HBITMAP hbmBmp, hbmMask; 
    BITMAP bm; 
    PAINTSTRUCT ps; 

    HDC hdc = BeginPaint(hWnd, &ps); 
    HWND hCtrl = GetDlgItem(hWnd, ID_BUTTONNEWGAME); 
    hbmBmp = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_NEWGAMEBUTTONBITMAP)); 
    GetObject(hbmBmp, sizeof(BITMAP), &bm); 
    hbmMask = CreateBitmapMask(hbmBmp, RGB(0, 0, 0)); 
    HDC hDCMem = CreateCompatibleDC(hdc); 
    HDC hDCMem2 = CreateCompatibleDC(hdc); 
    HDC hdcResult = CreateCompatibleDC(hdc); 

    SelectObject(hDCMem, hbmMask); 
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCAND); 

    SelectObject(hDCMem, hbmBmp); 
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCPAINT); 

    // At this point I can see the bitmap with a transparent background at (0,0) 
    // The following code attempts to copy from hdc into a memory DCand to form a new bitmap 
    //that I use in the STM_SETIMAGE message 

    HBITMAP newBitmap = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight); // create blank bitmap 
    SelectObject(hdcResult, newBitmap); // store in memory DC 
    BitBlt(hdcResult, 0, 0, bm.bmWidth, bm.bmHeight, hdc, 0, 0, SRCCOPY); // copy from hdc to memory DC 

    // This line is just for checking that hdcResult contains the correct data 
    // It copies back from the memory DC into hdc to the right of the original bitmap 
    // I now see two bitmaps with transparent bitmaps next to each other as I expected 
    BitBlt(hdc, bm.bmWidth, 0, bm.bmWidth, bm.bmHeight, hdcResult, 0, 0, SRCCOPY); 
    EndPaint(hWnd, &ps); 

    // sending this does not set the bitmap on the static control 
    // I do not see anything where the control should be 
    SendMessage(hCtrl, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)newBitmap); 
} 
break; 

静的コントロールは、次のコードでSS_BITMAPスタイルで作成されています。私は、次のコードを持っています私は何かを完全に不可能/愚かなことをしていますか?

+0

私は、使用後にデバイスのコンテキストも削除する必要があります。 – Paul

+0

(アルファ)透明のビットマップを作成していません。 'BitBlt'への最初の2回の呼び出しは、マスクされていないピクセルに書き込むだけで、透明度の**錯覚**を作成します。いったん終了すると、まだ変更されていないピクセルは背景色を持ちます。透明化したい場合は、[STM_SETIMAGE](https://msdn.microsoft.com/en-us/library/windows/desktop/bb760782.aspx)と 'IMAGE_ICON'を使用してください。アイコンは透明度をサポートしています(PNGサポートの紹介ではアルファ透明度さえも可能です)(https://blogs.msdn.microsoft.com/oldnewthing/20101022-00/?p=12473))。 – IInspectable

+0

ありがとうございますが、私はボタン上に何も表示されていません。透過性のないビットマップさえありません。 OPを編集してより明確にする。 – Paul

答えて

-1

私はコントロールを作るとは思わないSS_BITMAPそしてWM_PAINTメッセージを処理することは意味があります。すべてのペイントリクエスト(WM_PAINTメッセージ)に応答してSTM_SETIMAGEを送信する(つまりビットマップを表示して変更する)ことはかなり残酷ですか?そして、あなたが完了した後、あなたはすべてのもの(あなたが作成したDC &ビットマップとSTM_SETIMAGEメッセージ(コントロールに渡される前のビットマップ)によって返された値を削除する必要があります。

制御SS_BITMAPを作成し、STM_SETIMAGEを使用するか、それを作るのどちらかオーナー描画とWM_DRAWITEMメッセージを処理する。

ます。またTransparentBlt()機能をチェックすることをお勧めします。

 


 

ここでは、動作例のコードをいくつか追加します。シンプルで実装が簡単で、コードを少ししか書く必要がありません。オーナーが描いたケースは実際に透明な領域を持つビットマップを描画します。すべては旧式のGDI(GDI +ではない)機能を使用して行われます。

  • IDC_IMG1::私は別の方法で実装3つの静的コントロールとの対話、作成この例では

    SS_BITMAPスタイルを、リソースファイルに設定された画像と
  • IDC_IMG2SS_BITMAP最初にイメージがないスタイル、STM_SETIMAGEメッセージで設定されたイメージ
  • IDC_IMG3SS_OWNERDRAWスタイル、透明な領域

 

リソースファイルの内容をビットマップをdislpaying:

IDB_BITMAP1 BITMAP "Image1.bmp" 
. 
. 
// Dialog Items 
CONTROL IDB_BITMAP1,IDC_IMG1,"Static",SS_BITMAP,7,7,136,126,WS_EX_CLIENTEDGE 
CONTROL "",IDC_IMG2,"Static",SS_BITMAP,154,7,17,15,WS_EX_CLIENTEDGE 
CONTROL "",IDC_IMG3,"Static",SS_OWNERDRAW,301,7,136,123,WS_EX_CLIENTEDGE 

  ソースコード:

// Resources 
HBITMAP hBitmap = NULL; 
int bmpW, bmpH; 

INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
     case WM_INITDIALOG: 
      if (!hBitmap) // Initialize resources if not initialized already 
      { 
       BITMAP bmp; 
       hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1)); 
       GetObject(hBitmap, sizeof(bmp), &bmp); 
       bmpW = bmp.bmWidth; 
       bmpH = bmp.bmHeight; 
      } 
      // Set bitmap in IDC_IMG2 
      SendDlgItemMessage(hDlg, IDC_IMG2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); 
      break; 
     case WM_DRAWITEM: 
      if (wParam==IDC_IMG3) // Draw transparent bitmap in IDC_IMG3 
      { 
       LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam; 
       HDC hMem = CreateCompatibleDC(lpDIS->hDC); 
       HGDIOBJ hOldBmp = SelectObject(hMem, hBitmap); 
       TransparentBlt(lpDIS->hDC, 0, 0, bmpW, bmpH, hMem, 0, 0, bmpW, bmpH, RGB(255,255,255)); 
       SelectObject(hMem, hOldBmp); 
       return TRUE; 
      } 
      break; 
     case WM_COMMAND: 
      if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
       EndDialog(hDlg, LOWORD(wParam)); 
      break; 
    } 
    return FALSE; 
} 

結果は次のとおりです。 enter image description here

+0

これは問題を解決しません。静的コントロールのスタイルを 'SS_BITMAP'を含むように設定し、**親**の' WM_PAINT'を処理することに全く問題はありません。そして 'TransparentBlt'は存在しない問題を解決しようとします。さらに、透明なビットマップも生成されません。 – IInspectable

+0

まあ、私はあなたがここで言うすべてに同意しない。もちろん、SS_BITMAP静的コントロールをペイントするのは間違いです。これらのコントロールには関連するビットマップ(リソースファイルで定義されているか、またはSTM_SETIMAGEメッセージで割り当てられたもの)があるためです。彼らは自分自身をペイントするので、ペイントするのは何ですか?そして、イメージは各ペイント要求(実際には何のSTM_SETIMAGE)で変更されるべきですか?ダメダメダメ!!! TransparentBlt()は存在しない問題を解決しようとしますか?もちろん、それは存在します、そして、それは正確にOPが後にあるものです。 1回の呼び出しでも簡単にできます! –

+0

これは意見ではありません。問題のコードの目的は、オンザフライでビットマップを生成し、静的コントロールのイメージとして設定することです。 'WM_PAINT'ハンドラー**は静的コントロールをペイントしません(オーナーコントロールとして作成されていません)。 'WM_PAINT'ハンドラにビットマップを設定するのは理想的ではありません(' WM_INITDIALOG'がより適切でしょう)。しかし、適切なリソース管理があれば、間違っている必要はありません。 'TransparentBlt'は役に立ちません。問題のコードが静的なコントロールをレンダリングしていると、あなたはまだ仮定しています。そうではなく、それを推測するためのすべての情報がそこにあります。 – IInspectable

関連する問題