From 881c3bf8a2018e4d2cadc7df41e46385d9d20781 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Mon, 7 Oct 2024 05:15:34 +0300 Subject: [PATCH 01/11] Theme fixes and enhancements - Advanced options menu Reset added --- SystemInformer/chdlg.c | 19 ++- SystemInformer/delayhook.c | 35 +++-- SystemInformer/options.c | 26 ++++ SystemInformer/sessshad.c | 2 + phlib/extlv.c | 18 ++- phlib/theme.c | 120 ++++++++++++++---- phlib/treenew.c | 10 +- .../ExtendedNotifications.rc | 2 +- plugins/ExtendedTools/ExtendedTools.rc | 2 +- plugins/ExtendedTools/disktab.c | 2 +- plugins/ExtendedTools/fwtab.c | 13 +- plugins/HardwareDevices/devicetree.c | 1 + plugins/NetworkTools/NetworkTools.rc | 16 +-- plugins/NetworkTools/options.c | 39 +++--- plugins/NetworkTools/resource.h | 4 +- plugins/ToolStatus/ToolStatus.rc | 2 +- tools/peview/delayhook.c | 17 ++- 17 files changed, 250 insertions(+), 78 deletions(-) diff --git a/SystemInformer/chdlg.c b/SystemInformer/chdlg.c index d889ad72746b..b267303ccd20 100644 --- a/SystemInformer/chdlg.c +++ b/SystemInformer/chdlg.c @@ -454,6 +454,10 @@ INT_PTR CALLBACK PhChooseNewPageDlgProc( } PhSetDialogFocus(WindowHandle, context->ComboBoxHandle); + + if (PhEnableThemeSupport) + DestroyWindow(GetDlgItem(WindowHandle, IDC_SIZE_)); + PhInitializeWindowTheme(WindowHandle, PhEnableThemeSupport); } break; case WM_DESTROY: @@ -560,7 +564,20 @@ INT_PTR CALLBACK PhChooseNewPageDlgProc( clientRect.top = clientRect.bottom; clientRect.bottom = clientRect.top + PhGetDpi(50, dpi); - FillRect(hdc, &clientRect, PhEnableThemeSupport ? PhThemeWindowBackgroundBrush : GetSysColorBrush(COLOR_3DFACE)); + + if (PhEnableThemeSupport) + { + SetDCBrushColor(hdc, RGB(50, 50, 50)); + FillRect(hdc, &clientRect, GetStockObject(DC_BRUSH)); + clientRect.bottom = clientRect.top + PhGetDpi(2, dpi); + InflateRect(&clientRect, -1, 0); + SetDCBrushColor(hdc, RGB(36, 36, 36)); + FillRect(hdc, &clientRect, GetStockObject(DC_BRUSH)); + } + else + { + FillRect(hdc, &clientRect, GetSysColorBrush(COLOR_3DFACE)); + } SetWindowLongPtr(WindowHandle, DWLP_MSGRESULT, TRUE); } diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 9f6f6411e3f9..aaa594255843 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -227,28 +227,34 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( PAINTSTRUCT ps; HDC hdc; HICON iconHandle; + RECT clientRect; if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) break; if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) { - if (hdc = BeginPaint(WindowHandle, &ps)) + if (BeginPaint(WindowHandle, &ps)) { - FillRect(hdc, &ps.rcPaint, PhThemeWindowBackgroundBrush); + // Fix artefacts when window moving back from off-screen (Dart Vanya) + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + + FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); DrawIconEx( hdc, - ps.rcPaint.left, - ps.rcPaint.top, + clientRect.left, + clientRect.top, iconHandle, - ps.rcPaint.right - ps.rcPaint.left, - ps.rcPaint.bottom - ps.rcPaint.top, + clientRect.right - clientRect.left, + clientRect.bottom - clientRect.top, 0, NULL, DI_NORMAL ); + ReleaseDC(WindowHandle, hdc); EndPaint(WindowHandle, &ps); } } @@ -378,17 +384,24 @@ VOID ThemeWindowStatusBarDrawPart( { SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); + blockRect.left -= 3, blockRect.top -= 1; FillRect(bufferDc, &blockRect, PhGetStockBrush(DC_BRUSH)); - //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + blockRect.left += 3, blockRect.top += 1; } else { + RECT separator; SetTextColor(bufferDc, PhThemeWindowTextColor); FillRect(bufferDc, &blockRect, PhThemeWindowBackgroundBrush); - //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + + separator = blockRect; + separator.left = separator.right - 1; + PhInflateRect(&separator, 0, -1); + SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); + FillRect(bufferDc, &separator, PhGetStockBrush(DC_BRUSH)); } - blockRect.left += 2; + blockRect.left += 2, blockRect.bottom -= 1; DrawText( bufferDc, text, @@ -396,7 +409,7 @@ VOID ThemeWindowStatusBarDrawPart( &blockRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX ); - blockRect.left -= 2; + blockRect.left -= 2, blockRect.bottom += 1; } VOID ThemeWindowRenderStatusBar( @@ -448,6 +461,8 @@ VOID ThemeWindowRenderStatusBar( DrawFrameControl(bufferDc, &sizeGripRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP); } + // Top statusbar border will be drawn by bottom tabcontrol border + for (INT i = 0; i < blockCount; i++) { ThemeWindowStatusBarDrawPart(Context, WindowHandle, bufferDc, clientRect, i); diff --git a/SystemInformer/options.c b/SystemInformer/options.c index 729437624385..e858aaf79f3d 100644 --- a/SystemInformer/options.c +++ b/SystemInformer/options.c @@ -3234,6 +3234,30 @@ INT_PTR CALLBACK PhpOptionsAdvancedDlgProc( PhDereferenceObject(text); } break; + case IDC_RESET: + { + PPH_OPTIONS_ADVANCED_ROOT_NODE* nodes; + ULONG numberOfNodes; + if (!GetSelectedOptionsAdvancedNodes(context, &nodes, &numberOfNodes)) + break; + for (ULONG i = 0; i < numberOfNodes; i++) + { + PhSettingFromString( + nodes[i]->Setting->Type, + &nodes[i]->Setting->DefaultValue, + NULL, + PhSystemDpi, + nodes[i]->Setting + ); + PhMoveReference( + &nodes[i]->ValueString, + PhSettingToString(nodes[i]->Setting->Type, nodes[i]->Setting) + ); + } + TreeNew_NodesStructured(context->TreeNewHandle); + PhApplyTreeNewFilters(&context->TreeFilterSupport); + } + break; } } break; @@ -3254,6 +3278,8 @@ INT_PTR CALLBACK PhpOptionsAdvancedDlgProc( PPH_EMENU_ITEM item; menu = PhCreateEMenu(); + PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_RESET, L"&Reset", NULL, NULL), ULONG_MAX); + PhInsertEMenuItem(menu, PhCreateEMenuSeparator(), ULONG_MAX); PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_COPY, L"&Copy\bCtrl+C", NULL, NULL), ULONG_MAX); PhInsertCopyCellEMenuItem(menu, IDC_COPY, context->TreeNewHandle, contextMenuEvent->Column); diff --git a/SystemInformer/sessshad.c b/SystemInformer/sessshad.c index 189428c492f2..8e25a44c7afd 100644 --- a/SystemInformer/sessshad.c +++ b/SystemInformer/sessshad.c @@ -159,6 +159,8 @@ INT_PTR CALLBACK PhpSessionShadowDlgProc( Button_SetCheck(GetDlgItem(hwndDlg, IDC_SHIFT), hotkey.Y & KBDSHIFT); Button_SetCheck(GetDlgItem(hwndDlg, IDC_CTRL), hotkey.Y & KBDCTRL); Button_SetCheck(GetDlgItem(hwndDlg, IDC_ALT), hotkey.Y & KBDALT); + + PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); } break; case WM_DESTROY: diff --git a/phlib/extlv.c b/phlib/extlv.c index 19e256e017cf..43af9f72b976 100644 --- a/phlib/extlv.c +++ b/phlib/extlv.c @@ -253,7 +253,23 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( if (newFont) SelectFont(customDraw->nmcd.hdc, newFont); - if (colorChanged) + // 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); diff --git a/phlib/theme.c b/phlib/theme.c index c802f41b2325..96f5ff38db0f 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -873,6 +873,14 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( PhInitializeWindowThemeACLUI(WindowHandle); } + else if (PhEqualStringZ(windowClassName, WC_EDIT, FALSE)) + { + // Fix scrollbar on multiline edit (Dart Vanya) + if (GetWindowLongPtr(WindowHandle, GWL_STYLE) & ES_MULTILINE) + { + PhWindowThemeSetDarkMode(WindowHandle, TRUE); + } + } return TRUE; } @@ -2193,7 +2201,9 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { HDC hdc = (HDC)wParam; - SetBkMode(hdc, TRANSPARENT); + //SetBkMode(hdc, TRANSPARENT); + // Fix typing in multiline edit (Dart Vanya) + SetBkColor(hdc, PhThemeWindowBackground2Color); SetTextColor(hdc, PhThemeWindowTextColor); SetDCBrushColor(hdc, PhThemeWindowBackground2Color); return (INT_PTR)PhGetStockBrush(DC_BRUSH); @@ -2310,12 +2320,19 @@ LRESULT CALLBACK PhpThemeWindowGroupBoxSubclassProc( case WM_PAINT: { PAINTSTRUCT ps; + HDC hdc; + RECT clientRect; if (!BeginPaint(WindowHandle, &ps)) break; - ThemeWindowRenderGroupBoxControl(WindowHandle, ps.hdc, &ps.rcPaint, oldWndProc); + // Fix artefacts when window moving back from off-screen (Dart Vanya) + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + + ThemeWindowRenderGroupBoxControl(WindowHandle, hdc, &clientRect, oldWndProc); + ReleaseDC(WindowHandle, hdc); EndPaint(WindowHandle, &ps); } goto DefaultWndProc; @@ -2392,17 +2409,44 @@ VOID ThemeWindowRenderTabControl( INT currentSelection = TabCtrl_GetCurSel(WindowHandle); INT count = TabCtrl_GetItemCount(WindowHandle); + RECT itemRect = { 0 }; + //RECT itemRectHighlighted; + //INT itemHighlighted = INT_ERROR; + INT headerBottom; + INT oldTop; + + oldTop = clientRect->top; + TabCtrl_GetItemRect(WindowHandle, 0, &itemRect); + clientRect->top += (itemRect.bottom - itemRect.top) * TabCtrl_GetRowCount(WindowHandle) + 2; + + SetDCBrushColor(bufferDc, PhThemeWindowBackground2Color); + FrameRect(bufferDc, clientRect, PhGetStockBrush(DC_BRUSH)); + headerBottom = clientRect->top; + clientRect->top = oldTop; + + TCITEM tabItem; + WCHAR tabHeaderText[MAX_PATH] = L""; + memset(&tabItem, 0, sizeof(TCITEM)); + + tabItem.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE; + tabItem.dwStateMask = TCIS_BUTTONPRESSED | TCIS_HIGHLIGHTED; + tabItem.cchTextMax = RTL_NUMBER_OF(tabHeaderText); + tabItem.pszText = tabHeaderText; + for (INT i = 0; i < count; i++) { - RECT itemRect; + if (i == currentSelection) + continue; TabCtrl_GetItemRect(WindowHandle, i, &itemRect); + PhOffsetRect(&itemRect, 2, 2); + itemRect.bottom += itemRect.bottom + 1 < headerBottom ? 1 : -1; + itemRect.right += itemRect.right + 1 < clientRect->right; + if (PhPtInRect(&itemRect, Context->CursorPos)) { - PhOffsetRect(&itemRect, 2, 2); - //switch (PhpThemeColorMode) //{ //case 0: // New colors @@ -2426,12 +2470,12 @@ VOID ThemeWindowRenderTabControl( SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); FillRect(bufferDc, &itemRect, PhGetStockBrush(DC_BRUSH)); - //FrameRect(bufferDc, &itemRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + //itemRectHighlighted = itemRect; + //itemHighlighted = i; + //continue; } else { - PhOffsetRect(&itemRect, 2, 2); - //switch (PhpThemeColorMode) //{ //case 0: // New colors @@ -2451,30 +2495,16 @@ VOID ThemeWindowRenderTabControl( // } // break; //case 1: // Old colors - if (currentSelection == i) { // SetTextColor(bufferDc, PhThemeWindowTextColor); - SetDCBrushColor(bufferDc, PhThemeWindowBackground2Color);// PhThemeWindowHighlightColor); // PhThemeWindowForegroundColor); + SetDCBrushColor(bufferDc, RGB(49, 49, 49)); FillRect(bufferDc, &itemRect, PhGetStockBrush(DC_BRUSH)); - } - else - { - // SetTextColor(bufferDc, PhThemeWindowTextColor); - FillRect(bufferDc, &itemRect, PhThemeWindowBackgroundBrush); + SetDCBrushColor(bufferDc, PhThemeWindowBackground2Color); + FrameRect(bufferDc, &itemRect, PhGetStockBrush(DC_BRUSH)); } } { - TCITEM tabItem; - WCHAR tabHeaderText[MAX_PATH] = L""; - - memset(&tabItem, 0, sizeof(TCITEM)); - - tabItem.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE; - tabItem.dwStateMask = TCIS_BUTTONPRESSED | TCIS_HIGHLIGHTED; - tabItem.cchTextMax = RTL_NUMBER_OF(tabHeaderText); - tabItem.pszText = tabHeaderText; - if (TabCtrl_GetItem(WindowHandle, i, &tabItem)) { DrawText( @@ -2487,6 +2517,46 @@ VOID ThemeWindowRenderTabControl( } } } + + { + TabCtrl_GetItemRect(WindowHandle, currentSelection, &itemRect); + + PhOffsetRect(&itemRect, 2, 2); + itemRect.bottom += itemRect.bottom + 1 < headerBottom ? 1 : -1; + itemRect.right += itemRect.right + 1 < clientRect->right; + PhInflateRect(&itemRect, 1, 1); // draw selected tab slightly bigger + itemRect.bottom -= 1; + SetDCBrushColor(bufferDc, PhPtInRect(&itemRect, Context->CursorPos) ? PhThemeWindowHighlightColor : RGB(0x50, 0x50, 0x50)); + FillRect(bufferDc, &itemRect, PhGetStockBrush(DC_BRUSH)); + + if (TabCtrl_GetItem(WindowHandle, currentSelection, &tabItem)) + { + DrawText( + bufferDc, + tabItem.pszText, + (UINT)PhCountStringZ(tabItem.pszText), + &itemRect, + DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX + ); + } + + //if (itemHighlighted != INT_ERROR) + //{ + // SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); + // FillRect(bufferDc, &itemRectHighlighted, PhGetStockBrush(DC_BRUSH)); + + // if (TabCtrl_GetItem(WindowHandle, itemHighlighted, &tabItem)) + // { + // DrawText( + // bufferDc, + // tabItem.pszText, + // (UINT)PhCountStringZ(tabItem.pszText), + // &itemRectHighlighted, + // DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX + // ); + // } + //} + } } LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( diff --git a/phlib/treenew.c b/phlib/treenew.c index 738fd8b6db73..ef9cafa91dcb 100644 --- a/phlib/treenew.c +++ b/phlib/treenew.c @@ -5359,9 +5359,6 @@ VOID PhTnpPaint( { if (bitmap = CreateCompatibleBitmap(hdc, 1, 1)) { - // Draw the outline of the selection rectangle. - //FrameRect(hdc, &rowRect, GetSysColorBrush(COLOR_HIGHLIGHT)); - // Fill in the selection rectangle. oldBitmap = SelectBitmap(tempDc, bitmap); tempRect.left = 0; @@ -5401,6 +5398,13 @@ VOID PhTnpPaint( blendFunction ); + // Draw the outline of the selection rectangle (Dart Vanya) + if (Context->HasFocus && node->Selected) + { + //SetDCBrushColor(hdc, RGB(0xF0, 0xF0, 0xF0)); + FrameRect(hdc, &rowRect, GetSysColorBrush(COLOR_WINDOW)); + } + SelectBitmap(tempDc, oldBitmap); DeleteBitmap(bitmap); } diff --git a/plugins/ExtendedNotifications/ExtendedNotifications.rc b/plugins/ExtendedNotifications/ExtendedNotifications.rc index f1d69874779f..80c6410419b1 100644 --- a/plugins/ExtendedNotifications/ExtendedNotifications.rc +++ b/plugins/ExtendedNotifications/ExtendedNotifications.rc @@ -109,7 +109,7 @@ BEGIN LTEXT "Log all events to this file (leave blank to disable this feature):",IDC_STATIC,13,18,196,8 EDITTEXT IDC_LOGFILENAME,13,29,178,12,ES_AUTOHSCROLL PUSHBUTTON "Browse...",IDC_BROWSE,194,28,50,14 - LTEXT "Changes will require a restart of System Informer.",IDC_STATIC,14,45,157,8 + LTEXT "Changes will require a restart of System Informer.",IDC_STATIC,14,45,210,8 END diff --git a/plugins/ExtendedTools/ExtendedTools.rc b/plugins/ExtendedTools/ExtendedTools.rc index ff4a1e0abf5b..68902b00767e 100644 --- a/plugins/ExtendedTools/ExtendedTools.rc +++ b/plugins/ExtendedTools/ExtendedTools.rc @@ -115,7 +115,7 @@ BEGIN CONTROL "Enable GPU monitoring",IDC_ENABLEGPUMONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,46,88,10 CONTROL "Enable NPU monitoring",IDC_ENABLENPUMONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,59,88,10 CONTROL "Enable GPU/NPU fahrenheit temperature",IDC_ENABLEFAHRENHEITTEMP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,72,140,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,72,210,10 CONTROL "Enable FPS monitoring",IDC_ENABLEFPSMONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,85,130,10 LTEXT "Note: FPS monitoring requires either administrative privileges or the current user a member of the ""Performance Log Users"" group.",IDC_STATIC,7,104,211,23 END diff --git a/plugins/ExtendedTools/disktab.c b/plugins/ExtendedTools/disktab.c index 26a08446e4c6..d51314074297 100644 --- a/plugins/ExtendedTools/disktab.c +++ b/plugins/ExtendedTools/disktab.c @@ -262,7 +262,7 @@ VOID EtInitializeDiskTreeList( { DiskTreeNewHandle = WindowHandle; - PhSetControlTheme(DiskTreeNewHandle, L"explorer"); + PhSetControlTheme(DiskTreeNewHandle, !PhGetIntegerSetting(L"EnableThemeSupport") ? L"explorer" : L"DarkMode_Explorer"); TreeNew_SetRedraw(WindowHandle, FALSE); SendMessage(TreeNew_GetTooltips(DiskTreeNewHandle), TTM_SETDELAYTIME, TTDT_AUTOPOP, 0x7fff); TreeNew_SetCallback(WindowHandle, EtpDiskTreeNewCallback, NULL); diff --git a/plugins/ExtendedTools/fwtab.c b/plugins/ExtendedTools/fwtab.c index 43d1391c7732..6aa9676aaa82 100644 --- a/plugins/ExtendedTools/fwtab.c +++ b/plugins/ExtendedTools/fwtab.c @@ -253,7 +253,7 @@ VOID InitializeFwTreeList( InitializeFwTreeListDpi(FwTreeNewHandle); - PhSetControlTheme(FwTreeNewHandle, L"explorer"); + PhSetControlTheme(FwTreeNewHandle, !PhGetIntegerSetting(L"EnableThemeSupport") ? L"explorer" : L"DarkMode_Explorer"); TreeNew_SetRedraw(FwTreeNewHandle, FALSE); TreeNew_SetCallback(FwTreeNewHandle, FwTreeNewCallback, NULL); @@ -360,6 +360,8 @@ VOID LoadSettingsFwTreeList( { SendMessage(TreeNew_GetTooltips(TreeNewHandle), TTM_SETDELAYTIME, TTDT_AUTOPOP, MAXSHORT); } + + LoadSettingsFwTreeUpdateMask(); } VOID SaveSettingsFwTreeList( @@ -1409,6 +1411,15 @@ BOOLEAN NTAPI FwTreeNewCallback( data.MouseEvent->ScreenLocation.y ); + if (data.Selection) + { + if (data.Selection->Id == PH_TN_COLUMN_MENU_HIDE_COLUMN_ID || + data.Selection->Id == PH_TN_COLUMN_MENU_CHOOSE_COLUMNS_ID) + { + LoadSettingsFwTreeUpdateMask(); + } + } + PhHandleTreeNewColumnMenu(&data); PhDeleteTreeNewColumnMenu(&data); } diff --git a/plugins/HardwareDevices/devicetree.c b/plugins/HardwareDevices/devicetree.c index a7cf62d93ad9..0025f8e0cd0c 100644 --- a/plugins/HardwareDevices/devicetree.c +++ b/plugins/HardwareDevices/devicetree.c @@ -1354,6 +1354,7 @@ VOID DevicesTreeInitialize( if (PhGetIntegerSetting(L"EnableThemeSupport")) { PhInitializeWindowTheme(DeviceTreeHandle, TRUE); + PhSetControlTheme(DeviceTreeHandle, L"DarkMode_Explorer"); TreeNew_ThemeSupport(DeviceTreeHandle, TRUE); } diff --git a/plugins/NetworkTools/NetworkTools.rc b/plugins/NetworkTools/NetworkTools.rc index 25cd16e7cb4a..e7c8654c9a35 100644 --- a/plugins/NetworkTools/NetworkTools.rc +++ b/plugins/NetworkTools/NetworkTools.rc @@ -69,14 +69,14 @@ BEGIN LTEXT "Max Tracert Hops:",IDC_STATIC,113,37,60,8 CONTROL "Enable extended TCP statistics",IDC_ENABLE_EXTENDED_TCP, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,19,115,10 - EDITTEXT IDC_KEYTEXT,16,100,184,14,ES_AUTOHSCROLL | ES_READONLY | WS_DISABLED + EDITTEXT IDC_GEOIDTEXT,16,100,184,14,ES_AUTOHSCROLL | ES_READONLY | WS_DISABLED LTEXT "MaxMind GeoLite Account ID:",IDC_STATIC,16,89,95,8 PUSHBUTTON "Open GeoIP.conf",IDC_GEOCONF,122,146,62,14 - PUSHBUTTON "Change",IDC_APIKEYBTN,202,100,50,14 + PUSHBUTTON "Change",IDC_APIKEYIDBTN,202,100,50,14 LTEXT "Note: You can also download GeoLite updates from the Main menu > Tools > Network Tools > Update GeoLite...",IDC_STATIC,16,167,271,24 - EDITTEXT IDC_GEOIDTEXT,16,126,184,14,ES_AUTOHSCROLL | ES_READONLY | WS_DISABLED + EDITTEXT IDC_KEYTEXT,16,126,184,14,ES_AUTOHSCROLL | ES_READONLY | WS_DISABLED LTEXT "MaxMind GeoLite License Key:",IDC_STATIC,16,116,97,8 - PUSHBUTTON "Change",IDC_APIKEYIDBTN,202,126,50,14 + PUSHBUTTON "Change",IDC_APIKEYBTN,202,126,50,14 PUSHBUTTON "Download update",IDRETRY,189,146,62,14 GROUPBOX "Network Tools",IDC_STATIC,7,7,222,63 GROUPBOX "GeoLite Update",IDC_STATIC,7,74,290,118 @@ -118,10 +118,10 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM CAPTION "Update MaxMind License Key" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - PUSHBUTTON "Save",IDYES,198,47,50,14 - DEFPUSHBUTTON "Cancel",IDCANCEL,252,47,50,14 - EDITTEXT IDC_KEYTEXT,7,24,295,14,ES_AUTOHSCROLL - LTEXT "Paste the license key here: ",IDC_STATIC,7,7,90,8 + DEFPUSHBUTTON "Save",IDYES,198,47,50,14 + PUSHBUTTON "Cancel",IDCANCEL,252,47,50,14 + EDITTEXT IDC_KEY_EDIT,7,24,295,14,ES_AUTOHSCROLL + LTEXT "Paste the",IDC_KEYTEXT_L,7,7,120,8 CONTROL "Checkout How-to-generate-a-license-key",IDC_HELPLINK, "SysLink",WS_TABSTOP,7,47,136,14 END diff --git a/plugins/NetworkTools/options.c b/plugins/NetworkTools/options.c index 90390b66290d..225171c9d289 100644 --- a/plugins/NetworkTools/options.c +++ b/plugins/NetworkTools/options.c @@ -46,8 +46,8 @@ INT_PTR CALLBACK OptionsDlgProc( PhSetDialogItemValue(WindowHandle, IDC_MAXHOPS, PhGetIntegerSetting(SETTING_NAME_TRACERT_MAX_HOPS), FALSE); Button_SetCheck(GetDlgItem(WindowHandle, IDC_ENABLE_EXTENDED_TCP), PhGetIntegerSetting(SETTING_NAME_EXTENDED_TCP_STATS) ? BST_CHECKED : BST_UNCHECKED); - PhSetDialogItemText(WindowHandle, IDC_KEYTEXT, PhGetStringOrEmpty(PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID))); - PhSetDialogItemText(WindowHandle, IDC_GEOIDTEXT, PhGetStringOrEmpty(PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY))); + PhSetDialogItemText(WindowHandle, IDC_KEYTEXT, PhGetStringOrEmpty(PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY))); + PhSetDialogItemText(WindowHandle, IDC_GEOIDTEXT, PhGetStringOrEmpty(PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID))); PhAddComboBoxStringRefs(comboHandle, OptionsGeoLiteEdition, RTL_NUMBER_OF(OptionsGeoLiteEdition)); ComboBox_SetCurSel(comboHandle, PhGetIntegerSetting(SETTING_NAME_GEOLITE_DB_TYPE)); @@ -87,7 +87,7 @@ INT_PTR CALLBACK OptionsDlgProc( ShowGeoLiteConfigDialog(WindowHandle, UlongToPtr(IDC_KEYTEXT)); - string = PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID); + string = PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY); PhSetDialogItemText(WindowHandle, IDC_KEYTEXT, PhGetStringOrEmpty(string)); } break; @@ -100,7 +100,7 @@ INT_PTR CALLBACK OptionsDlgProc( ShowGeoLiteConfigDialog(WindowHandle, UlongToPtr(IDC_GEOIDTEXT)); - string = PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY); + string = PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID); PhSetDialogItemText(WindowHandle, IDC_GEOIDTEXT, PhGetStringOrEmpty(string)); } break; @@ -181,12 +181,20 @@ INT_PTR CALLBACK OptionsGeoLiteDlgProc( PhCenterWindow(WindowHandle, GetParent(WindowHandle)); if (id == IDC_KEYTEXT) - PhSetDialogItemText(WindowHandle, id, PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID)->Buffer); + { + PhSetDialogItemText(WindowHandle, IDC_KEYTEXT_L, L"Paste the license key here:"); + PhSetDialogItemText(WindowHandle, IDC_KEY_EDIT, PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY)->Buffer); + } else - PhSetDialogItemText(WindowHandle, id, PhaGetStringSetting(SETTING_NAME_GEOLITE_API_KEY)->Buffer); + { + PhSetDialogItemText(WindowHandle, IDC_KEYTEXT_L, L"Paste the account id here:"); + PhSetDialogItemText(WindowHandle, IDC_KEY_EDIT, PhaGetStringSetting(SETTING_NAME_GEOLITE_API_ID)->Buffer); + } - PhSetDialogFocus(WindowHandle, GetDlgItem(WindowHandle, IDCANCEL)); - } + PhSetDialogFocus(WindowHandle, GetDlgItem(WindowHandle, IDC_KEY_EDIT)); + + PhInitializeWindowTheme(WindowHandle, !!PhGetIntegerSetting(L"EnableThemeSupport")); + } break; case WM_DESTROY: { @@ -205,18 +213,9 @@ INT_PTR CALLBACK OptionsGeoLiteDlgProc( ULONG id = PtrToUlong(PhGetWindowContext(WindowHandle, PH_WINDOW_CONTEXT_DEFAULT)); PPH_STRING string; - if (id == IDC_KEYTEXT) - { - string = PhGetWindowText(GetDlgItem(WindowHandle, IDC_KEYTEXT)); - PhSetStringSetting(SETTING_NAME_GEOLITE_API_ID, PhGetStringOrEmpty(string)); - PhClearReference(&string); - } - else - { - string = PhGetWindowText(GetDlgItem(WindowHandle, IDC_KEYTEXT)); - PhSetStringSetting(SETTING_NAME_GEOLITE_API_KEY, PhGetStringOrEmpty(string)); - PhClearReference(&string); - } + string = PhGetWindowText(GetDlgItem(WindowHandle, IDC_KEY_EDIT)); + PhSetStringSetting(id == IDC_KEYTEXT ? SETTING_NAME_GEOLITE_API_KEY : SETTING_NAME_GEOLITE_API_ID, PhGetStringOrEmpty(string)); + PhClearReference(&string); EndDialog(WindowHandle, IDOK); } diff --git a/plugins/NetworkTools/resource.h b/plugins/NetworkTools/resource.h index 397ec339323c..1e88a53926f3 100644 --- a/plugins/NetworkTools/resource.h +++ b/plugins/NetworkTools/resource.h @@ -281,6 +281,8 @@ #define IDC_APIKEYBTN 1039 #define IDC_GEODBCOMBO 1040 #define IDC_GEOCONF 1041 +#define IDC_KEYTEXT_L 1042 +#define IDC_KEY_EDIT 1043 // Next default values for new objects // @@ -288,7 +290,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 112 #define _APS_NEXT_COMMAND_VALUE 40006 -#define _APS_NEXT_CONTROL_VALUE 1042 +#define _APS_NEXT_CONTROL_VALUE 1044 #define _APS_NEXT_SYMED_VALUE 104 #endif #endif diff --git a/plugins/ToolStatus/ToolStatus.rc b/plugins/ToolStatus/ToolStatus.rc index f7c34016fadc..7dd7a4b8fedc 100644 --- a/plugins/ToolStatus/ToolStatus.rc +++ b/plugins/ToolStatus/ToolStatus.rc @@ -61,7 +61,7 @@ BEGIN CONTROL "Auto-hide main menu (Alt or F10 key toggle)",IDC_ENABLE_AUTOHIDE_MENU, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,78,157,10 CONTROL "Enable auto focus to search box",IDC_ENABLE_AUTOFOCUS_SEARCH, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,90,113,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,90,210,10 LTEXT "Note: Right-click the toolbar on the main window to customize the icons and graphs.",IDC_STATIC,7,7,157,18 COMBOBOX IDC_CURRENT,14,143,119,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Select the graph to show on the taskbar:",IDC_STATIC,14,132,132,8 diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index b4c949ccfa31..5a351df0b4c7 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -379,17 +379,24 @@ VOID ThemeWindowStatusBarDrawPart( { SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); + blockRect.left -= 3, blockRect.top -= 1; FillRect(bufferDc, &blockRect, PhGetStockBrush(DC_BRUSH)); - //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + blockRect.left += 3, blockRect.top += 1; } else { + RECT separator; SetTextColor(bufferDc, PhThemeWindowTextColor); FillRect(bufferDc, &blockRect, PhThemeWindowBackgroundBrush); - //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + + CopyRect(&separator, &blockRect); + separator.left = separator.right - 1; + InflateRect(&separator, 0, -1); + SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); + FillRect(bufferDc, &separator, PhGetStockBrush(DC_BRUSH)); } - blockRect.left += 2; + blockRect.left += 2, blockRect.bottom -= 1; DrawText( bufferDc, text, @@ -397,7 +404,7 @@ VOID ThemeWindowStatusBarDrawPart( &blockRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX ); - blockRect.left -= 2; + blockRect.left -= 2, blockRect.bottom += 1; } VOID ThemeWindowRenderStatusBar( @@ -449,6 +456,8 @@ VOID ThemeWindowRenderStatusBar( DrawFrameControl(bufferDc, &sizeGripRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP); } + // Top statusbar border will be drawn by bottom tabcontrol border + for (INT i = 0; i < blockCount; i++) { ThemeWindowStatusBarDrawPart(Context, WindowHandle, bufferDc, clientRect, i); From fc395e6dd565351dfc046c0dc2e80bc335b703e2 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Wed, 9 Oct 2024 11:04:47 +0300 Subject: [PATCH 02/11] Full DarkMode support for TaskDialog Credits to https://github.com/SFTRS/DarkTaskDialog - Highlighting and Graph colors: menu - Reset added - Fix drawing of disabled ListView in dark theme - SysLink theme support (call PhInitializeSysLinkTheme to apply to control) --- SystemInformer/about.c | 2 + SystemInformer/chdlg.c | 12 +- SystemInformer/delayhook.c | 634 ++++++++++++++++++++++++++------- SystemInformer/hidnproc.c | 2 +- SystemInformer/main.c | 3 +- SystemInformer/options.c | 150 ++++++++ SystemInformer/prpggen.c | 6 +- phlib/extlv.c | 50 +-- phlib/include/guisup.h | 7 + phlib/theme.c | 133 ++++++- plugins/UserNotes/options.c | 2 +- tools/peview/delayhook.c | 681 ++++++++++++++++++++++++++++-------- tools/peview/peprp.c | 3 + tools/peview/prpsh.c | 2 +- 14 files changed, 1388 insertions(+), 299 deletions(-) diff --git a/SystemInformer/about.c b/SystemInformer/about.c index 7fc18297abb8..296a26966bc6 100644 --- a/SystemInformer/about.c +++ b/SystemInformer/about.c @@ -72,6 +72,8 @@ static INT_PTR CALLBACK PhpAboutDlgProc( PhRegisterWindowCallback(hwndDlg, PH_PLUGIN_WINDOW_EVENT_TYPE_TOPMOST, NULL); PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); + if (PhEnableThemeSupport) + PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_LINK_SF)); } break; case WM_DESTROY: diff --git a/SystemInformer/chdlg.c b/SystemInformer/chdlg.c index b267303ccd20..adc6063d2f0b 100644 --- a/SystemInformer/chdlg.c +++ b/SystemInformer/chdlg.c @@ -568,11 +568,13 @@ INT_PTR CALLBACK PhChooseNewPageDlgProc( if (PhEnableThemeSupport) { SetDCBrushColor(hdc, RGB(50, 50, 50)); - FillRect(hdc, &clientRect, GetStockObject(DC_BRUSH)); - clientRect.bottom = clientRect.top + PhGetDpi(2, dpi); - InflateRect(&clientRect, -1, 0); - SetDCBrushColor(hdc, RGB(36, 36, 36)); - FillRect(hdc, &clientRect, GetStockObject(DC_BRUSH)); + FillRect(hdc, &clientRect, PhGetStockBrush(DC_BRUSH)); + clientRect.bottom = clientRect.top + 1; + SetDCBrushColor(hdc, PhThemeWindowForegroundColor); + FillRect(hdc, &clientRect, PhGetStockBrush(DC_BRUSH)); + PhOffsetRect(&clientRect, 0, 1); + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &clientRect, PhGetStockBrush(DC_BRUSH)); } else { diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index aaa594255843..72e0b299a329 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "settings.h" @@ -866,35 +867,40 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( { CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam; - if (createStruct->hwndParent) + // Don't apply header theme for unsupported dialogs: Advanced Security and Digital Signature Details (Dart Vanya) + if (!FindWindowEx(GetAncestor(WindowHandle, GA_ROOT), NULL, L"DirectUIHWND", NULL) && + !FindWindowEx(GetParent(createStruct->hwndParent), NULL, L"NativeFontCtl", NULL)) { - WCHAR windowClassName[MAX_PATH]; - - if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; - - if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) + if (createStruct->hwndParent) { - LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); + WCHAR windowClassName[MAX_PATH]; + + if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; - if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) { - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); - return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + + return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + } } } - } - - context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); - context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); - context->CursorPos.x = LONG_MIN; - context->CursorPos.y = LONG_MIN; - PhSetWindowContext(WindowHandle, LONG_MAX, context); + + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); + context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); + context->CursorPos.x = LONG_MIN; + context->CursorPos.y = LONG_MIN; + PhSetWindowContext(WindowHandle, LONG_MAX, context); - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - InvalidateRect(WindowHandle, NULL, FALSE); + InvalidateRect(WindowHandle, NULL, FALSE); + } } else { @@ -1200,14 +1206,53 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( _In_ LPCRECT ClipRect ) = NULL; -//static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( -// _In_ HTHEME Theme, -// _In_ HDC hdc, -// _In_ INT PartId, -// _In_ INT StateId, -// _In_ LPCRECT Rect, -// _In_ PVOID Options -// ) = NULL; +static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCRECT pRect, + _In_ const DTBGOPTS* pOptions + ) = NULL; + +static HRESULT(WINAPI* PhDefaultDrawThemeText)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _In_ DWORD dwTextFlags2, + _In_ LPCRECT pRect + ) = NULL; + +static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _Inout_ LPRECT pRect, + _In_ const DTTOPTS* pOptions + ) = NULL; + +static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( + _In_ const TASKDIALOGCONFIG* pTaskConfig, + _Out_opt_ int* pnButton, + _Out_opt_ int* pnRadioButton, + _Out_opt_ BOOL* pfVerificationFlagChecked + ) = NULL; + +static HRESULT(WINAPI* PhDefaultGetThemeColor)( + _In_ HTHEME hTheme, + _In_ int iPartId, + _In_ int iStateId, + _In_ int iPropId, + _Out_ COLORREF* pColor + ) = NULL; static BOOL (WINAPI* PhDefaultSystemParametersInfo)( _In_ UINT uiAction, @@ -1231,10 +1276,44 @@ static HWND (WINAPI* PhDefaultCreateWindowEx)( _In_opt_ PVOID Param ) = NULL; -//static COLORREF (WINAPI* PhDefaultSetTextColor)( -// _In_ HDC hdc, -// _In_ COLORREF color -// ) = NULL; +typedef struct _TASKDIALOG_CALLBACK_WRAP +{ + PFTASKDIALOGCALLBACK pfCallback; + LONG_PTR lpCallbackData; +} TASKDIALOG_CALLBACK_WRAP, * PTASKDIALOG_CALLBACK_WRAP; + +typedef struct _TASKDIALOG_CONTROL_CONTEXT +{ + WNDPROC DefaultWindowProc; + ULONG Painting; +} TASKDIALOG_CONTROL_CONTEXT, * PTASKDIALOG_CONTROL_CONTEXT; + +typedef struct _TASKDIALOG_WINDOW_CONTEXT +{ + WNDPROC DefaultWindowProc; + ULONG Painting; + PTASKDIALOG_CALLBACK_WRAP CallbackData; +} TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; + +HRESULT CALLBACK ThemeTaskDialogCallbackHook( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam, + _In_ LONG_PTR dwRefData +); + +LRESULT CALLBACK ThemeTaskDialogMasterSubclass( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam +); + +BOOLEAN CALLBACK PhInitializeTaskDialogTheme( + _In_ HWND hwndDlg, + _In_opt_ PVOID Context +); HRESULT PhDrawThemeBackgroundHook( _In_ HTHEME Theme, @@ -1245,11 +1324,12 @@ HRESULT PhDrawThemeBackgroundHook( _In_ LPCRECT ClipRect ) { + WCHAR className[MAX_PATH]; + BOOLEAN hasThemeClass = PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className)); + if (WindowsVersion >= WINDOWS_11) { - WCHAR className[MAX_PATH]; - - if (PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className))) + if (hasThemeClass) { if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) { @@ -1262,44 +1342,104 @@ HRESULT PhDrawThemeBackgroundHook( } } + if (hasThemeClass) + { + if (PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE)) + { + if (PartId == PP_TRANSPARENTBAR) // Progress bar background. + { + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); + FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + } + } + return PhDefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); } -//HRESULT WINAPI PhDrawThemeBackgroundExHook( -// _In_ HTHEME Theme, -// _In_ HDC hdc, -// _In_ INT PartId, -// _In_ INT StateId, -// _In_ LPCRECT Rect, -// _In_ PVOID Options // DTBGOPTS -// ) -//{ -// //HWND windowHandle = WindowFromDC(hdc); -// WCHAR className[MAX_PATH]; -// -// if (PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className))) -// { -// if (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) -// goto CleanupExit; -// } -// -// if (PartId == TDLG_PRIMARYPANEL && StateId == 0) -// { -// SetDCBrushColor(hdc, RGB(65, 65, 65)); -// FillRect(hdc, Rect, PhGetStockBrush(DC_BRUSH)); -// return S_OK; -// } -// -// if (PartId == TDLG_SECONDARYPANEL && StateId == 0) -// { -// SetDCBrushColor(hdc, RGB(45, 45, 45)); -// FillRect(hdc, Rect, PhGetStockBrush(DC_BRUSH)); -// return S_OK; -// } -// -//CleanupExit: -// return PhDefaultDrawThemeBackgroundEx(Theme, hdc, PartId, StateId, Rect, Options); -//} +HRESULT WINAPI PhDrawThemeBackgroundExHook( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCRECT pRect, + _In_ const DTBGOPTS* pOptions +) +{ + 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 (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) + return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + } + + 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: + { + 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: + { + // 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; + } + } + + return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); +} HWND PhCreateWindowExHook( _In_ ULONG ExStyle, @@ -1344,24 +1484,13 @@ HWND PhCreateWindowExHook( PhSetWindowAcrylicCompositionColor(windowHandle, MakeABGRFromCOLORREF(0, RGB(10, 10, 10))); } } - else + else if (PhEnableThemeSupport) { - //HWND parentHandle; - // - //if (parentHandle = GetAncestor(windowHandle, GA_ROOT)) - //{ - // if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, L"DirectUIHWND", TRUE)) - // { - // PhInitializeTaskDialogTheme(windowHandle, PhDefaultThemeSupport); // don't initialize parentHandle themes - // PhInitializeThemeWindowFrame(parentHandle); - // - // if (PhDefaultEnableStreamerMode) - // { - // if (SetWindowDisplayAffinity_Import()) - // SetWindowDisplayAffinity_Import()(parentHandle, WDA_EXCLUDEFROMCAPTURE); - // } - // } - //} + // Early subclassing of the SysLink control to eliminate blinking during page switches. + if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, WC_LINK, TRUE)) + { + PhInitializeTaskDialogTheme(windowHandle, 0); + } } return windowHandle; @@ -1466,33 +1595,277 @@ BOOL WINAPI PhSystemParametersInfoHook( // RGB(GetBValue(color), GetGValue(color), GetRValue(color)); //#define RGB_FROM_COLOREF(cref) \ // ((((cref) & 0x000000FF) << 16) | (((cref) & 0x0000FF00)) | (((cref) & 0x00FF0000) >> 16)) -// -//COLORREF WINAPI PhSetTextColorHook( -// _In_ HDC hdc, -// _In_ COLORREF color -// ) -//{ -// //HWND windowHandle = WindowFromDC(hdc); -// -// if (!(PhTaskDialogThemeHookIndex && PhTlsGetValue(PhTaskDialogThemeHookIndex))) -// goto CleanupExit; -// -// if (RGB_FROM_COLOREF(RGB_FROM_COLOREF(color)) == RGB(0, 51, 153)) // TMT_TEXTCOLOR (TaskDialog InstructionPane) -// { -// color = RGB(0, 102, 255); -// } -// else if (RGB_FROM_COLOREF(RGB_FROM_COLOREF(color)) == RGB(0, 102, 204)) // TaskDialog Link -// { -// color = RGB(0, 128, 0); // RGB(128, 255, 128); -// } -// else -// { -// color = RGB(255, 255, 255); // GetBkColor(hdc); -// } -// -//CleanupExit: -// return PhDefaultSetTextColor(hdc, color); -//} + +#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, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _In_ DWORD dwTextFlags2, + _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) + { + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + } + } + + return PhDefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); +} + +HRESULT WINAPI PhDrawThemeTextExHook( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _Inout_ LPRECT pRect, + _In_ const DTTOPTS* pOptions + ) +{ + WCHAR className[MAX_PATH]; + + if (iPartId == BP_COMMANDLINK) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + { + DTTOPTS options; + if (pOptions) + options = *pOptions; + else { + memset(&options, 0, sizeof(options)); + options.dwSize = sizeof(DTTOPTS); + } + options.dwFlags |= DTT_TEXTCOLOR; + PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); + options.crText = PhMakeColorBrighter(options.crText, 90); + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); + } + } + + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); +} + +HRESULT PhGetThemeColorHook( + _In_ HTHEME hTheme, + _In_ int iPartId, + _In_ int iStateId, + _In_ int iPropId, + _Out_ COLORREF* pColor + ) +{ + WCHAR className[MAX_PATH]; + + HRESULT retVal = PhDefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); + + if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + { + *pColor = PhMakeColorBrighter(*pColor, 150); // Main header. + } + } + else if (iPropId == TMT_TEXTCOLOR) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + { + *pColor = PhThemeWindowTextColor; // Text color for check boxes, expanded text, and expander button text. + } + } + + return retVal; +} + +BOOLEAN CALLBACK PhInitializeTaskDialogTheme( + _In_ HWND WindowHandle, + _In_opt_ PVOID CallbackData +) +{ + WCHAR windowClassName[MAX_PATH]; + PTASKDIALOG_CONTROL_CONTEXT context; + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, LONG_MIN); + + if (CallbackData && !windowHasContext) + { + PhInitializeThemeWindowFrame(WindowHandle); + + if (PhDefaultEnableStreamerMode) + { + if (SetWindowDisplayAffinity_Import()) + SetWindowDisplayAffinity_Import()(WindowHandle, WDA_EXCLUDEFROMCAPTURE); + } + + PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); + context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); + context->CallbackData = CallbackData; + PhSetWindowContext(WindowHandle, LONG_MIN, context); + windowHasContext = TRUE; + } + + PhEnumChildWindows( + WindowHandle, + 0x1000, + PhInitializeTaskDialogTheme, + NULL + ); + + if (windowHasContext) // HACK + return TRUE; + + GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); + + context = PhAllocateZero(sizeof(TASKDIALOG_CONTROL_CONTEXT)); + context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); + PhSetWindowContext(WindowHandle, LONG_MIN, context); + + if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || + PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + } + else if (PhEqualStringZ(windowClassName, L"DirectUIHWND", FALSE)) + { + //WINDOWPLACEMENT pos = { 0 }; + //GetWindowPlacement(GetParent(WindowHandle), &pos); + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + //SetWindowPlacement(GetParent(WindowHandle), &pos); + } + + return TRUE; +} + +LRESULT CALLBACK ThemeTaskDialogMasterSubclass( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + LRESULT result; + PTASKDIALOG_CONTROL_CONTEXT context; + WNDPROC OldWndProc; + + if (!(context = PhGetWindowContext(hwnd, LONG_MIN))) + return 0; + + OldWndProc = context->DefaultWindowProc; + + switch (uMsg) + { + case WM_ERASEBKGND: + { + HDC hdc = (HDC)wParam; + RECT rect; + WCHAR windowClassName[MAX_PATH]; + + SetTextColor(hdc, PhThemeWindowTextColor); // Color for SysLink, which must be set in its parent. + + if (!context->Painting) + { + GETCLASSNAME_OR_NULL(hwnd, windowClassName); + // Avoid erasing the background for links, as they will blink white on the extender and during page switches. + if (!PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + { + GetClipBox(hdc, &rect); + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + } + else + { + PhInitializeSysLinkTheme(hwnd); // this doesn't work in EnumWindows callback, I don't know why + } + } + } + return TRUE; + case TDM_NAVIGATE_PAGE: + { + PTASKDIALOG_WINDOW_CONTEXT WindowContext = (PTASKDIALOG_WINDOW_CONTEXT)context; + PTASKDIALOGCONFIG trueConfig = (PTASKDIALOGCONFIG)lParam; + PTASKDIALOGCONFIG myConfig; + TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) }; + + WindowContext->CallbackData->pfCallback = trueConfig ? trueConfig->pfCallback : NULL; + WindowContext->CallbackData->lpCallbackData = trueConfig ? trueConfig->lpCallbackData : 0; + myConfig = trueConfig ? trueConfig : &config; + myConfig->pfCallback = ThemeTaskDialogCallbackHook; + myConfig->lpCallbackData = (LONG_PTR)WindowContext->CallbackData; + + return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, (LPARAM)myConfig); + } + case WM_DESTROY: + { + PhSetWindowProcedure(hwnd, OldWndProc); + PhRemoveWindowContext(hwnd, LONG_MIN); + PhFree(context); + } + return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); + case WM_CTLCOLORDLG: + return (LRESULT)PhThemeWindowBackgroundBrush; // Window background color when the extender resizes upward (Windows 10 only). + } + + context->Painting++; + result = CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); + context->Painting--; + return result; +} + +HRESULT CALLBACK ThemeTaskDialogCallbackHook( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam, + _In_ LONG_PTR dwRefData + ) +{ + HRESULT result = S_OK; + + PTASKDIALOG_CALLBACK_WRAP CallbackData = (PTASKDIALOG_CALLBACK_WRAP)dwRefData; + + if (uMsg == TDN_DIALOG_CONSTRUCTED) // Called on each new page, including the first one. + { + PhInitializeTaskDialogTheme(hwndDlg, CallbackData); + } + + if (CallbackData->pfCallback) + result = CallbackData->pfCallback(hwndDlg, uMsg, wParam, lParam, CallbackData->lpCallbackData); + + return result; +} + +// https://github.com/SFTRS/DarkTaskDialog +HRESULT PhTaskDialogIndirectHook( + _In_ const TASKDIALOGCONFIG* pTaskConfig, + _Out_opt_ int* pnButton, + _Out_opt_ int* pnRadioButton, + _Out_opt_ BOOL* pfVerificationFlagChecked + ) +{ + TASKDIALOG_CALLBACK_WRAP CallbackData; + CallbackData.pfCallback = pTaskConfig->pfCallback; + CallbackData.lpCallbackData = pTaskConfig->lpCallbackData; + TASKDIALOGCONFIG myConfig = *pTaskConfig; + myConfig.pfCallback = ThemeTaskDialogCallbackHook; + myConfig.lpCallbackData = (LONG_PTR)&CallbackData; + + return PhDefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); +} VOID PhRegisterDetoursHooks( VOID @@ -1501,10 +1874,11 @@ VOID PhRegisterDetoursHooks( NTSTATUS status; PVOID baseAddress; - //if (baseAddress = PhGetLoaderEntryDllBaseZ(L"gdi32.dll")) - //{ - // PhDefaultSetTextColor = PhGetDllBaseProcedureAddress(baseAddress, "SetTextColor", 0); - //} + // For early TaskDialog with PhStartupParameters.ShowOptions + if (!PhThemeWindowBackgroundBrush) + { + PhThemeWindowBackgroundBrush = CreateSolidBrush(PhThemeWindowBackgroundColor); + } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"user32.dll")) { @@ -1515,7 +1889,15 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); - //PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); + PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); + PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + } + + if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) + { + PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); } if (!NT_SUCCESS(status = DetourTransactionBegin())) @@ -1525,16 +1907,22 @@ VOID PhRegisterDetoursHooks( { if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) goto CleanupExit; - //if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) - // 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 (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + goto CleanupExit; } if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) goto CleanupExit; - //if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSetTextColor, (PVOID)PhSetTextColorHook))) - // goto CleanupExit; if (!NT_SUCCESS(status = DetourTransactionCommit())) goto CleanupExit; diff --git a/SystemInformer/hidnproc.c b/SystemInformer/hidnproc.c index 2af8b7cb1d4d..64edcc0be8e5 100644 --- a/SystemInformer/hidnproc.c +++ b/SystemInformer/hidnproc.c @@ -554,7 +554,7 @@ COLORREF NTAPI PhpZombieProcessesColorFunction( return RGB(0x77, 0x77, 0x77); } - return GetSysColor(COLOR_WINDOW); + return PhEnableThemeSupport ? PhThemeWindowBackgroundColor : GetSysColor(COLOR_WINDOW); } BOOLEAN NTAPI PhpZombieProcessesCallback( diff --git a/SystemInformer/main.c b/SystemInformer/main.c index 317aeb2f9de4..956dc66207a3 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -173,6 +173,8 @@ INT WINAPI wWinMain( } } + PhInitializeSuperclassControls(); + if (PhEnableKsiSupport && !PhStartupParameters.ShowOptions) { @@ -194,7 +196,6 @@ INT WINAPI wWinMain( PhGraphControlInitialization(); PhHexEditInitialization(); PhColorBoxInitialization(); - PhInitializeSuperclassControls(); PhInitializeAppSystem(); PhInitializeCallbacks(); diff --git a/SystemInformer/options.c b/SystemInformer/options.c index e858aaf79f3d..9ec2a23f133c 100644 --- a/SystemInformer/options.c +++ b/SystemInformer/options.c @@ -3531,6 +3531,8 @@ INT_PTR CALLBACK PhpOptionsHighlightingDlgProc( } PhSaveCustomColorList(L"OptionsCustomColorList", customColors, RTL_NUMBER_OF(customColors)); + + ListView_SetItemState(HighlightingListViewHandle, -1, 0, LVIS_SELECTED); } } } @@ -3552,6 +3554,101 @@ INT_PTR CALLBACK PhpOptionsHighlightingDlgProc( REFLECT_MESSAGE_DLG(hwndDlg, HighlightingListViewHandle, uMsg, wParam, lParam); } break; + case WM_CONTEXTMENU: + { + if ((HWND)wParam == HighlightingListViewHandle) + { + POINT point; + PPH_EMENU menu; + PPH_EMENU item; + PCOLOR_ITEM ColorItem; + + point.x = GET_X_LPARAM(lParam); + point.y = GET_Y_LPARAM(lParam); + + if (point.x == -1 && point.y == -1) + PhGetListViewContextMenuPoint(HighlightingListViewHandle, &point); + + if (ColorItem = PhGetSelectedListViewItemParam(HighlightingListViewHandle)) + { + menu = PhCreateEMenu(); + PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_RESET, L"&Reset", NULL, NULL), ULONG_MAX); + + item = PhShowEMenu( + menu, + hwndDlg, + PH_EMENU_SHOW_LEFTRIGHT, + PH_ALIGN_LEFT | PH_ALIGN_TOP, + point.x, + point.y + ); + + if (item && item->Id == IDC_RESET) + { + PH_STRINGREF SettingName; + PH_STRINGREF UseSettingName; + PPH_SETTING Color; + PPH_SETTING UseColor; + + PhInitializeStringRef(&SettingName, ColorItem->SettingName); + PhInitializeStringRef(&UseSettingName, ColorItem->UseSettingName); + Color = PhGetSetting(&SettingName); + UseColor = PhGetSetting(&UseSettingName); + + PhSettingFromString(Color->Type, &Color->DefaultValue, NULL, PhSystemDpi, Color); + PhSettingFromString(UseColor->Type, &UseColor->DefaultValue, NULL, PhSystemDpi, UseColor); + + ColorItem->CurrentColor = Color->u.Integer; + ColorItem->CurrentUse = !!UseColor->u.Integer; + + INT index = PhFindListViewItemByParam(HighlightingListViewHandle, INT_ERROR, ColorItem); + ListView_SetCheckState(HighlightingListViewHandle, index, ColorItem->CurrentUse); + ListView_SetItemState(HighlightingListViewHandle, index, 0, LVIS_SELECTED); + } + + PhDestroyEMenu(menu); + } + } + else if ((HWND)wParam == GetDlgItem(hwndDlg, IDC_NEWOBJECTS) || (HWND)wParam == GetDlgItem(hwndDlg, IDC_REMOVEDOBJECTS)) + { + POINT point; + PPH_EMENU menu; + PPH_EMENU item; + + point.x = GET_X_LPARAM(lParam); + point.y = GET_Y_LPARAM(lParam); + + menu = PhCreateEMenu(); + PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_RESET, L"&Reset", NULL, NULL), ULONG_MAX); + + item = PhShowEMenu( + menu, + hwndDlg, + PH_EMENU_SHOW_LEFTRIGHT, + PH_ALIGN_LEFT | PH_ALIGN_TOP, + point.x, + point.y + ); + + if (item && item->Id == IDC_RESET) + { + PH_STRINGREF SettingName; + PPH_SETTING Color; + BOOLEAN setNew = (HWND)wParam == GetDlgItem(hwndDlg, IDC_NEWOBJECTS); + + PhInitializeStringRef(&SettingName, setNew ? L"ColorNew" : L"ColorRemoved"); + Color = PhGetSetting(&SettingName); + + PhSettingFromString(Color->Type, &Color->DefaultValue, NULL, PhSystemDpi, Color); + + ColorBox_SetColor(GetDlgItem(hwndDlg, setNew ? IDC_NEWOBJECTS : IDC_REMOVEDOBJECTS), Color->u.Integer); + InvalidateRect(GetDlgItem(hwndDlg, setNew ? IDC_NEWOBJECTS : IDC_REMOVEDOBJECTS), NULL, TRUE); + } + + PhDestroyEMenu(menu); + } + } + break; case WM_CTLCOLORBTN: return HANDLE_WM_CTLCOLORBTN(hwndDlg, wParam, lParam, PhWindowThemeControlColor); case WM_CTLCOLORDLG: @@ -3645,6 +3742,8 @@ 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); } break; } @@ -3684,6 +3783,8 @@ INT_PTR CALLBACK PhpOptionsGraphsDlgProc( } PhSaveCustomColorList(L"OptionsCustomColorList", customColors, RTL_NUMBER_OF(customColors)); + + ListView_SetItemState(PhpGraphListViewHandle, -1, 0, LVIS_SELECTED); } } } @@ -3708,6 +3809,55 @@ INT_PTR CALLBACK PhpOptionsGraphsDlgProc( } } break; + case WM_CONTEXTMENU: + { + if ((HWND)wParam == PhpGraphListViewHandle) + { + POINT point; + PPH_EMENU menu; + PPH_EMENU item; + PCOLOR_ITEM ColorItem; + + point.x = GET_X_LPARAM(lParam); + point.y = GET_Y_LPARAM(lParam); + + if (point.x == -1 && point.y == -1) + PhGetListViewContextMenuPoint(PhpGraphListViewHandle, &point); + + if (ColorItem = PhGetSelectedListViewItemParam(PhpGraphListViewHandle)) + { + menu = PhCreateEMenu(); + PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_RESET, L"&Reset", NULL, NULL), ULONG_MAX); + + item = PhShowEMenu( + menu, + hwndDlg, + PH_EMENU_SHOW_LEFTRIGHT, + PH_ALIGN_LEFT | PH_ALIGN_TOP, + point.x, + point.y + ); + + if (item && item->Id == IDC_RESET) + { + PH_STRINGREF SettingName; + PPH_SETTING Color; + + PhInitializeStringRef(&SettingName, ColorItem->SettingName); + Color = PhGetSetting(&SettingName); + + PhSettingFromString(Color->Type, &Color->DefaultValue, NULL, PhSystemDpi, Color); + + ColorItem->CurrentColor = Color->u.Integer; + + ListView_SetItemState(PhpGraphListViewHandle, -1, 0, LVIS_SELECTED); + } + + PhDestroyEMenu(menu); + } + } + } + break; case WM_CTLCOLORBTN: return HANDLE_WM_CTLCOLORBTN(hwndDlg, wParam, lParam, PhWindowThemeControlColor); case WM_CTLCOLORDLG: diff --git a/SystemInformer/prpggen.c b/SystemInformer/prpggen.c index 1fc38e029df3..ade818ab5dc1 100644 --- a/SystemInformer/prpggen.c +++ b/SystemInformer/prpggen.c @@ -542,7 +542,11 @@ INT_PTR CALLBACK PhpProcessGeneralDlgProc( PhSetDialogItemText(hwndDlg, IDC_PROCESSTYPETEXT, PH_AUTO_T(PH_STRING, PhGetProcessItemImageTypeText(processItem))->Buffer); - PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); + if (PhEnableThemeSupport) + { + PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); + PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_COMPANYNAME_LINK)); + } PhSetTimer(hwndDlg, PH_WINDOW_TIMER_DEFAULT, 1000, NULL); } diff --git a/phlib/extlv.c b/phlib/extlv.c index 43af9f72b976..25a0ac54488d 100644 --- a/phlib/extlv.c +++ b/phlib/extlv.c @@ -230,8 +230,9 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( { BOOLEAN colorChanged = FALSE; HFONT newFont = NULL; + BOOLEAN isWindowDisabled = (BOOLEAN)GetProp(context->Handle, L"ELVM_WindowDisabled"); // HACK - if (context->ItemColorFunction) + if (context->ItemColorFunction && !isWindowDisabled) { customDraw->clrTextBk = context->ItemColorFunction( (INT)customDraw->nmcd.dwItemSpec, @@ -253,29 +254,36 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( if (newFont) SelectFont(customDraw->nmcd.hdc, newFont); - // Fix text readability for hot and selected colored items (Dart Vanya) - BOOLEAN UseThemeTextColor = FALSE; - if (PhEnableThemeSupport) + if (!isWindowDisabled) { - 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; + // 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); + } } - - if (UseThemeTextColor) - { - customDraw->clrText = PhThemeWindowTextColor; - } - else if (colorChanged) + else { - if (PhGetColorBrightness(customDraw->clrTextBk) > 100) // slightly less than half - customDraw->clrText = RGB(0x00, 0x00, 0x00); - else - customDraw->clrText = RGB(0xff, 0xff, 0xff); - } + customDraw->clrText = RGB(169, 169, 169); // Light Grey + } if (!newFont) return CDRF_DODEFAULT; diff --git a/phlib/include/guisup.h b/phlib/include/guisup.h index d4f59e515a9a..c127fbe97de7 100644 --- a/phlib/include/guisup.h +++ b/phlib/include/guisup.h @@ -2090,6 +2090,13 @@ PhInitializeWindowThemeEx( _In_ HWND WindowHandle ); +PHLIBAPI +VOID +NTAPI +PhInitializeSysLinkTheme( + _In_ HWND WindowHandle + ); + PHLIBAPI VOID NTAPI diff --git a/phlib/theme.c b/phlib/theme.c index 96f5ff38db0f..b2ec2d38ec44 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -108,6 +108,13 @@ 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 @@ -280,6 +287,22 @@ VOID PhInitializeWindowThemeEx( PhInitializeWindowTheme(WindowHandle, enableThemeSupport); } +VOID PhInitializeSysLinkTheme( + _In_ HWND WindowHandle + ) +{ + WCHAR windowClassName[MAX_PATH]; + if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + + if (PhEqualStringZ(windowClassName, WC_LINK, TRUE)) + { + LITEM linkChanges = { LIF_ITEMINDEX | LIF_STATE, 0, LIS_DEFAULTCOLORS , LIS_DEFAULTCOLORS }; + while (SendMessage(WindowHandle, LM_SETITEM, 0, (LPARAM)&linkChanges)) + linkChanges.iLink++; + } +} + VOID PhReInitializeWindowTheme( _In_ HWND WindowHandle ) @@ -656,6 +679,16 @@ 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 @@ -684,10 +717,15 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( } else if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE)) { - if ((PhGetWindowStyle(WindowHandle) & BS_GROUPBOX) == BS_GROUPBOX) + LONG_PTR style = PhGetWindowStyle(WindowHandle); + if ((style & BS_GROUPBOX) == BS_GROUPBOX) { PhInitializeThemeWindowGroupBox(WindowHandle); } + else if (style > BS_DEFPUSHBUTTON) // apply theme for CheckBox, Radio (Dart Vanya) + { + PhWindowThemeSetDarkMode(WindowHandle, TRUE); + } } else if (PhEqualStringZ(windowClassName, WC_TABCONTROL, FALSE)) { @@ -747,7 +785,8 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( ListView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) ListView_SetTextBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) ListView_SetTextColor(WindowHandle, PhThemeWindowTextColor); - //InvalidateRect(WindowHandle, NULL, FALSE); + + PhInitializeWindowThemeListView(WindowHandle); } else if (PhEqualStringZ(windowClassName, WC_TREEVIEW, FALSE)) { @@ -2211,7 +2250,6 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( break; case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: - case WM_CTLCOLORSTATIC: case WM_CTLCOLORLISTBOX: { HDC hdc = (HDC)wParam; @@ -2221,6 +2259,26 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( return (INT_PTR)PhThemeWindowBackgroundBrush; } break; + case WM_CTLCOLORSTATIC: + { + HDC hdc = (HDC)wParam; + HWND hControl = (HWND)lParam; + BOOLEAN useColorLink = FALSE; + WCHAR windowClassName[MAX_PATH]; + + if (!GetClassName(hControl, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) { + LITEM litem = { LIF_ITEMINDEX | LIF_STATE, 0, 0, LIS_DEFAULTCOLORS }; + if (SendMessage(hControl, LM_GETITEM, 0, (LPARAM)&litem)) + useColorLink = litem.state & LIS_DEFAULTCOLORS; + } + + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, !useColorLink ? PhThemeWindowTextColor : 0xE9BD5B); // To apply color for SysLink call PhInitializeSysLinkTheme() first + return (INT_PTR)PhThemeWindowBackgroundBrush; + } + break; case WM_MEASUREITEM: if (PhThemeWindowMeasureItem(hWnd, (LPMEASUREITEMSTRUCT)lParam)) return TRUE; @@ -3169,3 +3227,72 @@ 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/plugins/UserNotes/options.c b/plugins/UserNotes/options.c index 1708cc8d5e9a..89d329f42f3d 100644 --- a/plugins/UserNotes/options.c +++ b/plugins/UserNotes/options.c @@ -292,7 +292,7 @@ INT_PTR CALLBACK OptionsDlgProc( for (LONG i = numberOfItems - 1; i >= 0; i--) { - PhRemoveListViewItem(listviewHandle, i); + PhRemoveListViewItem(listviewHandle, PhFindListViewItemByParam(listviewHandle, INT_ERROR, listviewItems[i])); } SendMessage(listviewHandle, WM_SETREDRAW, TRUE, 0); diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 5a351df0b4c7..6e5360d49231 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -12,12 +12,12 @@ #include #include #include - +#include #include #include +#include #include "settings.h" -#include // https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-procedures#window-procedure-superclassing static WNDPROC PhDefaultMenuWindowProcedure = NULL; @@ -228,28 +228,34 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( PAINTSTRUCT ps; HDC hdc; HICON iconHandle; + RECT clientRect; if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) break; if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) { - if (hdc = BeginPaint(WindowHandle, &ps)) + if (BeginPaint(WindowHandle, &ps)) { - FillRect(hdc, &ps.rcPaint, PhThemeWindowBackgroundBrush); + // Fix artefacts when window moving back from off-screen (Dart Vanya) + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + + FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); DrawIconEx( hdc, - ps.rcPaint.left, - ps.rcPaint.top, + clientRect.left, + clientRect.top, iconHandle, - ps.rcPaint.right - ps.rcPaint.left, - ps.rcPaint.bottom - ps.rcPaint.top, + clientRect.right - clientRect.left, + clientRect.bottom - clientRect.top, 0, NULL, DI_NORMAL ); + ReleaseDC(WindowHandle, hdc); EndPaint(WindowHandle, &ps); } } @@ -389,9 +395,9 @@ VOID ThemeWindowStatusBarDrawPart( SetTextColor(bufferDc, PhThemeWindowTextColor); FillRect(bufferDc, &blockRect, PhThemeWindowBackgroundBrush); - CopyRect(&separator, &blockRect); + separator = blockRect; separator.left = separator.right - 1; - InflateRect(&separator, 0, -1); + PhInflateRect(&separator, 0, -1); SetDCBrushColor(bufferDc, PhThemeWindowHighlightColor); FillRect(bufferDc, &separator, PhGetStockBrush(DC_BRUSH)); } @@ -861,35 +867,40 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( { CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam; - if (createStruct->hwndParent) + // Don't apply header theme for unsupported dialogs: Advanced Security and Digital Signature Details (Dart Vanya) + if (!FindWindowEx(GetAncestor(WindowHandle, GA_ROOT), NULL, L"DirectUIHWND", NULL) && + !FindWindowEx(GetParent(createStruct->hwndParent), NULL, L"NativeFontCtl", NULL)) { - WCHAR windowClassName[MAX_PATH]; - - if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; - - if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) + if (createStruct->hwndParent) { - LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); + WCHAR windowClassName[MAX_PATH]; + + if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; - if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) { - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); - return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + + return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + } } } - } + + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); + context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); + context->CursorPos.x = LONG_MIN; + context->CursorPos.y = LONG_MIN; + PhSetWindowContext(WindowHandle, LONG_MAX, context); - context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); - context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); - context->CursorPos.x = LONG_MIN; - context->CursorPos.y = LONG_MIN; - PhSetWindowContext(WindowHandle, LONG_MAX, context); + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - - InvalidateRect(WindowHandle, NULL, FALSE); + InvalidateRect(WindowHandle, NULL, FALSE); + } } else { @@ -1035,7 +1046,9 @@ VOID PhRegisterDialogSuperClass( PhDefaultDialogWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhDialogWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; + UnregisterClass(L"#32770", NULL); if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1053,7 +1066,9 @@ VOID PhRegisterMenuSuperClass( PhDefaultMenuWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhMenuWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; + UnregisterClass(L"#32768", NULL); if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1071,9 +1086,9 @@ VOID PhRegisterRebarSuperClass( PhDefaultRebarWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhRebarWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; UnregisterClass(REBARCLASSNAME, NULL); - if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1091,9 +1106,9 @@ VOID PhRegisterComboBoxSuperClass( PhDefaultComboBoxWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhComboBoxWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; - UnregisterClass(WC_COMBOBOX, NULL); // Must be unregistered first? (dmex) - + UnregisterClass(WC_COMBOBOX, NULL); if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1111,9 +1126,9 @@ VOID PhRegisterStaticSuperClass( PhDefaultStaticWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhStaticWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; UnregisterClass(WC_STATIC, NULL); - if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1131,9 +1146,9 @@ VOID PhRegisterStatusBarSuperClass( PhDefaultStatusbarWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhStatusBarWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; UnregisterClass(STATUSCLASSNAME, NULL); - if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1151,9 +1166,9 @@ VOID PhRegisterEditSuperClass( PhDefaultEditWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhEditWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; - UnregisterClass(WC_EDIT, NULL); // Must be unregistered first? (dmex) - + UnregisterClass(WC_EDIT, NULL); if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1171,9 +1186,9 @@ VOID PhRegisterHeaderSuperClass( PhDefaultHeaderWindowProcedure = wcex.lpfnWndProc; wcex.lpfnWndProc = PhHeaderWindowHookProcedure; + wcex.style = wcex.style | CS_PARENTDC | CS_GLOBALCLASS; - UnregisterClass(WC_HEADER, NULL); // Must be unregistered first? (dmex) - + UnregisterClass(WC_HEADER, NULL); if (RegisterClassEx(&wcex) == INVALID_ATOM) { PhShowStatus(NULL, L"Unable to register window class.", 0, GetLastError()); @@ -1191,14 +1206,53 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( _In_ LPCRECT ClipRect ) = NULL; -//static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( -// _In_ HTHEME Theme, -// _In_ HDC hdc, -// _In_ INT PartId, -// _In_ INT StateId, -// _In_ LPCRECT Rect, -// _In_ PVOID Options -// ) = NULL; +static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCRECT pRect, + _In_ const DTBGOPTS* pOptions + ) = NULL; + +static HRESULT(WINAPI* PhDefaultDrawThemeText)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _In_ DWORD dwTextFlags2, + _In_ LPCRECT pRect + ) = NULL; + +static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _Inout_ LPRECT pRect, + _In_ const DTTOPTS* pOptions + ) = NULL; + +static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( + _In_ const TASKDIALOGCONFIG* pTaskConfig, + _Out_opt_ int* pnButton, + _Out_opt_ int* pnRadioButton, + _Out_opt_ BOOL* pfVerificationFlagChecked + ) = NULL; + +static HRESULT(WINAPI* PhDefaultGetThemeColor)( + _In_ HTHEME hTheme, + _In_ int iPartId, + _In_ int iStateId, + _In_ int iPropId, + _Out_ COLORREF* pColor + ) = NULL; static BOOL (WINAPI* PhDefaultSystemParametersInfo)( _In_ UINT uiAction, @@ -1222,10 +1276,44 @@ static HWND (WINAPI* PhDefaultCreateWindowEx)( _In_opt_ PVOID Param ) = NULL; -//static COLORREF (WINAPI* PhDefaultSetTextColor)( -// _In_ HDC hdc, -// _In_ COLORREF color -// ) = NULL; +typedef struct _TASKDIALOG_CALLBACK_WRAP +{ + PFTASKDIALOGCALLBACK pfCallback; + LONG_PTR lpCallbackData; +} TASKDIALOG_CALLBACK_WRAP, * PTASKDIALOG_CALLBACK_WRAP; + +typedef struct _TASKDIALOG_CONTROL_CONTEXT +{ + WNDPROC DefaultWindowProc; + ULONG Painting; +} TASKDIALOG_CONTROL_CONTEXT, * PTASKDIALOG_CONTROL_CONTEXT; + +typedef struct _TASKDIALOG_WINDOW_CONTEXT +{ + WNDPROC DefaultWindowProc; + ULONG Painting; + PTASKDIALOG_CALLBACK_WRAP CallbackData; +} TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; + +HRESULT CALLBACK ThemeTaskDialogCallbackHook( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam, + _In_ LONG_PTR dwRefData +); + +LRESULT CALLBACK ThemeTaskDialogMasterSubclass( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam +); + +BOOLEAN CALLBACK PhInitializeTaskDialogTheme( + _In_ HWND hwndDlg, + _In_opt_ PVOID Context +); HRESULT PhDrawThemeBackgroundHook( _In_ HTHEME Theme, @@ -1236,11 +1324,12 @@ HRESULT PhDrawThemeBackgroundHook( _In_ LPCRECT ClipRect ) { + WCHAR className[MAX_PATH]; + BOOLEAN hasThemeClass = PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className)); + if (WindowsVersion >= WINDOWS_11) { - WCHAR className[MAX_PATH]; - - if (PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className))) + if (hasThemeClass) { if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) { @@ -1253,44 +1342,104 @@ HRESULT PhDrawThemeBackgroundHook( } } + if (hasThemeClass) + { + if (PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE)) + { + if (PartId == PP_TRANSPARENTBAR) // Progress bar background. + { + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); + FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; + } + } + } + return PhDefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); } -//HRESULT WINAPI PhDrawThemeBackgroundExHook( -// _In_ HTHEME Theme, -// _In_ HDC hdc, -// _In_ INT PartId, -// _In_ INT StateId, -// _In_ LPCRECT Rect, -// _In_ PVOID Options // DTBGOPTS -// ) -//{ -// //HWND windowHandle = WindowFromDC(hdc); -// WCHAR className[MAX_PATH]; -// -// if (PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className))) -// { -// if (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) -// goto CleanupExit; -// } -// -// if (PartId == TDLG_PRIMARYPANEL && StateId == 0) -// { -// SetDCBrushColor(hdc, RGB(65, 65, 65)); -// FillRect(hdc, Rect, PhGetStockBrush(DC_BRUSH)); -// return S_OK; -// } -// -// if (PartId == TDLG_SECONDARYPANEL && StateId == 0) -// { -// SetDCBrushColor(hdc, RGB(45, 45, 45)); -// FillRect(hdc, Rect, PhGetStockBrush(DC_BRUSH)); -// return S_OK; -// } -// -//CleanupExit: -// return PhDefaultDrawThemeBackgroundEx(Theme, hdc, PartId, StateId, Rect, Options); -//} +HRESULT WINAPI PhDrawThemeBackgroundExHook( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCRECT pRect, + _In_ const DTBGOPTS* pOptions +) +{ + 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 (!PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE)) + return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + } + + 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: + { + 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: + { + // 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; + } + } + + return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); +} HWND PhCreateWindowExHook( _In_ ULONG ExStyle, @@ -1335,24 +1484,13 @@ HWND PhCreateWindowExHook( PhSetWindowAcrylicCompositionColor(windowHandle, MakeABGRFromCOLORREF(0, RGB(10, 10, 10))); } } - else + else if (PhEnableThemeSupport) { - //HWND parentHandle; - // - //if (parentHandle = GetAncestor(windowHandle, GA_ROOT)) - //{ - // if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, L"DirectUIHWND", TRUE)) - // { - // PhInitializeTaskDialogTheme(windowHandle, PhDefaultThemeSupport); // don't initialize parentHandle themes - // PhInitializeThemeWindowFrame(parentHandle); - // - // if (PhDefaultEnableStreamerMode) - // { - // if (SetWindowDisplayAffinity_Import()) - // SetWindowDisplayAffinity_Import()(parentHandle, WDA_EXCLUDEFROMCAPTURE); - // } - // } - //} + // Early subclassing of the SysLink control to eliminate blinking during page switches. + if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, WC_LINK, TRUE)) + { + PhInitializeTaskDialogTheme(windowHandle, 0); + } } return windowHandle; @@ -1457,33 +1595,277 @@ BOOL WINAPI PhSystemParametersInfoHook( // RGB(GetBValue(color), GetGValue(color), GetRValue(color)); //#define RGB_FROM_COLOREF(cref) \ // ((((cref) & 0x000000FF) << 16) | (((cref) & 0x0000FF00)) | (((cref) & 0x00FF0000) >> 16)) -// -//COLORREF WINAPI PhSetTextColorHook( -// _In_ HDC hdc, -// _In_ COLORREF color -// ) -//{ -// //HWND windowHandle = WindowFromDC(hdc); -// -// if (!(PhTaskDialogThemeHookIndex && PhTlsGetValue(PhTaskDialogThemeHookIndex))) -// goto CleanupExit; -// -// if (RGB_FROM_COLOREF(RGB_FROM_COLOREF(color)) == RGB(0, 51, 153)) // TMT_TEXTCOLOR (TaskDialog InstructionPane) -// { -// color = RGB(0, 102, 255); -// } -// else if (RGB_FROM_COLOREF(RGB_FROM_COLOREF(color)) == RGB(0, 102, 204)) // TaskDialog Link -// { -// color = RGB(0, 128, 0); // RGB(128, 255, 128); -// } -// else -// { -// color = RGB(255, 255, 255); // GetBkColor(hdc); -// } -// -//CleanupExit: -// return PhDefaultSetTextColor(hdc, color); -//} + +#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, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _In_ DWORD dwTextFlags2, + _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) + { + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + } + } + + return PhDefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); +} + +HRESULT WINAPI PhDrawThemeTextExHook( + _In_ HTHEME hTheme, + _In_ HDC hdc, + _In_ int iPartId, + _In_ int iStateId, + _In_ LPCWSTR pszText, + _In_ int cchText, + _In_ DWORD dwTextFlags, + _Inout_ LPRECT pRect, + _In_ const DTTOPTS* pOptions + ) +{ + WCHAR className[MAX_PATH]; + + if (iPartId == BP_COMMANDLINK) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + { + DTTOPTS options; + if (pOptions) + options = *pOptions; + else { + memset(&options, 0, sizeof(options)); + options.dwSize = sizeof(DTTOPTS); + } + options.dwFlags |= DTT_TEXTCOLOR; + PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); + options.crText = PhMakeColorBrighter(options.crText, 90); + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); + } + } + + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); +} + +HRESULT PhGetThemeColorHook( + _In_ HTHEME hTheme, + _In_ int iPartId, + _In_ int iStateId, + _In_ int iPropId, + _Out_ COLORREF* pColor + ) +{ + WCHAR className[MAX_PATH]; + + HRESULT retVal = PhDefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); + + if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + { + *pColor = PhMakeColorBrighter(*pColor, 150); // Main header. + } + } + else if (iPropId == TMT_TEXTCOLOR) + { + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && + PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + { + *pColor = PhThemeWindowTextColor; // Text color for check boxes, expanded text, and expander button text. + } + } + + return retVal; +} + +BOOLEAN CALLBACK PhInitializeTaskDialogTheme( + _In_ HWND WindowHandle, + _In_opt_ PVOID CallbackData +) +{ + WCHAR windowClassName[MAX_PATH]; + PTASKDIALOG_CONTROL_CONTEXT context; + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, LONG_MIN); + + if (CallbackData && !windowHasContext) + { + PhInitializeThemeWindowFrame(WindowHandle); + + if (PhDefaultEnableStreamerMode) + { + if (SetWindowDisplayAffinity_Import()) + SetWindowDisplayAffinity_Import()(WindowHandle, WDA_EXCLUDEFROMCAPTURE); + } + + PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); + context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); + context->CallbackData = CallbackData; + PhSetWindowContext(WindowHandle, LONG_MIN, context); + windowHasContext = TRUE; + } + + PhEnumChildWindows( + WindowHandle, + 0x1000, + PhInitializeTaskDialogTheme, + NULL + ); + + if (windowHasContext) // HACK + return TRUE; + + GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); + + context = PhAllocateZero(sizeof(TASKDIALOG_CONTROL_CONTEXT)); + context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); + PhSetWindowContext(WindowHandle, LONG_MIN, context); + + if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || + PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + } + else if (PhEqualStringZ(windowClassName, L"DirectUIHWND", FALSE)) + { + //WINDOWPLACEMENT pos = { 0 }; + //GetWindowPlacement(GetParent(WindowHandle), &pos); + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + //SetWindowPlacement(GetParent(WindowHandle), &pos); + } + + return TRUE; +} + +LRESULT CALLBACK ThemeTaskDialogMasterSubclass( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + LRESULT result; + PTASKDIALOG_CONTROL_CONTEXT context; + WNDPROC OldWndProc; + + if (!(context = PhGetWindowContext(hwnd, LONG_MIN))) + return 0; + + OldWndProc = context->DefaultWindowProc; + + switch (uMsg) + { + case WM_ERASEBKGND: + { + HDC hdc = (HDC)wParam; + RECT rect; + WCHAR windowClassName[MAX_PATH]; + + SetTextColor(hdc, PhThemeWindowTextColor); // Color for SysLink, which must be set in its parent. + + if (!context->Painting) + { + GETCLASSNAME_OR_NULL(hwnd, windowClassName); + // Avoid erasing the background for links, as they will blink white on the extender and during page switches. + if (!PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + { + GetClipBox(hdc, &rect); + SetDCBrushColor(hdc, PhThemeWindowBackground2Color); + FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); + } + else + { + PhInitializeSysLinkTheme(hwnd); // this doesn't work in EnumWindows callback, I don't know why + } + } + } + return TRUE; + case TDM_NAVIGATE_PAGE: + { + PTASKDIALOG_WINDOW_CONTEXT WindowContext = (PTASKDIALOG_WINDOW_CONTEXT)context; + PTASKDIALOGCONFIG trueConfig = (PTASKDIALOGCONFIG)lParam; + PTASKDIALOGCONFIG myConfig; + TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) }; + + WindowContext->CallbackData->pfCallback = trueConfig ? trueConfig->pfCallback : NULL; + WindowContext->CallbackData->lpCallbackData = trueConfig ? trueConfig->lpCallbackData : 0; + myConfig = trueConfig ? trueConfig : &config; + myConfig->pfCallback = ThemeTaskDialogCallbackHook; + myConfig->lpCallbackData = (LONG_PTR)WindowContext->CallbackData; + + return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, (LPARAM)myConfig); + } + case WM_DESTROY: + { + PhSetWindowProcedure(hwnd, OldWndProc); + PhRemoveWindowContext(hwnd, LONG_MIN); + PhFree(context); + } + return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); + case WM_CTLCOLORDLG: + return (LRESULT)PhThemeWindowBackgroundBrush; // Window background color when the extender resizes upward (Windows 10 only). + } + + context->Painting++; + result = CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); + context->Painting--; + return result; +} + +HRESULT CALLBACK ThemeTaskDialogCallbackHook( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam, + _In_ LONG_PTR dwRefData + ) +{ + HRESULT result = S_OK; + + PTASKDIALOG_CALLBACK_WRAP CallbackData = (PTASKDIALOG_CALLBACK_WRAP)dwRefData; + + if (uMsg == TDN_DIALOG_CONSTRUCTED) // Called on each new page, including the first one. + { + PhInitializeTaskDialogTheme(hwndDlg, CallbackData); + } + + if (CallbackData->pfCallback) + result = CallbackData->pfCallback(hwndDlg, uMsg, wParam, lParam, CallbackData->lpCallbackData); + + return result; +} + +// https://github.com/SFTRS/DarkTaskDialog +HRESULT PhTaskDialogIndirectHook( + _In_ const TASKDIALOGCONFIG* pTaskConfig, + _Out_opt_ int* pnButton, + _Out_opt_ int* pnRadioButton, + _Out_opt_ BOOL* pfVerificationFlagChecked + ) +{ + TASKDIALOG_CALLBACK_WRAP CallbackData; + CallbackData.pfCallback = pTaskConfig->pfCallback; + CallbackData.lpCallbackData = pTaskConfig->lpCallbackData; + TASKDIALOGCONFIG myConfig = *pTaskConfig; + myConfig.pfCallback = ThemeTaskDialogCallbackHook; + myConfig.lpCallbackData = (LONG_PTR)&CallbackData; + + return PhDefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); +} VOID PhRegisterDetoursHooks( VOID @@ -1492,10 +1874,11 @@ VOID PhRegisterDetoursHooks( NTSTATUS status; PVOID baseAddress; - //if (baseAddress = PhGetLoaderEntryDllBaseZ(L"gdi32.dll")) - //{ - // PhDefaultSetTextColor = PhGetDllBaseProcedureAddress(baseAddress, "SetTextColor", 0); - //} + // For early TaskDialog with PhStartupParameters.ShowOptions + if (!PhThemeWindowBackgroundBrush) + { + PhThemeWindowBackgroundBrush = CreateSolidBrush(PhThemeWindowBackgroundColor); + } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"user32.dll")) { @@ -1506,7 +1889,15 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); - //PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); + PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); + PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + } + + if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) + { + PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); } if (!NT_SUCCESS(status = DetourTransactionBegin())) @@ -1516,16 +1907,22 @@ VOID PhRegisterDetoursHooks( { if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) goto CleanupExit; - //if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) - // 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 (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) + goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + goto CleanupExit; } if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) goto CleanupExit; - //if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSetTextColor, (PVOID)PhSetTextColorHook))) - // goto CleanupExit; if (!NT_SUCCESS(status = DetourTransactionCommit())) goto CleanupExit; diff --git a/tools/peview/peprp.c b/tools/peview/peprp.c index ff2ace39a7da..4f4740b13f33 100644 --- a/tools/peview/peprp.c +++ b/tools/peview/peprp.c @@ -2184,6 +2184,9 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( { PhSetDialogItemText(hwndDlg, IDC_COMPANYNAME, PvpGetStringOrNa(PvImageVersionInfo.CompanyName)); } + + if (PhEnableThemeSupport) + PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_COMPANYNAME_LINK)); } break; case PVM_ENTROPY_DONE: diff --git a/tools/peview/prpsh.c b/tools/peview/prpsh.c index 9e04aef07289..3d4ad7c981d6 100644 --- a/tools/peview/prpsh.c +++ b/tools/peview/prpsh.c @@ -209,7 +209,7 @@ static HWND PvpCreateSecurityButton( WC_BUTTON, L"Security", WS_CHILD | WS_VISIBLE | WS_TABSTOP, - rect.right, + rect.right + 3, rect.top, rect.right - rect.left, rect.bottom - rect.top, From 69992ccee58c3c78ccd53204fd927bd64c3ebf72 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Fri, 11 Oct 2024 05:20:09 +0300 Subject: [PATCH 03/11] 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"); From 0d532c58ac3cc03e435066ebbd3dcc0f8474779e Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Fri, 11 Oct 2024 14:59:29 +0300 Subject: [PATCH 04/11] Security page CHECKLIST_ACLUI checks theme support --- SystemInformer/delayhook.c | 91 +++++++++++++++++++++++++++---------- phlib/secedit.c | 2 +- phlib/theme.c | 5 +- tools/peview/delayhook.c | 93 ++++++++++++++++++++++++++++---------- 4 files changed, 139 insertions(+), 52 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 82902eee728d..14ab5478520a 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -226,42 +226,80 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( break; case WM_PAINT: { - PAINTSTRUCT ps; HDC hdc; - HICON iconHandle; + //HICON iconHandle; RECT clientRect; + WCHAR windowClassName[MAX_PATH]; if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) break; - if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) + if (!GetClassName(GetParent(WindowHandle), windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) { - if (BeginPaint(WindowHandle, &ps)) + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static HFONT hCheckFont = NULL; + + LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; + INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); + if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked { - // Fix artefacts when window moving back from off-screen (Dart Vanya) - hdc = GetDC(WindowHandle); - GetClientRect(WindowHandle, &clientRect); - + if (PhBeginInitOnce(&initOnce)) // cache font + { + hCheckFont = CreateFont( + clientRect.bottom - clientRect.top - 1, + clientRect.right - clientRect.left - 3, + 0, 0, + FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, + VARIABLE_PITCH, L"Segoe UI"); + PhEndInitOnce(&initOnce); + } + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SelectObject(hdc, hCheckFont); + //HFONT hFontOriginal = (HFONT)SelectObject(hdc, hCheckFont); FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); - - DrawIconEx( - hdc, - clientRect.left, - clientRect.top, - iconHandle, - clientRect.right - clientRect.left, - clientRect.bottom - clientRect.top, - 0, - NULL, - DI_NORMAL - ); - - ReleaseDC(WindowHandle, hdc); - EndPaint(WindowHandle, &ps); + DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); + //SelectObject(hdc, hFontOriginal); } + ReleaseDC(WindowHandle, hdc); + return retval; } + //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) + //{ + // PAINTSTRUCT ps; + // if (PhGetWindowContext(GetParent(WindowHandle), LONG_MAX) && + // BeginPaint(WindowHandle, &ps)) + // { + // // Fix artefacts when window moving back from off-screen (Dart Vanya) + // hdc = GetDC(WindowHandle); + // GetClientRect(WindowHandle, &clientRect); + + // FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); + + // DrawIconEx( + // hdc, + // clientRect.left, + // clientRect.top, + // iconHandle, + // clientRect.right - clientRect.left, + // clientRect.bottom - clientRect.top, + // 0, + // NULL, + // DI_NORMAL + // ); + + // ReleaseDC(WindowHandle, hdc); + // EndPaint(WindowHandle, &ps); + // } + //} } - return DefWindowProc(WindowHandle, WindowMessage, wParam, lParam); } return CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); @@ -1498,6 +1536,11 @@ HWND PhCreateWindowExHook( { PhInitializeTaskDialogTheme(windowHandle, 0); } + else if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, WC_BUTTON, TRUE) && + PhGetWindowContext(GetAncestor(Parent, GA_ROOT), LONG_MAX)) + { + PhSetControlTheme(windowHandle, L"DarkMode_Explorer"); + } } return windowHandle; diff --git a/phlib/secedit.c b/phlib/secedit.c index 0ad0449c4f5d..20c88aced9e9 100644 --- a/phlib/secedit.c +++ b/phlib/secedit.c @@ -662,7 +662,7 @@ HRESULT STDMETHODCALLTYPE PhSecurityInformation_PropertySheetPageCallback( if (!this->IsPage) PhCenterWindow(GetParent(hwnd), GetParent(GetParent(hwnd))); - PhInitializeWindowTheme(hwnd, PhEnableThemeSupport); + PhInitializeWindowTheme(GetParent(hwnd), PhEnableThemeSupport); } return E_NOTIMPL; diff --git a/phlib/theme.c b/phlib/theme.c index acd1ed83317d..476604c264ef 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -707,7 +707,7 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( { PhInitializeThemeWindowGroupBox(WindowHandle); } - else if (style > BS_DEFPUSHBUTTON) // apply theme for CheckBox, Radio (Dart Vanya) + else // apply theme for CheckBox, Radio (Dart Vanya) { PhWindowThemeSetDarkMode(WindowHandle, TRUE); } @@ -3197,7 +3197,7 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( HDC hdc = (HDC)wParam; RECT clientRect; - GetClientRect(WindowHandle, &clientRect); + GetClipBox(hdc, &clientRect); FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); } return TRUE; @@ -3210,6 +3210,5 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( return (INT_PTR)PhThemeWindowBackgroundBrush; } } - return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); } diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index d801df5d4e32..1f8666b84966 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -226,42 +226,80 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( break; case WM_PAINT: { - PAINTSTRUCT ps; HDC hdc; - HICON iconHandle; + //HICON iconHandle; RECT clientRect; + WCHAR windowClassName[MAX_PATH]; if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) break; - if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) + if (!GetClassName(GetParent(WindowHandle), windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) { - if (BeginPaint(WindowHandle, &ps)) + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static HFONT hCheckFont = NULL; + + LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; + INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); + if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked { - // Fix artefacts when window moving back from off-screen (Dart Vanya) - hdc = GetDC(WindowHandle); - GetClientRect(WindowHandle, &clientRect); - + if (PhBeginInitOnce(&initOnce)) // cache font + { + hCheckFont = CreateFont( + clientRect.bottom - clientRect.top - 1, + clientRect.right - clientRect.left - 3, + 0, 0, + FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, + VARIABLE_PITCH, L"Segoe UI"); + PhEndInitOnce(&initOnce); + } + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SelectObject(hdc, hCheckFont); + //HFONT hFontOriginal = (HFONT)SelectObject(hdc, hCheckFont); FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); - - DrawIconEx( - hdc, - clientRect.left, - clientRect.top, - iconHandle, - clientRect.right - clientRect.left, - clientRect.bottom - clientRect.top, - 0, - NULL, - DI_NORMAL - ); - - ReleaseDC(WindowHandle, hdc); - EndPaint(WindowHandle, &ps); + DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); + //SelectObject(hdc, hFontOriginal); } + ReleaseDC(WindowHandle, hdc); + return retval; } + //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) + //{ + // PAINTSTRUCT ps; + // if (PhGetWindowContext(GetParent(WindowHandle), LONG_MAX) && + // BeginPaint(WindowHandle, &ps)) + // { + // // Fix artefacts when window moving back from off-screen (Dart Vanya) + // hdc = GetDC(WindowHandle); + // GetClientRect(WindowHandle, &clientRect); + + // FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); + + // DrawIconEx( + // hdc, + // clientRect.left, + // clientRect.top, + // iconHandle, + // clientRect.right - clientRect.left, + // clientRect.bottom - clientRect.top, + // 0, + // NULL, + // DI_NORMAL + // ); + + // ReleaseDC(WindowHandle, hdc); + // EndPaint(WindowHandle, &ps); + // } + //} } - return DefWindowProc(WindowHandle, WindowMessage, wParam, lParam); } return CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); @@ -1498,6 +1536,11 @@ HWND PhCreateWindowExHook( { PhInitializeTaskDialogTheme(windowHandle, 0); } + else if (!IS_INTRESOURCE(ClassName) && PhEqualStringZ((PWSTR)ClassName, WC_BUTTON, TRUE) && + PhGetWindowContext(GetAncestor(Parent, GA_ROOT), LONG_MAX)) + { + PhSetControlTheme(windowHandle, L"DarkMode_Explorer"); + } } return windowHandle; @@ -1985,9 +2028,11 @@ VOID PvInitializeSuperclassControls( if (WindowsVersion >= WINDOWS_11) { PhDefaultEnableThemeAcrylicWindowSupport = !!PhGetIntegerSetting(L"EnableThemeAcrylicWindowSupport"); + PhEnableThemeAcrylicWindowSupport = PhDefaultEnableThemeAcrylicWindowSupport; } PhDefaultEnableThemeAnimation = !!PhGetIntegerSetting(L"EnableThemeAnimation"); + PhEnableThemeNativeButtons = !!PhGetIntegerSetting(L"EnableThemeNativeButtons"); PhRegisterDialogSuperClass(); PhRegisterMenuSuperClass(); From 4e999708d9c9883648bbd8da1ce2d98917c107c8 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Sat, 12 Oct 2024 07:09:24 +0300 Subject: [PATCH 05/11] Transit from PhShow(Error|Warning|Information) to PhShow(Error|Warning|Information)2 --- SystemInformer/actions.c | 8 ++------ SystemInformer/delayhook.c | 11 ++++++++++- SystemInformer/findobj.c | 7 ++++--- SystemInformer/hidnproc.c | 2 +- SystemInformer/hndlmenu.c | 2 +- SystemInformer/main.c | 9 +++++---- SystemInformer/memedit.c | 6 +++--- SystemInformer/memsrch.c | 6 +++--- SystemInformer/procrec.c | 2 +- SystemInformer/prpggen.c | 2 +- SystemInformer/prpgvdm.c | 2 +- SystemInformer/prpgwmi.c | 6 +++--- SystemInformer/sessshad.c | 2 +- SystemInformer/sysinfo.c | 2 +- SystemInformer/thrdstks.c | 2 +- SystemInformer/tokprp.c | 2 +- phlib/mapldr.c | 6 ++++-- phlib/theme.c | 2 ++ phlib/util.c | 6 +++--- plugins/ExtendedServices/other.c | 5 +++-- plugins/ExtendedServices/recovery.c | 10 +++++++--- plugins/ExtendedServices/trigger.c | 4 ++-- plugins/ExtendedServices/triggpg.c | 5 +++-- plugins/ExtendedTools/gpudetails.c | 2 +- plugins/ExtendedTools/gpunodes.c | 2 +- plugins/ExtendedTools/npudetails.c | 2 +- plugins/ExtendedTools/npunodes.c | 2 +- plugins/ExtendedTools/objmgr.c | 2 +- plugins/ExtendedTools/pooldialog.c | 2 +- plugins/ExtendedTools/thrdact.c | 2 +- plugins/ExtendedTools/waitchain.c | 2 +- plugins/ExtendedTools/wswatch.c | 2 +- plugins/HardwareDevices/diskdetails.c | 2 +- plugins/HardwareDevices/gpunodes.c | 4 ++-- plugins/HardwareDevices/netdetails.c | 2 +- plugins/NetworkTools/update.c | 4 ++-- plugins/ToolStatus/main.c | 4 ++-- plugins/Updater/updater.c | 2 +- plugins/UserNotes/main.c | 6 +++--- plugins/WindowExplorer/wnddlg.c | 12 ++++++------ tools/peview/strings.c | 2 +- 41 files changed, 91 insertions(+), 74 deletions(-) diff --git a/SystemInformer/actions.c b/SystemInformer/actions.c index c7ff91cd40d4..d1adc16868e2 100644 --- a/SystemInformer/actions.c +++ b/SystemInformer/actions.c @@ -4952,11 +4952,7 @@ BOOLEAN PhUiCloseConnections( if (!SetTcpEntry_I) { - PhShowError( - WindowHandle, - L"%s", - L"This feature is not supported by your operating system." - ); + PhShowError2(WindowHandle, L"This feature is not supported by your operating system.", L"%s", L""); return FALSE; } @@ -5640,7 +5636,7 @@ BOOLEAN PhUiUnloadModule( if (status == STATUS_DLL_NOT_FOUND) { - PhShowError(WindowHandle, L"%s", L"Unable to find the module to unload."); + PhShowError2(WindowHandle, L"Unable to find the module to unload.", L"%s", L""); return FALSE; } diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 14ab5478520a..b702d9aad900 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -1667,7 +1667,16 @@ HRESULT WINAPI PhDrawThemeTextHook( // 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)) + PhEqualStringZ((PWSTR)pszText, L"Canary\n - Preview", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Realtime", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"High", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Above normal", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Normal", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Below normal", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Idle", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Medium", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Low", FALSE) || + PhEqualStringZ((PWSTR)pszText, L"Very low", FALSE)) { DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); diff --git a/SystemInformer/findobj.c b/SystemInformer/findobj.c index a968f72e3779..feed994ee1b8 100644 --- a/SystemInformer/findobj.c +++ b/SystemInformer/findobj.c @@ -1695,9 +1695,10 @@ INT_PTR CALLBACK PhpFindObjectsDlgProc( if ((NTSTATUS)wParam == STATUS_INSUFFICIENT_RESOURCES) { - PhShowWarning( + PhShowWarning2( hwndDlg, - L"Unable to search for handles because the total number of handles on the system is too large.\r\n%s", + L"Unable to search for handles because the total number of handles on the system is too large.", + L"%s", L"Please check if there are any processes with an extremely large number of handles open." ); } @@ -1768,7 +1769,7 @@ VOID PhShowFindObjectsDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&PhFindObjectsThreadHandle, PhpFindObjectsDialogThreadStart, NULL))) { - PhShowError(PhMainWndHandle, L"%s", L"Unable to create the window."); + PhShowError2(PhMainWndHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/SystemInformer/hidnproc.c b/SystemInformer/hidnproc.c index 64edcc0be8e5..95df94aa4a79 100644 --- a/SystemInformer/hidnproc.c +++ b/SystemInformer/hidnproc.c @@ -431,7 +431,7 @@ INT_PTR CALLBACK PhpZombieProcessesDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"Unable to create a process structure for the selected process."); + PhShowError2(hwndDlg, L"Unable to create a process structure for the selected process.", L"%s", L""); } } } diff --git a/SystemInformer/hndlmenu.c b/SystemInformer/hndlmenu.c index b0b97dd0e7a7..dfa7d84ed028 100644 --- a/SystemInformer/hndlmenu.c +++ b/SystemInformer/hndlmenu.c @@ -272,7 +272,7 @@ VOID PhShowHandleObjectProperties1( PPH_SHOW_MEMORY_EDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOW_MEMORY_EDITOR)); if (tooBig) - PhShowWarning(hWnd, L"%s", L"The section size is greater than 32 MB. Only the first 32 MB will be available."); + PhShowWarning2(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available.", L"%s", L""); memset(showMemoryEditor, 0, sizeof(PH_SHOW_MEMORY_EDITOR)); showMemoryEditor->ProcessId = NtCurrentProcessId(); diff --git a/SystemInformer/main.c b/SystemInformer/main.c index fc5d597b9bb4..3db3564e76b1 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -233,8 +233,9 @@ INT WINAPI wWinMain( #ifndef DEBUG if (PhIsExecutingInWow64()) { - PhShowWarning( + PhShowWarning2( NULL, + L"Warning.", L"%s", L"You are attempting to run the 32-bit version of System Informer on 64-bit Windows. " L"Most features will not work correctly.\n\n" @@ -261,7 +262,7 @@ INT WINAPI wWinMain( if (!PhMainWndInitialization(CmdShow)) { - PhShowError(NULL, L"%s", L"Unable to initialize the main window."); + PhShowError2(NULL, L"Unable to initialize the main window.", L"%s", L""); return 1; } @@ -1448,10 +1449,10 @@ VOID PhpProcessStartupParameters( NULL ) || PhStartupParameters.Help) { - PhShowInformation( + PhShowInformation2( NULL, + L"Command line options:", L"%s", - L"Command line options:\n\n" L"-debug\n" L"-elevate\n" L"-help\n" diff --git a/SystemInformer/memedit.c b/SystemInformer/memedit.c index 055fbbe70e3f..1731e21b7105 100644 --- a/SystemInformer/memedit.c +++ b/SystemInformer/memedit.c @@ -195,7 +195,7 @@ INT_PTR CALLBACK PhpMemoryEditorDlgProc( if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { - PhShowError(context->OwnerHandle, L"%s", L"Unable to edit the memory region because it is too large."); + PhShowError2(context->OwnerHandle, L"Unable to edit the memory region because it is too large.", L"%s", L""); return TRUE; } @@ -213,7 +213,7 @@ INT_PTR CALLBACK PhpMemoryEditorDlgProc( if (!context->Buffer) { - PhShowError(context->OwnerHandle, L"%s", L"Unable to allocate memory for the buffer."); + PhShowError2(context->OwnerHandle, L"Unable to allocate memory for the buffer.", L"%s", L""); return TRUE; } @@ -433,7 +433,7 @@ INT_PTR CALLBACK PhpMemoryEditorDlgProc( { if (offset >= context->RegionSize) { - PhShowError(hwndDlg, L"%s", L"The offset is too large."); + PhShowError2(hwndDlg, L"The offset is too large.", L"%s", L""); continue; } diff --git a/SystemInformer/memsrch.c b/SystemInformer/memsrch.c index f9389c7cf285..e0517e46dcd9 100644 --- a/SystemInformer/memsrch.c +++ b/SystemInformer/memsrch.c @@ -553,7 +553,7 @@ INT_PTR CALLBACK PhpMemoryStringDlgProc( if (minimumLength < 4) { - PhShowError(hwndDlg, L"%s", L"The minimum length must be at least 4."); + PhShowError2(hwndDlg, L"The minimum length must be at least 4.", L"%s", L""); break; } @@ -1458,7 +1458,7 @@ INT_PTR CALLBACK PhpMemoryStringsTreeMinimumLengthDlgProc( if (!minimumLength || minimumLength > MAXULONG32) { - PhShowError(hwndDlg, L"%s", L"Invalid minimum length"); + PhShowError2(hwndDlg, L"Invalid minimum length", L"%s", L""); break; } @@ -2006,7 +2006,7 @@ BOOLEAN PhpShowMemoryStringTreeDialog( if (!NT_SUCCESS(PhCreateThread2(PhpShowMemoryStringTreeDialogThreadStart, context))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); PhDereferenceObject(context->ProcessItem); NtClose(context->ProcessHandle); PhFree(context); diff --git a/SystemInformer/procrec.c b/SystemInformer/procrec.c index e6df84e3693b..3bccdbfc7134 100644 --- a/SystemInformer/procrec.c +++ b/SystemInformer/procrec.c @@ -253,7 +253,7 @@ INT_PTR CALLBACK PhpProcessRecordDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The process has already terminated; only the process record is available."); + PhShowError2(hwndDlg, L"The process has already terminated; only the process record is available.", L"%s", L""); } } break; diff --git a/SystemInformer/prpggen.c b/SystemInformer/prpggen.c index ade818ab5dc1..15a32ff07918 100644 --- a/SystemInformer/prpggen.c +++ b/SystemInformer/prpggen.c @@ -706,7 +706,7 @@ INT_PTR CALLBACK PhpProcessGeneralDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The process does not exist."); + PhShowError2(hwndDlg, L"The process does not exist.", L"%s", L""); } } break; diff --git a/SystemInformer/prpgvdm.c b/SystemInformer/prpgvdm.c index fcea5b517dad..d14a48e328d7 100644 --- a/SystemInformer/prpgvdm.c +++ b/SystemInformer/prpgvdm.c @@ -393,7 +393,7 @@ INT_PTR CALLBACK PhpProcessVdmHostProcessDlgProc( { if (!PhpTerminateVdmTask(processItem, entry->Task16)) { - PhShowError(hwndDlg, L"%s", L"Unable to terminate the task."); + PhShowError2(hwndDlg, L"Unable to terminate the task.", L"%s", L""); } } break; diff --git a/SystemInformer/prpgwmi.c b/SystemInformer/prpgwmi.c index 24aac77070a1..8f8a7026bffe 100644 --- a/SystemInformer/prpgwmi.c +++ b/SystemInformer/prpgwmi.c @@ -1031,7 +1031,7 @@ VOID PhpShowWmiProviderStatus( } else { - PhShowError(hWnd, L"%s", statusMessage->Buffer); + PhShowError2(hWnd, statusMessage->Buffer, L"%s", L""); } PhDereferenceObject(statusMessage); @@ -1040,11 +1040,11 @@ VOID PhpShowWmiProviderStatus( { if (Message) { - PhShowError(hWnd, L"%s", Message); + PhShowError2(hWnd, Message, L"%s", L""); } else { - PhShowError(hWnd, L"%s", L"Unable to perform the operation."); + PhShowError2(hWnd, L"Unable to perform the operation.", L"%s", L""); } } } diff --git a/SystemInformer/sessshad.c b/SystemInformer/sessshad.c index 8e25a44c7afd..b76118ef601d 100644 --- a/SystemInformer/sessshad.c +++ b/SystemInformer/sessshad.c @@ -220,7 +220,7 @@ INT_PTR CALLBACK PhpSessionShadowDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The computer name is too long."); + PhShowError2(hwndDlg, L"The computer name is too long.", L"%s", L""); } } break; diff --git a/SystemInformer/sysinfo.c b/SystemInformer/sysinfo.c index 50ba53428f53..fa4f4faba7cd 100644 --- a/SystemInformer/sysinfo.c +++ b/SystemInformer/sysinfo.c @@ -78,7 +78,7 @@ VOID PhShowSystemInformationDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&PhSipThread, PhSipSysInfoThreadStart, NULL))) { - PhShowError(PhMainWndHandle, L"%s", L"Unable to create the window."); + PhShowError2(PhMainWndHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/SystemInformer/thrdstks.c b/SystemInformer/thrdstks.c index 764a66fb6b3f..8b4d45f28984 100644 --- a/SystemInformer/thrdstks.c +++ b/SystemInformer/thrdstks.c @@ -1861,7 +1861,7 @@ VOID PhShowThreadStacksDialog( if (!NT_SUCCESS(PhCreateThread2(PhpThreadStacksDialogThreadStart, context))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); PhDereferenceObject(context); } } diff --git a/SystemInformer/tokprp.c b/SystemInformer/tokprp.c index 062f9df0b351..97b3ffa4f2fe 100644 --- a/SystemInformer/tokprp.c +++ b/SystemInformer/tokprp.c @@ -295,7 +295,7 @@ VOID PhCreateTokenDialog( DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ))) { - PhShowError(NULL, L"%s", "Unable to duplicate the token."); + PhShowError2(NULL, L"Unable to duplicate the token.", L"%s", L""); return; } diff --git a/phlib/mapldr.c b/phlib/mapldr.c index 37ff9a4a3b14..981035d38403 100644 --- a/phlib/mapldr.c +++ b/phlib/mapldr.c @@ -1706,8 +1706,9 @@ VOID PhLoaderEntrySnapShowErrorMessage( if (IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal)) { - PhShowError( + PhShowError2( NULL, + L"Error.", L"Unable to load plugin.\r\nName: %s\r\nOrdinal: %u\r\nModule: %hs", PhGetStringOrEmpty(fileName), IMAGE_ORDINAL(OriginalThunk->u1.Ordinal), @@ -1720,8 +1721,9 @@ VOID PhLoaderEntrySnapShowErrorMessage( importByName = PTR_ADD_OFFSET(BaseAddress, OriginalThunk->u1.AddressOfData); - PhShowError( + PhShowError2( NULL, + L"Error.", L"Unable to load plugin.\r\nName: %s\r\nFunction: %hs\r\nModule: %hs", PhGetStringOrEmpty(fileName), importByName->Name, diff --git a/phlib/theme.c b/phlib/theme.c index 476604c264ef..1a06e1cc2afc 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -2359,6 +2359,8 @@ LRESULT CALLBACK PhpThemeWindowGroupBoxSubclassProc( PhRemoveWindowContext(WindowHandle, LONG_MAX); } break; + case WM_ENABLE: + goto DefaultWndProc; case WM_ERASEBKGND: return TRUE; case WM_PAINT: diff --git a/phlib/util.c b/phlib/util.c index 2faef918c421..9d7efa35e34e 100644 --- a/phlib/util.c +++ b/phlib/util.c @@ -897,7 +897,7 @@ VOID PhShowStatus( } else { - PhShowError(WindowHandle, L"%s", statusMessage->Buffer); + PhShowError2(WindowHandle, statusMessage->Buffer, L"%s", L""); } PhDereferenceObject(statusMessage); @@ -906,11 +906,11 @@ VOID PhShowStatus( { if (Message) { - PhShowError(WindowHandle, L"%s", Message); + PhShowError2(WindowHandle, Message, L"%s", L""); } else { - PhShowError(WindowHandle, L"%s", L"Unable to perform the operation."); + PhShowError2(WindowHandle, L"Unable to perform the operation.", L"%s", L""); } } } diff --git a/plugins/ExtendedServices/other.c b/plugins/ExtendedServices/other.c index b8046437a9cc..c8ff475da63d 100644 --- a/plugins/ExtendedServices/other.c +++ b/plugins/ExtendedServices/other.c @@ -364,9 +364,10 @@ INT_PTR CALLBACK EspServiceOtherDlgProc( { PPH_STRING errorMessage = PhGetNtMessage(status); - PhShowWarning( + PhShowWarning2( WindowHandle, - L"Unable to query service information: %s", + L"Unable to query service information." + L"%s", PhGetStringOrDefault(errorMessage, L"Unknown error.") ); diff --git a/plugins/ExtendedServices/recovery.c b/plugins/ExtendedServices/recovery.c index 789f31c3828d..41caf3eb0281 100644 --- a/plugins/ExtendedServices/recovery.c +++ b/plugins/ExtendedServices/recovery.c @@ -297,8 +297,9 @@ INT_PTR CALLBACK EspServiceRecoveryDlgProc( { if (context->NumberOfActions > 3) { - PhShowWarning( + PhShowWarning2( WindowHandle, + L"Warning.", L"The service has %lu failure actions configured, but this program only supports editing 3. " L"If you save the recovery information using this program, the additional failure actions will be lost.", context->NumberOfActions @@ -314,9 +315,10 @@ INT_PTR CALLBACK EspServiceRecoveryDlgProc( context->EnableFlagCheckBox = TRUE; EnableWindow(GetDlgItem(WindowHandle, IDC_ENABLEFORERRORSTOPS), TRUE); - PhShowWarning( + PhShowWarning2( WindowHandle, - L"Unable to query service recovery information: %s", + L"Unable to query service recovery information.", + L"%s", PhGetStringOrDefault(errorMessage, L"Unknown error.") ); @@ -585,6 +587,8 @@ INT_PTR CALLBACK EspServiceRecovery2DlgProc( _In_ LPARAM lParam ) { + if (WindowMessage == WM_INITDIALOG) + PhInitializeWindowTheme(WindowHandle, !!PhGetIntegerSetting(L"EnableThemeSupport")); return FALSE; } diff --git a/plugins/ExtendedServices/trigger.c b/plugins/ExtendedServices/trigger.c index e4355dca5fcf..f44fab2a2f3c 100644 --- a/plugins/ExtendedServices/trigger.c +++ b/plugins/ExtendedServices/trigger.c @@ -1429,7 +1429,7 @@ INT_PTR CALLBACK EspServiceTriggerDlgProc( { if (!EspLookupEtwPublisherGuid(&subTypeString->sr, &context->EditingInfo->SubtypeBuffer)) { - PhShowError(WindowHandle, L"%s", L"Unable to find the ETW publisher GUID."); + PhShowError2(WindowHandle, L"Unable to find the ETW publisher GUID.", L"%s", L""); goto DoNotClose; } @@ -1459,7 +1459,7 @@ INT_PTR CALLBACK EspServiceTriggerDlgProc( } else { - PhShowError(WindowHandle, L"%s", L"The custom subtype is invalid. Please ensure that the string is a valid GUID: \"{x-x-x-x-x}\"."); + PhShowError2(WindowHandle, L"The custom subtype is invalid.", L"%s", L"Please ensure that the string is a valid GUID: \"{x-x-x-x-x}\"."); goto DoNotClose; } } diff --git a/plugins/ExtendedServices/triggpg.c b/plugins/ExtendedServices/triggpg.c index db9ea7bd86fd..cfc849bfdcc3 100644 --- a/plugins/ExtendedServices/triggpg.c +++ b/plugins/ExtendedServices/triggpg.c @@ -91,9 +91,10 @@ INT_PTR CALLBACK EspServiceTriggersDlgProc( { PPH_STRING errorMessage = PhGetNtMessage(status); - PhShowWarning( + PhShowWarning2( WindowHandle, - L"Unable to query service trigger information: %s", + L"Unable to query service trigger information." + L"%s", PhGetStringOrDefault(errorMessage, L"Unknown error.") ); diff --git a/plugins/ExtendedTools/gpudetails.c b/plugins/ExtendedTools/gpudetails.c index 4e5f9e2b2f5c..d6c36368fd0f 100644 --- a/plugins/ExtendedTools/gpudetails.c +++ b/plugins/ExtendedTools/gpudetails.c @@ -577,7 +577,7 @@ VOID EtShowGpuDetailsDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtGpuDetailsDialogThreadHandle, EtGpuDetailsDialogThreadStart, ParentWindowHandle))) { - PhShowError(NULL, L"%s", L"Unable to create the window."); + PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/gpunodes.c b/plugins/ExtendedTools/gpunodes.c index ae438f5570ac..74357e582777 100644 --- a/plugins/ExtendedTools/gpunodes.c +++ b/plugins/ExtendedTools/gpunodes.c @@ -88,7 +88,7 @@ VOID EtShowGpuNodesDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtGpuNodesThreadHandle, EtpGpuNodesDialogThreadStart, ParentWindowHandle))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/npudetails.c b/plugins/ExtendedTools/npudetails.c index f86b891d3ac9..8a0bb1fdd20b 100644 --- a/plugins/ExtendedTools/npudetails.c +++ b/plugins/ExtendedTools/npudetails.c @@ -579,7 +579,7 @@ VOID EtShowNpuDetailsDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtNpuDetailsDialogThreadHandle, EtNpuDetailsDialogThreadStart, ParentWindowHandle))) { - PhShowError(NULL, L"%s", L"Unable to create the window."); + PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/npunodes.c b/plugins/ExtendedTools/npunodes.c index 386ff65a7bb5..a825d0c4e895 100644 --- a/plugins/ExtendedTools/npunodes.c +++ b/plugins/ExtendedTools/npunodes.c @@ -89,7 +89,7 @@ VOID EtShowNpuNodesDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtNpuNodesThreadHandle, EtpNpuNodesDialogThreadStart, ParentWindowHandle))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/objmgr.c b/plugins/ExtendedTools/objmgr.c index a980f7c218e6..1416981281a8 100644 --- a/plugins/ExtendedTools/objmgr.c +++ b/plugins/ExtendedTools/objmgr.c @@ -1326,7 +1326,7 @@ VOID EtShowObjectManagerDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtObjectManagerDialogThreadHandle, EtShowObjectManagerDialogThread, ParentWindowHandle))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/pooldialog.c b/plugins/ExtendedTools/pooldialog.c index 85bf0d7b1935..c132d012b271 100644 --- a/plugins/ExtendedTools/pooldialog.c +++ b/plugins/ExtendedTools/pooldialog.c @@ -399,7 +399,7 @@ VOID EtShowPoolTableDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtPoolTagDialogThreadHandle, EtShowPoolMonDialogThread, ParentWindowHandle))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/thrdact.c b/plugins/ExtendedTools/thrdact.c index 15d6e87d7f8b..991f80dc1cbf 100644 --- a/plugins/ExtendedTools/thrdact.c +++ b/plugins/ExtendedTools/thrdact.c @@ -41,7 +41,7 @@ BOOLEAN EtUiCancelIoThread( if (status == STATUS_NOT_FOUND) { - PhShowInformation(hWnd, L"%s", L"There is no synchronous I/O to cancel."); + PhShowInformation2(hWnd, L"There is no synchronous I/O to cancel.", L"%s", L""); return FALSE; } else if (!NT_SUCCESS(status)) diff --git a/plugins/ExtendedTools/waitchain.c b/plugins/ExtendedTools/waitchain.c index ebabc9222db6..663907cb73e9 100644 --- a/plugins/ExtendedTools/waitchain.c +++ b/plugins/ExtendedTools/waitchain.c @@ -522,7 +522,7 @@ INT_PTR CALLBACK WaitChainDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The process does not exist."); + PhShowError2(hwndDlg, L"The process does not exist.", L"%s", L""); } } } diff --git a/plugins/ExtendedTools/wswatch.c b/plugins/ExtendedTools/wswatch.c index 981dcfbb5183..b9db76d10cfc 100644 --- a/plugins/ExtendedTools/wswatch.c +++ b/plugins/ExtendedTools/wswatch.c @@ -516,7 +516,7 @@ INT_PTR CALLBACK EtpWsWatchDlgProc( if (!context->SymbolProvider) { - PhShowError(hwndDlg, L"%s", L"Unable to create the symbol provider."); + PhShowError2(hwndDlg, L"Unable to create the symbol provider.", L"%s", L""); EndDialog(hwndDlg, IDCANCEL); break; } diff --git a/plugins/HardwareDevices/diskdetails.c b/plugins/HardwareDevices/diskdetails.c index f64828734956..6039248df83c 100644 --- a/plugins/HardwareDevices/diskdetails.c +++ b/plugins/HardwareDevices/diskdetails.c @@ -956,7 +956,7 @@ VOID ShowDiskDeviceDetailsDialog( if (!NT_SUCCESS(PhCreateThreadEx(&threadHandle, ShowDiskDeviceDetailsDialogThread, pageContext))) { - PhShowError(Context->WindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(Context->WindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/HardwareDevices/gpunodes.c b/plugins/HardwareDevices/gpunodes.c index d0f4aa1e59fa..7b8679bc918a 100644 --- a/plugins/HardwareDevices/gpunodes.c +++ b/plugins/HardwareDevices/gpunodes.c @@ -78,7 +78,7 @@ VOID GraphicsDeviceShowNodesDialog( { if (Context->DeviceEntry->NumberOfNodes == 0) { - PhShowError(ParentWindowHandle, L"%s", L"There are no graphics nodes to display."); + PhShowError2(ParentWindowHandle, L"There are no graphics nodes to display.", L"%s", L""); return; } @@ -88,7 +88,7 @@ VOID GraphicsDeviceShowNodesDialog( if (!NT_SUCCESS(PhCreateThreadEx(&Context->NodeWindowThreadHandle, EtpGpuNodesDialogThreadStart, Context))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); PhDereferenceObject(Context); return; } diff --git a/plugins/HardwareDevices/netdetails.c b/plugins/HardwareDevices/netdetails.c index 435603f49384..4dc45efb1bb5 100644 --- a/plugins/HardwareDevices/netdetails.c +++ b/plugins/HardwareDevices/netdetails.c @@ -876,7 +876,7 @@ VOID ShowNetAdapterDetailsDialog( if (!NT_SUCCESS(PhCreateThreadEx(&threadHandle, ShowNetAdapterDetailsDialogThread, context))) { - PhShowError(Context->WindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(Context->WindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/NetworkTools/update.c b/plugins/NetworkTools/update.c index 59bbabd6d1c9..a4376bbfad32 100644 --- a/plugins/NetworkTools/update.c +++ b/plugins/NetworkTools/update.c @@ -814,7 +814,7 @@ VOID ShowGeoLiteUpdateDialog( { if (!GeoLiteCheckUpdatePlatformSupported()) { - PhShowError(ParentWindowHandle, L"%s", L"The GeoLite updater doesn't support legacy versions of Windows."); + PhShowError2(ParentWindowHandle, L"The GeoLite updater doesn't support legacy versions of Windows.", L"%s", L""); return; } @@ -853,7 +853,7 @@ VOID ShowGeoLiteUpdateDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&UpdateDialogThreadHandle, GeoLiteUpdateTaskDialogThread, ParentWindowHandle))) { - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ToolStatus/main.c b/plugins/ToolStatus/main.c index ecad333d411e..c56e4e4db1b1 100644 --- a/plugins/ToolStatus/main.c +++ b/plugins/ToolStatus/main.c @@ -1405,7 +1405,7 @@ LRESULT CALLBACK MainWindowProc( } else { - PhShowError(WindowHandle, L"The process (PID %lu) does not exist.", processId); + PhShowError2(WindowHandle, L"Error.", L"The process (PID %lu) does not exist.", processId); } } break; @@ -1420,7 +1420,7 @@ LRESULT CALLBACK MainWindowProc( } else { - PhShowError(WindowHandle, L"The process (PID %lu) does not exist.", processId); + PhShowError2(WindowHandle, L"Error.", L"The process (PID %lu) does not exist.", processId); } } break; diff --git a/plugins/Updater/updater.c b/plugins/Updater/updater.c index 1cdb575a9021..749d4207c59b 100644 --- a/plugins/Updater/updater.c +++ b/plugins/Updater/updater.c @@ -1377,7 +1377,7 @@ VOID ShowUpdateDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&UpdateDialogThreadHandle, ShowUpdateDialogThread, Context))) { - PhShowError(NULL, L"%s", L"Unable to create the window."); + PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/UserNotes/main.c b/plugins/UserNotes/main.c index 8e75b6369341..6067f67cac99 100644 --- a/plugins/UserNotes/main.c +++ b/plugins/UserNotes/main.c @@ -840,7 +840,7 @@ VOID NTAPI MenuItemCallback( if (NT_SUCCESS(status)) { - PhShowInformation(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", status, 0); + PhShowInformation2(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", L"%s", L""); } else { @@ -877,7 +877,7 @@ VOID NTAPI MenuItemCallback( if (NT_SUCCESS(status)) { - PhShowInformation(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", status, 0); + PhShowInformation2(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", L"%s", L""); } else { @@ -914,7 +914,7 @@ VOID NTAPI MenuItemCallback( if (NT_SUCCESS(status)) { - PhShowInformation(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", status, 0); + PhShowInformation2(menuItem->OwnerWindow, L"Successfully deleted the IFEO key.", L"%s", L""); } else { diff --git a/plugins/WindowExplorer/wnddlg.c b/plugins/WindowExplorer/wnddlg.c index 1d05fce1c078..74666d380c15 100644 --- a/plugins/WindowExplorer/wnddlg.c +++ b/plugins/WindowExplorer/wnddlg.c @@ -132,7 +132,7 @@ VOID WeShowWindowsDialog( if (!NT_SUCCESS(PhCreateThreadEx(&WepWindowsDialogThreadHandle, WepShowWindowsDialogThread, context))) { PhFree(context); - PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window."); + PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L""); return; } @@ -1244,7 +1244,7 @@ INT_PTR CALLBACK WepWindowsDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The process does not exist."); + PhShowError2(hwndDlg, L"The window does not exist.", L"%s", L""); } } } @@ -1270,7 +1270,7 @@ INT_PTR CALLBACK WepWindowsDlgProc( } else { - PhShowError(hwndDlg, L"%s", L"The process does not exist."); + PhShowError2(hwndDlg, L"The window does not exist.", L"%s", L""); } } } @@ -1327,7 +1327,7 @@ INT_PTR CALLBACK WepWindowsDlgProc( { if (!WeShowWindowProperties(hwndDlg, selectedNode->WindowHandle, !!selectedNode->WindowMessageOnly, &selectedNode->ClientId)) { - PhShowError(hwndDlg, L"%s", L"The window does not exist."); + PhShowError2(hwndDlg, L"The window does not exist.", L"%s", L""); } } } @@ -1972,7 +1972,7 @@ INT_PTR CALLBACK WepWindowsPageProc( } else { - PhShowError(hwndDlg, L"%s", L"The process does not exist."); + PhShowError2(hwndDlg, L"The window does not exist.", L"%s", L""); } } } @@ -2029,7 +2029,7 @@ INT_PTR CALLBACK WepWindowsPageProc( { if (!WeShowWindowProperties(hwndDlg, selectedNode->WindowHandle, !!selectedNode->WindowMessageOnly, &selectedNode->ClientId)) { - PhShowError(hwndDlg, L"%s", L"The window does not exist."); + PhShowError2(hwndDlg, L"The window does not exist.", L"%s", L""); } } } diff --git a/tools/peview/strings.c b/tools/peview/strings.c index 9308ff74fcf0..08764bf48119 100644 --- a/tools/peview/strings.c +++ b/tools/peview/strings.c @@ -673,7 +673,7 @@ INT_PTR CALLBACK PvpStringsMinimumLengthDlgProc( if (!minimumLength || minimumLength > MAXULONG32) { - PhShowError(hwndDlg, L"%s", L"Invalid minimum length"); + PhShowError2(hwndDlg, L"Invalid minimum length", L"%s", L""); break; } From fc988a21548ae6b246a117c3f859d30bf36e161e Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Sat, 12 Oct 2024 23:34:53 +0300 Subject: [PATCH 06/11] Public PhThemeWindowDrawButton: tristate checkbox, radio, multiline - Fix the annoying white border what remained from the previous active control in CHECKLIST_ACLUI - ExtendedServices: MessageBox to TaskDialog transit --- SystemInformer/delayhook.c | 131 ++++++++++++-------- SystemInformer/main.c | 14 ++- SystemInformer/tokprp.c | 2 +- phlib/include/guisup.h | 7 ++ phlib/theme.c | 186 +++++++++++++++++++++------- plugins/ExtendedServices/other.c | 45 ++++--- plugins/ExtendedServices/recovery.c | 9 +- plugins/ExtendedServices/trigger.c | 11 +- plugins/ExtendedServices/triggpg.c | 13 +- plugins/ExtendedTools/gpudetails.c | 2 +- plugins/ExtendedTools/npudetails.c | 2 +- plugins/Updater/updater.c | 2 +- tools/peview/delayhook.c | 118 +++++++++++------- tools/peview/main.c | 15 ++- 14 files changed, 362 insertions(+), 195 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index b702d9aad900..48f4d20307cf 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -224,10 +224,26 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( return TRUE; } break; + case WM_KILLFOCUS: + { + WCHAR windowClassName[MAX_PATH]; + HWND ParentHandle = GetParent(WindowHandle); + if (!GetClassName(ParentHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) + { + RECT rectClient; + GetClientRect(WindowHandle, &rectClient); + InflateRect(&rectClient, 2, 2); + MapWindowRect(WindowHandle, ParentHandle, &rectClient); + InvalidateRect(ParentHandle, &rectClient, TRUE); // fix the annoying white border left by the previous active control + } + } + break; case WM_PAINT: { HDC hdc; - //HICON iconHandle; + HICON iconHandle; RECT clientRect; WCHAR windowClassName[MAX_PATH]; @@ -238,38 +254,41 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( windowClassName[0] = UNICODE_NULL; if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) { - static PH_INITONCE initOnce = PH_INITONCE_INIT; - static HFONT hCheckFont = NULL; - - LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - hdc = GetDC(WindowHandle); - GetClientRect(WindowHandle, &clientRect); - INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; - INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; - COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); - if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked + if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) { - if (PhBeginInitOnce(&initOnce)) // cache font + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static HFONT hCheckFont = NULL; + + LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; + INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); + if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked { - hCheckFont = CreateFont( - clientRect.bottom - clientRect.top - 1, - clientRect.right - clientRect.left - 3, - 0, 0, - FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, - CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, - VARIABLE_PITCH, L"Segoe UI"); - PhEndInitOnce(&initOnce); + if (PhBeginInitOnce(&initOnce)) // cache font + { + hCheckFont = CreateFont( + clientRect.bottom - clientRect.top - 1, + clientRect.right - clientRect.left - 3, + 0, 0, + FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, + VARIABLE_PITCH, L"Segoe UI"); + PhEndInitOnce(&initOnce); + } + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SelectFont(hdc, hCheckFont); + //HFONT hFontOriginal = SelectFont(hdc, hCheckFont); + FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); + DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); + //SelectFont(hdc, hFontOriginal); } - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); - SelectObject(hdc, hCheckFont); - //HFONT hFontOriginal = (HFONT)SelectObject(hdc, hCheckFont); - FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); - DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); - //SelectObject(hdc, hFontOriginal); + ReleaseDC(WindowHandle, hdc); + return retval; } - ReleaseDC(WindowHandle, hdc); - return retval; } //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) //{ @@ -1658,25 +1677,25 @@ HRESULT WINAPI PhDrawThemeTextHook( _In_ LPCRECT pRect ) { - if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) + if ((iPartId == BP_COMMANDLINK /*|| iPartId == BP_RADIOBUTTON*/) && iStateId != PBS_DISABLED) { WCHAR className[MAX_PATH]; if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { // 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) || - PhEqualStringZ((PWSTR)pszText, L"Realtime", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"High", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Above normal", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Normal", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Below normal", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Idle", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Medium", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Low", FALSE) || - PhEqualStringZ((PWSTR)pszText, L"Very low", FALSE)) + //if (iPartId == BP_COMMANDLINK || + // PhEqualStringZ((PWSTR)pszText, L"Stable\n - Recommended", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Canary\n - Preview", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Realtime", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"High", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Above normal", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Normal", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Below normal", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Idle", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Medium", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Low", FALSE) || + // PhEqualStringZ((PWSTR)pszText, L"Very low", FALSE)) { DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); @@ -1705,13 +1724,9 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { - DTTOPTS options; + DTTOPTS options = { sizeof(DTTOPTS) }; if (pOptions) options = *pOptions; - else { - memset(&options, 0, sizeof(options)); - options.dwSize = sizeof(DTTOPTS); - } options.dwFlags |= DTT_TEXTCOLOR; PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); options.crText = PhMakeColorBrighter(options.crText, 90); @@ -1765,14 +1780,14 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( if (CallbackData && !windowHasContext) { - PhInitializeThemeWindowFrame(WindowHandle); - if (PhDefaultEnableStreamerMode) { if (SetWindowDisplayAffinity_Import()) SetWindowDisplayAffinity_Import()(WindowHandle, WDA_EXCLUDEFROMCAPTURE); } + PhInitializeThemeWindowFrame(WindowHandle); + PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; @@ -1855,6 +1870,24 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( } } return TRUE; + case WM_NOTIFY: + { + LPNMHDR data = (LPNMHDR)lParam; + + if (data->code == NM_CUSTOMDRAW) + { + LPNMCUSTOMDRAW customDraw = (LPNMCUSTOMDRAW)lParam; + WCHAR className[MAX_PATH]; + + if (!GetClassName(customDraw->hdr.hwndFrom, className, RTL_NUMBER_OF(className))) + className[0] = UNICODE_NULL; + if (PhEqualStringZ(className, WC_BUTTON, FALSE)) + { + return PhThemeWindowDrawButton(customDraw); + } + } + } + break; case TDM_NAVIGATE_PAGE: { PTASKDIALOG_WINDOW_CONTEXT WindowContext = (PTASKDIALOG_WINDOW_CONTEXT)context; diff --git a/SystemInformer/main.c b/SystemInformer/main.c index 3db3564e76b1..daa30dc89c9b 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -234,7 +234,7 @@ INT WINAPI wWinMain( if (PhIsExecutingInWow64()) { PhShowWarning2( - NULL, + GetDesktopWindow(), L"Warning.", L"%s", L"You are attempting to run the 32-bit version of System Informer on 64-bit Windows. " @@ -262,7 +262,7 @@ INT WINAPI wWinMain( if (!PhMainWndInitialization(CmdShow)) { - PhShowError2(NULL, L"Unable to initialize the main window.", L"%s", L""); + PhShowError2(GetDesktopWindow(), L"Unable to initialize the main window.", L"%s", L""); return 1; } @@ -1449,8 +1449,14 @@ VOID PhpProcessStartupParameters( NULL ) || PhStartupParameters.Help) { + if (PhStartupParameters.Help) + { + PhGuiSupportInitialization(); + PhpInitializeSettings(); + PhInitializeSuperclassControls(); + } PhShowInformation2( - NULL, + GetDesktopWindow(), L"Command line options:", L"%s", L"-debug\n" @@ -1469,7 +1475,7 @@ VOID PhpProcessStartupParameters( L"-settings filename\n" L"-sysinfo [section-name]\n" L"-channel [channel-name]\n" - L"-v\n" + L"-v" ); if (PhStartupParameters.Help) diff --git a/SystemInformer/tokprp.c b/SystemInformer/tokprp.c index 97b3ffa4f2fe..2f04bd3b86f7 100644 --- a/SystemInformer/tokprp.c +++ b/SystemInformer/tokprp.c @@ -295,7 +295,7 @@ VOID PhCreateTokenDialog( DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ))) { - PhShowError2(NULL, L"Unable to duplicate the token.", L"%s", L""); + PhShowError2(GetDesktopWindow(), L"Unable to duplicate the token.", L"%s", L""); return; } diff --git a/phlib/include/guisup.h b/phlib/include/guisup.h index 86cd80317e07..8bb1c2678f78 100644 --- a/phlib/include/guisup.h +++ b/phlib/include/guisup.h @@ -2131,6 +2131,13 @@ PhThemeWindowDrawItem( _In_ PDRAWITEMSTRUCT DrawInfo ); +PHLIBAPI +LRESULT +NTAPI +PhThemeWindowDrawButton( + _In_ LPNMCUSTOMDRAW DrawInfo + ); + PHLIBAPI BOOLEAN NTAPI diff --git a/phlib/theme.c b/phlib/theme.c index 1a06e1cc2afc..9f7a4f59ec85 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -1570,12 +1570,20 @@ VOID PhThemeDrawButtonIcon( } } -LRESULT CALLBACK PhpThemeWindowDrawButton( +LRESULT CALLBACK PhThemeWindowDrawButton( _In_ LPNMCUSTOMDRAW DrawInfo ) { + LONG_PTR buttonStyle; + + buttonStyle = PhGetWindowStyle(DrawInfo->hdr.hwndFrom); + // COMMANDLINK unsupported + if ((buttonStyle & BS_COMMANDLINK) == BS_COMMANDLINK || (buttonStyle & BS_DEFCOMMANDLINK) == BS_DEFCOMMANDLINK) + return CDRF_DODEFAULT; + BOOLEAN isGrayed = (DrawInfo->uItemState & CDIS_GRAYED) == CDIS_GRAYED; BOOLEAN isChecked = (DrawInfo->uItemState & CDIS_CHECKED) == CDIS_CHECKED; + BOOLEAN isMixed = (DrawInfo->uItemState & CDIS_INDETERMINATE) == CDIS_INDETERMINATE; BOOLEAN isDisabled = (DrawInfo->uItemState & CDIS_DISABLED) == CDIS_DISABLED; BOOLEAN isSelected = (DrawInfo->uItemState & CDIS_SELECTED) == CDIS_SELECTED; BOOLEAN isHighlighted = (DrawInfo->uItemState & CDIS_HOT) == CDIS_HOT; @@ -1592,32 +1600,51 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( case CDDS_PREPAINT: { PPH_STRING buttonText; - LONG_PTR buttonStyle; HICON buttonIcon; LONG dpiValue; + BOOLEAN isCheckbox = (buttonStyle & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX || (buttonStyle & BS_AUTO3STATE) == BS_AUTO3STATE; + BOOLEAN isRadio = (buttonStyle & BS_AUTORADIOBUTTON) == BS_AUTORADIOBUTTON; + + if (!isCheckbox && !isRadio && PhEnableThemeNativeButtons && !PhEnableThemeAcrylicWindowSupport) + return CDRF_DODEFAULT; + dpiValue = PhGetWindowDpi(DrawInfo->hdr.hwndFrom); buttonText = PhGetWindowText(DrawInfo->hdr.hwndFrom); - buttonStyle = PhGetWindowStyle(DrawInfo->hdr.hwndFrom); if (!(buttonIcon = Static_GetIcon(DrawInfo->hdr.hwndFrom, 0))) buttonIcon = (HICON)SendMessage(DrawInfo->hdr.hwndFrom, BM_GETIMAGE, IMAGE_ICON, 0); - if ((buttonStyle & BS_CHECKBOX) == BS_CHECKBOX) + // Add support for disabled and tristate checkboxes, support for radio with multiline (ex. TaskDialog) (Dart Vanya) + if (isCheckbox || isRadio) { - INT state = CBS_UNCHECKEDNORMAL; + INT state = isCheckbox ? CBS_UNCHECKEDNORMAL : RBS_UNCHECKEDNORMAL; HTHEME themeHandle; - isChecked = Button_GetCheck(DrawInfo->hdr.hwndFrom) == BST_CHECKED; + isChecked = Button_GetCheck(DrawInfo->hdr.hwndFrom) & BST_CHECKED; + isMixed = Button_GetCheck(DrawInfo->hdr.hwndFrom) & BST_INDETERMINATE; - if (DrawInfo->uItemState & CDIS_SELECTED) - state = isChecked ? CBS_CHECKEDPRESSED : CBS_UNCHECKEDPRESSED; + if (isCheckbox) + { + if (isDisabled) + state = isChecked ? CBS_CHECKEDDISABLED : isMixed ? CBS_MIXEDDISABLED : CBS_UNCHECKEDDISABLED; + else if (isSelected) + state = isChecked ? CBS_CHECKEDPRESSED : isMixed ? CBS_MIXEDPRESSED : CBS_UNCHECKEDPRESSED; + else if (isHighlighted) + state = isChecked ? CBS_CHECKEDHOT : isMixed ? CBS_MIXEDHOT : CBS_UNCHECKEDHOT; + else + state = isChecked ? CBS_CHECKEDNORMAL : isMixed ? CBS_MIXEDNORMAL : CBS_UNCHECKEDNORMAL; + } else { - if (DrawInfo->uItemState & CDIS_HOT) - state = isChecked ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT; + if (isDisabled) + state = isChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED; + else if (isSelected) + state = isChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED; + else if (isHighlighted) + state = isChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT; else - state = isChecked ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL; + state = isChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL; } if (buttonIcon) @@ -1662,63 +1689,102 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( } else { + SetBkMode(DrawInfo->hdc, TRANSPARENT); + SetTextColor(DrawInfo->hdc, !isDisabled ? PhThemeWindowTextColor : RGB(0x9B, 0x9B, 0x9B)); + if (themeHandle = PhOpenThemeData(DrawInfo->hdr.hwndFrom, VSCLASS_BUTTON, dpiValue)) { SIZE checkBoxSize = { 0 }; + SIZE textSize = { 0 }; + INT linesCount; PhGetThemePartSize( themeHandle, DrawInfo->hdc, - BP_CHECKBOX, + isCheckbox ? BP_CHECKBOX : BP_RADIOBUTTON, state, &bufferRect, TS_TRUE, &checkBoxSize ); + GetTextExtentPoint32W(DrawInfo->hdc, L"T", 1, &textSize); bufferRect.left = 0; bufferRect.right = checkBoxSize.cx; + linesCount = (bufferRect.bottom - bufferRect.top) / textSize.cy; + if (linesCount > 1) + bufferRect.bottom -= textSize.cy * (linesCount - 1); // HACK (very sensitive value) - //if (IsThemeBackgroundPartiallyTransparent(themeHandle, BP_CHECKBOX, state)) + //if (IsThemeBackgroundPartiallyTransparent(themeHandle, isCheckbox ? BP_CHECKBOX : BP_RADIOBUTTON, state)) // DrawThemeParentBackground(DrawInfo->hdr.hwndFrom, DrawInfo->hdc, NULL); PhDrawThemeBackground( themeHandle, DrawInfo->hdc, - BP_CHECKBOX, + isCheckbox ? BP_CHECKBOX : BP_RADIOBUTTON, state, &bufferRect, NULL ); - //DTTOPTS opts = { 0 }; - //opts.dwSize = sizeof(DTTOPTS); - //opts.crText = RGB(255, 255, 255); - //opts.dwFlags |= DTT_TEXTCOLOR; - // - //DrawThemeTextEx( - // themeHandle, - // DrawInfo->hdc, - // BP_CHECKBOX, - // state, - // buttonText->Buffer, - // (UINT)buttonText->Length / sizeof(WCHAR), - // DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX, - // &bufferRect, - // &opts - // ); - - bufferRect.left = checkBoxSize.cx + 5; // TNP_ICON_RIGHT_PADDING - bufferRect.right = DrawInfo->rc.right; + bufferRect = DrawInfo->rc; + bufferRect.left = checkBoxSize.cx + 4; // TNP_ICON_RIGHT_PADDING - DrawText( - DrawInfo->hdc, - buttonText->Buffer, - (UINT)buttonText->Length / sizeof(WCHAR), - &bufferRect, - DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX + if (linesCount == 1) + { + DrawText( + DrawInfo->hdc, + buttonText->Buffer, + (UINT)buttonText->Length / sizeof(WCHAR), + &bufferRect, + DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_HIDEPREFIX + ); + } + else + { + DrawText( + DrawInfo->hdc, + buttonText->Buffer, + (UINT)buttonText->Length / sizeof(WCHAR), + &bufferRect, + DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX ); + bufferRect.top = (DrawInfo->rc.bottom - DrawInfo->rc.top) / 2 - (bufferRect.bottom - bufferRect.top) / 2 - 1; + bufferRect.bottom = DrawInfo->rc.bottom, bufferRect.right = DrawInfo->rc.right; + + DrawText( + DrawInfo->hdc, + buttonText->Buffer, + (UINT)buttonText->Length / sizeof(WCHAR), + &bufferRect, + DT_LEFT | DT_TOP | DT_HIDEPREFIX + ); + } + + if (isFocused && (DrawInfo->uItemState & CDIS_SHOWKEYBOARDCUES) == CDIS_SHOWKEYBOARDCUES) + { + DrawText( + DrawInfo->hdc, + buttonText->Buffer, + (UINT)buttonText->Length / sizeof(WCHAR), + &bufferRect, + DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX + ); + PhInflateRect(&bufferRect, 1, 0); + bufferRect.top += 1, bufferRect.bottom += 2; + if (bufferRect.bottom > DrawInfo->rc.bottom - 1) bufferRect.bottom = DrawInfo->rc.bottom - 1; + + for (INT i = 0; i < bufferRect.right - bufferRect.left - 1; i += 2) + SetPixel(DrawInfo->hdc, bufferRect.left + i + 1, bufferRect.bottom, PhThemeWindowHighlight2Color); + for (INT i = 0; i < bufferRect.bottom - bufferRect.top - 1; i += 2) + SetPixel(DrawInfo->hdc, bufferRect.right, bufferRect.bottom - i - 1, PhThemeWindowHighlight2Color); + for (INT i = 0; i < bufferRect.right - bufferRect.left - 1; i += 2) + SetPixel(DrawInfo->hdc, bufferRect.right - i - 1, bufferRect.top, PhThemeWindowHighlight2Color); + for (INT i = 0; i < bufferRect.bottom - bufferRect.top - 1; i += 2) + SetPixel(DrawInfo->hdc, bufferRect.left, bufferRect.top + i + 1, PhThemeWindowHighlight2Color); + } + PhCloseThemeData(themeHandle); } else @@ -1756,7 +1822,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( DeleteFont(newFont); } - //bufferRect.left = checkBoxSize.cx + 5; // TNP_ICON_RIGHT_PADDING + bufferRect.left = 17; bufferRect.right = DrawInfo->rc.right; DrawText( @@ -1771,9 +1837,6 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( } else { - if (PhEnableThemeNativeButtons && !PhEnableThemeAcrylicWindowSupport) - return CDRF_DODEFAULT; - if (isSelected) { //switch (PhpThemeColorMode) @@ -1807,7 +1870,8 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( FillRect(DrawInfo->hdc, &DrawInfo->rc, PhThemeWindowBackgroundBrush); } - SetDCBrushColor(DrawInfo->hdc, PhThemeWindowBackground2Color); + SetBkMode(DrawInfo->hdc, TRANSPARENT); + SetDCBrushColor(DrawInfo->hdc, !isFocused ? PhThemeWindowBackground2Color : PhThemeWindowHighlightColor); FrameRect(DrawInfo->hdc, &DrawInfo->rc, PhGetStockBrush(DC_BRUSH)); PhThemeDrawButtonIcon(DrawInfo, buttonIcon, &bufferRect, dpiValue); @@ -1823,6 +1887,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( ); } } + PhDereferenceObject(buttonText); } return CDRF_SKIPDEFAULT; @@ -2195,7 +2260,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( if (PhEqualStringZ(className, WC_BUTTON, FALSE)) { - return PhpThemeWindowDrawButton(customDraw); + return PhThemeWindowDrawButton(customDraw); } else if (PhEqualStringZ(className, REBARCLASSNAME, FALSE)) { @@ -2240,7 +2305,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { HDC hdc = (HDC)wParam; - SetBkMode(hdc, TRANSPARENT); + SetBkColor(hdc, PhThemeWindowBackgroundColor); SetTextColor(hdc, PhThemeWindowTextColor); return (INT_PTR)PhThemeWindowBackgroundBrush; } @@ -2260,7 +2325,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( useColorLink = litem.state & LIS_DEFAULTCOLORS; } - SetBkMode(hdc, TRANSPARENT); + SetBkColor(hdc, PhThemeWindowBackgroundColor); SetTextColor(hdc, !useColorLink ? PhThemeWindowTextColor : 0xE9BD5B); // To apply color for SysLink call PhInitializeSysLinkTheme() first return (INT_PTR)PhThemeWindowBackgroundBrush; } @@ -3188,6 +3253,33 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( switch (uMsg) { + case WM_NOTIFY: + { + LPNMHDR data = (LPNMHDR)lParam; + + if (data->code == NM_CUSTOMDRAW) + { + LPNMCUSTOMDRAW customDraw = (LPNMCUSTOMDRAW)lParam; + WCHAR className[MAX_PATH]; + + if (customDraw->dwDrawStage == CDDS_PREPAINT) + { + if (!GetClassName(customDraw->hdr.hwndFrom, className, RTL_NUMBER_OF(className))) + className[0] = UNICODE_NULL; + if (PhEqualStringZ(className, WC_BUTTON, FALSE)) + { + HDC hdc = GetDC(WindowHandle); + RECT rectControl = customDraw->rc; + InflateRect(&rectControl, 2, 2); + MapWindowRect(customDraw->hdr.hwndFrom, WindowHandle, &rectControl); + FillRect(hdc, &rectControl, PhThemeWindowBackgroundBrush); // fix the annoying white border left by the previous active control + ReleaseDC(WindowHandle, hdc); + } + return CDRF_DODEFAULT; + } + } + } + break; case WM_NCDESTROY: { PhRemoveWindowContext(WindowHandle, LONG_MAX); diff --git a/plugins/ExtendedServices/other.c b/plugins/ExtendedServices/other.c index c8ff475da63d..e91ae1591af5 100644 --- a/plugins/ExtendedServices/other.c +++ b/plugins/ExtendedServices/other.c @@ -452,11 +452,10 @@ INT_PTR CALLBACK EspServiceOtherDlgProc( if (found) { - if (PhShowMessage( - WindowHandle, - MB_OKCANCEL | MB_ICONERROR, - L"The selected privilege has already been added." - ) == IDOK) + if (PhShowMessage2(WindowHandle, TD_OK_BUTTON | TD_CANCEL_BUTTON, TD_ERROR_ICON, + L"The selected privilege has already been added.", + L"%s", + L"") == IDOK) { continue; } @@ -565,11 +564,24 @@ INT_PTR CALLBACK EspServiceOtherDlgProc( if (context->LaunchProtectedValid && launchProtected != 0 && launchProtected != context->OriginalLaunchProtected) { - if (PhShowMessage( - WindowHandle, - MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2, - L"Setting service protection will prevent the service from being controlled, modified, or deleted. Do you want to continue?" - ) == IDNO) + INT result; + TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) }; + + config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW; + config.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON; + config.nDefaultButton = IDNO; + config.hwndParent = WindowHandle; + config.pszWindowTitle = L"System Informer"; + config.pszMainIcon = TD_WARNING_ICON; + config.pszMainInstruction = L"Setting service protection will prevent the service from being controlled, modified, or deleted."; + config.pszContent = L"Do you want to continue?"; + + if (!PhShowTaskDialog( + &config, + &result, + NULL, + NULL + ) || result != IDYES) { SetWindowLongPtr(WindowHandle, DWLP_MSGRESULT, PSNRET_INVALID); return TRUE; @@ -682,19 +694,14 @@ INT_PTR CALLBACK EspServiceOtherDlgProc( if (!NT_SUCCESS(status)) { - PPH_STRING errorMessage = PhGetNtMessage(status); - - if (status == STATUS_CANCELLED || PhShowMessage( + if (PhShowContinueStatus( WindowHandle, - MB_ICONERROR | MB_RETRYCANCEL, - L"Unable to change service information: %s", - PhGetStringOrDefault(errorMessage, L"Unknown error.") - ) == IDRETRY) + L"Unable to change service information.", + status, + 0)) { SetWindowLongPtr(WindowHandle, DWLP_MSGRESULT, PSNRET_INVALID); } - - PhClearReference(&errorMessage); } } diff --git a/plugins/ExtendedServices/recovery.c b/plugins/ExtendedServices/recovery.c index 41caf3eb0281..4c3a22fbeaa9 100644 --- a/plugins/ExtendedServices/recovery.c +++ b/plugins/ExtendedServices/recovery.c @@ -558,12 +558,11 @@ INT_PTR CALLBACK EspServiceRecoveryDlgProc( { PPH_STRING errorMessage = PhGetNtMessage(status); - if (PhShowMessage( + if (PhShowContinueStatus( WindowHandle, - MB_ICONERROR | MB_RETRYCANCEL, - L"Unable to change service recovery information: %s", - PhGetStringOrDefault(errorMessage, L"Unknown error.") - ) == IDRETRY) + L"Unable to change service recovery information.", + status, + 0)) { SetWindowLongPtr(WindowHandle, DWLP_MSGRESULT, PSNRET_INVALID); } diff --git a/plugins/ExtendedServices/trigger.c b/plugins/ExtendedServices/trigger.c index f44fab2a2f3c..c6080b532c86 100644 --- a/plugins/ExtendedServices/trigger.c +++ b/plugins/ExtendedServices/trigger.c @@ -1479,13 +1479,10 @@ INT_PTR CALLBACK EspServiceTriggerDlgProc( ) { // This trigger has data items, but the trigger type doesn't allow them. - if (PhShowMessage( - WindowHandle, - MB_OKCANCEL | MB_ICONWARNING, - L"The trigger type \"%s\" does not allow data items to be configured. " - L"If you continue, they will be removed.", - typeString->Buffer - ) != IDOK) + if (PhShowMessage2(WindowHandle, TD_OK_BUTTON | TD_CANCEL_BUTTON, TD_WARNING_ICON, + PhaFormatString(L"The trigger type \"%s\" does not allow data items to be configured.", typeString->Buffer)->Buffer, + L"%s", + L"If you continue, they will be removed.") != IDOK) { goto DoNotClose; } diff --git a/plugins/ExtendedServices/triggpg.c b/plugins/ExtendedServices/triggpg.c index cfc849bfdcc3..bb7fd5ebd82b 100644 --- a/plugins/ExtendedServices/triggpg.c +++ b/plugins/ExtendedServices/triggpg.c @@ -164,19 +164,14 @@ INT_PTR CALLBACK EspServiceTriggersDlgProc( } else { - PPH_STRING errorMessage = PhGetNtMessage(status); - - if (PhShowMessage( + if (PhShowContinueStatus( WindowHandle, - MB_ICONERROR | MB_RETRYCANCEL, - L"Unable to change service trigger information: %s", - PhGetStringOrDefault(errorMessage, L"Unknown error.") - ) == IDRETRY) + L"Unable to change service trigger information.", + status, + 0)) { SetWindowLongPtr(WindowHandle, DWLP_MSGRESULT, PSNRET_INVALID); } - - PhClearReference(&errorMessage); } } diff --git a/plugins/ExtendedTools/gpudetails.c b/plugins/ExtendedTools/gpudetails.c index d6c36368fd0f..5cd83bb2c138 100644 --- a/plugins/ExtendedTools/gpudetails.c +++ b/plugins/ExtendedTools/gpudetails.c @@ -577,7 +577,7 @@ VOID EtShowGpuDetailsDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtGpuDetailsDialogThreadHandle, EtGpuDetailsDialogThreadStart, ParentWindowHandle))) { - PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); + PhShowError2(GetDesktopWindow(), L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/ExtendedTools/npudetails.c b/plugins/ExtendedTools/npudetails.c index 8a0bb1fdd20b..fb101c7efe81 100644 --- a/plugins/ExtendedTools/npudetails.c +++ b/plugins/ExtendedTools/npudetails.c @@ -579,7 +579,7 @@ VOID EtShowNpuDetailsDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&EtNpuDetailsDialogThreadHandle, EtNpuDetailsDialogThreadStart, ParentWindowHandle))) { - PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); + PhShowError2(GetDesktopWindow(), L"Unable to create the window.", L"%s", L""); return; } diff --git a/plugins/Updater/updater.c b/plugins/Updater/updater.c index 749d4207c59b..328352deda81 100644 --- a/plugins/Updater/updater.c +++ b/plugins/Updater/updater.c @@ -1377,7 +1377,7 @@ VOID ShowUpdateDialog( { if (!NT_SUCCESS(PhCreateThreadEx(&UpdateDialogThreadHandle, ShowUpdateDialogThread, Context))) { - PhShowError2(NULL, L"Unable to create the window.", L"%s", L""); + PhShowError2(GetDesktopWindow(), L"Unable to create the window.", L"%s", L""); return; } diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 1f8666b84966..27d2abdf6ce1 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -224,10 +224,26 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( return TRUE; } break; + case WM_KILLFOCUS: + { + WCHAR windowClassName[MAX_PATH]; + HWND ParentHandle = GetParent(WindowHandle); + if (!GetClassName(ParentHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) + { + RECT rectClient; + GetClientRect(WindowHandle, &rectClient); + InflateRect(&rectClient, 2, 2); + MapWindowRect(WindowHandle, ParentHandle, &rectClient); + InvalidateRect(ParentHandle, &rectClient, TRUE); // fix the annoying white border left by the previous active control + } + } + break; case WM_PAINT: { HDC hdc; - //HICON iconHandle; + HICON iconHandle; RECT clientRect; WCHAR windowClassName[MAX_PATH]; @@ -238,38 +254,41 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( windowClassName[0] = UNICODE_NULL; if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) { - static PH_INITONCE initOnce = PH_INITONCE_INIT; - static HFONT hCheckFont = NULL; - - LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - hdc = GetDC(WindowHandle); - GetClientRect(WindowHandle, &clientRect); - INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; - INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; - COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); - if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked + if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) { - if (PhBeginInitOnce(&initOnce)) // cache font + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static HFONT hCheckFont = NULL; + + LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + hdc = GetDC(WindowHandle); + GetClientRect(WindowHandle, &clientRect); + INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; + INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); + if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked { - hCheckFont = CreateFont( - clientRect.bottom - clientRect.top - 1, - clientRect.right - clientRect.left - 3, - 0, 0, - FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, - CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, - VARIABLE_PITCH, L"Segoe UI"); - PhEndInitOnce(&initOnce); + if (PhBeginInitOnce(&initOnce)) // cache font + { + hCheckFont = CreateFont( + clientRect.bottom - clientRect.top - 1, + clientRect.right - clientRect.left - 3, + 0, 0, + FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, + VARIABLE_PITCH, L"Segoe UI"); + PhEndInitOnce(&initOnce); + } + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SelectFont(hdc, hCheckFont); + //HFONT hFontOriginal = SelectFont(hdc, hCheckFont); + FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); + DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); + //SelectFont(hdc, hFontOriginal); } - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); - SelectObject(hdc, hCheckFont); - //HFONT hFontOriginal = (HFONT)SelectObject(hdc, hCheckFont); - FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); - DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); - //SelectObject(hdc, hFontOriginal); + ReleaseDC(WindowHandle, hdc); + return retval; } - ReleaseDC(WindowHandle, hdc); - return retval; } //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) //{ @@ -1658,20 +1677,14 @@ HRESULT WINAPI PhDrawThemeTextHook( _In_ LPCRECT pRect ) { - if ((iPartId == BP_RADIOBUTTON || iPartId == BP_COMMANDLINK) && iStateId != PBS_DISABLED) + if (iPartId == BP_COMMANDLINK && iStateId != PBS_DISABLED) { WCHAR className[MAX_PATH]; if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { - // 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); - } + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); } } @@ -1696,13 +1709,9 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { - DTTOPTS options; + DTTOPTS options = { sizeof(DTTOPTS) }; if (pOptions) options = *pOptions; - else { - memset(&options, 0, sizeof(options)); - options.dwSize = sizeof(DTTOPTS); - } options.dwFlags |= DTT_TEXTCOLOR; PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); options.crText = PhMakeColorBrighter(options.crText, 90); @@ -1756,14 +1765,14 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( if (CallbackData && !windowHasContext) { - PhInitializeThemeWindowFrame(WindowHandle); - if (PhDefaultEnableStreamerMode) { if (SetWindowDisplayAffinity_Import()) SetWindowDisplayAffinity_Import()(WindowHandle, WDA_EXCLUDEFROMCAPTURE); } + PhInitializeThemeWindowFrame(WindowHandle); + PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; @@ -1846,6 +1855,24 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( } } return TRUE; + case WM_NOTIFY: + { + LPNMHDR data = (LPNMHDR)lParam; + + if (data->code == NM_CUSTOMDRAW) + { + LPNMCUSTOMDRAW customDraw = (LPNMCUSTOMDRAW)lParam; + WCHAR className[MAX_PATH]; + + if (!GetClassName(customDraw->hdr.hwndFrom, className, RTL_NUMBER_OF(className))) + className[0] = UNICODE_NULL; + if (PhEqualStringZ(className, WC_BUTTON, FALSE)) + { + return PhThemeWindowDrawButton(customDraw); + } + } + } + break; case TDM_NAVIGATE_PAGE: { PTASKDIALOG_WINDOW_CONTEXT WindowContext = (PTASKDIALOG_WINDOW_CONTEXT)context; @@ -2028,7 +2055,6 @@ VOID PvInitializeSuperclassControls( if (WindowsVersion >= WINDOWS_11) { PhDefaultEnableThemeAcrylicWindowSupport = !!PhGetIntegerSetting(L"EnableThemeAcrylicWindowSupport"); - PhEnableThemeAcrylicWindowSupport = PhDefaultEnableThemeAcrylicWindowSupport; } PhDefaultEnableThemeAnimation = !!PhGetIntegerSetting(L"EnableThemeAnimation"); diff --git a/tools/peview/main.c b/tools/peview/main.c index 63ee1b55e146..8cfa230a63c0 100644 --- a/tools/peview/main.c +++ b/tools/peview/main.c @@ -117,13 +117,18 @@ INT WINAPI wWinMain( #ifndef DEBUG if (PhIsExecutingInWow64()) { - PhShowWarning( - NULL, + PhGuiSupportInitialization(); + PhSettingsInitialization(); + PvInitializeSettings(); + PvInitializeSuperclassControls(); + PhShowWarning2( + GetDesktopWindow(), + L"Warning.", L"%s", L"You are attempting to run the 32-bit version of PE Viewer on 64-bit Windows. " L"Most features will not work correctly.\n\n" L"Please run the 64-bit version of PE Viewer instead." - ); + ); PhExitApplication(STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT); } #endif @@ -306,9 +311,9 @@ INT WINAPI wWinMain( if (!NT_SUCCESS(status)) { if (status == STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT) - PhShowError2(NULL, L"Unable to load the file.", L"%s", L"PE Viewer does not support this image type."); + PhShowError2(GetDesktopWindow(), L"Unable to load the file.", L"%s", L"PE Viewer does not support this image type."); else - PhShowStatus(NULL, L"Unable to load the file.", status, 0); + PhShowStatus(GetDesktopWindow(), L"Unable to load the file.", status, 0); } } From 77db313ae065ab13b6906deddf3541478b70832d Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Wed, 16 Oct 2024 22:21:33 +0300 Subject: [PATCH 07/11] Better ListView theme (OpenNcThemeData hook) --- SystemInformer/delayhook.c | 84 ++++++++++++++++++++++++++------------ phlib/theme.c | 17 ++++++-- tools/peview/delayhook.c | 82 ++++++++++++++++++++++++++----------- 3 files changed, 131 insertions(+), 52 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 48f4d20307cf..3a2dc3f15626 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -32,6 +32,10 @@ static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; +BOOL(WINAPI* PhIsDarkModeAllowedForWindow_I)( + _In_ HWND WindowHandle + ) = NULL; + LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, _In_ UINT WindowMessage, @@ -234,7 +238,7 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( { RECT rectClient; GetClientRect(WindowHandle, &rectClient); - InflateRect(&rectClient, 2, 2); + PhInflateRect(&rectClient, 2, 2); MapWindowRect(WindowHandle, ParentHandle, &rectClient); InvalidateRect(ParentHandle, &rectClient, TRUE); // fix the annoying white border left by the previous active control } @@ -925,40 +929,35 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( { CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam; - // Don't apply header theme for unsupported dialogs: Advanced Security and Digital Signature Details (Dart Vanya) - if (!FindWindowEx(GetAncestor(WindowHandle, GA_ROOT), NULL, L"DirectUIHWND", NULL) && - !FindWindowEx(GetParent(createStruct->hwndParent), NULL, L"NativeFontCtl", NULL)) + if (createStruct->hwndParent) { - if (createStruct->hwndParent) - { - WCHAR windowClassName[MAX_PATH]; + WCHAR windowClassName[MAX_PATH]; - if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; + if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; - if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) - { - LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); + if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) + { + LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); - if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) - { - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - } + return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); } } + } - context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); - context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); - context->CursorPos.x = LONG_MIN; - context->CursorPos.y = LONG_MIN; - PhSetWindowContext(WindowHandle, LONG_MAX, context); + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); + context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); + context->CursorPos.x = LONG_MIN; + context->CursorPos.y = LONG_MIN; + PhSetWindowContext(WindowHandle, LONG_MAX, context); - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - InvalidateRect(WindowHandle, NULL, FALSE); - } + InvalidateRect(WindowHandle, NULL, FALSE); } else { @@ -1043,6 +1042,17 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( break; case WM_PAINT: { + // Don't apply header theme for unsupported dialogs: Advanced Security, Digital Signature Details, etc. (Dart Vanya) + if (!PhIsDarkModeAllowedForWindow_I(GetParent(WindowHandle))) + { + PhRemoveWindowContext(WindowHandle, LONG_MAX); + if (context->ThemeHandle) + PhCloseThemeData(context->ThemeHandle); + PhFree(context); + PhSetControlTheme(WindowHandle, L"Explorer"); + break; + } + //PAINTSTRUCT ps; //HDC BufferedHDC; //HPAINTBUFFER BufferedPaint; @@ -1312,6 +1322,12 @@ static HRESULT(WINAPI* PhDefaultGetThemeColor)( _Out_ COLORREF* pColor ) = NULL; +// uxtheme.dll ordinal 49 +static HTHEME(WINAPI* PhDefaultOpenNcThemeData)( + _In_ HWND hwnd, + _In_ LPCWSTR pszClassList + ) = NULL; + static BOOL (WINAPI* PhDefaultSystemParametersInfo)( _In_ UINT uiAction, _In_ UINT uiParam, @@ -1769,6 +1785,20 @@ HRESULT PhGetThemeColorHook( return retVal; } +HTHEME PhOpenNcThemeDataHook( + _In_ HWND hwnd, + _In_ LPCWSTR pszClassList + ) +{ + if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && + PhIsDarkModeAllowedForWindow_I(hwnd)) + { + return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); + } + + return PhDefaultOpenNcThemeData(hwnd, pszClassList); +} + BOOLEAN CALLBACK PhInitializeTaskDialogTheme( _In_ HWND WindowHandle, _In_opt_ PVOID CallbackData @@ -1987,6 +2017,8 @@ VOID PhRegisterDetoursHooks( PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); + PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) @@ -2014,6 +2046,8 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) + goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) goto CleanupExit; } diff --git a/phlib/theme.c b/phlib/theme.c index 9f7a4f59ec85..9db805bda05f 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -240,8 +240,17 @@ VOID PhInitializeWindowTheme( if (defaultWindowProc != PhpThemeWindowSubclassProc) { + WCHAR windowClassName[MAX_PATH]; PhSetWindowContext(WindowHandle, LONG_MAX, defaultWindowProc); SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowSubclassProc); + + if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if ((PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE) || PhEqualStringZ(windowClassName, WC_LISTVIEW, FALSE)) && + WindowsVersion >= WINDOWS_10_RS5) + { + AllowDarkModeForWindow_I(WindowHandle, TRUE); // HACK for dynamically generated plugin tabs + } } PhEnumChildWindows( @@ -742,7 +751,9 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( // PhSetControlTheme(tooltipWindow, L""); // break; //case 1: // Old colors - PhWindowThemeSetDarkMode(WindowHandle, TRUE); + //PhWindowThemeSetDarkMode(WindowHandle, TRUE); + AllowDarkModeForWindow_I(WindowHandle, TRUE); + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); PhWindowThemeSetDarkMode(tooltipWindow, TRUE); } @@ -821,6 +832,7 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( //case 1: // Old colors PhWindowThemeSetDarkMode(tooltipWindow, TRUE); PhWindowThemeSetDarkMode(WindowHandle, TRUE); + AllowDarkModeForWindow_I(WindowHandle, TRUE); } if (PhEnableThemeListviewBorder) @@ -3270,12 +3282,11 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( { HDC hdc = GetDC(WindowHandle); RECT rectControl = customDraw->rc; - InflateRect(&rectControl, 2, 2); + PhInflateRect(&rectControl, 2, 2); MapWindowRect(customDraw->hdr.hwndFrom, WindowHandle, &rectControl); FillRect(hdc, &rectControl, PhThemeWindowBackgroundBrush); // fix the annoying white border left by the previous active control ReleaseDC(WindowHandle, hdc); } - return CDRF_DODEFAULT; } } } diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 27d2abdf6ce1..1bc60cd4993c 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -32,6 +32,10 @@ static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; +BOOL(WINAPI* PhIsDarkModeAllowedForWindow_I)( + _In_ HWND WindowHandle + ) = NULL; + LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, _In_ UINT WindowMessage, @@ -925,40 +929,35 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( { CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam; - // Don't apply header theme for unsupported dialogs: Advanced Security and Digital Signature Details (Dart Vanya) - if (!FindWindowEx(GetAncestor(WindowHandle, GA_ROOT), NULL, L"DirectUIHWND", NULL) && - !FindWindowEx(GetParent(createStruct->hwndParent), NULL, L"NativeFontCtl", NULL)) + if (createStruct->hwndParent) { - if (createStruct->hwndParent) - { - WCHAR windowClassName[MAX_PATH]; + WCHAR windowClassName[MAX_PATH]; - if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; + if (!GetClassName(createStruct->hwndParent, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; - if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) - { - LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); + if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) + { + LONG_PTR windowStyle = PhGetWindowStyle(createStruct->hwndParent); - if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) - { - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + if (BooleanFlagOn(windowStyle, TN_STYLE_CUSTOM_HEADERDRAW)) + { + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - } + return CallWindowProc(PhDefaultHeaderWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); } } + } - context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); - context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); - context->CursorPos.x = LONG_MIN; - context->CursorPos.y = LONG_MIN; - PhSetWindowContext(WindowHandle, LONG_MAX, context); + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); + context->ThemeHandle = PhOpenThemeData(WindowHandle, VSCLASS_HEADER, PhGetWindowDpi(WindowHandle)); + context->CursorPos.x = LONG_MIN; + context->CursorPos.y = LONG_MIN; + PhSetWindowContext(WindowHandle, LONG_MAX, context); - PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); + PhSetControlTheme(WindowHandle, L"DarkMode_ItemsView"); - InvalidateRect(WindowHandle, NULL, FALSE); - } + InvalidateRect(WindowHandle, NULL, FALSE); } else { @@ -1043,6 +1042,17 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( break; case WM_PAINT: { + // Don't apply header theme for unsupported dialogs: Advanced Security, Digital Signature Details, etc. (Dart Vanya) + if (!PhIsDarkModeAllowedForWindow_I(GetParent(WindowHandle))) + { + PhRemoveWindowContext(WindowHandle, LONG_MAX); + if (context->ThemeHandle) + PhCloseThemeData(context->ThemeHandle); + PhFree(context); + PhSetControlTheme(WindowHandle, L"Explorer"); + break; + } + //PAINTSTRUCT ps; //HDC BufferedHDC; //HPAINTBUFFER BufferedPaint; @@ -1312,6 +1322,12 @@ static HRESULT(WINAPI* PhDefaultGetThemeColor)( _Out_ COLORREF* pColor ) = NULL; +// uxtheme.dll ordinal 49 +static HTHEME(WINAPI* PhDefaultOpenNcThemeData)( + _In_ HWND hwnd, + _In_ LPCWSTR pszClassList + ) = NULL; + static BOOL (WINAPI* PhDefaultSystemParametersInfo)( _In_ UINT uiAction, _In_ UINT uiParam, @@ -1754,6 +1770,20 @@ HRESULT PhGetThemeColorHook( return retVal; } +HTHEME PhOpenNcThemeDataHook( + _In_ HWND hwnd, + _In_ LPCWSTR pszClassList +) +{ + if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && + PhIsDarkModeAllowedForWindow_I(hwnd)) + { + return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); + } + + return PhDefaultOpenNcThemeData(hwnd, pszClassList); +} + BOOLEAN CALLBACK PhInitializeTaskDialogTheme( _In_ HWND WindowHandle, _In_opt_ PVOID CallbackData @@ -1972,6 +2002,8 @@ VOID PhRegisterDetoursHooks( PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); + PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) @@ -1999,6 +2031,8 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) goto CleanupExit; + if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) + goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) goto CleanupExit; } From f906b11d8c1eba7165cbc5778f77c88a139c13b1 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Wed, 30 Oct 2024 22:21:57 +0300 Subject: [PATCH 08/11] New SysLink coloring method via IAT hook - Remove PhInitializeSysLinkTheme --- SystemInformer/about.c | 2 - SystemInformer/delayhook.c | 103 ++++++++++++++++++++++++++++++---- SystemInformer/prpggen.c | 1 - phlib/include/guisup.h | 7 --- phlib/theme.c | 41 ++------------ tools/peview/delayhook.c | 111 +++++++++++++++++++++++++++++++------ tools/peview/peprp.c | 3 - 7 files changed, 192 insertions(+), 76 deletions(-) diff --git a/SystemInformer/about.c b/SystemInformer/about.c index e93a2ff0b72d..3cee50b1a738 100644 --- a/SystemInformer/about.c +++ b/SystemInformer/about.c @@ -72,8 +72,6 @@ static INT_PTR CALLBACK PhpAboutDlgProc( PhRegisterWindowCallback(hwndDlg, PH_PLUGIN_WINDOW_EVENT_TYPE_TOPMOST, NULL); PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); - if (PhEnableThemeSupport) - PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_LINK_SF)); } break; case WM_DESTROY: diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 326001a92f67..13694328bf9e 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -32,10 +32,34 @@ static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; +BOOL(WINAPI* PhAllowDarkModeForWindow_I)( + _In_ HWND WindowHandle + ) = NULL; + BOOL(WINAPI* PhIsDarkModeAllowedForWindow_I)( _In_ HWND WindowHandle ) = NULL; +BOOLEAN PhAllowDarkModeForWindow( + _In_ HWND WindowHandle + ) +{ + if (!PhAllowDarkModeForWindow_I) + return FALSE; + + return !!PhAllowDarkModeForWindow_I(WindowHandle); +} + +BOOLEAN PhIsDarkModeAllowedForWindow( + _In_ HWND WindowHandle +) +{ + if (!PhIsDarkModeAllowedForWindow_I) + return FALSE; + + return !!PhIsDarkModeAllowedForWindow_I(WindowHandle); +} + LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, _In_ UINT WindowMessage, @@ -1043,7 +1067,7 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( case WM_PAINT: { // Don't apply header theme for unsupported dialogs: Advanced Security, Digital Signature Details, etc. (Dart Vanya) - if (!PhIsDarkModeAllowedForWindow_I(GetParent(WindowHandle))) + if (!PhIsDarkModeAllowedForWindow(GetParent(WindowHandle))) { PhRemoveWindowContext(WindowHandle, LONG_MAX); if (context->ThemeHandle) @@ -1307,6 +1331,14 @@ static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( _In_ const DTTOPTS* pOptions ) = NULL; +int (WINAPI* PhDefaultComCtl32DrawTextW)( + _In_ HDC hdc, + _Inout_ LPCWSTR lpchText, + _In_ int cchText, + _Inout_ LPRECT lprc, + _In_ UINT format + ) = NULL; + static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( _In_ const TASKDIALOGCONFIG* pTaskConfig, _Out_opt_ int* pnButton, @@ -1369,6 +1401,8 @@ typedef struct _TASKDIALOG_WINDOW_CONTEXT PTASKDIALOG_CALLBACK_WRAP CallbackData; } TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; +#define TASKDIALOG_CONTEXT_TAG (ULONG)'TDLG' + #define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL HRESULT CALLBACK ThemeTaskDialogCallbackHook( @@ -1753,6 +1787,49 @@ HRESULT WINAPI PhDrawThemeTextExHook( return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); } +int PhDetoursComCtl32DrawTextW( + _In_ HDC hdc, + _Inout_ LPCWSTR lpchText, + _In_ int cchText, + _Inout_ LPRECT lprc, + _In_ UINT format + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static COLORREF colLinkNormal = RGB(0, 0 ,0); + static COLORREF colLinkHot = RGB(0, 0, 0); + static COLORREF colLinkPressed = RGB(0, 0, 0); + HWND WindowHandle; + + if (PhBeginInitOnce(&initOnce)) + { + HTHEME hTextTheme = PhOpenThemeData(NULL, VSCLASS_TEXTSTYLE, 0); + if (hTextTheme) + { + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); + PhCloseThemeData(hTextTheme); + } + PhEndInitOnce(&initOnce); + } + + if ((WindowHandle = WindowFromDC(hdc)) && + (PhIsDarkModeAllowedForWindow(WindowHandle) || PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG))) // HACK + { + WCHAR windowClassName[MAX_PATH]; + GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); + if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + { + COLORREF color = GetTextColor(hdc); + if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed) + SetTextColor(hdc, PhMakeColorBrighter(color, 95)); + } + } + + return PhDefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); +} + HRESULT PhGetThemeColorHook( _In_ HTHEME hTheme, _In_ int iPartId, @@ -1791,7 +1868,7 @@ HTHEME PhOpenNcThemeDataHook( ) { if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && - PhIsDarkModeAllowedForWindow_I(hwnd)) + PhIsDarkModeAllowedForWindow(hwnd)) { return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); } @@ -1806,7 +1883,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( { WCHAR windowClassName[MAX_PATH]; PTASKDIALOG_COMMON_CONTEXT context; - BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, (ULONG)'TDLG'); + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG); if (CallbackData && !windowHasContext) { @@ -1821,7 +1898,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; - PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); + PhSetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG, context); windowHasContext = TRUE; } @@ -1839,13 +1916,17 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( context = PhAllocateZero(sizeof(TASKDIALOG_COMMON_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); - PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); + PhSetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG, context); if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) { PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); } + //else if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + //{ + // PhAllowDarkModeForWindow(WindowHandle); // this doesn't work, idk why + //} else if (PhEqualStringZ(windowClassName, L"DirectUIHWND", FALSE)) { //WINDOWPLACEMENT pos = { 0 }; @@ -1868,7 +1949,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( PTASKDIALOG_COMMON_CONTEXT context; WNDPROC OldWndProc; - if (!(context = PhGetWindowContext(hwnd, (ULONG)'TDLG'))) + if (!(context = PhGetWindowContext(hwnd, TASKDIALOG_CONTEXT_TAG))) return 0; OldWndProc = context->DefaultWindowProc; @@ -1893,10 +1974,6 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( SetDCBrushColor(hdc, PhThemeWindowBackground2Color); FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); } - else - { - PhInitializeSysLinkTheme(hwnd); // this doesn't work in EnumWindows callback, I don't know why - } } } return TRUE; @@ -1936,7 +2013,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( case WM_DESTROY: { PhSetWindowProcedure(hwnd, OldWndProc); - PhRemoveWindowContext(hwnd, (ULONG)'TDLG'); + PhRemoveWindowContext(hwnd, TASKDIALOG_CONTEXT_TAG); PhFree(context); } return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); @@ -2012,18 +2089,20 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { + PhAllowDarkModeForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 133); + PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); - PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&PhDefaultComCtl32DrawTextW); } if (!NT_SUCCESS(status = DetourTransactionBegin())) diff --git a/SystemInformer/prpggen.c b/SystemInformer/prpggen.c index 15a32ff07918..bae28044616c 100644 --- a/SystemInformer/prpggen.c +++ b/SystemInformer/prpggen.c @@ -545,7 +545,6 @@ INT_PTR CALLBACK PhpProcessGeneralDlgProc( if (PhEnableThemeSupport) { PhInitializeWindowTheme(hwndDlg, PhEnableThemeSupport); - PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_COMPANYNAME_LINK)); } PhSetTimer(hwndDlg, PH_WINDOW_TIMER_DEFAULT, 1000, NULL); diff --git a/phlib/include/guisup.h b/phlib/include/guisup.h index b1460a6ec2ca..644c6a3b85ed 100644 --- a/phlib/include/guisup.h +++ b/phlib/include/guisup.h @@ -2099,13 +2099,6 @@ PhInitializeWindowThemeEx( _In_ HWND WindowHandle ); -PHLIBAPI -VOID -NTAPI -PhInitializeSysLinkTheme( - _In_ HWND WindowHandle - ); - PHLIBAPI VOID NTAPI diff --git a/phlib/theme.c b/phlib/theme.c index 6498d00eb101..5759665292ef 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -291,22 +291,6 @@ VOID PhInitializeWindowThemeEx( PhInitializeWindowTheme(WindowHandle, enableThemeSupport); } -VOID PhInitializeSysLinkTheme( - _In_ HWND WindowHandle - ) -{ - WCHAR windowClassName[MAX_PATH]; - if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; - - 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)) - linkChanges.iLink++; - } -} - VOID PhReInitializeWindowTheme( _In_ HWND WindowHandle ) @@ -915,6 +899,11 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( PhWindowThemeSetDarkMode(WindowHandle, TRUE); } } + else if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + { + // SysLink theme support (Dart Vanya) + AllowDarkModeForWindow_I(WindowHandle, TRUE); + } return TRUE; } @@ -2313,6 +2302,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( break; case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: case WM_CTLCOLORLISTBOX: { HDC hdc = (HDC)wParam; @@ -2322,26 +2312,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( return (INT_PTR)PhThemeWindowBackgroundBrush; } break; - case WM_CTLCOLORSTATIC: - { - HDC hdc = (HDC)wParam; - HWND hControl = (HWND)lParam; - BOOLEAN useColorLink = FALSE; - WCHAR windowClassName[MAX_PATH]; - - if (!GetClassName(hControl, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; - if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) { - LITEM litem = { LIF_ITEMINDEX | LIF_STATE, 0, 0, LIS_DEFAULTCOLORS }; - if (SendMessage(hControl, LM_GETITEM, 0, (LPARAM)&litem)) - useColorLink = litem.state & LIS_DEFAULTCOLORS; - } - SetBkColor(hdc, PhThemeWindowBackgroundColor); - SetTextColor(hdc, !useColorLink ? PhThemeWindowTextColor : 0xE9BD5B); // To apply color for SysLink call PhInitializeSysLinkTheme() first - return (INT_PTR)PhThemeWindowBackgroundBrush; - } - break; case WM_MEASUREITEM: if (PhThemeWindowMeasureItem(hWnd, (LPMEASUREITEMSTRUCT)lParam)) return TRUE; diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 1bc60cd4993c..7c727c6414da 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -32,10 +32,34 @@ static BOOLEAN PhDefaultEnableStreamerMode = FALSE; static BOOLEAN PhDefaultEnableThemeAcrylicWindowSupport = FALSE; static BOOLEAN PhDefaultEnableThemeAnimation = FALSE; +BOOL(WINAPI* PhAllowDarkModeForWindow_I)( + _In_ HWND WindowHandle + ) = NULL; + BOOL(WINAPI* PhIsDarkModeAllowedForWindow_I)( _In_ HWND WindowHandle ) = NULL; +BOOLEAN PhAllowDarkModeForWindow( + _In_ HWND WindowHandle + ) +{ + if (!PhAllowDarkModeForWindow_I) + return FALSE; + + return !!PhAllowDarkModeForWindow_I(WindowHandle); +} + +BOOLEAN PhIsDarkModeAllowedForWindow( + _In_ HWND WindowHandle +) +{ + if (!PhIsDarkModeAllowedForWindow_I) + return FALSE; + + return !!PhIsDarkModeAllowedForWindow_I(WindowHandle); +} + LRESULT CALLBACK PhMenuWindowHookProcedure( _In_ HWND WindowHandle, _In_ UINT WindowMessage, @@ -238,7 +262,7 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( { RECT rectClient; GetClientRect(WindowHandle, &rectClient); - InflateRect(&rectClient, 2, 2); + PhInflateRect(&rectClient, 2, 2); MapWindowRect(WindowHandle, ParentHandle, &rectClient); InvalidateRect(ParentHandle, &rectClient, TRUE); // fix the annoying white border left by the previous active control } @@ -1043,7 +1067,7 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( case WM_PAINT: { // Don't apply header theme for unsupported dialogs: Advanced Security, Digital Signature Details, etc. (Dart Vanya) - if (!PhIsDarkModeAllowedForWindow_I(GetParent(WindowHandle))) + if (!PhIsDarkModeAllowedForWindow(GetParent(WindowHandle))) { PhRemoveWindowContext(WindowHandle, LONG_MAX); if (context->ThemeHandle) @@ -1051,7 +1075,7 @@ LRESULT CALLBACK PhHeaderWindowHookProcedure( PhFree(context); PhSetControlTheme(WindowHandle, L"Explorer"); break; - } + } //PAINTSTRUCT ps; //HDC BufferedHDC; @@ -1307,6 +1331,14 @@ static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( _In_ const DTTOPTS* pOptions ) = NULL; +int (WINAPI* PhDefaultComCtl32DrawTextW)( + _In_ HDC hdc, + _Inout_ LPCWSTR lpchText, + _In_ int cchText, + _Inout_ LPRECT lprc, + _In_ UINT format + ) = NULL; + static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( _In_ const TASKDIALOGCONFIG* pTaskConfig, _Out_opt_ int* pnButton, @@ -1369,6 +1401,8 @@ typedef struct _TASKDIALOG_WINDOW_CONTEXT PTASKDIALOG_CALLBACK_WRAP CallbackData; } TASKDIALOG_WINDOW_CONTEXT, * PTASKDIALOG_WINDOW_CONTEXT; +#define TASKDIALOG_CONTEXT_TAG (ULONG)'TDLG' + #define GETCLASSNAME_OR_NULL(WindowHandle, ClassName) if (!GetClassName(WindowHandle, ClassName, RTL_NUMBER_OF(ClassName))) ClassName[0] = UNICODE_NULL HRESULT CALLBACK ThemeTaskDialogCallbackHook( @@ -1693,7 +1727,7 @@ HRESULT WINAPI PhDrawThemeTextHook( _In_ LPCRECT pRect ) { - if (iPartId == BP_COMMANDLINK && iStateId != PBS_DISABLED) + if ((iPartId == BP_COMMANDLINK /*|| iPartId == BP_RADIOBUTTON*/) && iStateId != PBS_DISABLED) { WCHAR className[MAX_PATH]; if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && @@ -1738,6 +1772,49 @@ HRESULT WINAPI PhDrawThemeTextExHook( return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); } +int PhDetoursComCtl32DrawTextW( + _In_ HDC hdc, + _Inout_ LPCWSTR lpchText, + _In_ int cchText, + _Inout_ LPRECT lprc, + _In_ UINT format + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static COLORREF colLinkNormal = RGB(0, 0 ,0); + static COLORREF colLinkHot = RGB(0, 0, 0); + static COLORREF colLinkPressed = RGB(0, 0, 0); + HWND WindowHandle; + + if (PhBeginInitOnce(&initOnce)) + { + HTHEME hTextTheme = PhOpenThemeData(NULL, VSCLASS_TEXTSTYLE, 0); + if (hTextTheme) + { + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); + PhCloseThemeData(hTextTheme); + } + PhEndInitOnce(&initOnce); + } + + if ((WindowHandle = WindowFromDC(hdc)) && + (PhIsDarkModeAllowedForWindow(WindowHandle) || PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG))) // HACK + { + WCHAR windowClassName[MAX_PATH]; + GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); + if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + { + COLORREF color = GetTextColor(hdc); + if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed) + SetTextColor(hdc, PhMakeColorBrighter(color, 95)); + } + } + + return PhDefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); +} + HRESULT PhGetThemeColorHook( _In_ HTHEME hTheme, _In_ int iPartId, @@ -1773,10 +1850,10 @@ HRESULT PhGetThemeColorHook( HTHEME PhOpenNcThemeDataHook( _In_ HWND hwnd, _In_ LPCWSTR pszClassList -) + ) { if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && - PhIsDarkModeAllowedForWindow_I(hwnd)) + PhIsDarkModeAllowedForWindow(hwnd)) { return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); } @@ -1791,7 +1868,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( { WCHAR windowClassName[MAX_PATH]; PTASKDIALOG_COMMON_CONTEXT context; - BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, (ULONG)'TDLG'); + BOOLEAN windowHasContext = !!PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG); if (CallbackData && !windowHasContext) { @@ -1806,7 +1883,7 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( PTASKDIALOG_WINDOW_CONTEXT context = PhAllocateZero(sizeof(TASKDIALOG_WINDOW_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); context->CallbackData = CallbackData; - PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); + PhSetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG, context); windowHasContext = TRUE; } @@ -1824,13 +1901,17 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( context = PhAllocateZero(sizeof(TASKDIALOG_COMMON_CONTEXT)); context->DefaultWindowProc = PhSetWindowProcedure(WindowHandle, ThemeTaskDialogMasterSubclass); - PhSetWindowContext(WindowHandle, (ULONG)'TDLG', context); + PhSetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG, context); if (PhEqualStringZ(windowClassName, WC_BUTTON, FALSE) || PhEqualStringZ(windowClassName, WC_SCROLLBAR, FALSE)) { PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); } + //else if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) + //{ + // PhAllowDarkModeForWindow(WindowHandle); // this doesn't work, idk why + //} else if (PhEqualStringZ(windowClassName, L"DirectUIHWND", FALSE)) { //WINDOWPLACEMENT pos = { 0 }; @@ -1853,7 +1934,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( PTASKDIALOG_COMMON_CONTEXT context; WNDPROC OldWndProc; - if (!(context = PhGetWindowContext(hwnd, (ULONG)'TDLG'))) + if (!(context = PhGetWindowContext(hwnd, TASKDIALOG_CONTEXT_TAG))) return 0; OldWndProc = context->DefaultWindowProc; @@ -1878,10 +1959,6 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( SetDCBrushColor(hdc, PhThemeWindowBackground2Color); FillRect(hdc, &rect, PhGetStockBrush(DC_BRUSH)); } - else - { - PhInitializeSysLinkTheme(hwnd); // this doesn't work in EnumWindows callback, I don't know why - } } } return TRUE; @@ -1921,7 +1998,7 @@ LRESULT CALLBACK ThemeTaskDialogMasterSubclass( case WM_DESTROY: { PhSetWindowProcedure(hwnd, OldWndProc); - PhRemoveWindowContext(hwnd, (ULONG)'TDLG'); + PhRemoveWindowContext(hwnd, TASKDIALOG_CONTEXT_TAG); PhFree(context); } return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam); @@ -1997,18 +2074,20 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { + PhAllowDarkModeForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 133); + PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); - PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&PhDefaultComCtl32DrawTextW); } if (!NT_SUCCESS(status = DetourTransactionBegin())) diff --git a/tools/peview/peprp.c b/tools/peview/peprp.c index 4f4740b13f33..ff2ace39a7da 100644 --- a/tools/peview/peprp.c +++ b/tools/peview/peprp.c @@ -2184,9 +2184,6 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( { PhSetDialogItemText(hwndDlg, IDC_COMPANYNAME, PvpGetStringOrNa(PvImageVersionInfo.CompanyName)); } - - if (PhEnableThemeSupport) - PhInitializeSysLinkTheme(GetDlgItem(hwndDlg, IDC_COMPANYNAME_LINK)); } break; case PVM_ENTROPY_DONE: From 79344550eed891af2e2abfb6a33184a336b787d0 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Fri, 1 Nov 2024 18:05:56 +0300 Subject: [PATCH 09/11] Small fixes --- SystemInformer/delayhook.c | 98 +++++++++++++++++++++++--------------- phlib/theme.c | 18 ++++--- tools/peview/delayhook.c | 98 +++++++++++++++++++++++--------------- 3 files changed, 131 insertions(+), 83 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 13694328bf9e..7f32938c704b 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -224,34 +224,26 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( _In_ LPARAM lParam ) { - switch (WindowMessage) + if (WindowMessage == WM_NCCREATE) { - case WM_NCCREATE: - { - LONG_PTR style = PhGetWindowStyle(WindowHandle); + LONG_PTR style = PhGetWindowStyle(WindowHandle); - if ((style & SS_ICON) == SS_ICON) - { - PhSetWindowContext(WindowHandle, SCHAR_MAX, (PVOID)TRUE); - } - } - break; - case WM_NCDESTROY: + if ((style & SS_ICON) == SS_ICON) { - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; - - PhRemoveWindowContext(WindowHandle, SCHAR_MAX); + PhSetWindowContext(WindowHandle, SCHAR_MAX, (PVOID)TRUE); } - break; - case WM_ERASEBKGND: - { - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; + } - return TRUE; - } + if (WindowMessage != WM_KILLFOCUS && !PhGetWindowContext(WindowHandle, SCHAR_MAX)) + return CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + + switch (WindowMessage) + { + case WM_NCDESTROY: + PhRemoveWindowContext(WindowHandle, SCHAR_MAX); break; + case WM_ERASEBKGND: + return TRUE; case WM_KILLFOCUS: { WCHAR windowClassName[MAX_PATH]; @@ -270,14 +262,11 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( break; case WM_PAINT: { - HDC hdc; HICON iconHandle; + PAINTSTRUCT ps; RECT clientRect; WCHAR windowClassName[MAX_PATH]; - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; - if (!GetClassName(GetParent(WindowHandle), windowClassName, RTL_NUMBER_OF(windowClassName))) windowClassName[0] = UNICODE_NULL; if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) @@ -287,13 +276,41 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( static PH_INITONCE initOnce = PH_INITONCE_INIT; static HFONT hCheckFont = NULL; - LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - hdc = GetDC(WindowHandle); + HDC hdc = BeginPaint(WindowHandle, &ps); GetClientRect(WindowHandle, &clientRect); - INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; - INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; - COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); - if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked + + HDC bufferDc = CreateCompatibleDC(hdc); + HBITMAP bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + HBITMAP oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + + enum { nocheck, check, graycheck } checkType = nocheck; + INT startX = clientRect.left + (clientRect.right - clientRect.bottom) / 2 + 1; + INT startY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + + DrawIconEx(bufferDc, clientRect.left, clientRect.top, iconHandle, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, + 0, NULL, DI_NORMAL); + + for (INT x = startX, y = startY; x < clientRect.right; x++) + { + COLORREF pixel = GetPixel(bufferDc, x, y); + if (pixel == RGB(0xB4, 0xB4, 0xB4)) + { + checkType = graycheck; + goto draw_acl_check; + } + } + for (INT x = startX, y = startY; x < clientRect.right; x++) + { + COLORREF pixel = GetPixel(bufferDc, x, y); + if (pixel == RGB(0, 0, 0) || pixel == PhThemeWindowTextColor) + { + checkType = check; + goto draw_acl_check; + } + } + + draw_acl_check: + if (checkType == check || checkType == graycheck) // right is checked or special permission checked { if (PhBeginInitOnce(&initOnce)) // cache font { @@ -306,16 +323,21 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( VARIABLE_PITCH, L"Segoe UI"); PhEndInitOnce(&initOnce); } + SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SetTextColor(hdc, checkType == check ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); SelectFont(hdc, hCheckFont); //HFONT hFontOriginal = SelectFont(hdc, hCheckFont); FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); //SelectFont(hdc, hFontOriginal); } - ReleaseDC(WindowHandle, hdc); - return retval; + + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + EndPaint(WindowHandle, &ps); + return 0; } } //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) @@ -1411,19 +1433,19 @@ HRESULT CALLBACK ThemeTaskDialogCallbackHook( _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ LONG_PTR dwRefData -); + ); LRESULT CALLBACK ThemeTaskDialogMasterSubclass( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam -); + ); BOOLEAN CALLBACK PhInitializeTaskDialogTheme( _In_ HWND hwndDlg, _In_opt_ PVOID Context -); + ); HRESULT PhDrawThemeBackgroundHook( _In_ HTHEME Theme, diff --git a/phlib/theme.c b/phlib/theme.c index 5759665292ef..aeb869af0565 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -1739,7 +1739,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_HIDEPREFIX - ); + ); } else { @@ -1749,7 +1749,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX - ); + ); bufferRect.top = (DrawInfo->rc.bottom - DrawInfo->rc.top) / 2 - (bufferRect.bottom - bufferRect.top) / 2 - 1; bufferRect.bottom = DrawInfo->rc.bottom, bufferRect.right = DrawInfo->rc.right; @@ -1760,7 +1760,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, DT_LEFT | DT_TOP | DT_HIDEPREFIX - ); + ); } if (isFocused && (DrawInfo->uItemState & CDIS_SHOWKEYBOARDCUES) == CDIS_SHOWKEYBOARDCUES) @@ -1771,7 +1771,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX - ); + ); PhInflateRect(&bufferRect, 1, 0); bufferRect.top += 1, bufferRect.bottom += 2; if (bufferRect.bottom > DrawInfo->rc.bottom - 1) bufferRect.bottom = DrawInfo->rc.bottom - 1; @@ -2631,7 +2631,7 @@ VOID ThemeWindowRenderTabControl( (UINT)PhCountStringZ(tabItem.pszText), &itemRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX - ); + ); } //if (itemHighlighted != INT_ERROR) @@ -2647,7 +2647,7 @@ VOID ThemeWindowRenderTabControl( // (UINT)PhCountStringZ(tabItem.pszText), // &itemRectHighlighted, // DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX - // ); + // ); // } //} } @@ -3236,6 +3236,10 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( switch (uMsg) { + case WM_VSCROLL: + case WM_MOUSEWHEEL: + InvalidateRect(WindowHandle, NULL, FALSE); + break; case WM_NOTIFY: { LPNMHDR data = (LPNMHDR)lParam; @@ -3245,7 +3249,7 @@ LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( LPNMCUSTOMDRAW customDraw = (LPNMCUSTOMDRAW)lParam; WCHAR className[MAX_PATH]; - if (customDraw->dwDrawStage == CDDS_PREPAINT) + if (customDraw->dwDrawStage == CDDS_PREPAINT && !(customDraw->uItemState & CDIS_FOCUS)) { if (!GetClassName(customDraw->hdr.hwndFrom, className, RTL_NUMBER_OF(className))) className[0] = UNICODE_NULL; diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 7c727c6414da..803bd7b6c7c8 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -224,34 +224,26 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( _In_ LPARAM lParam ) { - switch (WindowMessage) + if (WindowMessage == WM_NCCREATE) { - case WM_NCCREATE: - { - LONG_PTR style = PhGetWindowStyle(WindowHandle); + LONG_PTR style = PhGetWindowStyle(WindowHandle); - if ((style & SS_ICON) == SS_ICON) - { - PhSetWindowContext(WindowHandle, SCHAR_MAX, (PVOID)TRUE); - } - } - break; - case WM_NCDESTROY: + if ((style & SS_ICON) == SS_ICON) { - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; - - PhRemoveWindowContext(WindowHandle, SCHAR_MAX); + PhSetWindowContext(WindowHandle, SCHAR_MAX, (PVOID)TRUE); } - break; - case WM_ERASEBKGND: - { - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; + } - return TRUE; - } + if (WindowMessage != WM_KILLFOCUS && !PhGetWindowContext(WindowHandle, SCHAR_MAX)) + return CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); + + switch (WindowMessage) + { + case WM_NCDESTROY: + PhRemoveWindowContext(WindowHandle, SCHAR_MAX); break; + case WM_ERASEBKGND: + return TRUE; case WM_KILLFOCUS: { WCHAR windowClassName[MAX_PATH]; @@ -270,14 +262,11 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( break; case WM_PAINT: { - HDC hdc; HICON iconHandle; + PAINTSTRUCT ps; RECT clientRect; WCHAR windowClassName[MAX_PATH]; - if (!PhGetWindowContext(WindowHandle, SCHAR_MAX)) - break; - if (!GetClassName(GetParent(WindowHandle), windowClassName, RTL_NUMBER_OF(windowClassName))) windowClassName[0] = UNICODE_NULL; if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) @@ -287,13 +276,41 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( static PH_INITONCE initOnce = PH_INITONCE_INIT; static HFONT hCheckFont = NULL; - LRESULT retval = CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, WindowMessage, wParam, lParam); - hdc = GetDC(WindowHandle); + HDC hdc = BeginPaint(WindowHandle, &ps); GetClientRect(WindowHandle, &clientRect); - INT buttonCenterX = clientRect.left + (clientRect.right - clientRect.left) / 2 + 1; - INT buttonCenterY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; - COLORREF checkCenter = GetPixel(hdc, buttonCenterX, buttonCenterY); - if (checkCenter == RGB(0, 0, 0) || checkCenter == RGB(0xB4, 0xB4, 0xB4)) // right is checked or special permission checked + + HDC bufferDc = CreateCompatibleDC(hdc); + HBITMAP bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + HBITMAP oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + + enum { nocheck, check, graycheck } checkType = nocheck; + INT startX = clientRect.left + (clientRect.right - clientRect.bottom) / 2 + 1; + INT startY = clientRect.top + (clientRect.bottom - clientRect.top) / 2; + + DrawIconEx(bufferDc, clientRect.left, clientRect.top, iconHandle, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, + 0, NULL, DI_NORMAL); + + for (INT x = startX, y = startY; x < clientRect.right; x++) + { + COLORREF pixel = GetPixel(bufferDc, x, y); + if (pixel == RGB(0xB4, 0xB4, 0xB4)) + { + checkType = graycheck; + goto draw_acl_check; + } + } + for (INT x = startX, y = startY; x < clientRect.right; x++) + { + COLORREF pixel = GetPixel(bufferDc, x, y); + if (pixel == RGB(0, 0, 0) || pixel == PhThemeWindowTextColor) + { + checkType = check; + goto draw_acl_check; + } + } + + draw_acl_check: + if (checkType == check || checkType == graycheck) // right is checked or special permission checked { if (PhBeginInitOnce(&initOnce)) // cache font { @@ -306,16 +323,21 @@ LRESULT CALLBACK PhStaticWindowHookProcedure( VARIABLE_PITCH, L"Segoe UI"); PhEndInitOnce(&initOnce); } + SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, checkCenter == RGB(0, 0, 0) ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); + SetTextColor(hdc, checkType == check ? PhThemeWindowTextColor : RGB(0xB4, 0xB4, 0xB4)); SelectFont(hdc, hCheckFont); //HFONT hFontOriginal = SelectFont(hdc, hCheckFont); FillRect(hdc, &clientRect, PhThemeWindowBackgroundBrush); DrawText(hdc, L"✓", 1, &clientRect, DT_CENTER | DT_VCENTER); //SelectFont(hdc, hFontOriginal); } - ReleaseDC(WindowHandle, hdc); - return retval; + + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + EndPaint(WindowHandle, &ps); + return 0; } } //else if (iconHandle = (HICON)(UINT_PTR)CallWindowProc(PhDefaultStaticWindowProcedure, WindowHandle, STM_GETICON, 0, 0)) // Static_GetIcon(WindowHandle, 0) @@ -1411,19 +1433,19 @@ HRESULT CALLBACK ThemeTaskDialogCallbackHook( _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ LONG_PTR dwRefData -); + ); LRESULT CALLBACK ThemeTaskDialogMasterSubclass( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam -); + ); BOOLEAN CALLBACK PhInitializeTaskDialogTheme( _In_ HWND hwndDlg, _In_opt_ PVOID Context -); + ); HRESULT PhDrawThemeBackgroundHook( _In_ HTHEME Theme, From ce9ebf9ff43ce28805f88d8f5ae775b5adb9bec0 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Tue, 5 Nov 2024 22:11:14 +0300 Subject: [PATCH 10/11] Requested changes --- SystemInformer/chdlg.c | 2 +- SystemInformer/delayhook.c | 95 +++++++++++----------- SystemInformer/main.c | 6 +- phlib/extlv.c | 8 +- phlib/mapldr.c | 2 +- phlib/theme.c | 66 +++++++-------- plugins/ExtendedServices/recovery.c | 2 +- plugins/ToolStatus/main.c | 4 +- tools/peview/delayhook.c | 119 ++++++++++++++-------------- 9 files changed, 146 insertions(+), 158 deletions(-) diff --git a/SystemInformer/chdlg.c b/SystemInformer/chdlg.c index ad9ebb947a15..7fcd37eea749 100644 --- a/SystemInformer/chdlg.c +++ b/SystemInformer/chdlg.c @@ -456,7 +456,7 @@ INT_PTR CALLBACK PhChooseNewPageDlgProc( PhSetDialogFocus(WindowHandle, context->ComboBoxHandle); if (PhEnableThemeSupport) - DestroyWindow(GetDlgItem(WindowHandle, IDC_SIZE_)); + ShowWindow(GetDlgItem(WindowHandle, IDC_SIZE_), SW_HIDE); PhInitializeWindowTheme(WindowHandle, PhEnableThemeSupport); } break; diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index 7f32938c704b..e70874df86eb 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -771,7 +771,8 @@ LRESULT CALLBACK PhEditWindowHookProcedure( if (GetFocus() == WindowHandle) { - SetDCBrushColor(hdc, GetSysColor(COLOR_HOTLIGHT)); // PhThemeWindowHighlightColor + // A little bit nicer and contrast color (Dart Vanya) + SetDCBrushColor(hdc, PhMakeColorBrighter(GetSysColor(COLOR_HOTLIGHT), 85)); // PhThemeWindowHighlightColor FrameRect(hdc, &windowRect, PhGetStockBrush(DC_BRUSH)); } else @@ -1311,7 +1312,7 @@ VOID PhRegisterHeaderSuperClass( // Detours export procedure hooks -static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( +static HRESULT (WINAPI* DefaultDrawThemeBackground)( _In_ HTHEME Theme, _In_ HDC Hdc, _In_ INT PartId, @@ -1320,7 +1321,7 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( _In_ LPCRECT ClipRect ) = NULL; -static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( +static HRESULT (WINAPI* DefaultDrawThemeBackgroundEx)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1329,7 +1330,7 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( _In_ const DTBGOPTS* pOptions ) = NULL; -static HRESULT(WINAPI* PhDefaultDrawThemeText)( +static HRESULT(WINAPI* DefaultDrawThemeText)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1341,7 +1342,7 @@ static HRESULT(WINAPI* PhDefaultDrawThemeText)( _In_ LPCRECT pRect ) = NULL; -static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( +static HRESULT(WINAPI* DefaultDrawThemeTextEx)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1353,7 +1354,7 @@ static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( _In_ const DTTOPTS* pOptions ) = NULL; -int (WINAPI* PhDefaultComCtl32DrawTextW)( +int (WINAPI* DefaultComCtl32DrawTextW)( _In_ HDC hdc, _Inout_ LPCWSTR lpchText, _In_ int cchText, @@ -1361,14 +1362,14 @@ int (WINAPI* PhDefaultComCtl32DrawTextW)( _In_ UINT format ) = NULL; -static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( +static HRESULT(WINAPI* DefaultTaskDialogIndirect)( _In_ const TASKDIALOGCONFIG* pTaskConfig, _Out_opt_ int* pnButton, _Out_opt_ int* pnRadioButton, _Out_opt_ BOOL* pfVerificationFlagChecked ) = NULL; -static HRESULT(WINAPI* PhDefaultGetThemeColor)( +static HRESULT(WINAPI* DefaultGetThemeColor)( _In_ HTHEME hTheme, _In_ int iPartId, _In_ int iStateId, @@ -1377,19 +1378,19 @@ static HRESULT(WINAPI* PhDefaultGetThemeColor)( ) = NULL; // uxtheme.dll ordinal 49 -static HTHEME(WINAPI* PhDefaultOpenNcThemeData)( +static HTHEME(WINAPI* DefaultOpenNcThemeData)( _In_ HWND hwnd, _In_ LPCWSTR pszClassList ) = NULL; -static BOOL (WINAPI* PhDefaultSystemParametersInfo)( +static BOOL (WINAPI* DefaultSystemParametersInfo)( _In_ UINT uiAction, _In_ UINT uiParam, _Pre_maybenull_ _Post_valid_ PVOID pvParam, _In_ UINT fWinIni ) = NULL; -static HWND (WINAPI* PhDefaultCreateWindowEx)( +static HWND (WINAPI* DefaultCreateWindowEx)( _In_ ULONG ExStyle, _In_opt_ PCWSTR ClassName, _In_opt_ PCWSTR WindowName, @@ -1488,7 +1489,7 @@ HRESULT PhDrawThemeBackgroundHook( } } - return PhDefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); + return DefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); } HRESULT WINAPI PhDrawThemeBackgroundExHook( @@ -1509,7 +1510,7 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( 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); + HRESULT retVal = DefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); if (darkButtonTheme) PhCloseThemeData(darkButtonTheme); return retVal; @@ -1559,7 +1560,7 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( static enum { yes, no, unknown } mustInvertButton = unknown; if (mustInvertButton == unknown) { - PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + DefaultDrawThemeBackgroundEx(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); @@ -1567,14 +1568,14 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( } FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); if (mustInvertButton == yes) InvertRect(hdc, pRect); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + HRESULT retVal = DefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); if (mustInvertButton == yes) InvertRect(hdc, pRect); return retVal; } } } - return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + return DefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); } HWND PhCreateWindowExHook( @@ -1592,7 +1593,7 @@ HWND PhCreateWindowExHook( _In_opt_ PVOID Param ) { - HWND windowHandle = PhDefaultCreateWindowEx( + HWND windowHandle = DefaultCreateWindowEx( ExStyle, ClassName, WindowName, @@ -1686,7 +1687,7 @@ BOOL WINAPI PhSystemParametersInfoHook( return TRUE; } - return PhDefaultSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); + return DefaultSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } //ULONG WINAPI GetSysColorHook(int nIndex) @@ -1770,12 +1771,12 @@ HRESULT WINAPI PhDrawThemeTextHook( // PhEqualStringZ((PWSTR)pszText, L"Very low", FALSE)) { DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); } } } - return PhDefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); + return DefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); } HRESULT WINAPI PhDrawThemeTextExHook( @@ -1800,13 +1801,13 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (pOptions) options = *pOptions; options.dwFlags |= DTT_TEXTCOLOR; - PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); + DefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); options.crText = PhMakeColorBrighter(options.crText, 90); - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); } } - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); } int PhDetoursComCtl32DrawTextW( @@ -1849,7 +1850,7 @@ int PhDetoursComCtl32DrawTextW( } } - return PhDefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); + return DefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); } HRESULT PhGetThemeColorHook( @@ -1862,7 +1863,7 @@ HRESULT PhGetThemeColorHook( { WCHAR className[MAX_PATH]; - HRESULT retVal = PhDefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); + HRESULT retVal = DefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) { @@ -1892,10 +1893,10 @@ HTHEME PhOpenNcThemeDataHook( if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && PhIsDarkModeAllowedForWindow(hwnd)) { - return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); + return DefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); } - return PhDefaultOpenNcThemeData(hwnd, pszClassList); + return DefaultOpenNcThemeData(hwnd, pszClassList); } BOOLEAN CALLBACK PhInitializeTaskDialogTheme( @@ -2087,7 +2088,7 @@ HRESULT PhTaskDialogIndirectHook( myConfig.pfCallback = ThemeTaskDialogCallbackHook; myConfig.lpCallbackData = (LONG_PTR)&CallbackData; - return PhDefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); + return DefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); } VOID PhRegisterDetoursHooks( @@ -2105,26 +2106,26 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"user32.dll")) { - PhDefaultCreateWindowEx = PhGetDllBaseProcedureAddress(baseAddress, "CreateWindowExW", 0); - PhDefaultSystemParametersInfo = PhGetDllBaseProcedureAddress(baseAddress, "SystemParametersInfoW", 0); + DefaultCreateWindowEx = PhGetDllBaseProcedureAddress(baseAddress, "CreateWindowExW", 0); + DefaultSystemParametersInfo = PhGetDllBaseProcedureAddress(baseAddress, "SystemParametersInfoW", 0); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { PhAllowDarkModeForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 133); PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); - PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); - PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); - PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); - PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); - PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); - PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); + DefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); + DefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + DefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); + DefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); + DefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + DefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { - PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); - PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&PhDefaultComCtl32DrawTextW); + DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&DefaultComCtl32DrawTextW); } if (!NT_SUCCESS(status = DetourTransactionBegin())) @@ -2132,28 +2133,28 @@ VOID PhRegisterDetoursHooks( if (PhEnableThemeSupport || PhEnableThemeAcrylicSupport) { - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) goto CleanupExit; if (!PhDefaultEnableThemeAnimation) { - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) goto CleanupExit; } - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) goto CleanupExit; } - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) goto CleanupExit; if (!NT_SUCCESS(status = DetourTransactionCommit())) goto CleanupExit; diff --git a/SystemInformer/main.c b/SystemInformer/main.c index 4ddb6f73d519..d29eda3ab85c 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -133,10 +133,7 @@ INT WINAPI wWinMain( } PhGuiSupportInitialization(); - if (!PhStartupParameters.Debug) - { - PhpInitializeSettings(); - } + PhpInitializeSettings(); if (PhGetIntegerSetting(L"AllowOnlyOneInstance") && !PhStartupParameters.NewInstance && @@ -1502,7 +1499,6 @@ VOID PhpProcessStartupParameters( if (PhStartupParameters.Debug) { // The symbol provider won't work if this is chosen. - PhpInitializeSettings(); PhShowDebugConsole(); } } diff --git a/phlib/extlv.c b/phlib/extlv.c index 1f6bf10b7e6a..cb1a1d6bb259 100644 --- a/phlib/extlv.c +++ b/phlib/extlv.c @@ -257,12 +257,8 @@ LRESULT CALLBACK PhpExtendedListViewWndProc( 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; + UseThemeTextColor = customDraw->nmcd.uItemState & CDIS_HOT || + ListView_GetItemState(hwnd, (INT)customDraw->nmcd.dwItemSpec, LVIS_SELECTED) & LVIS_SELECTED; } if (UseThemeTextColor) diff --git a/phlib/mapldr.c b/phlib/mapldr.c index 5461fb18808d..e7d8209765a6 100644 --- a/phlib/mapldr.c +++ b/phlib/mapldr.c @@ -1714,7 +1714,7 @@ VOID PhLoaderEntrySnapShowErrorMessage( { PhShowError2( NULL, - L"Error.", + PhApplicationName, L"Unable to load plugin.\r\nName: %s\r\nOrdinal: %u\r\nModule: %hs", PhGetStringOrEmpty(fileName), IMAGE_ORDINAL(OriginalThunk->u1.Ordinal), diff --git a/phlib/theme.c b/phlib/theme.c index aeb869af0565..55ca02d2a7e2 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -240,17 +240,17 @@ VOID PhInitializeWindowTheme( if (defaultWindowProc != PhpThemeWindowSubclassProc) { - WCHAR windowClassName[MAX_PATH]; PhSetWindowContext(WindowHandle, LONG_MAX, defaultWindowProc); SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowSubclassProc); - if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) - windowClassName[0] = UNICODE_NULL; - if ((PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE) || PhEqualStringZ(windowClassName, WC_LISTVIEW, FALSE)) && - WindowsVersion >= WINDOWS_10_RS5) + if (WindowsVersion >= WINDOWS_10_RS5) { - AllowDarkModeForWindow_I(WindowHandle, TRUE); // HACK for dynamically generated plugin tabs - } + WCHAR windowClassName[MAX_PATH]; + if (!GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName))) + windowClassName[0] = UNICODE_NULL; + if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE) || PhEqualStringZ(windowClassName, WC_LISTVIEW, FALSE)) + AllowDarkModeForWindow_I(WindowHandle, TRUE); // HACK for dynamically generated plugin tabs + } } PhEnumChildWindows( @@ -1589,6 +1589,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( BOOLEAN isSelected = (DrawInfo->uItemState & CDIS_SELECTED) == CDIS_SELECTED; BOOLEAN isHighlighted = (DrawInfo->uItemState & CDIS_HOT) == CDIS_HOT; BOOLEAN isFocused = (DrawInfo->uItemState & CDIS_FOCUS) == CDIS_FOCUS; + BOOLEAN isKeyboardFocused = isFocused && (DrawInfo->uItemState & CDIS_SHOWKEYBOARDCUES) == CDIS_SHOWKEYBOARDCUES; RECT bufferRect = { 0, 0, @@ -1738,7 +1739,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_HIDEPREFIX + DT_LEFT | DT_SINGLELINE | DT_VCENTER | (!isKeyboardFocused ? DT_HIDEPREFIX : 0) ); } else @@ -1748,7 +1749,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX + DT_LEFT | DT_TOP | DT_CALCRECT | (!isKeyboardFocused ? DT_HIDEPREFIX : 0) ); bufferRect.top = (DrawInfo->rc.bottom - DrawInfo->rc.top) / 2 - (bufferRect.bottom - bufferRect.top) / 2 - 1; @@ -1759,18 +1760,18 @@ LRESULT CALLBACK PhThemeWindowDrawButton( buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_LEFT | DT_TOP | DT_HIDEPREFIX + DT_LEFT | DT_TOP | (!isKeyboardFocused ? DT_HIDEPREFIX : 0) ); } - if (isFocused && (DrawInfo->uItemState & CDIS_SHOWKEYBOARDCUES) == CDIS_SHOWKEYBOARDCUES) + if (isKeyboardFocused) { DrawText( DrawInfo->hdc, buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_LEFT | DT_TOP | DT_CALCRECT | DT_HIDEPREFIX + DT_LEFT | DT_TOP | DT_CALCRECT ); PhInflateRect(&bufferRect, 1, 0); bufferRect.top += 1, bufferRect.bottom += 2; @@ -1831,7 +1832,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX + DT_LEFT | DT_VCENTER | DT_SINGLELINE | (!isKeyboardFocused ? DT_HIDEPREFIX : 0) ); } } @@ -1884,7 +1885,7 @@ LRESULT CALLBACK PhThemeWindowDrawButton( buttonText->Buffer, (UINT)buttonText->Length / sizeof(WCHAR), &bufferRect, - DT_CENTER | DT_SINGLELINE | DT_VCENTER | DT_HIDEPREFIX + DT_CENTER | DT_SINGLELINE | DT_VCENTER | (!isKeyboardFocused ? DT_HIDEPREFIX : 0) ); } } @@ -2292,9 +2293,11 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { HDC hdc = (HDC)wParam; - //SetBkMode(hdc, TRANSPARENT); - // Fix typing in multiline edit (Dart Vanya) - SetBkColor(hdc, PhThemeWindowBackground2Color); + //Fix typing in multiline edit (Dart Vanya) + if (PhGetWindowStyle((HWND)lParam) & ES_MULTILINE) + SetBkColor(hdc, PhThemeWindowBackground2Color); + else + SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, PhThemeWindowTextColor); SetDCBrushColor(hdc, PhThemeWindowBackground2Color); return (INT_PTR)PhGetStockBrush(DC_BRUSH); @@ -2307,7 +2310,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { HDC hdc = (HDC)wParam; - SetBkColor(hdc, PhThemeWindowBackgroundColor); + SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, PhThemeWindowTextColor); return (INT_PTR)PhThemeWindowBackgroundBrush; } @@ -2407,35 +2410,26 @@ LRESULT CALLBACK PhpThemeWindowGroupBoxSubclassProc( PhRemoveWindowContext(WindowHandle, LONG_MAX); } break; - case WM_ENABLE: - goto DefaultWndProc; case WM_ERASEBKGND: - return TRUE; - case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc; + HDC hdc = (HDC)wParam; RECT clientRect; - if (!BeginPaint(WindowHandle, &ps)) - break; - - // Fix artefacts when window moving back from off-screen (Dart Vanya) - hdc = GetDC(WindowHandle); GetClientRect(WindowHandle, &clientRect); - + ThemeWindowRenderGroupBoxControl(WindowHandle, hdc, &clientRect, oldWndProc); - - ReleaseDC(WindowHandle, hdc); + } + return TRUE; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(WindowHandle, &ps); EndPaint(WindowHandle, &ps); } - goto DefaultWndProc; + return 0; } return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); - -DefaultWndProc: - return DefWindowProc(WindowHandle, uMsg, wParam, lParam); } VOID ThemeWindowRenderTabControl( diff --git a/plugins/ExtendedServices/recovery.c b/plugins/ExtendedServices/recovery.c index c65a2f0e7ecd..2a0d6b60ef0a 100644 --- a/plugins/ExtendedServices/recovery.c +++ b/plugins/ExtendedServices/recovery.c @@ -299,7 +299,7 @@ INT_PTR CALLBACK EspServiceRecoveryDlgProc( { PhShowWarning2( WindowHandle, - L"Warning.", + PhApplicationName, L"The service has %lu failure actions configured, but this program only supports editing 3. " L"If you save the recovery information using this program, the additional failure actions will be lost.", context->NumberOfActions diff --git a/plugins/ToolStatus/main.c b/plugins/ToolStatus/main.c index c0f2a982d281..d8fbf0b0adf2 100644 --- a/plugins/ToolStatus/main.c +++ b/plugins/ToolStatus/main.c @@ -1413,7 +1413,7 @@ LRESULT CALLBACK MainWindowProc( } else { - PhShowError2(WindowHandle, L"Error.", L"The process (PID %lu) does not exist.", processId); + PhShowError2(WindowHandle, PhApplicationName, L"The process (PID %lu) does not exist.", processId); } } break; @@ -1428,7 +1428,7 @@ LRESULT CALLBACK MainWindowProc( } else { - PhShowError2(WindowHandle, L"Error.", L"The process (PID %lu) does not exist.", processId); + PhShowError2(WindowHandle, PhApplicationName, L"The process (PID %lu) does not exist.", processId); } } break; diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 803bd7b6c7c8..778e3f440c25 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -441,14 +441,14 @@ VOID ThemeWindowStatusBarDestroyBufferedContext( } } -INT ThemeWindowStatusBarUpdateRectToIndex( +LONG ThemeWindowStatusBarUpdateRectToIndex( _In_ HWND WindowHandle, _In_ WNDPROC WindowProcedure, _In_ PRECT UpdateRect, - _In_ INT Count + _In_ LONG Count ) { - for (INT i = 0; i < Count; i++) + for (LONG i = 0; i < Count; i++) { RECT blockRect = { 0 }; @@ -474,7 +474,7 @@ VOID ThemeWindowStatusBarDrawPart( _In_ HWND WindowHandle, _In_ HDC bufferDc, _In_ PRECT clientRect, - _In_ INT Index + _In_ LONG Index ) { RECT blockRect = { 0 }; @@ -533,7 +533,7 @@ VOID ThemeWindowRenderStatusBar( FillRect(bufferDc, clientRect, PhThemeWindowBackgroundBrush); - INT blockCount = (INT)CallWindowProc( + LONG blockCount = (LONG)CallWindowProc( PhDefaultStatusbarWindowProcedure, WindowHandle, SB_GETPARTS, @@ -572,7 +572,7 @@ VOID ThemeWindowRenderStatusBar( // Top statusbar border will be drawn by bottom tabcontrol border - for (INT i = 0; i < blockCount; i++) + for (LONG i = 0; i < blockCount; i++) { ThemeWindowStatusBarDrawPart(Context, WindowHandle, bufferDc, clientRect, i); } @@ -771,7 +771,8 @@ LRESULT CALLBACK PhEditWindowHookProcedure( if (GetFocus() == WindowHandle) { - SetDCBrushColor(hdc, GetSysColor(COLOR_HOTLIGHT)); // PhThemeWindowHighlightColor + // A little bit nicer and contrast color (Dart Vanya) + SetDCBrushColor(hdc, PhMakeColorBrighter(GetSysColor(COLOR_HOTLIGHT), 85)); // PhThemeWindowHighlightColor FrameRect(hdc, &windowRect, PhGetStockBrush(DC_BRUSH)); } else @@ -1311,7 +1312,7 @@ VOID PhRegisterHeaderSuperClass( // Detours export procedure hooks -static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( +static HRESULT (WINAPI* DefaultDrawThemeBackground)( _In_ HTHEME Theme, _In_ HDC Hdc, _In_ INT PartId, @@ -1320,7 +1321,7 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackground)( _In_ LPCRECT ClipRect ) = NULL; -static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( +static HRESULT (WINAPI* DefaultDrawThemeBackgroundEx)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1329,7 +1330,7 @@ static HRESULT (WINAPI* PhDefaultDrawThemeBackgroundEx)( _In_ const DTBGOPTS* pOptions ) = NULL; -static HRESULT(WINAPI* PhDefaultDrawThemeText)( +static HRESULT(WINAPI* DefaultDrawThemeText)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1341,7 +1342,7 @@ static HRESULT(WINAPI* PhDefaultDrawThemeText)( _In_ LPCRECT pRect ) = NULL; -static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( +static HRESULT(WINAPI* DefaultDrawThemeTextEx)( _In_ HTHEME hTheme, _In_ HDC hdc, _In_ int iPartId, @@ -1353,7 +1354,7 @@ static HRESULT(WINAPI* PhDefaultDrawThemeTextEx)( _In_ const DTTOPTS* pOptions ) = NULL; -int (WINAPI* PhDefaultComCtl32DrawTextW)( +int (WINAPI* DefaultComCtl32DrawTextW)( _In_ HDC hdc, _Inout_ LPCWSTR lpchText, _In_ int cchText, @@ -1361,14 +1362,14 @@ int (WINAPI* PhDefaultComCtl32DrawTextW)( _In_ UINT format ) = NULL; -static HRESULT(WINAPI* PhDefaultTaskDialogIndirect)( +static HRESULT(WINAPI* DefaultTaskDialogIndirect)( _In_ const TASKDIALOGCONFIG* pTaskConfig, _Out_opt_ int* pnButton, _Out_opt_ int* pnRadioButton, _Out_opt_ BOOL* pfVerificationFlagChecked ) = NULL; -static HRESULT(WINAPI* PhDefaultGetThemeColor)( +static HRESULT(WINAPI* DefaultGetThemeColor)( _In_ HTHEME hTheme, _In_ int iPartId, _In_ int iStateId, @@ -1377,19 +1378,19 @@ static HRESULT(WINAPI* PhDefaultGetThemeColor)( ) = NULL; // uxtheme.dll ordinal 49 -static HTHEME(WINAPI* PhDefaultOpenNcThemeData)( +static HTHEME(WINAPI* DefaultOpenNcThemeData)( _In_ HWND hwnd, _In_ LPCWSTR pszClassList ) = NULL; -static BOOL (WINAPI* PhDefaultSystemParametersInfo)( +static BOOL (WINAPI* DefaultSystemParametersInfo)( _In_ UINT uiAction, _In_ UINT uiParam, _Pre_maybenull_ _Post_valid_ PVOID pvParam, _In_ UINT fWinIni ) = NULL; -static HWND (WINAPI* PhDefaultCreateWindowEx)( +static HWND (WINAPI* DefaultCreateWindowEx)( _In_ ULONG ExStyle, _In_opt_ PCWSTR ClassName, _In_opt_ PCWSTR WindowName, @@ -1450,8 +1451,8 @@ BOOLEAN CALLBACK PhInitializeTaskDialogTheme( HRESULT PhDrawThemeBackgroundHook( _In_ HTHEME Theme, _In_ HDC Hdc, - _In_ INT PartId, - _In_ INT StateId, + _In_ LONG PartId, + _In_ LONG StateId, _In_ LPCRECT Rect, _In_ LPCRECT ClipRect ) @@ -1488,7 +1489,7 @@ HRESULT PhDrawThemeBackgroundHook( } } - return PhDefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); + return DefaultDrawThemeBackground(Theme, Hdc, PartId, StateId, Rect, ClipRect); } HRESULT WINAPI PhDrawThemeBackgroundExHook( @@ -1509,7 +1510,7 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( 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); + HRESULT retVal = DefaultDrawThemeBackgroundEx(darkButtonTheme ? darkButtonTheme : hTheme, hdc, iPartId, iStateId, pRect, pOptions); if (darkButtonTheme) PhCloseThemeData(darkButtonTheme); return retVal; @@ -1559,7 +1560,7 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( static enum { yes, no, unknown } mustInvertButton = unknown; if (mustInvertButton == unknown) { - PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + DefaultDrawThemeBackgroundEx(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); @@ -1567,14 +1568,14 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( } FillRect(hdc, pRect, PhThemeWindowBackgroundBrush); if (mustInvertButton == yes) InvertRect(hdc, pRect); - HRESULT retVal = PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + HRESULT retVal = DefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); if (mustInvertButton == yes) InvertRect(hdc, pRect); return retVal; } } } - return PhDefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); + return DefaultDrawThemeBackgroundEx(hTheme, hdc, iPartId, iStateId, pRect, pOptions); } HWND PhCreateWindowExHook( @@ -1582,17 +1583,17 @@ HWND PhCreateWindowExHook( _In_opt_ PCWSTR ClassName, _In_opt_ PCWSTR WindowName, _In_ ULONG Style, - _In_ INT X, - _In_ INT Y, - _In_ INT Width, - _In_ INT Height, + _In_ LONG X, + _In_ LONG Y, + _In_ LONG Width, + _In_ LONG Height, _In_opt_ HWND Parent, _In_opt_ HMENU Menu, _In_opt_ PVOID Instance, _In_opt_ PVOID Param ) { - HWND windowHandle = PhDefaultCreateWindowEx( + HWND windowHandle = DefaultCreateWindowEx( ExStyle, ClassName, WindowName, @@ -1686,7 +1687,7 @@ BOOL WINAPI PhSystemParametersInfoHook( return TRUE; } - return PhDefaultSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); + return DefaultSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } //ULONG WINAPI GetSysColorHook(int nIndex) @@ -1756,11 +1757,11 @@ HRESULT WINAPI PhDrawThemeTextHook( PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) { DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); } } - return PhDefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); + return DefaultDrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect); } HRESULT WINAPI PhDrawThemeTextExHook( @@ -1785,13 +1786,13 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (pOptions) options = *pOptions; options.dwFlags |= DTT_TEXTCOLOR; - PhDefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); + DefaultGetThemeColor(hTheme, iPartId, iStateId, TMT_TEXTCOLOR, &options.crText); options.crText = PhMakeColorBrighter(options.crText, 90); - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, &options); } } - return PhDefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); } int PhDetoursComCtl32DrawTextW( @@ -1834,7 +1835,7 @@ int PhDetoursComCtl32DrawTextW( } } - return PhDefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); + return DefaultComCtl32DrawTextW(hdc, lpchText, cchText, lprc, format); } HRESULT PhGetThemeColorHook( @@ -1847,7 +1848,7 @@ HRESULT PhGetThemeColorHook( { WCHAR className[MAX_PATH]; - HRESULT retVal = PhDefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); + HRESULT retVal = DefaultGetThemeColor(hTheme, iPartId, iStateId, iPropId, pColor); if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) { @@ -1877,10 +1878,10 @@ HTHEME PhOpenNcThemeDataHook( if (PhEqualStringZ((PWSTR)pszClassList, VSCLASS_SCROLLBAR, TRUE) && PhIsDarkModeAllowedForWindow(hwnd)) { - return PhDefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); + return DefaultOpenNcThemeData(NULL, L"Explorer::ScrollBar"); } - return PhDefaultOpenNcThemeData(hwnd, pszClassList); + return DefaultOpenNcThemeData(hwnd, pszClassList); } BOOLEAN CALLBACK PhInitializeTaskDialogTheme( @@ -2072,7 +2073,7 @@ HRESULT PhTaskDialogIndirectHook( myConfig.pfCallback = ThemeTaskDialogCallbackHook; myConfig.lpCallbackData = (LONG_PTR)&CallbackData; - return PhDefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); + return DefaultTaskDialogIndirect(&myConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); } VOID PhRegisterDetoursHooks( @@ -2090,26 +2091,26 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"user32.dll")) { - PhDefaultCreateWindowEx = PhGetDllBaseProcedureAddress(baseAddress, "CreateWindowExW", 0); - PhDefaultSystemParametersInfo = PhGetDllBaseProcedureAddress(baseAddress, "SystemParametersInfoW", 0); + DefaultCreateWindowEx = PhGetDllBaseProcedureAddress(baseAddress, "CreateWindowExW", 0); + DefaultSystemParametersInfo = PhGetDllBaseProcedureAddress(baseAddress, "SystemParametersInfoW", 0); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"uxtheme.dll")) { PhAllowDarkModeForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 133); PhIsDarkModeAllowedForWindow_I = PhGetDllBaseProcedureAddress(baseAddress, NULL, 137); - PhDefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); - PhDefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); - PhDefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); - PhDefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); - PhDefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); - PhDefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); + DefaultDrawThemeBackground = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackground", 0); + DefaultDrawThemeBackgroundEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeBackgroundEx", 0); + DefaultDrawThemeText = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeText", 0); + DefaultDrawThemeTextEx = PhGetDllBaseProcedureAddress(baseAddress, "DrawThemeTextEx", 0); + DefaultGetThemeColor = PhGetDllBaseProcedureAddress(baseAddress, "GetThemeColor", 0); + DefaultOpenNcThemeData = PhGetDllBaseProcedureAddress(baseAddress, NULL, 49); } if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { - PhDefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); - PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&PhDefaultComCtl32DrawTextW); + DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&DefaultComCtl32DrawTextW); } if (!NT_SUCCESS(status = DetourTransactionBegin())) @@ -2117,28 +2118,28 @@ VOID PhRegisterDetoursHooks( if (PhEnableThemeSupport || PhEnableThemeAcrylicSupport) { - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeBackground, (PVOID)PhDrawThemeBackgroundHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeBackgroundEx, (PVOID)PhDrawThemeBackgroundExHook))) goto CleanupExit; if (!PhDefaultEnableThemeAnimation) { - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultSystemParametersInfo, (PVOID)PhSystemParametersInfoHook))) goto CleanupExit; } - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeText, (PVOID)PhDrawThemeTextHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultDrawThemeTextEx, (PVOID)PhDrawThemeTextExHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultGetThemeColor, (PVOID)PhGetThemeColorHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) goto CleanupExit; } - if (!NT_SUCCESS(status = DetourAttach((PVOID)&PhDefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) goto CleanupExit; if (!NT_SUCCESS(status = DetourTransactionCommit())) goto CleanupExit; From 11f2c6fd8fc507f19b0fc940a588d7928a7b6cde Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Wed, 6 Nov 2024 01:14:11 +0300 Subject: [PATCH 11/11] Fix SysLink theme support on Windows 10 - TaskDialog theme on Windows 10 currently unsupported... --- SystemInformer/delayhook.c | 108 ++++++++++++++++--------------------- phlib/theme.c | 5 +- tools/peview/delayhook.c | 91 +++++++++++++++---------------- 3 files changed, 97 insertions(+), 107 deletions(-) diff --git a/SystemInformer/delayhook.c b/SystemInformer/delayhook.c index e70874df86eb..722af3837370 100644 --- a/SystemInformer/delayhook.c +++ b/SystemInformer/delayhook.c @@ -1460,32 +1460,27 @@ HRESULT PhDrawThemeBackgroundHook( WCHAR className[MAX_PATH]; BOOLEAN hasThemeClass = PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className)); - if (WindowsVersion >= WINDOWS_11) + if (WindowsVersion >= WINDOWS_11 && hasThemeClass) { - if (hasThemeClass) + if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) { - if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) + if (PartId == MENU_POPUPGUTTER || PartId == MENU_POPUPBORDERS) { - if (PartId == MENU_POPUPGUTTER || PartId == MENU_POPUPBORDERS) - { - FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); - return S_OK; - } + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + return S_OK; } } } - if (hasThemeClass) + if (hasThemeClass && PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(Hdc) == NULL*/) { - if (PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE)) + if (PartId == PP_TRANSPARENTBAR || PartId == PP_TRANSPARENTBARVERT) // Progress bar background { - if (PartId == PP_TRANSPARENTBAR) // Progress bar background. - { - FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); - SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); - FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); + FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; } } @@ -1519,8 +1514,8 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( // 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)) + PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { switch (iPartId) { @@ -1753,26 +1748,11 @@ HRESULT WINAPI PhDrawThemeTextHook( if ((iPartId == BP_COMMANDLINK /*|| iPartId == BP_RADIOBUTTON*/) && iStateId != PBS_DISABLED) { WCHAR className[MAX_PATH]; - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { - // 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) || - // PhEqualStringZ((PWSTR)pszText, L"Realtime", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"High", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Above normal", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Normal", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Below normal", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Idle", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Medium", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Low", FALSE) || - // PhEqualStringZ((PWSTR)pszText, L"Very low", FALSE)) - { - DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; - return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); - } + DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; + return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); } } @@ -1794,8 +1774,8 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (iPartId == BP_COMMANDLINK) { WCHAR className[MAX_PATH]; - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { DTTOPTS options = { sizeof(DTTOPTS) }; if (pOptions) @@ -1824,19 +1804,6 @@ int PhDetoursComCtl32DrawTextW( static COLORREF colLinkPressed = RGB(0, 0, 0); HWND WindowHandle; - if (PhBeginInitOnce(&initOnce)) - { - HTHEME hTextTheme = PhOpenThemeData(NULL, VSCLASS_TEXTSTYLE, 0); - if (hTextTheme) - { - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); - PhCloseThemeData(hTextTheme); - } - PhEndInitOnce(&initOnce); - } - if ((WindowHandle = WindowFromDC(hdc)) && (PhIsDarkModeAllowedForWindow(WindowHandle) || PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG))) // HACK { @@ -1844,9 +1811,26 @@ int PhDetoursComCtl32DrawTextW( GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) { + if (PhBeginInitOnce(&initOnce)) + { + HTHEME hTextTheme = PhOpenThemeData(WindowHandle, VSCLASS_TEXTSTYLE, PhGetWindowDpi(WindowHandle)); + if (hTextTheme) + { + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); + PhCloseThemeData(hTextTheme); + } + PhEndInitOnce(&initOnce); + } + COLORREF color = GetTextColor(hdc); - if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed) + + if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed || + WindowsVersion < WINDOWS_11 && color == RGB(0x00, 0x66, 0xCC)) // on Windows 10 PhGetThemeColor returns 0xFFFFFF for any StateId + { SetTextColor(hdc, PhMakeColorBrighter(color, 95)); + } } } @@ -1867,16 +1851,16 @@ HRESULT PhGetThemeColorHook( if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) { - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE) + /*|| WindowsVersion < WINDOWS_11*/) { *pColor = PhMakeColorBrighter(*pColor, 150); // Main header. } } else if (iPropId == TMT_TEXTCOLOR) { - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE) + /*|| WindowsVersion < WINDOWS_11*/) { *pColor = PhThemeWindowTextColor; // Text color for check boxes, expanded text, and expander button text. } @@ -2124,7 +2108,8 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { - DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + if (WindowsVersion >= WINDOWS_11) // TaskDialog theme on Windows 10 currently unsupported... + DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&DefaultComCtl32DrawTextW); } @@ -2150,8 +2135,9 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) - goto CleanupExit; + if (WindowsVersion >= WINDOWS_11) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + goto CleanupExit; } if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) diff --git a/phlib/theme.c b/phlib/theme.c index be997cca1fb8..5b25c12cc2df 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -2310,7 +2310,10 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { HDC hdc = (HDC)wParam; - SetBkMode(hdc, TRANSPARENT); + if (uMsg == WM_CTLCOLORBTN) // for correct drawing of system KEYBOARDCUES + SetBkColor(hdc, PhThemeWindowBackground2Color); + else + SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, PhThemeWindowTextColor); return (INT_PTR)PhThemeWindowBackgroundBrush; } diff --git a/tools/peview/delayhook.c b/tools/peview/delayhook.c index 778e3f440c25..0792be5c4b07 100644 --- a/tools/peview/delayhook.c +++ b/tools/peview/delayhook.c @@ -1460,32 +1460,27 @@ HRESULT PhDrawThemeBackgroundHook( WCHAR className[MAX_PATH]; BOOLEAN hasThemeClass = PhGetThemeClass(Theme, className, RTL_NUMBER_OF(className)); - if (WindowsVersion >= WINDOWS_11) + if (WindowsVersion >= WINDOWS_11 && hasThemeClass) { - if (hasThemeClass) + if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) { - if (PhEqualStringZ(className, VSCLASS_MENU, TRUE)) + if (PartId == MENU_POPUPGUTTER || PartId == MENU_POPUPBORDERS) { - if (PartId == MENU_POPUPGUTTER || PartId == MENU_POPUPBORDERS) - { - FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); - return S_OK; - } + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + return S_OK; } } } - if (hasThemeClass) + if (hasThemeClass && PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(Hdc) == NULL*/) { - if (PhEqualStringZ(className, VSCLASS_PROGRESS, TRUE)) + if (PartId == PP_TRANSPARENTBAR || PartId == PP_TRANSPARENTBARVERT) // Progress bar background { - if (PartId == PP_TRANSPARENTBAR) // Progress bar background. - { - FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); - SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); - FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); - return S_OK; - } + FillRect(Hdc, Rect, PhThemeWindowBackgroundBrush); + SetDCBrushColor(Hdc, RGB(0x60, 0x60, 0x60)); + FrameRect(Hdc, Rect, PhGetStockBrush(DC_BRUSH)); + return S_OK; } } @@ -1519,8 +1514,8 @@ HRESULT WINAPI PhDrawThemeBackgroundExHook( // 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)) + PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOG, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { switch (iPartId) { @@ -1753,8 +1748,8 @@ HRESULT WINAPI PhDrawThemeTextHook( if ((iPartId == BP_COMMANDLINK /*|| iPartId == BP_RADIOBUTTON*/) && iStateId != PBS_DISABLED) { WCHAR className[MAX_PATH]; - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { DTTOPTS options = { sizeof(DTTOPTS), DTT_TEXTCOLOR, PhThemeWindowTextColor }; return DefaultDrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText, dwTextFlags, (LPRECT)pRect, &options); @@ -1779,8 +1774,8 @@ HRESULT WINAPI PhDrawThemeTextExHook( if (iPartId == BP_COMMANDLINK) { WCHAR className[MAX_PATH]; - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_BUTTON, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_BUTTON, TRUE) + /*|| WindowsVersion < WINDOWS_11 && WindowFromDC(hdc) == NULL*/) { DTTOPTS options = { sizeof(DTTOPTS) }; if (pOptions) @@ -1809,19 +1804,6 @@ int PhDetoursComCtl32DrawTextW( static COLORREF colLinkPressed = RGB(0, 0, 0); HWND WindowHandle; - if (PhBeginInitOnce(&initOnce)) - { - HTHEME hTextTheme = PhOpenThemeData(NULL, VSCLASS_TEXTSTYLE, 0); - if (hTextTheme) - { - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); - PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); - PhCloseThemeData(hTextTheme); - } - PhEndInitOnce(&initOnce); - } - if ((WindowHandle = WindowFromDC(hdc)) && (PhIsDarkModeAllowedForWindow(WindowHandle) || PhGetWindowContext(WindowHandle, TASKDIALOG_CONTEXT_TAG))) // HACK { @@ -1829,9 +1811,26 @@ int PhDetoursComCtl32DrawTextW( GETCLASSNAME_OR_NULL(WindowHandle, windowClassName); if (PhEqualStringZ(windowClassName, WC_LINK, FALSE)) { + if (PhBeginInitOnce(&initOnce)) + { + HTHEME hTextTheme = PhOpenThemeData(WindowHandle, VSCLASS_TEXTSTYLE, PhGetWindowDpi(WindowHandle)); + if (hTextTheme) + { + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_NORMAL, TMT_TEXTCOLOR, &colLinkNormal); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_HOT, TMT_TEXTCOLOR, &colLinkHot); + PhGetThemeColor(hTextTheme, TEXT_HYPERLINKTEXT, TS_HYPERLINK_PRESSED, TMT_TEXTCOLOR, &colLinkPressed); + PhCloseThemeData(hTextTheme); + } + PhEndInitOnce(&initOnce); + } + COLORREF color = GetTextColor(hdc); - if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed) + + if (color == colLinkNormal || color == colLinkHot || color == colLinkPressed || + WindowsVersion < WINDOWS_11 && color == RGB(0x00, 0x66, 0xCC)) // on Windows 10 PhGetThemeColor returns 0xFFFFFF for any StateId + { SetTextColor(hdc, PhMakeColorBrighter(color, 95)); + } } } @@ -1852,16 +1851,16 @@ HRESULT PhGetThemeColorHook( if (iPropId == TMT_TEXTCOLOR && iPartId == TDLG_MAININSTRUCTIONPANE) { - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE) + /*|| WindowsVersion < WINDOWS_11*/) { *pColor = PhMakeColorBrighter(*pColor, 150); // Main header. } } else if (iPropId == TMT_TEXTCOLOR) { - if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && - PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE)) + if (PhGetThemeClass(hTheme, className, RTL_NUMBER_OF(className)) && PhEqualStringZ(className, VSCLASS_TASKDIALOGSTYLE, TRUE) + /*|| WindowsVersion < WINDOWS_11*/) { *pColor = PhThemeWindowTextColor; // Text color for check boxes, expanded text, and expander button text. } @@ -2109,7 +2108,8 @@ VOID PhRegisterDetoursHooks( if (baseAddress = PhGetLoaderEntryDllBaseZ(L"Comctl32.dll")) { - DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); + if (WindowsVersion >= WINDOWS_11) // TaskDialog theme on Windows 10 currently unsupported... + DefaultTaskDialogIndirect = PhGetDllBaseProcedureAddress(baseAddress, "TaskDialogIndirect", 0); PhLoaderEntryDetourImportProcedure(baseAddress, "User32.dll", "DrawTextW", PhDetoursComCtl32DrawTextW, (PVOID*)&DefaultComCtl32DrawTextW); } @@ -2135,8 +2135,9 @@ VOID PhRegisterDetoursHooks( goto CleanupExit; if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultOpenNcThemeData, (PVOID)PhOpenNcThemeDataHook))) goto CleanupExit; - if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) - goto CleanupExit; + if (WindowsVersion >= WINDOWS_11) + if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultTaskDialogIndirect, (PVOID)PhTaskDialogIndirectHook))) + goto CleanupExit; } if (!NT_SUCCESS(status = DetourAttach((PVOID)&DefaultCreateWindowEx, (PVOID)PhCreateWindowExHook))) @@ -2177,7 +2178,7 @@ BOOLEAN PhIsThemeTransparencyEnabled( VOID PvInitializeSuperclassControls( VOID - ) +) { PhDefaultEnableStreamerMode = !!PhGetIntegerSetting(L"EnableStreamerMode");