Errors from log
[{
"resource": "/c:/ProgramData/Windhawk/EditorWorkspace/mod.wh.cpp",
"owner": "_generated_diagnostic_collection_name_#0",
"code": "expected_unqualified_id",
"severity": 8,
"message": "Expected unqualified-id",
"source": "clang",
"startLineNumber": 23,
"startColumn": 1,
"endLineNumber": 23,
"endColumn": 2
}]
c:ProgramDataWindhawkEditorWorkspacemod.wh.cpp:24:3: error: expected unqualified-id
24 | "closeButtonHoverColor": {
| ^
c:ProgramDataWindhawkEditorWorkspacemod.wh.cpp:81:16: error: expected ')'
81 | Wh_Log(buffer); // Ensure macro expansion is correct
| ^
c:ProgramDataWindhawkEditorWorkspacemod.wh.cpp:81:9: note: to match this '('
81 | Wh_Log(buffer); // Ensure macro expansion is correct
| ^
c:/Program Files/Windhawk/Compiler/include/windhawk_api.h:71:35: note: expanded from macro 'Wh_Log'
71 | InternalWh_Log_Wrapper(L"[%d:%S]: " message, __LINE__,
| ^
2 errors generated.
Full mode code
// ==WindhawkMod==
// @id close-button-hover-color-changer
// @name Close Button Hover Color Changer
// @description Changes the close button's hover color across all applications
// @version 1.0
// @author AssistantModder
// @github https://github.com/AssistantModder
// @include *
// @compilerOptions -ldwmapi -luser32 -lgdi32
// ==/WindhawkMod==
// ==WindhawkModReadme==
/*
This mod customizes the close button's hover color across all applications that use the Windows DWM API.
Features:
- Change the hover color of the close button.
- Basic error handling and logging for troubleshooting.
*/
// ==/WindhawkModReadme==
// Define Windhawk Mod Settings
// ==WindhawkModSettings==
{
"closeButtonHoverColor": {
"type": "string",
"default": "#FF6666",
"title": "Hover Color",
"description": "Color when hovering over the close button."
},
"enableMod": {
"type": "boolean",
"default": true,
"title": "Mod Enabled",
"description": "Toggle the mod on or off."
},
"logLevel": {
"type": "integer",
"default": 1,
"minimum": 0,
"maximum": 4,
"title": "Logging Level",
"description": "Set logging level: 0-None, 1-Error, 2-Warning, 3-Info, 4-Debug"
}
}
// ==/WindhawkModSettings==
#include <windows.h>
#include <dwmapi.h>
#include <windhawk_utils.h>
// Structure to hold the mod's settings
struct ModSettings {
COLORREF hoverColor;
BOOL enableMod;
int logLevel;
} settings;
// Function prototype for the DWM API call
typedef HRESULT (WINAPI *DwmSetWindowAttributeFptr)(HWND, DWORD, LPCVOID, DWORD);
// Original function pointer
DwmSetWindowAttributeFptr OriginalDwmSetWindowAttribute = nullptr;
// Converts a hex string to COLORREF
COLORREF HexStringToCOLORREF(const wchar_t* hexColor) {
unsigned int r, g, b;
if (wcslen(hexColor) == 7 && swscanf_s(hexColor, L"#%02x%02x%02x", &r, &g, &b) == 3) {
return RGB(r, g, b);
}
Wh_Log(L"Error: Invalid hex color format '%s'. Using default red.", hexColor);
return RGB(255, 0, 0); // Default to red on failure
}
// Custom logging function based on the log level
void CustomLog(int level, const wchar_t* format, ...) {
if (level <= settings.logLevel) {
va_list args;
va_start(args, format);
wchar_t buffer[256];
vswprintf_s(buffer, sizeof(buffer) / sizeof(buffer[0]), format, args);
Wh_Log(buffer); // Ensure macro expansion is correct
va_end(args);
}
}
// Hook function for DwmSetWindowAttribute to change close button hover color
HRESULT WINAPI HookDwmSetWindowAttribute(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) {
if (settings.enableMod && dwAttribute == 35) { // 35 is the undocumented DWMWA_CAPTION_COLOR_HOVER
*(COLORREF*)pvAttribute = settings.hoverColor;
CustomLog(4, L"Set hover caption color to 0x%06X", settings.hoverColor);
}
return OriginalDwmSetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
}
// Load settings from the Windhawk mod settings
void LoadSettings() {
settings.hoverColor = HexStringToCOLORREF(Wh_GetStringSetting(L"closeButtonHoverColor"));
settings.enableMod = Wh_GetIntSetting(L"enableMod") != 0; // Interpret as boolean
settings.logLevel = Wh_GetIntSetting(L"logLevel");
}
// Initialization function for the mod
BOOL Wh_ModInit() {
LoadSettings();
HMODULE dwmapiModule = GetModuleHandle(L"dwmapi.dll");
if (!dwmapiModule) {
CustomLog(1, L"Failed to get dwmapi.dll module handle");
return FALSE;
}
OriginalDwmSetWindowAttribute = (DwmSetWindowAttributeFptr)GetProcAddress(dwmapiModule, "DwmSetWindowAttribute");
if (!OriginalDwmSetWindowAttribute) {
CustomLog(1, L"Failed to get DwmSetWindowAttribute function address");
return FALSE;
}
// Hook the DwmSetWindowAttribute function
Wh_SetFunctionHook((void*)OriginalDwmSetWindowAttribute, (void*)HookDwmSetWindowAttribute, (void**)&OriginalDwmSetWindowAttribute);
CustomLog(3, L"Mod initialized successfully");
return TRUE;
}
// Function called when the mod settings are changed
void Wh_ModSettingsChanged() {
LoadSettings();
CustomLog(3, L"Settings reloaded");
}
// Uninitialization function for the mod
void Wh_ModUninit() {
CustomLog(3, L"Mod uninitialized");
}
Summary of Fixes Attempted So Far
Corrected Comment Placement:
Moved the Windhawk mod settings outside of comment blocks.
Fixed errors where mod settings were not properly defined outside comment blocks.
Adjusted Logging Macro:
Ensured correct usage of Wh_Log macro.
Verified the logging function handles format strings properly using vswprintf_s.
Fixed Use of Reserved Keywords:
Avoided using reserved keywords like char for variable names.
Corrected Function Pointer Handling:
Ensured function pointers for DwmSetWindowAttribute are correctly defined and used.
Error Handling in HexStringToCOLORREF:
Added error handling for invalid hex color format.
Boolean Settings Retrieval:
Used Wh_GetBoolSetting for retrieving boolean settings.