Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 30 additions & 102 deletions ContextMenuNormalizer/ContextMenuNormalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <vssym32.h>
#include <sysinfoapi.h>

#include "ThemeEditor.h"
#include "PopupMenus.h"

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "uxtheme.lib")
#pragma warning(disable : 4996)
Expand All @@ -12,34 +15,6 @@
#include <iostream>
#endif

#pragma region Pixel Color

inline int PixClr(int val)
{
return val & 0xFFFFFF;
}

inline int PixR(BYTE* pPixel)
{
return PixClr(pPixel[2]);
}
inline int PixG(BYTE* pPixel)
{
return PixClr(pPixel[1]);
}
inline int PixB(BYTE* pPixel)
{
return PixClr(pPixel[0]);
}
inline int PixA(BYTE* pPixel)
{
return PixClr(pPixel[3]);
}

#pragma endregion

typedef void (*BitmapHandler)(int* r, int* g, int* b, int* a);

#pragma region Recolorizators

#define CONTEXT_MENU_BACKGROUND_LIGHT 238
Expand Down Expand Up @@ -162,61 +137,6 @@ void Recolorize_Menu_PopupSeparator11(int* r, int* g, int* b, int* a) {
}
#pragma endregion

int RecolorizeBitmap(HBITMAP hbm, BitmapHandler handler)
{
BITMAP bm;
GetObject(hbm, sizeof(bm), &bm);

if (!hbm || bm.bmBitsPixel != 32) {
return FALSE;
}

BYTE* pBits = new BYTE[bm.bmWidth * bm.bmHeight * 4];
GetBitmapBits(hbm, bm.bmWidth * bm.bmHeight * 4, pBits);

for (int y = 0; y < bm.bmHeight; y++) {
BYTE* pPixel = (BYTE*)pBits + bm.bmWidth * 4 * y;

for (int x = 0; x < bm.bmWidth; x++) {

int r = PixR(pPixel); // [2]
int g = PixG(pPixel); // [1]
int b = PixB(pPixel); // [0]
int a = PixA(pPixel); // [3]

#if _DEBUG
_RPT1(0, "(%d, %d, %d / %d) \n", r, g, b, a);
#endif

handler(&r, &g, &b, &a);

pPixel[2] = r;
pPixel[1] = g;
pPixel[0] = b;
pPixel[3] = a;

pPixel += 4;
}
}


SetBitmapBits(hbm, bm.bmWidth * bm.bmHeight * 4, pBits);

delete[] pBits;
return TRUE;
}

int NormalizeContextMenu(LPCWSTR pszClassList, int iPartId, BitmapHandler handler)
{
HBITMAP hBitmap;

HTHEME hTheme = OpenThemeData(GetForegroundWindow(), pszClassList);
GetThemeBitmap(hTheme, iPartId, 0, TMT_DIBDATA, GBF_DIRECT, &hBitmap);
CloseThemeData(hTheme);

return RecolorizeBitmap(hBitmap, handler);
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
Expand All @@ -226,28 +146,36 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((LPOSVERSIONINFO)&info);

if (info.dwBuildNumber < 22000)
{
NormalizeContextMenu(L"Menu", 14, Recolorize_Menu_PopupItem);
NormalizeContextMenu(L"Menu", 13, Recolorize_Menu_PopupGutter);
NormalizeContextMenu(L"Menu", 12, Recolorize_Menu_CheckBackground);
NormalizeContextMenu(L"Menu", 8, Recolorize_Menu_BarItem);

NormalizeContextMenu(L"ImmersiveStart::Menu", 15, Recolorize_ImmersiveMenu_PopupSeparator);
NormalizeContextMenu(L"ImmersiveStart::Menu", 14, Recolorize_ImmersiveMenu_PopupItem);
NormalizeContextMenu(L"ImmersiveStart::Menu", 9, Recolorize_ImmersiveMenu_PopupBackground);

NormalizeContextMenu(L"ImmersiveStartDark::Menu", 15, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode_ImmersiveStart::Menu", 15, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode::Menu", 15, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode::Menu", 12, Recolorize_ImmersiveMenuDark_CheckBackground);
NormalizeContextMenu(L"DarkMode::Menu", 10, Recolorize_ImmersiveMenuDark_PopupBorders);
}
else
// Windows 10
NormalizeContextMenu(L"Menu", MENU_POPUPITEM, Recolorize_Menu_PopupItem);
NormalizeContextMenu(L"Menu", MENU_POPUPGUTTER, Recolorize_Menu_PopupGutter);
NormalizeContextMenu(L"Menu", MENU_POPUPCHECKBACKGROUND, Recolorize_Menu_CheckBackground);
NormalizeContextMenu(L"Menu", MENU_BARITEM, Recolorize_Menu_BarItem);

NormalizeContextMenu(L"ImmersiveStart::Menu", MENU_POPUPSEPARATOR, Recolorize_ImmersiveMenu_PopupSeparator);
NormalizeContextMenu(L"ImmersiveStart::Menu", MENU_POPUPITEM, Recolorize_ImmersiveMenu_PopupItem);
NormalizeContextMenu(L"ImmersiveStart::Menu", MENU_POPUPBACKGROUND, Recolorize_ImmersiveMenu_PopupBackground);

NormalizeContextMenu(L"ImmersiveStartDark::Menu", MENU_POPUPSEPARATOR, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode_ImmersiveStart::Menu", MENU_POPUPSEPARATOR, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode::Menu", MENU_POPUPSEPARATOR, Recolorize_ImmersiveMenuDark_PopupSeparator);
NormalizeContextMenu(L"DarkMode::Menu", MENU_POPUPCHECKBACKGROUND, Recolorize_ImmersiveMenuDark_CheckBackground);
NormalizeContextMenu(L"DarkMode::Menu", MENU_POPUPBORDERS, Recolorize_ImmersiveMenuDark_PopupBorders);
}
else if (info.dwBuildNumber < 22621)
{
NormalizeContextMenu(L"Menu", 14, Recolorize_Menu_PopupItem11);
NormalizeContextMenu(L"Menu", 15, Recolorize_Menu_PopupSeparator11);
// before Win11 22H2
NormalizeContextMenu(L"Menu", MENU_POPUPITEM, Recolorize_Menu_PopupItem11);
NormalizeContextMenu(L"Menu", MENU_POPUPSEPARATOR, Recolorize_Menu_PopupSeparator11);
}
else {
// Win11 22H2 and after
ModifyContextMenuBitmap(L"Menu", 27, iWin11_21H1_PopupMenu, NULL); // The new "MENU_POPUPITEM" in use
ModifyContextMenuBitmap(L"Menu", MENU_POPUPITEM, iWin11_21H1_PopupMenu, NULL);
ModifyContextMenuBitmap(L"ImmersiveStart::Menu", MENU_POPUPITEM, iWin11_21H1_PopupMenu, NULL);
}

return 0;
Expand Down
13 changes: 9 additions & 4 deletions ContextMenuNormalizer/ContextMenuNormalizer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
Expand Down Expand Up @@ -140,6 +140,9 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ContextMenuNormalizer.cpp" />
<ClCompile Include="Win11_21H1.cpp" />
<ClCompile Include="ThemeEditor.cpp" />
<ClCompile Include="Win8RP.cpp" />
</ItemGroup>
<ItemGroup>
<Manifest Include="ContextMenuNormalizer.exe.manifest" />
Expand All @@ -149,6 +152,8 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
<ClInclude Include="ThemeEditor.h" />
<ClInclude Include="PopupMenus.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
15 changes: 15 additions & 0 deletions ContextMenuNormalizer/ContextMenuNormalizer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
<ClCompile Include="ContextMenuNormalizer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ThemeEditor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win8RP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win11_21H1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Manifest Include="ContextMenuNormalizer.exe.manifest">
Expand All @@ -33,5 +42,11 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ThemeEditor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PopupMenus.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions ContextMenuNormalizer/PopupMenus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef __INCLUDE_WIN8RP_H_
#define __INCLUDE_WIN8RP_H_

#include "ThemeEditor.h"

int iWin8_RP_PopupMenu(int iWidth, int iHeight, Pixel_t* pPixels, void* pParam);
int iWin11_21H1_PopupMenu(int iWidth, int iHeight, Pixel_t* pPixels, void* pParam);

#endif // __INCLUDE_WIN8RP_H_
140 changes: 140 additions & 0 deletions ContextMenuNormalizer/ThemeEditor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include "ThemeEditor.h"

#include <stdint.h>
#include <stdlib.h>

#include <Windows.h>
#include <Uxtheme.h>
#include <vsstyle.h>
#include <vssym32.h>
#include <sysinfoapi.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "uxtheme.lib")
#pragma warning(disable : 4996)

#if _DEBUG
#include <iostream>
#endif

#pragma region Pixel Color

static inline int PixClr(int val)
{
return val & 0xFFFFFF;
}

static inline int PixR(BYTE* pPixel)
{
return PixClr(pPixel[2]);
}
static inline int PixG(BYTE* pPixel)
{
return PixClr(pPixel[1]);
}
static inline int PixB(BYTE* pPixel)
{
return PixClr(pPixel[0]);
}
static inline int PixA(BYTE* pPixel)
{
return PixClr(pPixel[3]);
}

#pragma endregion

typedef struct {
PixelModifier pmPixelModifier;
BitmapHandler pmSimpleReplacer;
} CallContext_t;

static void prvSimpleWrapper(const RBContext_t* pxContext, Pixel_t* pPixel, void* pParam) {
CallContext_t* pCallContext = (CallContext_t*)pParam;
int r = pPixel->bits.r;
int g = pPixel->bits.g;
int b = pPixel->bits.b;
int a = pPixel->bits.a;
pCallContext->pmSimpleReplacer(&r, &g, &b, &a);
pPixel->bits.r = r;
pPixel->bits.g = g;
pPixel->bits.b = b;
pPixel->bits.a = a;
}

static int prvRecolorizeBitmap(int iWidth, int iHeight, Pixel_t *pPixels, void* pParam)
{
RBContext_t xRBContext;
xRBContext.width = iWidth;
xRBContext.height = iHeight;

for (xRBContext.y = 0; xRBContext.y < iHeight; xRBContext.y++) {
Pixel_t* pPixel = pPixels + (iWidth * xRBContext.y);

for (xRBContext.x = 0; xRBContext.x < iWidth; xRBContext.x++) {
#if _DEBUG
_RPT1(0, "(%d, %d, %d / %d) \n", pPixel->bits.r, pPixel->bits.g, pPixel->bits.b, pPixel->bits.a);
#endif
CallContext_t* pCallContext = (CallContext_t*) pParam;
pCallContext->pmPixelModifier(&xRBContext, pPixel, pParam);

pPixel ++;
}
}

return TRUE;
}

int ModifyContextMenuBitmap(LPCWSTR pszClassList, int iPartId, BitmapModifier pmModifier, void* pParam)
{
HBITMAP hBitmap;

HTHEME hTheme = OpenThemeData(GetForegroundWindow(), pszClassList);
GetThemeBitmap(hTheme, iPartId, 0, TMT_DIBDATA, GBF_DIRECT, &hBitmap);
CloseThemeData(hTheme);

BITMAP xBitMap;
GetObject(hBitmap, sizeof(xBitMap), &xBitMap);

if (!hBitmap || xBitMap.bmBitsPixel != 32) {
// Format is not ARGB
return FALSE;
}

int result = FALSE;
LONG xPixelCount = xBitMap.bmWidth * xBitMap.bmHeight;
LONG xBitCount = xPixelCount * sizeof(Pixel_t);
Pixel_t* pPixels = (Pixel_t*)malloc(xBitCount);
if (!pPixels) {
return result;
}

if (!GetBitmapBits(hBitmap, xBitCount, pPixels)) {
goto free_bits;
}

result = pmModifier(xBitMap.bmWidth, xBitMap.bmHeight, pPixels, pParam);

if (!SetBitmapBits(hBitmap, xBitCount, pPixels)) {
goto free_bits;
}

free_bits:
if (pPixels) {
free(pPixels);
}

return result;
}

int NormalizeContextMenu(LPCWSTR pszClassList, int iPartId, BitmapHandler pmHandler) {
CallContext_t xContext;
xContext.pmPixelModifier = prvSimpleWrapper;
xContext.pmSimpleReplacer = pmHandler;
return ModifyContextMenuBitmap(pszClassList, iPartId, prvRecolorizeBitmap, &xContext);
}

int NormalizeContextMenuEx(LPCWSTR pszClassList, int iPartId, PixelModifier pmHandler) {
CallContext_t xContext;
xContext.pmPixelModifier = pmHandler;
return ModifyContextMenuBitmap(pszClassList, iPartId, prvRecolorizeBitmap, &xContext);
}
Loading