WildByDesign Posted June 20, 2025 Posted June 20, 2025 Recently I have been playing around with _WinAPI_SetTextColor, _WinAPI_SetBkColor, _WinAPI_SetBkMode and a few other functions in an attempt to change the background color and text color of another app. We can use Notepad (classic win32 notepad) as an example. I have been able to successfully get the handle for Notepad, for the Edit box class and the DC handle. However, none of the colors seem to change. But I guess what I am wondering is if what I am trying to do is technically even possible or not. I just don't want to put too much time into it if it's impossible to do. You have to have Notepad (classic win32) already running for my example because it gets the handle by looking for window title 'Untitled - Notepad' or modified unsaved '*Untitled - Notepad'. Anyway, just wondering if anyone has any experience with doing this or knows if it's technically possible or not. Thank you for your time. Here is some of what I have been trying: Spoiler expandcollapse popup#include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <WinAPIGdi.au3> #include <WinAPITheme.au3> #include <FontConstants.au3> #include <MsgBoxConstants.au3> #include <StructureConstants.au3> #include <WinAPIGdi.au3> #include <WinAPIGdiDC.au3> #include <WinAPIHObj.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $aArray, $sClassName, $hWndExplorer, $g_hDC, $test1, $test2, $test3 $aArray = WinList() For $n = 1 To $aArray[0][0] $sClassName = _WinAPI_GetClassName($aArray[$n][1]) ; get handle for File Explorer ;If $sClassName = "CabinetWClass" Then $hWndExplorer = $aArray[$n][1] If $aArray[$n][0] = 'Untitled - Notepad' Then $hWndExplorer = $aArray[$n][1] If $aArray[$n][0] = '*Untitled - Notepad' Then $hWndExplorer = $aArray[$n][1] Next ConsoleWrite($hWndExplorer & @CRLF) Local $hGUI = GUICreate("The external process 3", 350, 220) Local $idButton_Add = GUICtrlCreateButton("Add $WS_EX_LAYERED and attributes" & @crlf & _ "To DetailsPaneHwndHostClass in Explorer", 25, 40, 300, 100, 0x2000) ; $BS_MULTILINE = 0x2000 GUISetState(@SW_SHOW, $hGUI) Local $nMsg While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idButton_Add ;Local $hControl = ControlGetHandle($hWndExplorer, "", "[CLASS:Microsoft.UI.Content.DesktopChildSiteBridge]") Local $hControl = ControlGetHandle($hWndExplorer, "", "[CLASS:Edit]") ConsoleWrite("$hControl " & $hControl & @CRLF) ConsoleWrite("$hWndExplorer " & $hWndExplorer & @CRLF) $g_hDC = _WinAPI_GetDC($hControl) ConsoleWrite("$g_hDC " & $g_hDC & @CRLF) $test1 = _WinAPI_SetTextColor($g_hDC, 0xFFFFFF) $test2 = _WinAPI_SetBkColor($g_hDC, 0xFFFFFF) $test3 = _WinAPI_SetBkMode($g_hDC, $OPAQUE) ConsoleWrite("$test1 " & $test1 & @CRLF) ConsoleWrite("$test2 " & $test2 & @CRLF) ConsoleWrite("$test3 " & $test3 & @CRLF) _WinAPI_ReleaseDC($hControl, $g_hDC) ;Local $hControl = ControlGetHandle($hWndExplorer, "", "[CLASS:DetailsPaneHwndHostClass]") ;Local $hControl = ControlGetHandle($hWndExplorer, "", "[CLASS:SysTreeView32]") ;Local $aList = WinList($hWndExplorer) ;_ArrayDisplay($aList, "test") ;WinSetTrans($hControl, "", 100) #cs Local $hRgn = _WinAPI_CreateEllipticRgn(_WinAPI_CreateRectEx(0, 0, 0, 0)) _WinAPI_DwmEnableBlurBehindWindow($hControl, 1, 0, $hRgn) If $hRgn Then _WinAPI_DeleteObject($hRgn) EndIf _WinAPI_DwmEnableBlurBehindWindow10($hControl, True) If $sClassName = "CabinetWClass" Then WinActivate("[CLASS:Shell_TrayWnd]") WinActivate($hControl) EndIf #ce ;_WinAPI_DwmExtendFrameIntoClientArea($hControl, _WinAPI_CreateMargins(-1, -1, -1, -1)) ;__WinAPI_Set_Window_Style($hControl, $WS_EX_LAYERED, _ ; ($nMsg = $idButton_Add ? True : False), _ ; add or remove... ; True) ; True = ...the extended style ;_WinAPI_SetLayeredWindowAttributes($hControl, 0xff222222, 120) ;_WinAPI_SetWindowTheme($hControl, "", "") ;_WinAPI_SetWindowTheme($hControl, 'CFD') Local $AlphaKey = 0x00000000 ;_WinAPI_SetLayeredWindowAttributes($hControl, $AlphaKey, 0, $LWA_COLORKEY + $LWA_ALPHA, True) ;_WinAPI_DwmExtendFrameIntoClientArea($hControl, _WinAPI_CreateMargins(-1, -1, -1, -1)) Local $iTransColor, $iAlpha Local $iInfo = _WinAPI_GetLayeredWindowAttributes($hControl, $iTransColor, $iAlpha) #cs MsgBox($MB_SYSTEMMODAL, 'Layered GUI', "Button on layered Window Clicked" & @CRLF & "Information about this window: " & @CRLF & _ "Transparent Color: " & $iTransColor & @CRLF & _ "Alpha Value: " & $iAlpha & @CRLF & _ "LWA_COLORKEY: " & (BitAND($iInfo, $LWA_COLORKEY) = $LWA_COLORKEY) & @CRLF & _ "LWA_ALPHA: " & (BitAND($iInfo, $LWA_ALPHA) = $LWA_ALPHA)) #ce _WinAPI_SetWindowPos($hControl, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_FRAMECHANGED, $SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER)) ; +++ EndSwitch WEnd ;=========================================== Func __WinAPI_Set_Window_Style($hWnd, $i_Style, $b_Add, $b_exStyle = False) ; compacted code (from Kafu's original) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $iIndex = $b_exStyle ? $GWL_EXSTYLE : $GWL_STYLE ; $iIndex as named by msdn & help file Local $i_Style_Old = _WinAPI_GetWindowLong($hWnd, $iIndex) If $b_Add Then If BitAND($i_Style_Old, $i_Style) Then Return ; style already applied _WinAPI_SetWindowLong($hWnd, $iIndex, BitOR($i_Style_Old, $i_Style)) Else ; remove If Not BitAND($i_Style_Old, $i_Style) Then Return ; style not set _WinAPI_SetWindowLong($hWnd, $iIndex, BitXOR($i_Style_Old, $i_Style)) EndIf Local $iRet = _WinAPI_SetWindowPos($hWnd, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_FRAMECHANGED, $SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER)) ; +++ If Not $iRet Then MsgBox($MB_TOPMOST, "_WinAPI_SetWindowPos", "Error = " & _WinAPI_GetLastError() & " Message = " & _WinAPI_GetLastErrorMessage()) EndFunc ;==>__WinAPI_Set_Window_Style
WildByDesign Posted June 20, 2025 Author Posted June 20, 2025 I was also trying with _WinAPI_SetSysColors but no success there either.
ahmet Posted June 20, 2025 Posted June 20, 2025 Can you try creating an edit box within your GUI? Then try to apply those functions to your edit box.
WildByDesign Posted June 20, 2025 Author Posted June 20, 2025 Yes, I have tried creating a GUI within AutoIt to confirm that those functions do work well. It just seems to not work on another process, in this case Notepad as example. The functions succeed without failure which is good, but nothing changes visually in Notepad.
ahmet Posted June 20, 2025 Posted June 20, 2025 Can you share the code that works where you set text color of an edit box inside AutoIt's GUI?
WildByDesign Posted June 22, 2025 Author Posted June 22, 2025 I apologize, I had assumed the you meant AutoIt GUI in general but you were specifically asking about Edit box in AutoIt GUI. I read too fast and missed that most important part. To answer that question, no I have not successfully applied those functions to an Edit box within AutoIt. Sorry about that. I was just running the functions for _WinAPI_SetTextColor, _WinAPI_SetBkColor and _WinAPI_SetBkMode that were provided on AutoIt web site.
WildByDesign Posted July 16, 2025 Author Posted July 16, 2025 (edited) I have had a small amount of progress on changing the background color and text color of other apps. Edited July 16, 2025 by WildByDesign
WildByDesign Posted July 16, 2025 Author Posted July 16, 2025 Yes, for sure. I am not at my PC right now but will share later. Although the code isn’t too special. I just used SetSysColors to change colors followed by restoring the original system colors when the script exits. This affects all apps though which is not what I originally wanted. I was hoping to target each app individually at execution time. But I was not successful with any of my attempts. SetSysColors is system-wide but only affects the current session so it is not permanent. ahmet 1
WildByDesign Posted July 16, 2025 Author Posted July 16, 2025 (edited) 1 hour ago, ahmet said: Are you willing to share code? Here is what I am using currently. As long as the AutoIt GUI that is spawns is open, it will affect most win32 apps that are opened. When you close the AutoIt GUI, it will restore the default system colors. I'm going to try to expand on this more later by trying to apply dark mode to menu bar and scrollbar and see how far it can go. Code: Spoiler expandcollapse popup#include <GUIConstantsEx.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Example() Func Example() Local $aElements[4] = [$COLOR_WINDOWTEXT, $COLOR_WINDOW, $COLOR_BTNFACE, $COLOR_3DHILIGHT] ; Red and Green Local $aColors[4] = [0x00FFFFFF, 0x00000000, 0x00000000, 0x00000000], $aSaveColors[4] GUICreate("My GUI", 300, 200) $aSaveColors[0] = _WinAPI_GetSysColor($COLOR_WINDOWTEXT) $aSaveColors[1] = _WinAPI_GetSysColor($COLOR_WINDOW) $aSaveColors[2] = _WinAPI_GetSysColor($COLOR_BTNFACE) $aSaveColors[3] = _WinAPI_GetSysColor($COLOR_3DHILIGHT) _WinAPI_SetSysColors($aElements, $aColors) GUISetState(@SW_SHOW) ;ShellExecute("notepad.exe") ;ShellExecute("win32calc.exe") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete() _WinAPI_SetSysColors($aElements, $aSaveColors) Exit EndFunc ;==>Example Edited July 16, 2025 by WildByDesign
WildByDesign Posted Saturday at 05:57 PM Author Posted Saturday at 05:57 PM (edited) Progress... I don't give up too easily. I'm attempting to make some sort of "universal dark mode" (something of a mythical unicorn) that would transform older win32 apps such as Notepad and the older Calculator (win32calc) to dark mode as well. This is the first time that I've ever been able to have any progress with the statusbar of Notepad. I think that I can probably do something with the buttons on Calculator as well. But as can be seen in the screenshot, the text color is a problem. Edited Saturday at 05:58 PM by WildByDesign
WildByDesign Posted 18 hours ago Author Posted 18 hours ago Some progress with Calculator (classic - win32calc.exe)... This was a bit more difficult but neat progress. Still the issue with text. The reason why I am tying to do this system-wide is because I would technically need _WinAPI_SetWindowsHookEx if I wanted to actually change things on an application level, from my understanding. The problem with that is because: Quote If the $iThreadId parameter is zero or specifies the identifier of a thread created by a different process, the $pProc parameter must point to a hook procedure in a DLL. That would require creating a DLL (which can't be done in AutoIt) and this DLL would need to inject into specific processes or all processes. Injecting an unsigned DLL is not going to go over very well for system security. Also, I don't have the skills with other programming languages to create a DLL with full hook procedure code. Plus I really wanted to go 100% AutoIt on this adventure. For what it's worth, I did try using exe_to_dll by the fabulous hasherezade to convert the compiled script to DLL. It did successfully add the necessary DLL exports. But it fails to run code from the DLL simply because the AutoIt interpreter was just not designed for that purpose.
WildByDesign Posted 17 hours ago Author Posted 17 hours ago (edited) Now, of course, we can always install third-party themes (msstyles) but those are unsupported as are the UxTheme patchers that can potentially have their own issues. Also, using high contrast themes can be another potential option for creating dark themes (that are supported) as we have seen from cool tools from @argumentum. However, my thought process here is: What if we could take a default Windows install and use the built-in default Aero theme resources to create a system-wide dark theme that also benefits older win32 apps? This the wild type of adventure that I put myself through. 😄 Edited 17 hours ago by WildByDesign
argumentum Posted 16 hours ago Posted 16 hours ago 46 minutes ago, WildByDesign said: 1) I don't have the skills with other programming languages to create a DLL with full hook procedure code. 2) Plus I really wanted to go 100% AutoIt on this adventure. Ok, thinking time. You wanna do it all in AutoIt (2) because you could really use knowing more (1). You would not think of taking php.exe and expect to DLL call a function from index.php called DllMain(). Or the same with python.exe of project.py calling DllMain(). Do read what Mav Leving was doing with his C code, because C and AutoIt's scripts are 2 very different animals. ( hasherezade was using his idea ) Because the difference between "Autoit.exe script.au3" and Script.exe, is not much. Before ( 3.3.6.1 ) the script was appended to the executable, now is a resource in the executable, but always a loaded script for the executable. Maybe read up on C# and you'll find ways to use AutoIt with that. You can compile C# on the fly too ( if memory serves ). Also @Trong posted a nice guide on DLL stuff. 17 minutes ago, WildByDesign said: This the wild type of adventure that I put myself through. 😄 Yes it is WildByDesign 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now