From 5083673dbec9bff295839d426816fc7aa3193d9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 22 Nov 2024 18:06:44 +0000 Subject: [PATCH] deploy: 23d47eaa50c0dd34b1bd7b843c4652f684198f14 --- catalog.json | 22 ++ ...segit-progress-animation-background-fix.md | 3 + ...t-progress-animation-background-fix.wh.cpp | 312 ++++++++++++++++++ updates.atom | 32 +- 4 files changed, 357 insertions(+), 12 deletions(-) create mode 100644 changelogs/tortoisegit-progress-animation-background-fix.md create mode 100644 mods/tortoisegit-progress-animation-background-fix.wh.cpp diff --git a/catalog.json b/catalog.json index 536de97b2..3acfa3f14 100644 --- a/catalog.json +++ b/catalog.json @@ -3225,6 +3225,28 @@ "version": "1.0" } }, + "tortoisegit-progress-animation-background-fix": { + "details": { + "defaultSorting": 0, + "published": 1732298725000, + "rating": 0, + "ratingUsers": 0, + "updated": 1732298725000, + "users": 0 + }, + "metadata": { + "author": "Roland Pihlakas", + "compilerOptions": "-lgdi32", + "description": "Fixes progress animation background in classic dark theme by replacing white background with a classic button face colour", + "github": "https://github.com/levitation", + "homepage": "https://www.simplify.ee/", + "include": [ + "TortoiseGitProc.exe" + ], + "name": "TortoiseGit progress animation background fix for classic dark theme", + "version": "1.0.0" + } + }, "transparent-screensaver-fix": { "details": { "defaultSorting": 2280, diff --git a/changelogs/tortoisegit-progress-animation-background-fix.md b/changelogs/tortoisegit-progress-animation-background-fix.md new file mode 100644 index 000000000..977847800 --- /dev/null +++ b/changelogs/tortoisegit-progress-animation-background-fix.md @@ -0,0 +1,3 @@ +## 1.0.0 ([Nov 22, 2024](https://github.com/ramensoftware/windhawk-mods/blob/23d47eaa50c0dd34b1bd7b843c4652f684198f14/mods/tortoisegit-progress-animation-background-fix.wh.cpp)) + +Initial release. diff --git a/mods/tortoisegit-progress-animation-background-fix.wh.cpp b/mods/tortoisegit-progress-animation-background-fix.wh.cpp new file mode 100644 index 000000000..03e1787af --- /dev/null +++ b/mods/tortoisegit-progress-animation-background-fix.wh.cpp @@ -0,0 +1,312 @@ +// ==WindhawkMod== +// @id tortoisegit-progress-animation-background-fix +// @name TortoiseGit progress animation background fix for classic dark theme +// @description Fixes progress animation background in classic dark theme by replacing white background with a classic button face colour +// @version 1.0.0 +// @author Roland Pihlakas +// @github https://github.com/levitation +// @homepage https://www.simplify.ee/ +// @compilerOptions -lgdi32 +// @include TortoiseGitProc.exe +// ==/WindhawkMod== + +// Source code is published under The GNU General Public License v3.0. +// +// For bug reports and feature requests, please open an issue here: +// https://github.com/levitation-opensource/my-windhawk-mods/issues +// +// For pull requests, development takes place here: +// https://github.com/levitation-opensource/my-windhawk-mods/ + +// ==WindhawkModReadme== +/* +# TortoiseGit progress animation background fix for classic dark theme + +Under classic dark theme, TortoiseGit progress animation has a white background, thus looking as if something is broken. + +This mod fixes the progress animation background in classic dark theme by replacing the white background with a classic button face colour. + +Before: + +![Before](https://raw.githubusercontent.com/levitation-opensource/my-windhawk-mods/main/screenshots/before-tortoisegit-progress-animation-background.png) + +After: + +![After](https://raw.githubusercontent.com/levitation-opensource/my-windhawk-mods/main/screenshots/after-tortoisegit-progress-animation-background.png) + + +## Known limitations + +There is still a brief flash of a white coloured box before the progress animation starts. I have tried various ways, but have been unable to get rid of that. If you have an idea how to fix that, please let me know! +*/ +// ==/WindhawkModReadme== + + +#include +#include +#include //std::nothrow + + +template +BOOL Wh_SetFunctionHookT( + FARPROC targetFunction, + T hookFunction, + T* originalFunction +) { + return Wh_SetFunctionHook((void*)targetFunction, (void*)hookFunction, (void**)originalFunction); +} + + +const COLORREF white = RGB(255, 255, 255); + + +std::atomic g_hookRefCount; + + +using BitBlt_t = decltype(&BitBlt); +BitBlt_t pOriginalBitBlt; + + +bool ControlNeedsBackgroundRepaint(HWND hWnd) { + + WCHAR szClassName[32]; + if ( + hWnd + && GetClassNameW(hWnd, szClassName, ARRAYSIZE(szClassName)) + && _wcsicmp(szClassName, L"SysAnimate32") == 0 + ) { + return true; + } + else { + return false; + } +} + +void ConditionalFillRect(HDC hdc, const RECT& rect, COLORREF oldColor, COLORREF newColor, int newColorIndex, bool useFloodFill) { + + int pixelCount = (rect.right - rect.left) * (rect.bottom - rect.top); + if (pixelCount == 0) { + //Wh_Log(L"pixelCount == 0"); + return; + } + + //Create a compatible DC and bitmap + HDC memDC = CreateCompatibleDC(hdc); + if (!memDC) { + Wh_Log(L"CreateCompatibleDC failed"); + return; + } + + HBITMAP memBitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top); + if (!memBitmap) { + Wh_Log(L"CreateCompatibleBitmap failed"); + } + else { + HGDIOBJ oldBitmap = SelectObject(memDC, memBitmap); + if (!oldBitmap) { + Wh_Log(L"SelectObject for memBitmap failed"); + } + else { + //copy the existing content from hdc + if (!pOriginalBitBlt(memDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left, rect.top, SRCCOPY)) { + Wh_Log(L"BitBlt to memDC failed"); + } + else { + if (useFloodFill) { + + HBRUSH newBrush = GetSysColorBrush(newColorIndex); + if (!newBrush) { + Wh_Log(L"GetSysColorBrush failed - is the colour supported by current OS?"); + } + else { + HGDIOBJ oldBrush = SelectObject(memDC, newBrush); + if (!oldBrush) { + Wh_Log(L"SelectObject for newBrush failed"); + } + else { + if (!ExtFloodFill( + memDC, + //start from top left corner + 0, //left + 0, //top + oldColor, + FLOODFILLSURFACE + )) { + //Wh_Log(L"ExtFloodFill failed"); + } + else { + //blit the modified content back to hdc + if (!pOriginalBitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, memDC, 0, 0, SRCCOPY)) + Wh_Log(L"BitBlt to hdc failed"); + } + + SelectObject(memDC, oldBrush); + } + } + } + else { //use conditional colour replacement on all pixels + + //get pixels array from bitmap + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = rect.right - rect.left; + bmi.bmiHeader.biHeight = rect.bottom - rect.top; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; //32-bit color depth + bmi.bmiHeader.biCompression = BI_RGB; + + COLORREF* pixels = new (std::nothrow) COLORREF[pixelCount]; + if (!pixels) { + Wh_Log(L"Allocating pixels array failed"); + } + else { + int getDIBitsResult = GetDIBits(memDC, memBitmap, 0, rect.bottom - rect.top, pixels, &bmi, DIB_RGB_COLORS); + if (getDIBitsResult == NULL || getDIBitsResult == ERROR_INVALID_PARAMETER) { + Wh_Log(L"GetDIBits failed"); + delete[] pixels; + } + else { + //modify the pixels + for (int i = 0; i < pixelCount; ++i) { + if (pixels[i] == oldColor) + pixels[i] = newColor; + } + + //save pixels array back to bitmap + int setDIBitsResult = SetDIBits(memDC, memBitmap, 0, rect.bottom - rect.top, pixels, &bmi, DIB_RGB_COLORS); + delete[] pixels; + + if (setDIBitsResult == NULL || setDIBitsResult == ERROR_INVALID_PARAMETER) { + Wh_Log(L"SetDIBits failed"); + } + else { + //blit the modified content back to hdc + if (!pOriginalBitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, memDC, 0, 0, SRCCOPY)) + Wh_Log(L"BitBlt to hdc failed"); + } + } + } + } + } + + //clean up + SelectObject(memDC, oldBitmap); + DeleteObject(memBitmap); + } + + DeleteDC(memDC); + } +} + +BOOL WINAPI BitBltHook( + IN HDC hdcDest, + IN int x, + IN int y, + IN int cx, + IN int cy, + IN HDC hdcSrc, + IN int xSrc, + IN int ySrc, + IN DWORD rop +) { + g_hookRefCount++; + + //Wh_Log(L"BitBltHook called"); + + + if ( + hdcSrc + && hdcDest + ) { + HWND hwndDest = WindowFromDC(hdcDest); + + if (ControlNeedsBackgroundRepaint(hwndDest)) { + + int colorIndex = COLOR_3DFACE; + + if (!GetSysColorBrush(colorIndex)) { //Verify that the brush is supported by the current system. GetSysColor() does not have return value, so need to use GetSysColorBrush() for verification purposes. + Wh_Log(L"GetSysColorBrush failed - is the colour supported by current OS?"); + } + else { + RECT rcPaint; + rcPaint.left = x; + rcPaint.top = y; + rcPaint.right = x + cx; + rcPaint.bottom = y + cy; + + COLORREF buttonFace = GetSysColor(colorIndex); + if (buttonFace != white) { + ConditionalFillRect(hdcSrc, rcPaint, white, buttonFace, colorIndex, /*useFloodFill*/true); + + //Wh_Log(L"ConditionalFillRect called"); + } + } + } + } + + + BOOL result = pOriginalBitBlt( + hdcDest, + x, + y, + cx, + cy, + hdcSrc, + xSrc, + ySrc, + rop + ); + + + g_hookRefCount--; + + return result; +} + +void Wh_ModAfterInit(void) { + + Wh_Log(L"Initialising hooks done"); +} + +BOOL Wh_ModInit() { + + Wh_Log(L"Init"); + + + HMODULE hGdi32 = GetModuleHandleW(L"gdi32.dll"); + if (!hGdi32) { + Wh_Log(L"Loading gdi32.dll failed"); + return FALSE; + } + + FARPROC pBitBlt = GetProcAddress(hGdi32, "BitBlt"); + if (!pBitBlt) { + Wh_Log(L"Finding hookable functions from gdi32.dll failed"); + return FALSE; + } + + + Wh_Log(L"Initialising hooks..."); + + Wh_SetFunctionHookT(pBitBlt, BitBltHook, &pOriginalBitBlt); + + return TRUE; +} + +void Wh_ModUninit() { + + Wh_Log(L"Uniniting..."); + + + //Wait for the hooked calls to exit. I have seen programs crashing during this mod's unload without this. + do { //first sleep, then check g_hookRefCount since some hooked function might have a) entered, but not increased g_hookRefCount yet, or b) has decremented g_hookRefCount but not returned to the caller yet + if (g_hookRefCount) + Wh_Log(L"g_hookRefCount: %lli", (long long)g_hookRefCount); + + Sleep(1000); //NB! Sleep always at least once. See the comment at the "do" keyword. + + } while (g_hookRefCount > 0); + + + Wh_Log(L"Uninit complete"); +} diff --git a/updates.atom b/updates.atom index d435462be..036ac23e6 100644 --- a/updates.atom +++ b/updates.atom @@ -2,12 +2,31 @@ https://windhawk.net/ Windhawk Mod Updates - 2024-11-22T00:42:56.000Z + 2024-11-22T18:05:25.000Z https://github.com/jpmonette/feed Updates in the official collection of Windhawk mods https://windhawk.net/favicon.ico Ramen Software + + <![CDATA[TortoiseGit progress animation background fix for classic dark theme 1.0.0]]> + https://windhawk.net/mods/tortoisegit-progress-animation-background-fix#23d47eaa50c0dd34b1bd7b843c4652f684198f14 + + 2024-11-22T18:05:25.000Z + TortoiseGit progress animation background fix for classic dark theme +

Under classic dark theme, TortoiseGit progress animation has a white background, thus looking as if something is broken.

+

This mod fixes the progress animation background in classic dark theme by replacing the white background with a classic button face colour.

+

Before:

+

Before

+

After:

+

After

+

Known limitations

+

There is still a brief flash of a white coloured box before the progress animation starts. I have tried various ways, but have been unable to get rid of that. If you have an idea how to fix that, please let me know!

]]>
+ + Roland Pihlakas + https://github.com/levitation + +
<![CDATA[Visual Studio Anti-Rich-Header 1.0.3]]> https://windhawk.net/mods/visual-studio-anti-rich-header#5c2c1aee4460b052b77496e4cbb4f00bddba510b @@ -274,15 +293,4 @@ center, etc. to another monitor.

https://github.com/m417z
- - <![CDATA[Legacy Alt+Tab dialog 1.0.1]]> - https://windhawk.net/mods/legacy-alt-tab#b3712cc03e6f39212f8e7e79b91acb36e87b2507 - - 2024-11-09T00:55:38.000Z - Add info on supported Windows versions.

]]>
- - Anixx - https://github.com/Anixx - -
\ No newline at end of file