diff options
Diffstat (limited to 'alf')
| -rw-r--r-- | alf/alfcompat.cpp | 175 | ||||
| -rw-r--r-- | alf/alfcompat.h | 3 | ||||
| -rw-r--r-- | alf/alflabel.cpp | 20 |
3 files changed, 188 insertions, 10 deletions
diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index 6321a44..df7f27d 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -4,6 +4,20 @@ DWORD _alf_compatBits = 0; +typedef struct { + LONG lock; + SIZE currentBitmapSize; + SIZE maxBitmapSize; + HDC hdcBuffer; + HBITMAP hbmBuffer; + HBITMAP hbmOld; + + HDC hdcTarget; + RECT rcTarget; +} ALFCompatBufferedPaintPriv; + +ALFCompatBufferedPaintPriv *_alf_compatBufferedPaintPriv = NULL; + static DWORD ALF_DllGetVersion(const char *dll) { @@ -290,6 +304,73 @@ ALF_Compat_fallbackBufferedPaintUnInit(void) return E_NOTIMPL; } +static ALF_Compat_HPAINTBUFFER WINAPI +ALF_Compat_fallbackBeginBufferedPaint(HDC hdc, const RECT *prcTarget, DWORD dwFormat, + ALF_Compat_BP_PAINTPARAMS *pPaintParams, + HDC *phdcTarget) +{ + if (dwFormat != 0 || pPaintParams != 0 + || !_alf_compatBufferedPaintPriv + || prcTarget->right - prcTarget->left > _alf_compatBufferedPaintPriv->maxBitmapSize.cx + || prcTarget->bottom - prcTarget->top > _alf_compatBufferedPaintPriv->maxBitmapSize.cy + || InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 1)) { + SetLastError(ERROR_NOT_SUPPORTED); + return NULL; + } + + // we have locked the buffer! now allocate the bitmap if necessary + if (!_alf_compatBufferedPaintPriv->hdcBuffer) { + _alf_compatBufferedPaintPriv->hdcBuffer = CreateCompatibleDC(NULL); + if (!_alf_compatBufferedPaintPriv->hdcBuffer) { + InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0); + return NULL; + } + } + + + if (!_alf_compatBufferedPaintPriv->hbmBuffer + || prcTarget->right - prcTarget->left > _alf_compatBufferedPaintPriv->currentBitmapSize.cx + || prcTarget->bottom - prcTarget->top > _alf_compatBufferedPaintPriv->currentBitmapSize.cy) { + + DeleteBitmap(_alf_compatBufferedPaintPriv->hbmBuffer); + + int neww = _alf_compatBufferedPaintPriv->currentBitmapSize.cx; + int newh = _alf_compatBufferedPaintPriv->currentBitmapSize.cy; + + if (neww < 1) + neww = 32; + if (newh < 1) + newh = 16; + + while (neww < prcTarget->right - prcTarget->left) { + neww *= 2; + } + while (newh < prcTarget->bottom - prcTarget->top) { + newh *= 2; + } + + HDC hdcScreen = GetDC(NULL); + _alf_compatBufferedPaintPriv->hbmBuffer = CreateCompatibleBitmap(hdcScreen, neww, newh); + ReleaseDC(NULL, hdcScreen); + + if (!_alf_compatBufferedPaintPriv->hbmBuffer) { + InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0); + return NULL; + } + + _alf_compatBufferedPaintPriv->currentBitmapSize.cx = neww; + _alf_compatBufferedPaintPriv->currentBitmapSize.cy = newh; + } + + _alf_compatBufferedPaintPriv->hbmOld = SelectBitmap(_alf_compatBufferedPaintPriv->hdcBuffer, _alf_compatBufferedPaintPriv->hbmBuffer); + + _alf_compatBufferedPaintPriv->hdcTarget = hdc; + _alf_compatBufferedPaintPriv->rcTarget = *prcTarget; + *phdcTarget = _alf_compatBufferedPaintPriv->hdcBuffer; + + return _alf_compatBufferedPaintPriv; +} + static ALF_Compat_HANIMATIONBUFFER WINAPI ALF_Compat_fallbackBeginBufferedAnimation(HWND hwnd, HDC hdcTarget, const RECT *prcTarget, DWORD dwFormat, @@ -297,18 +378,41 @@ ALF_Compat_fallbackBeginBufferedAnimation(HWND hwnd, HDC hdcTarget, ALF_Compat_BP_ANIMATIONPARAMS *pAnimationParams, HDC *phdcFrom, HDC *phdcTo) { - (void)hwnd; (void)hdcTarget; (void)prcTarget; (void)dwFormat; - (void)pPaintParams; (void)pAnimationParams; (void)phdcFrom; (void)phdcTo; + (void)hwnd; + if (pAnimationParams != NULL && pAnimationParams->dwDuration == 0) { + *phdcFrom = NULL; + return ALF_Compat_fallbackBeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcTo); + } else { + SetLastError(ERROR_NOT_SUPPORTED); + return NULL; + } +} - return NULL; +extern HRESULT WINAPI +ALF_Compat_fallbackEndBufferedPaint(ALF_Compat_HPAINTBUFFER hpbBuffer, BOOL fUpdateTarget) +{ + if (hpbBuffer != _alf_compatBufferedPaintPriv) + return E_INVALIDARG; + + if (fUpdateTarget) + BitBlt(_alf_compatBufferedPaintPriv->hdcTarget, + _alf_compatBufferedPaintPriv->rcTarget.left, + _alf_compatBufferedPaintPriv->rcTarget.top, + _alf_compatBufferedPaintPriv->rcTarget.right - _alf_compatBufferedPaintPriv->rcTarget.left, + _alf_compatBufferedPaintPriv->rcTarget.bottom - _alf_compatBufferedPaintPriv->rcTarget.top, + _alf_compatBufferedPaintPriv->hdcBuffer, + 0, 0, SRCCOPY); + + SelectBitmap(_alf_compatBufferedPaintPriv->hdcBuffer, _alf_compatBufferedPaintPriv->hbmOld); + _alf_compatBufferedPaintPriv->hdcTarget = NULL; + InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0); + return S_OK; } static HRESULT WINAPI ALF_Compat_fallbackEndBufferedAnimation(ALF_Compat_HANIMATIONBUFFER hbpAnimation, BOOL fUpdateTarget) { - (void)hbpAnimation; (void)fUpdateTarget; - - return E_NOTIMPL; + return ALF_Compat_fallbackEndBufferedPaint(hbpAnimation, fUpdateTarget); } static BOOL WINAPI @@ -499,7 +603,9 @@ void ALF_LoadCompatFunctions(void) LOAD_FUNC(uxtheme, BufferedPaintInit); LOAD_FUNC(uxtheme, BufferedPaintUnInit); LOAD_FUNC(uxtheme, BeginBufferedAnimation); + LOAD_FUNC(uxtheme, BeginBufferedPaint); LOAD_FUNC(uxtheme, EndBufferedAnimation); + LOAD_FUNC(uxtheme, EndBufferedPaint); LOAD_FUNC(uxtheme, BufferedPaintRenderAnimation); LOAD_FUNC(uxtheme, GetThemeTransitionDuration); LOAD_FUNC(uxtheme, GetThemePartSize); @@ -516,10 +622,63 @@ void ALF_LoadCompatFunctions(void) } else { ALF_Compat_DrawDisabledText = ALF_Compat_DrawDisabledText31; } + + // initialize double buffering wrapper + if (ALF_Compat_BufferedPaintInit == ALF_Compat_fallbackBufferedPaintInit) { + // set max size based on available RAM, so that at most 1‰ of it is spent on us + int maxx = 0; + int maxy = 0; + + MEMORYSTATUS ms; + ZeroMemory(&ms, sizeof(ms)); + GlobalMemoryStatus(&ms); + + if (ms.dwTotalPhys >= 16777216u) { + maxx = 128; + maxy = 32; + } + if (ms.dwTotalPhys >= 33554432u) { + maxy = 64; + } + if (ms.dwTotalPhys >= 67108864u) { + maxx = 256; + } + if (ms.dwTotalPhys >= 134217728u) { + maxy = 128; + } + if (ms.dwTotalPhys >= 268435456u) { + maxx = 512; + } + if (ms.dwTotalPhys >= 536870912u) { + maxx = 1024; + } + if (ms.dwTotalPhys >= 1073741824u) { + maxy = 256; + } + if (ms.dwTotalPhys >= 2147483648u) { + maxy = 512; + } + if (ms.dwTotalPhys == (SIZE_T)-1) { + maxy = 1024; + } + + if (maxx > 0 && maxy > 0) { + _alf_compatBufferedPaintPriv = ALF_New(ALFCompatBufferedPaintPriv, 1); + _alf_compatBufferedPaintPriv->maxBitmapSize.cx = maxx; + _alf_compatBufferedPaintPriv->maxBitmapSize.cy = maxy; + } + } } void ALF_UnloadCompatFunctions(void) { + if (_alf_compatBufferedPaintPriv) { + DeleteDC(_alf_compatBufferedPaintPriv->hdcBuffer); + DeleteBitmap(_alf_compatBufferedPaintPriv->hbmBuffer); + ALF_Free(_alf_compatBufferedPaintPriv); + _alf_compatBufferedPaintPriv = NULL; + } + UNLOAD_FUNC(IsAppThemed); UNLOAD_FUNC(GetDpiForWindow); UNLOAD_FUNC(AdjustWindowRectExForDpi); @@ -537,7 +696,9 @@ void ALF_UnloadCompatFunctions(void) UNLOAD_FUNC(BufferedPaintInit); UNLOAD_FUNC(BufferedPaintUnInit); UNLOAD_FUNC(BeginBufferedAnimation); + UNLOAD_FUNC(BeginBufferedPaint); UNLOAD_FUNC(EndBufferedAnimation); + UNLOAD_FUNC(EndBufferedPaint); UNLOAD_FUNC(BufferedPaintRenderAnimation); UNLOAD_FUNC(GetThemeTransitionDuration); UNLOAD_FUNC(GetThemePartSize); @@ -573,7 +734,9 @@ HRESULT (WINAPI *ALF_Compat_GetThemePartSize)(HTHEME,HDC,int,int,RECT *,THEMESIZ HRESULT (WINAPI *ALF_Compat_BufferedPaintInit)(void) = NULL; HRESULT (WINAPI *ALF_Compat_BufferedPaintUnInit)(void) = NULL; ALF_Compat_HANIMATIONBUFFER (WINAPI *ALF_Compat_BeginBufferedAnimation)(HWND,HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,ALF_Compat_BP_ANIMATIONPARAMS *,HDC *,HDC *) = NULL; +ALF_Compat_HPAINTBUFFER (WINAPI *ALF_Compat_BeginBufferedPaint)(HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,HDC *) = NULL; HRESULT (WINAPI *ALF_Compat_EndBufferedAnimation)(ALF_Compat_HANIMATIONBUFFER,BOOL) = NULL; +HRESULT (WINAPI *ALF_Compat_EndBufferedPaint)(ALF_Compat_HPAINTBUFFER,BOOL) = NULL; BOOL (WINAPI *ALF_Compat_BufferedPaintRenderAnimation)(HWND,HDC) = NULL; HRESULT (WINAPI *ALF_Compat_GetThemeTransitionDuration)(HTHEME,int,int,int,int,DWORD*) = NULL; HRESULT (WINAPI *ALF_Compat_GetThemeColor)(HTHEME,int,int,int,COLORREF*) = NULL; diff --git a/alf/alfcompat.h b/alf/alfcompat.h index 5fa37e6..5360d9d 100644 --- a/alf/alfcompat.h +++ b/alf/alfcompat.h @@ -56,6 +56,7 @@ long ALF_GetAveCharWidth(HDC hdc); typedef void *ALF_Compat_HANIMATIONBUFFER; +typedef void *ALF_Compat_HPAINTBUFFER; typedef enum { ALF_Compat_BPAS_NONE, @@ -129,7 +130,9 @@ extern BOOL (WINAPI *ALF_Compat_TrackMouseEvent)(LPTRACKMOUSEEVENT tme); extern HRESULT (WINAPI *ALF_Compat_BufferedPaintInit)(void); extern HRESULT (WINAPI *ALF_Compat_BufferedPaintUnInit)(void); extern ALF_Compat_HANIMATIONBUFFER (WINAPI *ALF_Compat_BeginBufferedAnimation)(HWND,HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,ALF_Compat_BP_ANIMATIONPARAMS *,HDC *,HDC *); +extern ALF_Compat_HPAINTBUFFER (WINAPI *ALF_Compat_BeginBufferedPaint)(HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,HDC *); extern HRESULT (WINAPI *ALF_Compat_EndBufferedAnimation)(ALF_Compat_HANIMATIONBUFFER,BOOL); +extern HRESULT (WINAPI *ALF_Compat_EndBufferedPaint)(ALF_Compat_HPAINTBUFFER,BOOL); extern BOOL (WINAPI *ALF_Compat_BufferedPaintRenderAnimation)(HWND,HDC); extern HRESULT (WINAPI *ALF_Compat_GetThemeTransitionDuration)(HTHEME,int,int,int,int,DWORD*); extern HRESULT (WINAPI *ALF_Compat_GetThemeColor)(HTHEME,int,int,int,COLORREF*); diff --git a/alf/alflabel.cpp b/alf/alflabel.cpp index b3a87c4..0a47d58 100644 --- a/alf/alflabel.cpp +++ b/alf/alflabel.cpp @@ -222,16 +222,28 @@ ALF_Label_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); - ALF_Label_Paint(hwnd, priv, hdc, &ps.rcPaint); + RECT rcClient; + GetClientRect(hwnd, &rcClient); + RECT rcPaint = { 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; + + HDC hdcBuffer = NULL; + ALF_Compat_HPAINTBUFFER hpb = ALF_Compat_BeginBufferedPaint(hdc, &rcPaint, 0, NULL, &hdcBuffer); + if (hpb) { + ALF_Label_Paint(hwnd, priv, hdcBuffer, &ps.rcPaint); + ALF_Compat_EndBufferedPaint(hpb, TRUE); + } else { + ALF_Label_Paint(hwnd, priv, hdc, &ps.rcPaint); + } EndPaint(hwnd, &ps); return TRUE; } else if (uMsg == WM_PRINTCLIENT) { - RECT rc; - GetClientRect(hwnd, &rc); + RECT rcClient; + GetClientRect(hwnd, &rcClient); + RECT rcPaint = { 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; - ALF_Label_Paint(hwnd, priv, (HDC)wParam, &rc); + ALF_Label_Paint(hwnd, priv, (HDC)wParam, &rcPaint); } else if (uMsg == WM_NCHITTEST) { return HTTRANSPARENT; } else if (uMsg == ALF_WM_QUERYSIZE) { |
