Index: reactos/win32ss/user/user32/CMakeLists.txt =================================================================== --- reactos/win32ss/user/user32/CMakeLists.txt (revision 72204) +++ reactos/win32ss/user/user32/CMakeLists.txt (working copy) @@ -78,6 +78,6 @@ endif() add_delay_importlibs(user32 imm32 usp10) -add_importlibs(user32 gdi32 advapi32 kernel32 ntdll) +add_importlibs(user32 gdi32 advapi32 kernel32 ntdll msimg32) add_pch(user32 include/user32.h SOURCE) add_cd_file(TARGET user32 DESTINATION reactos/system32 FOR all) Index: reactos/win32ss/user/user32/controls/static.c =================================================================== --- reactos/win32ss/user/user32/controls/static.c (revision 72204) +++ reactos/win32ss/user/user32/controls/static.c (working copy) @@ -62,7 +62,8 @@ #define HFONT_GWL_OFFSET 0 #define HICON_GWL_OFFSET (sizeof(HFONT)) #define UISTATE_GWL_OFFSET (HICON_GWL_OFFSET+sizeof(HICON)) // ReactOS: keep in sync with STATIC_UISTATE_GWL_OFFSET -#define STATIC_EXTRA_BYTES (UISTATE_GWL_OFFSET + sizeof(LONG)) +#define HBITMAPPM_GWL_OFFSET (UISTATE_GWL_OFFSET + sizeof(LONG)) +#define STATIC_EXTRA_BYTES (HBITMAPPM_GWL_OFFSET + sizeof(HBITMAP)) typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style ); @@ -159,7 +160,40 @@ if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { BITMAP bm; + HBITMAP hbmPM; GetObjectW(hBitmap, sizeof(bm), &bm); + + /* delete the previous premultiplied bitmap */ + hbmPM = (HBITMAP)GetWindowLongPtrW(hwnd, HBITMAPPM_GWL_OFFSET); + if (hbmPM) + { + DeleteObject(hbmPM); + SetWindowLongPtrW(hwnd, HBITMAPPM_GWL_OFFSET, 0); + } + + if (bm.bmBitsPixel == 32) + { + /* create a premultiplied bitmap */ + hbmPM = CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + if (hbmPM) + { + DWORD cdw; + BYTE *pb; + BITMAP bmPM; + GetObject(hbmPM, sizeof(BITMAP), &bmPM); + cdw = bm.bmWidth * bm.bmHeight; + pb = (BYTE *)bmPM.bmBits; + while (cdw-- > 0) + { + pb[0] = (BYTE)(pb[0] * pb[3] / 256); + pb[1] = (BYTE)(pb[1] * pb[3] / 256); + pb[2] = (BYTE)(pb[2] * pb[3] / 256); + pb += 4; + } + SetWindowLongPtrW(hwnd, HBITMAPPM_GWL_OFFSET, (LONG_PTR)hbmPM); + } + } + /* Windows currently doesn't implement SS_RIGHTJUST */ /* if ((style & SS_RIGHTJUST) != 0) @@ -391,9 +425,20 @@ break; case WM_NCDESTROY: + /* delete the premultiplied bitmap if any */ + { + HBITMAP hbmPM; + hbmPM = (HBITMAP)GetWindowLongPtrW(hwnd, HBITMAPPM_GWL_OFFSET); + if (hbmPM) + { + DeleteObject(hbmPM); + } + } + #ifdef __REACTOS__ NtUserSetWindowFNID(hwnd, FNID_DESTROY); #endif + if (style == SS_ICON) { /* * FIXME @@ -810,12 +855,15 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style ) { HDC hMemDC; - HBITMAP hBitmap, oldbitmap; + HBITMAP hBitmap, oldbitmap, hbmPM; HBRUSH hbrush; /* message is still sent, even if the returned brush is not used */ hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc); + /* premultiplied bitmap */ + hbmPM = (HBITMAP)GetWindowLongPtrW(hwnd, HBITMAPPM_GWL_OFFSET); + if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )) && (GetObjectType(hBitmap) == OBJ_BITMAP) && (hMemDC = CreateCompatibleDC( hdc ))) @@ -825,7 +873,10 @@ LOGBRUSH brush; GetObjectW(hBitmap, sizeof(bm), &bm); - oldbitmap = SelectObject(hMemDC, hBitmap); + if (hbmPM) + oldbitmap = SelectObject(hMemDC, hbmPM); + else + oldbitmap = SelectObject(hMemDC, hBitmap); /* Set the background color for monochrome bitmaps to the color of the background brush */ @@ -843,9 +894,23 @@ rcClient.right = rcClient.left + bm.bmWidth; rcClient.bottom = rcClient.top + bm.bmHeight; } - StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left, - rcClient.bottom - rcClient.top, hMemDC, - 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + if (hbmPM) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + AlphaBlend(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top, hMemDC, + 0, 0, bm.bmWidth, bm.bmHeight, bf); + } + else + { + StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top, hMemDC, + 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + } SelectObject(hMemDC, oldbitmap); DeleteDC(hMemDC); }