WildByDesign Posted April 7 Posted April 7 (edited) This is something that I need for the GUIDarkTheme UDF project, but would be beneficial in general for anyone using dark mode in their GUI. For Windows 11 users, there is no problem because you can use _WinAPI_SetWindowTheme($h_UpDown, "DarkMode_Explorer") on the UpDown control handle. Problem: This does not work for Windows 10 users because DarkMode_Explorer pulls the resources from DarkMode_Explorer::Spin in the msstyles theme file and those specific resources do not exist for Windows 10 users. We would have to do subclassing to achieve dark mode on UpDown controls for Windows 10 users and this is where I need some help. If you have some time and have to skills to do this, I would really appreciate it. Please and thank you. There are some good examples for subclassing UpDown controls in C++ in the win32-darkmodelib library: Link: win32-darkmodelib/src/DmlibSubclassControl.cpp at main · ozone10/win32-darkmodelib Link: win32-darkmodelib/src/Darkmodelib.cpp at main · ozone10/win32-darkmodelib I've made an example to get things started: expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPITheme.au3> #include <WinAPISysWin.au3> #include <WindowsNotifsConstants.au3> #include <WinAPIGdiDC.au3> #include <APIGdiConstants.au3> Example() Func Example() GUICreate("Dark Mode UpDown", 400, 300) GUISetBkColor(0x323232) GUISetFont(14) ; Apply dark mode to GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") Local $idInput = GUICtrlCreateInput("2", 100, 100, 50, 20, -1, $WS_EX_STATICEDGE) Local $h_Input = GUICtrlGetHandle($idInput) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $h_UpDown = GUICtrlGetHandle($idUpDown) ; Resize input control GUICtrlSetPos($idInput, 150, 100, 100, 40) If @OSBuild >= 22000 Then ; Apply dark mode to UpDown (spinner) control on Windows 11 _WinAPI_SetWindowTheme($h_UpDown, "DarkMode_Explorer") ; pulls resources from DarkMode_Explorer::Spin in theme file ; Problem: Windows 10 does not have DarkMode_Explorer::Spin EndIf If @OSBuild > 10240 And @OSBuild <= 19045 Then ; Apply dark mode to UpDown (spinner) control on Windows 10 ; TODO: This would have to be achieved with subclassing ; C++ subclassing examples: ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/DmlibSubclassControl.cpp#L1020 ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/Darkmodelib.cpp#L1168 EndIf GUISetState(@SW_SHOW) Local $idMsg ; Loop until the user exits. While 1 $idMsg = GUIGetMsg() Switch $idMsg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hDC = $wParam Local $hCtrl = $lParam _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hBrush = _WinAPI_CreateSolidBrush(0x202020) _WinAPI_SetBkColor($hDC, 0x202020) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Edited April 7 by WildByDesign
Nine Posted April 9 Posted April 9 Here something to get you started : expandcollapse popup; From Nine #include <GUIConstants.au3> #include <WinAPI.au3> #include <WindowsNotifsConstants.au3> Global Const $UDM_GETBUDDY = 1130 Example() Func Example() GUICreate("UpDown") Local $idInput = GUICtrlCreateInput("0", 10, 10, 50, 20) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle($idUpDown) Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) DllCallbackFree($hDll) EndFunc ;==>Example Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hBrush = _WinAPI_CreateSolidBrush(0x808080) _WinAPI_SetBkMode($hDC, $TRANSPARENT) _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRect) _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(8, 6) _WinAPI_SelectObject($hDC, $hFont) $tRect.top += 2 _WinAPI_DrawText($hDC, "▲" & @LF & "▼", $tRect, $DT_CENTER) _WinAPI_DeleteObject($hBrush) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) Return Case $WM_LBUTTONUP, $WM_MOUSEMOVE _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub That should work with any OS... WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 9 Author Posted April 9 (edited) 9 hours ago, Nine said: Here something to get you started : Thank you so much. I've been playing around with this example off and on throughout the day trying various things. I appreciate that you took time to help me out with this. Your example works great, as always. I tried a few times through the day to extend this in various ways but failed spectacularly on all attempts. I tried, for example: Split the rectangle into two separate rectangles based on the height of the control (since height could vary) Adding indication of hovering the cursor over the rectangle(s) to show different color Usually I am pretty good at figuring things out, but UpDown controls are peculiar. I like your idea of using fonts to draw the arrows. I was hoping to split the rectangle into two rectangles (buttons) and draw the arrow in each, horizontally and vertically centered, since from the perspective of the UDF these UpDown controls could vary in height. I was really hoping that I could make some progress on my own before reaching out for more help. Sorry about that. Edited April 9 by WildByDesign
Nine Posted April 10 Posted April 10 Here a tad more elaborated : expandcollapse popup; From Nine #include <GUIConstants.au3> #include <WinAPI.au3> #include <WindowsNotifsConstants.au3> Global Const $UDM_GETBUDDY = 1130 Example() Func Example() GUICreate("UpDown") Local $idInput = GUICtrlCreateInput("0", 10, 10, 60, 25) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle($idUpDown) Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) DllCallbackFree($hDll) EndFunc ;==>Example Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x808080) _WinAPI_SetBkMode($hDC, $TRANSPARENT) _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRect) _WinAPI_DrawLine($hDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) $hBrush = _WinAPI_CreateSolidBrush(0xA0A0A0) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then $tRectTmp.top = Int($tRect.bottom / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(Int($tRect.bottom / 3), Int($tRect.right / 3)) _WinAPI_SelectObject($hDC, $hFont) $tRect.top += 2 _WinAPI_DrawText($hDC, "▲", $tRect, $DT_CENTER) $tRect.top += Int($tRect.bottom / 2) _WinAPI_DrawText($hDC, "▼", $tRect, $DT_CENTER) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) Return Case $WM_LBUTTONUP _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 10 Author Posted April 10 (edited) 1 hour ago, Nine said: Here a tad more elaborated : This is fantastic. Works very well and definitely something that I can work with and hopefully expand some more. Thank you. Here is what I have done so far: Made everything more dark mode Moved the UpDown control to the right by 2 pixels to prevent clipping by Edit control (Windows issue with UpDown controls by default) Question: Do you know if anything can be done about the flickering that sometimes (not always) happens when hovering over the UpDown buttons? My current testing example: expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPITheme.au3> #include <WinAPISysWin.au3> #include <WindowsNotifsConstants.au3> #include <WinAPIGdiDC.au3> #include <APIGdiConstants.au3> #include <GUIConstants.au3> #include <WinAPI.au3> #include <Array.au3> Global Const $UDM_GETBUDDY = 1130 Example() Func Example() Local $hGUI = GUICreate("Dark Mode UpDown", 400, 300) GUISetBkColor(0x323232) GUISetFont(14) ; Apply dark mode to Edit box GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") Local $idInput = GUICtrlCreateInput("2", 100, 100, 50, 20, -1, $WS_EX_STATICEDGE) Local $h_Input = GUICtrlGetHandle($idInput) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle($idUpDown) ; Resize input control GUICtrlSetPos($idInput, 150, 100, 100, 40) ; Move UpDown control by 2 pixels to prevent clipping Local $aPos = ControlGetPos($hGUI, "", "[CLASS:msctls_updown32]") GUICtrlSetPos($idUpDown, $aPos[0] + 2, $aPos[1]) If @OSBuild >= 22000 Then ; Apply dark mode to UpDown (spinner) control on Windows 11 ;_WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer") ; pulls resources from DarkMode_Explorer::Spin in theme file ; Problem: Windows 10 does not have DarkMode_Explorer::Spin EndIf If @OSBuild > 10240 And @OSBuild <= 19045 Then ; Apply dark mode to UpDown (spinner) control on Windows 10 ; TODO: This would have to be achieved with subclassing ; C++ subclassing examples: ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/DmlibSubclassControl.cpp#L1020 ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/Darkmodelib.cpp#L1168 Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) EndIf Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) GUISetState(@SW_SHOW) Local $idMsg ; Loop until the user exits. While 1 $idMsg = GUIGetMsg() Switch $idMsg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) DllCallbackFree($hDll) EndFunc ;==>Example Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hDC = $wParam Local $hCtrl = $lParam _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hBrush = _WinAPI_CreateSolidBrush(0x202020) _WinAPI_SetBkColor($hDC, 0x202020) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x808080) _WinAPI_SetBkMode($hDC, $TRANSPARENT) _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRect) _WinAPI_DrawLine($hDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) $hBrush = _WinAPI_CreateSolidBrush(0xA0A0A0) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then $tRectTmp.top = Int($tRect.bottom / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(Int($tRect.bottom / 3), Int($tRect.right / 3)) _WinAPI_SelectObject($hDC, $hFont) $tRect.top += 2 _WinAPI_DrawText($hDC, "▲", $tRect, $DT_CENTER) $tRect.top += Int($tRect.bottom / 2) _WinAPI_DrawText($hDC, "▼", $tRect, $DT_CENTER) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) Return Case $WM_LBUTTONUP _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub Edited April 10 by WildByDesign
Nine Posted April 10 Posted April 10 2 hours ago, WildByDesign said: Do you know if anything can be done about the flickering Yes, just use a memory DC to draw in. See _WinAPI_CreateCompatibleDC. You have used that API previously... WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 10 Author Posted April 10 7 hours ago, Nine said: See _WinAPI_CreateCompatibleDC. You have used that API previously... Yes, it is included in a few of my projects. But unfortunately, it is copy and pasted and I don't truly understand it. So I spent a few hours today trying to learn and understand it. I attempted to follow 4 or 5 different examples since they were all slightly different. All of my attempts failed to show anything on the buttons at all. I really wanted to at least be able to contribute something to this. After failing with the double-buffering stuff, I tried to trigger a button color change on click so that I could at least come back with something. I was able to get the color change working on click. But from all of my attempts, the color would stay until I would move the cursor a bit. I even tried messing with timers and much more. No luck. You've got something really special started with this. It works very well and looks even better than what Microsoft provides with their own UpDown control. However, my skills and lack of understanding of subclassing is not able to provide anything to build onto what you have started. I apologize. I put in a lot of time and tried my best.
Solution Nine Posted April 11 Solution Posted April 11 (edited) I included your control move of the up-down so it looks better when interacting with the input box. expandcollapse popup; From Nine #include <GUIConstants.au3> #include <WinAPI.au3> #include <WindowsNotifsConstants.au3> Global Const $UDM_GETBUDDY = 1130 Example() Func Example() GUICreate("UpDown") Local $idInput = GUICtrlCreateInput("0", 10, 10, 60, 25) GUICtrlSetFont(-1, 12) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle(-1) GUICtrlSetPos(-1, ControlGetPos("", "", $hUpDown)[0] + 2) Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) DllCallbackFree($hDll) EndFunc ;==>Example Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $tRect.right, $tRect.bottom) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x808080) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRect) _WinAPI_DrawLine($hMemDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) $hBrush = _WinAPI_CreateSolidBrush(0xA0A0A0) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then $tRectTmp.top = Int($tRect.bottom / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hMemDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(Int($tRect.bottom / 3), Int($tRect.right / 3)) _WinAPI_SelectObject($hMemDC, $hFont) $tRect.top += 2 _WinAPI_DrawText($hMemDC, "▲", $tRect, $DT_CENTER) $tRect.top += Int($tRect.bottom / 2) _WinAPI_DrawText($hMemDC, "▼", $tRect, $DT_CENTER) _WinAPI_BitBlt($hDC, 0, 0, $tRect.right, $tRect.bottom, $hMemDC, 0, 0, $SRCCOPY) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) Return Case $WM_LBUTTONUP _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub Edited April 11 by Nine WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 11 Author Posted April 11 11 minutes ago, Nine said: I included your control move of the up-down so it looks better when interacting with the input box. Thank you for the update, I appreciate it. The double-buffering makes a significant difference. I can immediately see where I went wrong with it. I had everything correct, except that I had my _WinAPI_BitBlt() function in the wrong place.
Nine Posted April 11 Posted April 11 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 11 Author Posted April 11 I'm finally starting to understand. I've got the "on click" button colour change now. All of the 3-4 methods that I did likely would have worked, but I was missing one thing: Case $WM_LBUTTONDOWN ; ... _WinAPI_InvalidateRect($hWnd, 0, False) Return I was reading up on how to trigger WM_PAINT. Then it was like "Uh Huh!" In the GUIDarkTheme UDF, I will have to check any UpDown controls for UDS_HORZ style and do a horizontal variant of the buttons at some point. But one step at a time. Question: The two rectangle buttons show a black line around them. Is it possible to change that outline colour? For example, maybe a plain white button outline colour. I am not quite sure what would look best in the end, but I am curious about that. Anyway, here is my current dark mode interpretation of @Nine's script with the addition of the "on click" button colour change: expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPITheme.au3> #include <WinAPISysWin.au3> #include <WindowsNotifsConstants.au3> #include <WinAPIGdiDC.au3> #include <APIGdiConstants.au3> #include <GUIConstants.au3> #include <WinAPI.au3> #include <Array.au3> #include <Misc.au3> Global Const $UDM_GETBUDDY = 1130 Global $hGUI Global $hUser32Dll = DllOpen("user32.dll") Example() Func Example() $hGUI = GUICreate("Dark Mode UpDown", 400, 300) GUISetBkColor(0x323232) GUISetFont(14) ; Apply dark mode to Edit box GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") Local $idInput = GUICtrlCreateInput("2", 100, 100, 50, 20, -1, $WS_EX_STATICEDGE) Local $h_Input = GUICtrlGetHandle($idInput) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle($idUpDown) ; Resize input control GUICtrlSetPos($idInput, 150, 100, 100, 40) ; Move UpDown control by 2 pixels to prevent clipping GUICtrlSetPos($idUpDown, ControlGetPos("", "", $hUpDown)[0] + 2) If @OSBuild >= 22000 Then ; Apply dark mode to UpDown (spinner) control on Windows 11 ;_WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer") ; pulls resources from DarkMode_Explorer::Spin in theme file ; Problem: Windows 10 does not have DarkMode_Explorer::Spin EndIf If @OSBuild > 10240 And @OSBuild <= 19045 Then ; Apply dark mode to UpDown (spinner) control on Windows 10 ; TODO: This would have to be achieved with subclassing ; C++ subclassing examples: ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/DmlibSubclassControl.cpp#L1020 ; https://github.com/ozone10/win32-darkmodelib/blob/main/src/Darkmodelib.cpp#L1168 Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) EndIf Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) GUISetState(@SW_SHOW) Local $idMsg ; Loop until the user exits. While 1 $idMsg = GUIGetMsg() Switch $idMsg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) DllCallbackFree($hDll) DllClose($hUser32Dll) EndFunc ;==>Example Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hDC = $wParam Local $hCtrl = $lParam _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hBrush = _WinAPI_CreateSolidBrush(0x202020) _WinAPI_SetBkColor($hDC, 0x202020) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $tRect.right, $tRect.bottom) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x242424) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRect) _WinAPI_DrawLine($hMemDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) $hBrush = _WinAPI_CreateSolidBrush(_IsPressed($VK_LBUTTON, $hUser32Dll) ? 0x404040 : 0x808080) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then $tRectTmp.top = Int($tRect.bottom / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hMemDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(Int($tRect.bottom / 3), Int($tRect.right / 3)) _WinAPI_SelectObject($hMemDC, $hFont) $tRect.top += 2 _WinAPI_DrawText($hMemDC, "▲", $tRect, $DT_CENTER) $tRect.top += Int($tRect.bottom / 2) _WinAPI_DrawText($hMemDC, "▼", $tRect, $DT_CENTER) _WinAPI_BitBlt($hDC, 0, 0, $tRect.right, $tRect.bottom, $hMemDC, 0, 0, $SRCCOPY) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_LBUTTONUP _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub
WildByDesign Posted April 11 Author Posted April 11 @Nine I have made some really nice progress this morning. Changes: Added example for UDS_HORZ in addition to the default UpDown control Updated subclass to detect UDS_HORZ and handle UDS_HORZ I made all of the necessary adjustments to support UDS_HORZ except for the DrawText part. Could you please help with the DrawText code for UDS_HORZ? This has also made me realize that we might need to know what type of class the buddy control is to help determine what should be done when clicking on the up/down buttons. I'm not even sure what we should do when it comes to tab controls and other control types. For now, I have added the following for whenever a button is clicked: Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) ; ... Local $iBuddyClass = _WinAPI_GetClassName($hBuddy) ConsoleWrite("What control class type is buddy? " & $iBuddyClass & @CRLF) And here is the updated script that has detection and handling of UDS_HORZ: expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPITheme.au3> #include <WinAPISysWin.au3> #include <WindowsNotifsConstants.au3> #include <WinAPIGdiDC.au3> #include <APIGdiConstants.au3> #include <GUIConstants.au3> #include <WinAPI.au3> #include <Array.au3> #include <Misc.au3> Global Const $UDM_GETBUDDY = 1130 Global $hGUI Global $hUser32Dll = DllOpen("user32.dll") Example() Func Example() $hGUI = GUICreate("Dark Mode UpDown", 400, 300) GUISetBkColor(0x323232) GUISetFont(14) ; Apply dark mode to Edit box GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") Local $idInput = GUICtrlCreateInput("2", 150, 80, 100, 40, -1, $WS_EX_STATICEDGE) Local $h_Input = GUICtrlGetHandle($idInput) Local $idUpDown = GUICtrlCreateUpdown($idInput) Local $hUpDown = GUICtrlGetHandle($idUpDown) Local $idInput2 = GUICtrlCreateInput("2", 150, 140, 100, 40, -1, $WS_EX_STATICEDGE) Local $h_Input2 = GUICtrlGetHandle($idInput2) Local $idUpDown2 = GUICtrlCreateUpdown($idInput2, $UDS_HORZ) ; UDS_HORZ testing Local $hUpDown2 = GUICtrlGetHandle($idUpDown2) ; Move UpDown control by 2 pixels to prevent clipping GUICtrlSetPos($idUpDown, ControlGetPos("", "", $hUpDown)[0] + 2) GUICtrlSetPos($idUpDown2, ControlGetPos("", "", $hUpDown2)[0] + 2) Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) _WinAPI_SetWindowSubclass($hUpDown2, DllCallbackGetPtr($hDll), $idUpDown2) GUISetState(@SW_SHOW) Local $idMsg ; Loop until the user exits. While 1 $idMsg = GUIGetMsg() Switch $idMsg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) _WinAPI_RemoveWindowSubclass($hUpDown2, DllCallbackGetPtr($hDll), $idUpDown2) DllCallbackFree($hDll) DllClose($hUser32Dll) EndFunc ;==>Example Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hDC = $wParam Local $hCtrl = $lParam _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hBrush = _WinAPI_CreateSolidBrush(0x202020) _WinAPI_SetBkColor($hDC, 0x202020) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Local $bHorz = BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $UDS_HORZ) Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $tRect.right, $tRect.bottom) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x242424) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRect) If $bHorz Then _WinAPI_DrawLine($hMemDC, Int($tRect.right / 2), 0, Int($tRect.right / 2), $tRect.bottom) Else _WinAPI_DrawLine($hMemDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) EndIf _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then If $bHorz Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).x / _WinAPI_GetClientRect($hWnd).right, 0) Else Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) EndIf $hBrush = _WinAPI_CreateSolidBrush(_IsPressed($VK_LBUTTON, $hUser32Dll) ? 0x404040 : 0x808080) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then If $bHorz Then $tRectTmp.left = Int($tRect.right / 2) Else $tRectTmp.top = Int($tRect.bottom / 2) EndIf Else If $bHorz Then $tRectTmp.right = Int($tRect.right / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf EndIf _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hMemDC, 0xFFFFFF) Local $hFont = _WinAPI_CreateFont(Int($tRect.bottom / 3), Int($tRect.right / 3)) _WinAPI_SelectObject($hMemDC, $hFont) $tRect.top += 2 If Not $bHorz Then _WinAPI_DrawText($hMemDC, "▲", $tRect, $DT_CENTER) $tRect.top += Int($tRect.bottom / 2) If Not $bHorz Then _WinAPI_DrawText($hMemDC, "▼", $tRect, $DT_CENTER) _WinAPI_BitBlt($hDC, 0, 0, $tRect.right, $tRect.bottom, $hMemDC, 0, 0, $SRCCOPY) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iBuddyClass = _WinAPI_GetClassName($hBuddy) ConsoleWrite("What control class type is buddy? " & $iBuddyClass & @CRLF) If $bHorz Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).x / _WinAPI_GetClientRect($hWnd).right, 0) Else Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) EndIf ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_LBUTTONUP _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub
Nine Posted April 11 Posted April 11 4 hours ago, WildByDesign said: Is it possible to change that outline colour? Just set the pen color you want, and select the object for the hMemDC (as per MSDN) WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
Nine Posted April 11 Posted April 11 3 hours ago, WildByDesign said: Could you please help with the DrawText code for UDS_HORZ? _WinAPI_SetTextColor($hMemDC, 0xFFFFFF) $tRectTmp = _WinAPI_GetClientRect($hWnd) Local $iFW = Int($tRect.right / ($bHorz ? 5 : 3)), $iFH = $iFW + ($bHorz ? 14 : 2) Local $hFont = _WinAPI_CreateFont($iFH, $iFW) _WinAPI_SelectObject($hMemDC, $hFont) If $bHorz Then $tRectTmp.top = Int(($tRect.bottom - $iFH) / 2) $tRectTmp.right = $tRect.right / 2 _WinAPI_DrawText($hMemDC, "◄", $tRectTmp, $DT_CENTER) $tRectTmp.left = Int($tRect.right/2) $tRectTmp.right = $tRect.right _WinAPI_DrawText($hMemDC, "►", $tRectTmp, $DT_CENTER) Else $tRectTmp.top = Int((Round($tRect.bottom / 2) - $iFH) / 2) _WinAPI_DrawText($hMemDC, "▲", $tRectTmp, $DT_CENTER) $tRectTmp.top += Round($tRect.bottom / 2) _WinAPI_DrawText($hMemDC, "▼", $tRectTmp, $DT_CENTER) EndIf Also you would want to change to XOR : Case $WM_LBUTTONDOWN Local $hBuddy = HWnd(_SendMessage($hWnd, $UDM_GETBUDDY)) Local $iBuddyClass = _WinAPI_GetClassName($hBuddy) ConsoleWrite("What control class type is buddy? " & $iBuddyClass & @CRLF) If $bHorz Then Local $iPos = BitXOR(Round(_WinAPI_GetMousePos(True, $hWnd).x / _WinAPI_GetClientRect($hWnd).right, 0), 1) ; <<<<<<<<<<< this line Else Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) EndIf ControlSetText("", "", $hBuddy, ControlGetText("", "", $hBuddy) + ($iPos ? -1 : +1)) _SendMessage($hBuddy, $EM_SETSEL, 0, -1) _WinAPI_InvalidateRect($hWnd, 0, False) Return WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 11 Author Posted April 11 Thank you. The DrawText code works perfectly and looks very nice too. I appreciate your help with this. 4 hours ago, Nine said: Also you would want to change to XOR : Your updated line with BitXOR works great. I must admit, I am not very familiar with BitXOR. I have another line that is similar: If $bHover Then If $bHorz Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).x / _WinAPI_GetClientRect($hWnd).right, 0) Else Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) EndIf Does that similar line under "If $bHorz Then" also need the BitXOR?
WildByDesign Posted April 11 Author Posted April 11 On 4/10/2026 at 9:57 AM, WildByDesign said: Moved the UpDown control to the right by 2 pixels to prevent clipping by Edit control (Windows issue with UpDown controls by default) It looks like I will also have to check for UDS_ALIGNLEFT style and in that case, minus 2 pixels to move the UpDown control.
Nine Posted April 11 Posted April 11 43 minutes ago, WildByDesign said: Does that similar line under "If $bHorz Then" also need the BitXOR? No. It was the meaning of the left and right arrow that differs from the up and down arrow. WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 12 Author Posted April 12 (edited) I have made some more progress. It is very close to being ready to add to GUIDarkTheme UDF. Added tab control to ensure that we can cycle through the tabs Realized that _SendMessage($hWnd, $UDM_GETBUDDY) does not seem to work to get tab control handle Realized that we can just get rid of the cases for $WM_LBUTTONDOWN and $WM_LBUTTONUP The OS seems to handle this exactly as needed for Edit boxes and tab controls First of all, sorry for the blinding contrast with the tab control. I wanted to keep the example small and therefore did not add the dark mode subclassing for the tab control. The only thing holding me back right now from adding it to the UDF is the arrow sizes. You'll notice that the arrow sizes are quite large for the tab control's UpDown. So I decided to look into the theme file (aero.msstyles) to see how Microsoft does it. Also by temporarily disabling the UpDown subclassing to check arrow sizes. So it seems that Microsoft uses the same size arrows, no matter the size of the UpDown buttons. The same size arrows differing by DPI, of course. I am just trying to figure out how to consolidate the arrow sizes to be consistent but when I mess with _WinAPI_CreateFont sizes it also messes with the placement/alignment within the buttons as well, so this part is complicated for me. 20 hours ago, Nine said: Just set the pen color you want, and select the object for the hMemDC (as per MSDN) When I change your: Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) To: Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0xFFFFFF) It still comes up as black lines. This is an area that I am not very familiar with. Anyway, here is the my current testing script with the addition of tab control (also one of the Edit boxes now has $UDS_ALIGNLEFT for testing UpDown): expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPITheme.au3> #include <WinAPISysWin.au3> #include <WindowsNotifsConstants.au3> #include <WinAPIGdiDC.au3> #include <APIGdiConstants.au3> #include <GUIConstants.au3> #include <WinAPI.au3> #include <Misc.au3> Global Const $UDM_GETBUDDY = 1130 Global $hGUI Global $hUser32Dll = DllOpen("user32.dll") Example() Func Example() $hGUI = GUICreate("Dark Mode UpDown", 400, 400) GUISetBkColor(0x323232) GUISetFont(14) ; Apply dark mode to Edit box GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") Local $idInput = GUICtrlCreateInput("2", 150, 80, 100, 40, -1, $WS_EX_STATICEDGE) Local $h_Input = GUICtrlGetHandle($idInput) Local $idUpDown = GUICtrlCreateUpdown($idInput, $UDS_ALIGNLEFT) Local $hUpDown = GUICtrlGetHandle($idUpDown) Local $idInput2 = GUICtrlCreateInput("2", 150, 140, 100, 40, -1, $WS_EX_STATICEDGE) Local $h_Input2 = GUICtrlGetHandle($idInput2) Local $idUpDown2 = GUICtrlCreateUpdown($idInput2, $UDS_HORZ) ; UDS_HORZ testing Local $hUpDown2 = GUICtrlGetHandle($idUpDown2) Local $iBuddyPos ; Move UpDown control by 2 pixels to prevent clipping If BitAND(_WinAPI_GetWindowLong($hUpDown, $GWL_STYLE), $UDS_ALIGNLEFT) Then $iBuddyPos = -2 Else $iBuddyPos = 2 EndIf GUICtrlSetPos($idUpDown, ControlGetPos("", "", $hUpDown)[0] + $iBuddyPos) If BitAND(_WinAPI_GetWindowLong($hUpDown2, $GWL_STYLE), $UDS_ALIGNLEFT) Then $iBuddyPos = -2 Else $iBuddyPos = 2 EndIf GUICtrlSetPos($idUpDown2, ControlGetPos("", "", $hUpDown2)[0] + $iBuddyPos) Local $hDll = DllCallbackRegister(UpDownSub, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) _WinAPI_SetWindowSubclass($hUpDown2, DllCallbackGetPtr($hDll), $idUpDown2) ; tab control test GUISetFont(9) Local $idTab = GUICtrlCreateTab(100, 200, 200, 100) Local $h_Tab = GUICtrlGetHandle($idTab) GUICtrlCreateTabItem("tab0") GUICtrlCreateTabItem("tab1") GUICtrlCreateTabItem("tab2") GUICtrlCreateTabItem("tab3") GUICtrlCreateTabItem("tab4") GUICtrlCreateTabItem("") ; find updown control Local $hUpDown3 = _WinAPI_FindWindowEx($h_Tab, 0, "msctls_updown32", "") _WinAPI_SetWindowSubclass($hUpDown3, DllCallbackGetPtr($hDll), $idTab) GUISetState(@SW_SHOW) Local $idMsg ; Loop until the user exits. While 1 $idMsg = GUIGetMsg() Switch $idMsg Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($hUpDown, DllCallbackGetPtr($hDll), $idUpDown) _WinAPI_RemoveWindowSubclass($hUpDown2, DllCallbackGetPtr($hDll), $idUpDown2) _WinAPI_RemoveWindowSubclass($hUpDown3, DllCallbackGetPtr($hDll), $idTab) DllCallbackFree($hDll) DllClose($hUser32Dll) EndFunc ;==>Example Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hDC = $wParam Local $hCtrl = $lParam _WinAPI_SetTextColor($hDC, 0xFFFFFF) Local $hBrush = _WinAPI_CreateSolidBrush(0x202020) _WinAPI_SetBkColor($hDC, 0x202020) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func UpDownSub($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover Local $bHorz = BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $UDS_HORZ) Switch $iMsg Case $WM_PAINT Local $tPaint, $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tRect = _WinAPI_GetClientRect($hWnd) Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $tRect.right, $tRect.bottom) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0) Local $hBrush = _WinAPI_CreateSolidBrush(0x242424) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRect) If $bHorz Then _WinAPI_DrawLine($hMemDC, Int($tRect.right / 2), 0, Int($tRect.right / 2), $tRect.bottom) Else _WinAPI_DrawLine($hMemDC, 0, Int($tRect.bottom / 2), $tRect.right, Int($tRect.bottom / 2)) EndIf _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) If $bHover Then If $bHorz Then Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).x / _WinAPI_GetClientRect($hWnd).right, 0) Else Local $iPos = Round(_WinAPI_GetMousePos(True, $hWnd).y / _WinAPI_GetClientRect($hWnd).bottom, 0) EndIf $hBrush = _WinAPI_CreateSolidBrush(_IsPressed($VK_LBUTTON, $hUser32Dll) ? 0x404040 : 0x606060) $tRectTmp = _WinAPI_GetClientRect($hWnd) If $iPos Then If $bHorz Then $tRectTmp.left = Int($tRect.right / 2) Else $tRectTmp.top = Int($tRect.bottom / 2) EndIf Else If $bHorz Then $tRectTmp.right = Int($tRect.right / 2) Else $tRectTmp.bottom = Int($tRect.bottom / 2) EndIf EndIf _WinAPI_SelectObject($hMemDC, $hBrush) _WinAPI_Rectangle($hMemDC, $tRectTmp) _WinAPI_DeleteObject($hBrush) EndIf _WinAPI_SetTextColor($hMemDC, 0xFFFFFF) $tRectTmp = _WinAPI_GetClientRect($hWnd) Local $iFW = Int($tRect.right / ($bHorz ? 5 : 3)), $iFH = $iFW + ($bHorz ? 14 : 2) Local $hFont = _WinAPI_CreateFont($iFH, $iFW) _WinAPI_SelectObject($hMemDC, $hFont) If $bHorz Then $tRectTmp.top = Int(($tRect.bottom - $iFH) / 2) $tRectTmp.right = $tRect.right / 2 _WinAPI_DrawText($hMemDC, "◄", $tRectTmp, BitOR($DT_CENTER, $DT_VCENTER, $DT_NOCLIP)) $tRectTmp.left = Int($tRect.right / 2) $tRectTmp.right = $tRect.right _WinAPI_DrawText($hMemDC, "►", $tRectTmp, BitOR($DT_CENTER, $DT_VCENTER, $DT_NOCLIP)) Else $tRectTmp.top = Int((Round($tRect.bottom / 2) - $iFH) / 2) _WinAPI_DrawText($hMemDC, "▲", $tRectTmp, BitOR($DT_CENTER, $DT_VCENTER, $DT_NOCLIP)) $tRectTmp.top += Round($tRect.bottom / 2) _WinAPI_DrawText($hMemDC, "▼", $tRectTmp, BitOR($DT_CENTER, $DT_VCENTER, $DT_NOCLIP)) EndIf _WinAPI_BitBlt($hDC, 0, 0, $tRect.right, $tRect.bottom, $hMemDC, 0, 0, $SRCCOPY) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_DeleteObject($hFont) _WinAPI_EndPaint($hWnd, $tPaint) Case $WM_MOUSEMOVE $bHover = True _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd, 0, False) Return Case $WM_MOUSELEAVE $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) Return EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>UpDownSub Func _WinAPI_FindWindowEx($hParent, $hAfter, $sClass, $sTitle = "") Local $ret = DllCall($hUser32Dll, "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hAfter, "wstr", $sClass, "wstr", $sTitle) If @error Or Not IsArray($ret) Then Return 0 Return $ret[0] EndFunc ;==>_WinAPI_FindWindowEx Edited April 12 by WildByDesign Nine 1
Nine Posted April 12 Posted April 12 43 minutes ago, WildByDesign said: It still comes up as black lines You are missing the select part of my comment. Add the following line after pen creation : _WinAPI_SelectObject($hMemDC, $hPen) Also I see better result in my case when the up-down control is moved only 1 pixel instead of 2 (right and left). ps. Your click color change resolves the issue with the buddy. Good catch. WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted April 12 Author Posted April 12 3 minutes ago, Nine said: You are missing the select part of my comment. Add the following line after pen creation : You're right. Adding that fixed my issue with changing pen colour. I've got a lot to learn with the WinAPI stuff. Thank you. 4 minutes ago, Nine said: Also I see better result in my case when the up-down control is moved only 1 pixel instead of 2 (right and left). Interesting, I appreciate this feedback. This makes me wonder if the number of pixels needed to move depends on DPI. My scaling is 125% and 2 pixels works best for mine. I would then assume that users with even higher scaling may need slightly differing pixel values. I will have to dig into this some more.
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