前提・実現したいこと
前回の質問:WinAPI AlphaBlendのDIB定義を参考に私なりに書いてみました。しかし背景の再描画がうまくいかない問題が解決できません。
下記のコードでWNDCLASSEX
で背景を(HBRUSH)WHITE_BRUSHとすると初期表示は
となりますがリサイズすると
周囲は再描画されないうえ、画像(透過の赤格子)がほかの画像(黄色の非透過)と重なっていない部分は背景の白ではなくおそらく黒とブレンドされます。
(HBRUSH)GRAY_BRUSHや(HBRUSH)BLACK_BRUSHの場合は正常にその背景色にブレンドされ、周囲の再描画もされます。
FillRect(hdc, &ps.rcPaint, WHITE_BRUSH);
でWM_PAINT内で塗れば正常には動きますが仕様等的に正しい使い方ではないのでしょうか?それともWM_PAINT内の解放等に誤りがあるのでしょうか?
コーディング上の指摘もありましたらお願いします。
該当のソースコード
C
1#define UNICODE 2 3#include <windows.h> 4#pragma comment(lib, "msimg32.lib") 5 6 7HINSTANCE hInst; 8 9LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 10 11const wchar_t CLASS_NAME[] = L"class name"; 12const wchar_t TITLE[] = L"Alpha transparent window"; 13 14struct ARGB 15{ 16 BYTE Blue; 17 BYTE Green; 18 BYTE Red; 19 BYTE Alpha; 20}; 21 22int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdline, int nCmdShow) { 23 UNREFERENCED_PARAMETER(hPrevInstance); 24 UNREFERENCED_PARAMETER(nCmdShow); 25 26 hInst = hInstance; 27 28 WNDCLASSEX wc = { 29 sizeof(WNDCLASSEX),CS_HREDRAW | CS_VREDRAW,WindowProc, 30 0,0,hInstance, 31 0,0,(HBRUSH)WHITE_BRUSH, 32 0,CLASS_NAME,0 }; 33 34 RegisterClassEx(&wc); 35 36 HWND hwnd = CreateWindowEx( 37 0, CLASS_NAME, TITLE, WS_OVERLAPPEDWINDOW, 38 CW_USEDEFAULT, CW_USEDEFAULT, 960, 540, 39 0, 0, hInstance, 0 40 ); 41 42 ShowWindow(hwnd, nCmdShow); 43 UpdateWindow(hwnd); 44 45 MSG msg = {}; 46 47 while (GetMessage(&msg, 0, 0, 0)) { 48 TranslateMessage(&msg); 49 DispatchMessageW(&msg); 50 } 51 52 return (int)msg.wParam; 53} 54 55LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 56 switch (uMsg) { 57 case WM_CREATE: 58 break; 59 60 case WM_PAINT: 61 { 62 PAINTSTRUCT ps; 63 HDC hdc = BeginPaint(hwnd, &ps); 64 65 //FillRect(hdc, &ps.rcPaint, WHITE_BRUSH); 66 67 BITMAPINFO bmpio; 68 69 bmpio.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 70 bmpio.bmiHeader.biWidth = 160; 71 bmpio.bmiHeader.biHeight = 90; 72 bmpio.bmiHeader.biPlanes = 1; 73 bmpio.bmiHeader.biBitCount = 32; 74 bmpio.bmiHeader.biCompression = BI_RGB; 75 bmpio.bmiHeader.biSizeImage = 160 * 90 * sizeof(ARGB); 76 77 DWORD *dib = (DWORD*)calloc(sizeof(DWORD) * 160 * 90, sizeof(sizeof(DWORD) * 160 * 90)); 78 79 for (int i = 0; i < 160; i++)for (int j = 0; j < 90; j++)dib[i + j * 160] = 0xffff00; 80 StretchDIBits( 81 hdc, 10, 10, 160, 90, 0, 0, 160, 90, dib, &bmpio, DIB_RGB_COLORS, SRCCOPY 82 ); 83 84 StretchDIBits( 85 hdc, 200, 200, 160*2, 90*2, 0, 0, 160, 90, dib, &bmpio, DIB_RGB_COLORS, SRCCOPY 86 ); 87 88 BITMAPINFO bmpi; 89 void* pv; 90 91 bmpi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 92 bmpi.bmiHeader.biWidth = 160; 93 bmpi.bmiHeader.biHeight = 90; 94 bmpi.bmiHeader.biPlanes = 1; 95 bmpi.bmiHeader.biBitCount = 32; 96 bmpi.bmiHeader.biCompression = BI_RGB; 97 bmpi.bmiHeader.biSizeImage = 160 * 90 * sizeof(ARGB); 98 99 HDC hdcimg = CreateCompatibleDC(hdc); 100 HBITMAP hbmp = CreateDIBSection(hdc, &bmpi, DIB_RGB_COLORS, &pv, NULL, 0); 101 SelectObject(hdcimg, hbmp); 102 103 GdiFlush(); 104 105 BYTE* pbits = reinterpret_cast<BYTE*>(pv); 106 for (size_t x = 0; x < 160; x++) 107 { 108 for (size_t y = 0; y < 90; y++) 109 { 110 ARGB* line = reinterpret_cast<ARGB*>(pbits + y * 160 * sizeof(ARGB) + x * sizeof(ARGB)); 111 if ((x / 10) % 2 == 0) { 112 line->Alpha = 0x7f; 113 line->Red = 0xff; 114 line->Blue = 0x0; 115 line->Green = 0x0; 116 } 117 else 118 { 119 line->Alpha = 0x0; 120 line->Red = 0xff; 121 line->Blue = 0x0; 122 line->Green = 0x0; 123 } 124 } 125 } 126 127 128 BLENDFUNCTION bf; 129 bf.BlendOp = AC_SRC_OVER; 130 bf.BlendFlags = 0; 131 bf.SourceConstantAlpha = 0xff; 132 bf.AlphaFormat = AC_SRC_ALPHA; 133 134 AlphaBlend(hdc, 10, 10, 160*3, 90*3, hdcimg, 0, 0, 160, 60, bf); 135 136 SelectObject(hdcimg, hbmp); 137 DeleteDC(hdcimg); 138 DeleteObject(hbmp); 139 EndPaint(hwnd, &ps); 140 } 141 142 break; 143 144 case WM_COMMAND: 145 InvalidateRect(hwnd, NULL, TRUE); 146 break; 147 148 case WM_DESTROY: 149 PostQuitMessage(0); 150 break; 151 } 152 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 153} 154
補足情報
VisualStudio2017 Community
Windows10
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。