From 69992ccee58c3c78ccd53204fd927bd64c3ebf72 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Fri, 11 Oct 2024 05:20:09 +0300 Subject: [PATCH] Minor fixes - Removed ListView subclass - Add options: EnableThemeAnimation (default 1), EnableThemeNativeButtons (default 0) --- SystemInformer/delayhook.c | 174 ++++++++++++++++++++----------------- SystemInformer/main.c | 8 +- SystemInformer/options.c | 12 ++- SystemInformer/settings.c | 2 + phlib/extlv.c | 48 +++++----- phlib/include/guisup.h | 2 + phlib/theme.c | 95 ++------------------ tools/peview/delayhook.c | 174 ++++++++++++++++++++----------------- tools/peview/settings.c | 2 + 9 files changed, 236 insertions(+), 281 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 72e0b299a329..82902eee728d 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -30,6 +30,7 @@ static WNDPROC PhDefaultEditWindowProcedure = NULL; static WNDPROC PhDefaultHeaderWindowProcedure = NULL; static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; +static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, @@ -1282,11 +1283,11 @@ typedef struct _TASKDIALOG_CALLBACK_WRAP LONG_PTR lpCallbackData; } TASKDIALOG_CALLBACK_WRAP, * PTASKDIALOG_CALLBACK_WRAP; -typedef struct _TASKDIALOG_CONTROL_CONTEXT +typedef struct _TASKDIALOG_COMMON_CONTEXT { WNDPROC DefaultWindowProc; ULONG Painting; -} TASKDIALOG_CONTROL_CONTEXT, * PTASKDIALOG_CONTROL_CONTEXT; +} TASKDIALOG_COMMON_CONTEXT, * PTASKDIALOG_COMMON_CONTEXT; typedef struct _TASKDIALOG_WINDOW_CONTEXT { @@ -1295,6 +1296,8 @@ typedef struct _TASKDIALOG_WINDOW_CONTEXT PTASKDIALOG_CALLBACK_WRAP CallbackData; } TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; +#define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL + HRESULT CALLBACK ThemeTaskDialogCallbackHook( _In_ HWND hwndDlg, _In_ UINT uMsg, @@ -1371,70 +1374,74 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( WCHAR className[MAX_PATH]; // Apply theme to ListView checkboxes - if (iPartId == BP_CHECKBOX || iPartId == BP_RADIOBUTTON) - { - HTHEME darkButtonTheme = PhOpenThemeData(NULL, L"DarkMode_Explorer::Button", 0); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); - if (darkButtonTheme) - PhCloseThemeData(darkButtonTheme); - return retVal; - } - - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className))) + if (iPartId == BP_CHECKBOX /*|| iPartId == BP_RADIOBUTTON*/) { - if (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) - return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + { + HTHEME darkButtonTheme = PhOpenThemeData(NULL, L"DarkMode_Explorer::Button", 0); + HRESULT retVal = PhDefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (darkButtonTheme) + PhCloseThemeData(darkButtonTheme); + return retVal; + } } - switch (iPartId) - { - case TDLG_PRIMARYPANEL: - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - case TDLG_FOOTNOTEPANE: - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - return S_OK; - case TDLG_SECONDARYPANEL: + // Micro optimization + if ((iPartId == TDLG_PRIMARYPANEL || iPartId == TDLG_FOOTNOTEPANE || iPartId == TDLG_SECONDARYPANEL || iPartId == TDLG_FOOTNOTESEPARATOR || iPartId == TDLG_EXPANDOBUTTON) && + PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) { - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - RECT rect = *pRect; - rect.bottom = rect.top + 1; - SetDCBrushColor(hdc, PhThemeWindowForegroundColor); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - PhOffsetRect(&rect, 0, 1); - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } - case TDLG_FOOTNOTESEPARATOR: - { - SetDCBrushColor(hdc, PhThemeWindowForegroundColor); - FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); - RECT rect = *pRect; - rect.top += 1; - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } - case TDLG_EXPANDOBUTTON: + switch (iPartId) + { + case TDLG_PRIMARYPANEL: + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + case TDLG_FOOTNOTEPANE: + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + return S_OK; + case TDLG_SECONDARYPANEL: + { + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + RECT rect = *pRect; + rect.bottom = rect.top + 1; + SetDCBrushColor(hdc, PhThemeWindowForegroundColor); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + PhOffsetRect(&rect, 0, 1); + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + case TDLG_FOOTNOTESEPARATOR: { - // In Windows 11, buttons lack background, making them indistinguishable on dark backgrounds. - // To address this, we invert the button. This technique isn't applicable to Windows 10 as it causes the button's border to appear chipped. - static enum { yes, no, unknown } mustInvertButton = unknown; - if (mustInvertButton == unknown) + SetDCBrushColor(hdc, PhThemeWindowForegroundColor); + FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); + RECT rect = *pRect; + rect.top += 1; + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + case TDLG_EXPANDOBUTTON: { - PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); - int buttonCenterX = pOptions->rcClip.left + (pOptions->rcClip.right - pOptions->rcClip.left) / 2; - int buttonCenterY = pOptions->rcClip.top + (pOptions->rcClip.bottom - pOptions->rcClip.top) / 2; - COLORREF centerPixel = GetPixel(hdc, buttonCenterX, buttonCenterY); - mustInvertButton = centerPixel == PhThemeWindowTextColor ? no : yes; + // In Windows 11, buttons lack background, making them indistinguishable on dark backgrounds. + // To address this, we invert the button. This technique isn't applicable to Windows 10 as it causes the button's border to appear chipped. + static enum { yes, no, unknown } mustInvertButton = unknown; + if (mustInvertButton == unknown) + { + PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + int buttonCenterX = pOptions->rcClip.left + (pOptions->rcClip.right - pOptions->rcClip.left) / 2; + int buttonCenterY = pOptions->rcClip.top + (pOptions->rcClip.bottom - pOptions->rcClip.top) / 2; + COLORREF centerPixel = GetPixel(hdc, buttonCenterX, buttonCenterY); + mustInvertButton = centerPixel == PhThemeWindowTextColor ? no : yes; + } + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + if (mustInvertButton == yes) InvertRect(hdc, pRect); + HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (mustInvertButton == yes) InvertRect(hdc, pRect); + return retVal; } - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - if (mustInvertButton == yes) InvertRect(hdc, pRect); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); - if (mustInvertButton == yes) InvertRect(hdc, pRect); - return retVal; } } @@ -1596,8 +1603,6 @@ BOOL WINAPI PhSystemParametersInfoHook( //#define RGB_FROM_COLOREF(cref) \ // ((((cref) & 0x000000FF) << 16) | (((cref) & 0x0000FF00)) | (((cref) & 0x00FF0000) >> 16)) -#define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL - HRESULT WINAPI PhDrawThemeTextHook( _In_ HTHEME hTheme, _In_ HDC hdc, @@ -1610,15 +1615,20 @@ HRESULT WINAPI PhDrawThemeTextHook( _In_ LPCRECT pRect ) { - WCHAR className[MAX_PATH]; - - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) { - if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) + WCHAR className[MAX_PATH]; + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { - DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + // I'm out of ideas how to not break radio buttons in other system dialogs other than using hardcoded white list + if (iPartId == BP_COMMANDLINK || + PhEqualStringZ((PWSTR)pszText, L"Stable\n - Recommended", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Canary\n - Preview", FALSE)) + { + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + } } } @@ -1637,10 +1647,9 @@ HRESULT WINAPI PhDrawThemeTextExHook( _In_ const DTTOPTS* pOptions ) { - WCHAR className[MAX_PATH]; - if (iPartId == BP_COMMANDLINK) { + WCHAR className[MAX_PATH]; if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { @@ -1699,8 +1708,8 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( ) { WCHAR windowClassName[MAX_PATH]; - PTASKDIALOG_CONTROL_CONTEXT context; - BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, LONG_MIN); + PTASKDIALOG_COMMON_CONTEXT context; + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, (ULONG)'TDLG'); if (CallbackData && !windowHasContext) { @@ -1715,7 +1724,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; - PhSetWindowContext(WindowHandle, LONG_MIN, context); + PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); windowHasContext = TRUE; } @@ -1731,9 +1740,9 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); - context = PhAllocateZero(sizeof(TASKDIALOG_CONTROL_CONTEXT)); + context = PhAllocateZero(sizeof(TASKDIALOG_COMMON_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); - PhSetWindowContext(WindowHandle, LONG_MIN, context); + PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) @@ -1759,10 +1768,10 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( ) { LRESULT result; - PTASKDIALOG_CONTROL_CONTEXT context; + PTASKDIALOG_COMMON_CONTEXT context; WNDPROC OldWndProc; - if (!(context = PhGetWindowContext(hwnd, LONG_MIN))) + if (!(context = PhGetWindowContext(hwnd, (ULONG)'TDLG'))) return 0; OldWndProc = context->DefaultWindowProc; @@ -1812,7 +1821,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( case WM_DESTROY: { PhSetWindowProcedure(hwnd, OldWndProc); - PhRemoveWindowContext(hwnd, LONG_MIN); + PhRemoveWindowContext(hwnd, (ULONG)'TDLG'); PhFree(context); } return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); @@ -1909,8 +1918,11 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) - goto CleanupExit; + if (!PhDefaultEnableThemeAnimation) + { + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) + goto CleanupExit; + } if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) @@ -1975,6 +1987,8 @@ VOID PhInitializeSuperclassControls( PhDefaultEnableThemeAcrylicWindowSupport = !!PhGetIntegerSetting(L"EnableThemeAcrylicWindowSupport"); } + PhDefaultEnableThemeAnimation = !!PhGetIntegerSetting(L"EnableThemeAnimation"); + PhRegisterDialogSuperClass(); PhRegisterMenuSuperClass(); PhRegisterRebarSuperClass(); diff --git a/SystemInformer/main.c b/SystemInformer/main.c index 956dc66207a3..fc5d597b9bb4 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -133,7 +133,10 @@ INT WINAPI wWinMain( } PhGuiSupportInitialization(); - PhpInitializeSettings(); + if (!PhStartupParameters.Debug) + { + PhpInitializeSettings(); + } if (PhGetIntegerSetting(L"AllowOnlyOneInstance") && !PhStartupParameters.NewInstance && @@ -1196,6 +1199,8 @@ VOID PhpInitializeSettings( PhEnableWindowText = !!PhGetIntegerSetting(L"EnableWindowText"); PhEnableThemeSupport = !!PhGetIntegerSetting(L"EnableThemeSupport"); PhEnableThemeAcrylicSupport = WindowsVersion >= WINDOWS_11 && !!PhGetIntegerSetting(L"EnableThemeAcrylicSupport"); + PhEnableThemeAcrylicWindowSupport = WindowsVersion >= WINDOWS_11 && !!PhGetIntegerSetting(L"EnableThemeAcrylicWindowSupport"); + PhEnableThemeNativeButtons = !!PhGetIntegerSetting(L"EnableThemeNativeButtons"); PhEnableThemeListviewBorder = !!PhGetIntegerSetting(L"TreeListBorderEnable"); PhEnableDeferredLayout = !!PhGetIntegerSetting(L"EnableDeferredLayout"); PhEnableServiceNonPoll = !!PhGetIntegerSetting(L"EnableServiceNonPoll"); @@ -1487,6 +1492,7 @@ VOID PhpProcessStartupParameters( if (PhStartupParameters.Debug) { // The symbol provider won't work if this is chosen. + PhpInitializeSettings(); PhShowDebugConsole(); } } diff --git a/SystemInformer/options.c b/SystemInformer/options.c index 9ec2a23f133c..8877773700fc 100644 --- a/SystemInformer/options.c +++ b/SystemInformer/options.c @@ -3710,6 +3710,11 @@ INT_PTR CALLBACK PhpOptionsGraphsDlgProc( if (PhGetIntegerSetting(L"GraphColorMode")) EnableWindow(PhpGraphListViewHandle, TRUE); + else if (PhEnableThemeSupport) + { + ShowWindow(PhpGraphListViewHandle, SW_HIDE); + EnableWindow(PhpGraphListViewHandle, TRUE); + } } break; case WM_DESTROY: @@ -3741,9 +3746,10 @@ INT_PTR CALLBACK PhpOptionsGraphsDlgProc( { ListView_SetItemState(PhpGraphListViewHandle, -1, 0, LVIS_SELECTED); // deselect all items - EnableWindow(PhpGraphListViewHandle, Button_GetCheck(GET_WM_COMMAND_HWND(wParam, lParam)) == BST_CHECKED); - if (PhEnableThemeSupport) // Checkbox glitches when theme enabled (Dart Vanya) - RedrawWindow(GET_WM_COMMAND_HWND(wParam, lParam), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + if (PhEnableThemeSupport) + ShowWindow(PhpGraphListViewHandle, Button_GetCheck(GET_WM_COMMAND_HWND(wParam, lParam)) == BST_CHECKED ? SW_SHOW : SW_HIDE); + else + EnableWindow(PhpGraphListViewHandle, Button_GetCheck(GET_WM_COMMAND_HWND(wParam, lParam)) == BST_CHECKED); } break; } diff --git a/SystemInformer/settings.c b/SystemInformer/settings.c index 72c07bc65084..bb606c285344 100644 --- a/SystemInformer/settings.c +++ b/SystemInformer/settings.c @@ -80,6 +80,8 @@ VOID PhAddDefaultSettings( PhpAddIntegerSetting(L"EnableThemeSupport", L"0"); PhpAddIntegerSetting(L"EnableThemeAcrylicSupport", L"0"); PhpAddIntegerSetting(L"EnableThemeAcrylicWindowSupport", L"0"); + PhpAddIntegerSetting(L"EnableThemeAnimation", L"1"); + PhpAddIntegerSetting(L"EnableThemeNativeButtons", L"0"); PhpAddIntegerSetting(L"EnableThreadStackInlineSymbols", L"1"); PhpAddIntegerSetting(L"EnableThreadStackLineInformation", L"1"); PhpAddIntegerSetting(L"EnableTokenRemovedPrivileges", L"0"); diff --git a/phlib/extlv.c b/phlib/extlv.c index 25a0ac54488d..240aa46abed4 100644 --- a/phlib/extlv.c +++ b/phlib/extlv.c @@ -230,9 +230,8 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( { BOOLEAN colorChanged = FALSE; HFONT newFont = NULL; - BOOLEAN isWindowDisabled = (BOOLEAN)GetProp(context->Handle, L"ELVM_WindowDisabled"); // HACK - if (context->ItemColorFunction && !isWindowDisabled) + if (context->ItemColorFunction) { customDraw->clrTextBk = context->ItemColorFunction( (INT)customDraw->nmcd.dwItemSpec, @@ -254,35 +253,28 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( if (newFont) SelectFont(customDraw->nmcd.hdc, newFont); - if (!isWindowDisabled) + // Fix text readability for hot and selected colored items (Dart Vanya) + BOOLEAN UseThemeTextColor = FALSE; + if (PhEnableThemeSupport) { - // Fix text readability for hot and selected colored items (Dart Vanya) - BOOLEAN UseThemeTextColor = FALSE; - if (PhEnableThemeSupport) - { - LVITEM item; - item.iItem = (DWORD)customDraw->nmcd.dwItemSpec; - item.mask = LVIF_STATE; - item.stateMask = LVIS_SELECTED; - ListView_GetItem(context->Handle, &item); - UseThemeTextColor = customDraw->nmcd.uItemState & CDIS_HOT || item.state & LVIS_SELECTED; - } - - if (UseThemeTextColor) - { - customDraw->clrText = PhThemeWindowTextColor; - } - else if (colorChanged) - { - if (PhGetColorBrightness(customDraw->clrTextBk) > 100) // slightly less than half - customDraw->clrText = RGB(0x00, 0x00, 0x00); - else - customDraw->clrText = RGB(0xff, 0xff, 0xff); - } + LVITEM item; + item.iItem = (DWORD)customDraw->nmcd.dwItemSpec; + item.mask = LVIF_STATE; + item.stateMask = LVIS_SELECTED; + ListView_GetItem(context->Handle, &item); + UseThemeTextColor = customDraw->nmcd.uItemState & CDIS_HOT || item.state & LVIS_SELECTED; } - else + + if (UseThemeTextColor) + { + customDraw->clrText = PhThemeWindowTextColor; + } + else if (colorChanged) { - customDraw->clrText = RGB(169, 169, 169); // Light Grey + if (PhGetColorBrightness(customDraw->clrTextBk) > 100) // slightly less than half + customDraw->clrText = RGB(0x00, 0x00, 0x00); + else + customDraw->clrText = RGB(0xff, 0xff, 0xff); } if (!newFont) diff --git a/phlib/include/guisup.h b/phlib/include/guisup.h index c127fbe97de7..86cd80317e07 100644 --- a/phlib/include/guisup.h +++ b/phlib/include/guisup.h @@ -2068,6 +2068,8 @@ extern HFONT PhMonospaceFont; extern HBRUSH PhThemeWindowBackgroundBrush; extern BOOLEAN PhEnableThemeSupport; extern BOOLEAN PhEnableThemeAcrylicSupport; +extern BOOLEAN PhEnableThemeAcrylicWindowSupport; +extern BOOLEAN PhEnableThemeNativeButtons; extern BOOLEAN PhEnableThemeListviewBorder; extern COLORREF PhThemeWindowForegroundColor; extern COLORREF PhThemeWindowBackgroundColor; diff --git a/phlib/theme.c b/phlib/theme.c index b2ec2d38ec44..acd1ed83317d 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -108,13 +108,6 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( _In_ LPARAM lParam ); -LRESULT CALLBACK PhpThemeWindowListViewSubclassProc( - _In_ HWND WindowHandle, - _In_ UINT uMsg, - _In_ WPARAM wParam, - _In_ LPARAM lParam - ); - // Win10-RS5 (uxtheme.dll ordinal 132) BOOL (WINAPI *ShouldAppsUseDarkMode_I)( VOID @@ -175,6 +168,8 @@ BOOL (WINAPI *IsDarkModeAllowedForApp_I)( BOOLEAN PhEnableThemeSupport = FALSE; BOOLEAN PhEnableThemeAcrylicSupport = FALSE; +BOOLEAN PhEnableThemeAcrylicWindowSupport = FALSE; +BOOLEAN PhEnableThemeNativeButtons = FALSE; BOOLEAN PhEnableThemeListviewBorder = FALSE; HBRUSH PhThemeWindowBackgroundBrush = NULL; COLORREF PhThemeWindowForegroundColor = RGB(28, 28, 28); @@ -295,7 +290,7 @@ VOID PhInitializeSysLinkTheme( if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) windowClassName[0] = UNICODE_NULL; - if (PhEqualStringZ(windowClassName, WC_LINK, TRUE)) + if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) { LITEM linkChanges = { LIF_ITEMINDEX | LIF_STATE, 0, LIS_DEFAULTCOLORS , LIS_DEFAULTCOLORS }; while (SendMessage(WindowHandle, LM_SETITEM, 0, (LPARAM)&linkChanges)) @@ -679,16 +674,6 @@ VOID PhInitializeWindowThemeACLUI( InvalidateRect(ACLUIControl, NULL, FALSE); } -VOID PhInitializeWindowThemeListView( - _In_ HWND ListViewControl -) -{ - PhSetWindowContext(ListViewControl, LONG_MAX, (PVOID)GetWindowLongPtr(ListViewControl, GWLP_WNDPROC)); - SetWindowLongPtr(ListViewControl, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowListViewSubclassProc); - - InvalidateRect(ListViewControl, NULL, FALSE); -} - BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( _In_ HWND WindowHandle, _In_opt_ PVOID Context @@ -785,8 +770,6 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( ListView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) ListView_SetTextBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) ListView_SetTextColor(WindowHandle, PhThemeWindowTextColor); - - PhInitializeWindowThemeListView(WindowHandle); } else if (PhEqualStringZ(windowClassName, WC_TREEVIEW, FALSE)) { @@ -1788,6 +1771,9 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( } else { + if (PhEnableThemeNativeButtons && !PhEnableThemeAcrylicWindowSupport) + return CDRF_DODEFAULT; + if (isSelected) { //switch (PhpThemeColorMode) @@ -3227,72 +3213,3 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); } - -// https://github.com/notepad-plus-plus/notepad-plus-plus/issues/13933 -LRESULT CALLBACK PhpThemeWindowListViewSubclassProc( - _In_ HWND WindowHandle, - _In_ UINT uMsg, - _In_ WPARAM wParam, - _In_ LPARAM lParam -) -{ - WNDPROC oldWndProc; - - if (!(oldWndProc = PhGetWindowContext(WindowHandle, LONG_MAX))) - return FALSE; - - switch (uMsg) - { - case WM_PAINT: - if (!IsWindowEnabled(WindowHandle)) - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(WindowHandle, &ps); - - // Create a memory DC for double buffering - HDC memDC = CreateCompatibleDC(hdc); - HBITMAP memBitmap = CreateCompatibleBitmap(hdc, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); - HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap); - - // Fill background with the desired color - SetDCBrushColor(memDC, PhThemeWindowForegroundColor); // Dark background - FillRect(memDC, &ps.rcPaint, PhGetStockBrush(DC_BRUSH)); - - // Temporarily enable the ListView to allow default painting - EnableWindow(WindowHandle, TRUE); - - // Set new colors - ListView_SetBkColor(WindowHandle, PhThemeWindowForegroundColor); // Dark background - ListView_SetTextBkColor(WindowHandle, PhThemeWindowForegroundColor); // Dark text background - ListView_SetTextColor(WindowHandle, RGB(169, 169, 169)); // Light Grey - - SetProp(WindowHandle, L"ELVM_WindowDisabled", (HANDLE)TRUE); // HACK - - // Call the default paint handler on the memory DC - CallWindowProc(oldWndProc, WindowHandle, WM_PRINTCLIENT, (WPARAM)memDC, PRF_CLIENT); - - RemoveProp(WindowHandle, L"ELVM_WindowDisabled"); - - // Restore original colors - ListView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor); - ListView_SetTextBkColor(WindowHandle, PhThemeWindowBackgroundColor); - ListView_SetTextColor(WindowHandle, PhThemeWindowTextColor); - - // Restore original enabled state - EnableWindow(WindowHandle, FALSE); - - // Copy the painted image from the memory DC to the original DC - BitBlt(hdc, 0, 0, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, memDC, 0, 0, SRCCOPY); - - // Cleanup - SelectObject(memDC, oldBitmap); - DeleteObject(memBitmap); - DeleteDC(memDC); - - EndPaint(WindowHandle, &ps); - return 0; - } - } - - return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); -} diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 6e5360d49231..d801df5d4e32 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -30,6 +30,7 @@ static WNDPROC PhDefaultEditWindowProcedure = NULL; static WNDPROC PhDefaultHeaderWindowProcedure = NULL; static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; +static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, @@ -1282,11 +1283,11 @@ typedef struct _TASKDIALOG_CALLBACK_WRAP LONG_PTR lpCallbackData; } TASKDIALOG_CALLBACK_WRAP, * PTASKDIALOG_CALLBACK_WRAP; -typedef struct _TASKDIALOG_CONTROL_CONTEXT +typedef struct _TASKDIALOG_COMMON_CONTEXT { WNDPROC DefaultWindowProc; ULONG Painting; -} TASKDIALOG_CONTROL_CONTEXT, * PTASKDIALOG_CONTROL_CONTEXT; +} TASKDIALOG_COMMON_CONTEXT, * PTASKDIALOG_COMMON_CONTEXT; typedef struct _TASKDIALOG_WINDOW_CONTEXT { @@ -1295,6 +1296,8 @@ typedef struct _TASKDIALOG_WINDOW_CONTEXT PTASKDIALOG_CALLBACK_WRAP CallbackData; } TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; +#define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL + HRESULT CALLBACK ThemeTaskDialogCallbackHook( _In_ HWND hwndDlg, _In_ UINT uMsg, @@ -1371,70 +1374,74 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( WCHAR className[MAX_PATH]; // Apply theme to ListView checkboxes - if (iPartId == BP_CHECKBOX || iPartId == BP_RADIOBUTTON) - { - HTHEME darkButtonTheme = PhOpenThemeData(NULL, L"DarkMode_Explorer::Button", 0); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); - if (darkButtonTheme) - PhCloseThemeData(darkButtonTheme); - return retVal; - } - - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className))) + if (iPartId == BP_CHECKBOX /*|| iPartId == BP_RADIOBUTTON*/) { - if (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) - return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + { + HTHEME darkButtonTheme = PhOpenThemeData(NULL, L"DarkMode_Explorer::Button", 0); + HRESULT retVal = PhDefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (darkButtonTheme) + PhCloseThemeData(darkButtonTheme); + return retVal; + } } - switch (iPartId) - { - case TDLG_PRIMARYPANEL: - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - case TDLG_FOOTNOTEPANE: - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - return S_OK; - case TDLG_SECONDARYPANEL: + // Micro optimization + if ((iPartId == TDLG_PRIMARYPANEL || iPartId == TDLG_FOOTNOTEPANE || iPartId == TDLG_SECONDARYPANEL || iPartId == TDLG_FOOTNOTESEPARATOR || iPartId == TDLG_EXPANDOBUTTON) && + PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) { - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - RECT rect = *pRect; - rect.bottom = rect.top + 1; - SetDCBrushColor(hdc, PhThemeWindowForegroundColor); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - PhOffsetRect(&rect, 0, 1); - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } - case TDLG_FOOTNOTESEPARATOR: - { - SetDCBrushColor(hdc, PhThemeWindowForegroundColor); - FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); - RECT rect = *pRect; - rect.top += 1; - SetDCBrushColor(hdc, PhThemeWindowBackground2Color); - FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } - case TDLG_EXPANDOBUTTON: + switch (iPartId) + { + case TDLG_PRIMARYPANEL: + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + case TDLG_FOOTNOTEPANE: + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + return S_OK; + case TDLG_SECONDARYPANEL: + { + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + RECT rect = *pRect; + rect.bottom = rect.top + 1; + SetDCBrushColor(hdc, PhThemeWindowForegroundColor); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + PhOffsetRect(&rect, 0, 1); + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + case TDLG_FOOTNOTESEPARATOR: { - // In Windows 11, buttons lack background, making them indistinguishable on dark backgrounds. - // To address this, we invert the button. This technique isn't applicable to Windows 10 as it causes the button's border to appear chipped. - static enum { yes, no, unknown } mustInvertButton = unknown; - if (mustInvertButton == unknown) + SetDCBrushColor(hdc, PhThemeWindowForegroundColor); + FillRect(hdc, pRect, PhGetStockBrush(DC_BRUSH)); + RECT rect = *pRect; + rect.top += 1; + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + case TDLG_EXPANDOBUTTON: { - PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); - int buttonCenterX = pOptions->rcClip.left + (pOptions->rcClip.right - pOptions->rcClip.left) / 2; - int buttonCenterY = pOptions->rcClip.top + (pOptions->rcClip.bottom - pOptions->rcClip.top) / 2; - COLORREF centerPixel = GetPixel(hdc, buttonCenterX, buttonCenterY); - mustInvertButton = centerPixel == PhThemeWindowTextColor ? no : yes; + // In Windows 11, buttons lack background, making them indistinguishable on dark backgrounds. + // To address this, we invert the button. This technique isn't applicable to Windows 10 as it causes the button's border to appear chipped. + static enum { yes, no, unknown } mustInvertButton = unknown; + if (mustInvertButton == unknown) + { + PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + int buttonCenterX = pOptions->rcClip.left + (pOptions->rcClip.right - pOptions->rcClip.left) / 2; + int buttonCenterY = pOptions->rcClip.top + (pOptions->rcClip.bottom - pOptions->rcClip.top) / 2; + COLORREF centerPixel = GetPixel(hdc, buttonCenterX, buttonCenterY); + mustInvertButton = centerPixel == PhThemeWindowTextColor ? no : yes; + } + FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); + if (mustInvertButton == yes) InvertRect(hdc, pRect); + HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + if (mustInvertButton == yes) InvertRect(hdc, pRect); + return retVal; } - FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); - if (mustInvertButton == yes) InvertRect(hdc, pRect); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); - if (mustInvertButton == yes) InvertRect(hdc, pRect); - return retVal; } } @@ -1596,8 +1603,6 @@ BOOL WINAPI PhSystemParametersInfoHook( //#define RGB_FROM_COLOREF(cref) \ // ((((cref) & 0x000000FF) << 16) | (((cref) & 0x0000FF00)) | (((cref) & 0x00FF0000) >> 16)) -#define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL - HRESULT WINAPI PhDrawThemeTextHook( _In_ HTHEME hTheme, _In_ HDC hdc, @@ -1610,15 +1615,20 @@ HRESULT WINAPI PhDrawThemeTextHook( _In_ LPCRECT pRect ) { - WCHAR className[MAX_PATH]; - - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) { - if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) + WCHAR className[MAX_PATH]; + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { - DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + // I'm out of ideas how to not break radio buttons in other system dialogs other than using hardcoded white list + if (iPartId == BP_COMMANDLINK || + PhEqualStringZ((PWSTR)pszText, L"Stable\n - Recommended", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Canary\n - Preview", FALSE)) + { + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + } } } @@ -1637,10 +1647,9 @@ HRESULT WINAPI PhDrawThemeTextExHook( _In_ const DTTOPTS* pOptions ) { - WCHAR className[MAX_PATH]; - if (iPartId == BP_COMMANDLINK) { + WCHAR className[MAX_PATH]; if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { @@ -1699,8 +1708,8 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( ) { WCHAR windowClassName[MAX_PATH]; - PTASKDIALOG_CONTROL_CONTEXT context; - BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, LONG_MIN); + PTASKDIALOG_COMMON_CONTEXT context; + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, (ULONG)'TDLG'); if (CallbackData && !windowHasContext) { @@ -1715,7 +1724,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; - PhSetWindowContext(WindowHandle, LONG_MIN, context); + PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); windowHasContext = TRUE; } @@ -1731,9 +1740,9 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); - context = PhAllocateZero(sizeof(TASKDIALOG_CONTROL_CONTEXT)); + context = PhAllocateZero(sizeof(TASKDIALOG_COMMON_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); - PhSetWindowContext(WindowHandle, LONG_MIN, context); + PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) @@ -1759,10 +1768,10 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( ) { LRESULT result; - PTASKDIALOG_CONTROL_CONTEXT context; + PTASKDIALOG_COMMON_CONTEXT context; WNDPROC OldWndProc; - if (!(context = PhGetWindowContext(hwnd, LONG_MIN))) + if (!(context = PhGetWindowContext(hwnd, (ULONG)'TDLG'))) return 0; OldWndProc = context->DefaultWindowProc; @@ -1812,7 +1821,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( case WM_DESTROY: { PhSetWindowProcedure(hwnd, OldWndProc); - PhRemoveWindowContext(hwnd, LONG_MIN); + PhRemoveWindowContext(hwnd, (ULONG)'TDLG'); PhFree(context); } return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); @@ -1909,8 +1918,11 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) - goto CleanupExit; + if (!PhDefaultEnableThemeAnimation) + { + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) + goto CleanupExit; + } if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) @@ -1975,6 +1987,8 @@ VOID PvInitializeSuperclassControls( PhDefaultEnableThemeAcrylicWindowSupport = !!PhGetIntegerSetting(L"EnableThemeAcrylicWindowSupport"); } + PhDefaultEnableThemeAnimation = !!PhGetIntegerSetting(L"EnableThemeAnimation"); + PhRegisterDialogSuperClass(); PhRegisterMenuSuperClass(); PhRegisterRebarSuperClass(); diff --git a/tools/peview/settings.c b/tools/peview/settings.c index e486643fc4a5..6e581c20d3fe 100644 --- a/tools/peview/settings.c +++ b/tools/peview/settings.c @@ -27,6 +27,8 @@ VOID PvAddDefaultSettings( PhpAddIntegerSetting(L"EnableThemeSupport", L"0"); PhpAddIntegerSetting(L"EnableThemeAcrylicSupport", L"1"); PhpAddIntegerSetting(L"EnableThemeAcrylicWindowSupport", L"0"); + PhpAddIntegerSetting(L"EnableThemeAnimation", L"1"); + PhpAddIntegerSetting(L"EnableThemeNativeButtons", L"0"); PhpAddIntegerSetting(L"EnableTreeListBorder", L"1"); PhpAddIntegerSetting(L"EnableVersionSupport", L"0"); PhpAddIntegerSetting(L"SearchControlRegex", L"0");