WildByDesign Posted 15 hours ago Posted 15 hours ago This is a continuation (in a slightly expanded way) from the original Move window behind desktop icons thread by @Parsix and should be an interesting challenge. This example uses some code put together from @UEZ, @Nine and @argumentum. For those not familiar with the previous thread, it is essentially moving the GUI in front of the wallpaper but behind the desktop icons in a WorkerW window within Progman (Program Manager). The goal of this thread is to see if there is any possible way to (at least momentarily) access controls in that GUI because you generally cannot click on them. Example: desktop widgets, live video wallpapers, etc. The example below can be exited by pressing Escape. It contains a simple Slider control with a label that changes based on the value of the Slider. There is a button, that when pressed, will initiate the drop into the WorkerW window. There is a Tooltip that will show the Parent window class and Child window class of whatever the cursor is over at the time. This may or may not be helpful for figuring out ideas. Anytime you click on the desktop (Progman), it will output a line into the console. It is that part of the code where I placed a comment "; do action here if needed" that would be a potential place to add code if there is something that we can do to access the control(s) based on clicking on the desktop. To be quite honest, I don't know if this is even possible. I don't know if we need to temporarily reverse the _WinAPI_SetParent function (initially GUI to WorkerW, maybe WorkerW back to GUI) although that would bring the entire GUI forward. It would be better if just the Slider control could somehow come forward in some way. Example: expandcollapse popup;Code by UEZ, Nine, argumentum #include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WindowsNotifsConstants.au3> #include <GuiSlider.au3> #include <SliderConstants.au3> #include <WinAPIvkeysConstants.au3> #include <Misc.au3> Opt("GUIOnEventMode", 1) HotKeySet("{Esc}", "_Exit") DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -4) Global $idSlider1, $idLabel1 Global Const $TRBN_THUMBPOSCHANGING = -1502 Global Const $tagTRBTHUMBPOSCHANGING = $tagNMHDR & ";dword Pos;int Reason" Global Const $TBS_NOTIFYBEFOREMOVE = 2048 Global $hParentWnd, $hMainWnd, $hRoot, $hChildWnd, $hMainWnd_Old = -1, $tPoint Global Static $iTimeLast Global $aKeys[1] = [$VK_LBUTTON] Global $hUser32 = DllOpen('user32.dll') Global $aPrimary = GetPrimaryMonitorCoords() If @error Then Exit MsgBox(16, "Error", "Unable to get primary monitor") Global $hProgman = WinGetHandle("[CLASS:Progman]"), $hWorkerW, $i If Not $hProgman Then Exit MsgBox(16, "ERROR", "Couldn't find Progman", 30) _WinAPI_SendMessageTimeout($hProgman, 0x052C, 13, 1, 250, $SMTO_NORMAL) Global $hWorkerW = _WinAPI_FindWindowEx($hProgman, 0, "WorkerW", "") If $hWorkerW = 0 Then Exit MsgBox(16, "ERROR", "Couldn't find WorkerW under Progman", 30) Local $aOrigin = GetDesktopOrigin() Local $iX = $aPrimary[0] - $aOrigin[0] Local $iY = $aPrimary[1] - $aOrigin[1] Global $hGUI = GUICreate("GUI behind Desktop icons", $aPrimary[4], $aPrimary[5], $iX, $iY, $WS_POPUP, $WS_EX_TOOLWINDOW) GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") GUISetBkColor(0x202020) GUISetFont(40) $idSlider1 = GUICtrlCreateSlider(@DesktopWidth / 4, @DesktopHeight / 4, @DesktopWidth / 2, @DesktopHeight / 6, BitOR($TBS_AUTOTICKS, $TBS_NOTIFYBEFOREMOVE)) GUICtrlSetBkColor(-1, 0x202020) GUICtrlSetColor(-1, 0xFFFFFF) GUICtrlSetLimit(-1, 100, 0) GUICtrlSetData($idSlider1, 100) $idLabel1 = GUICtrlCreateLabel("100", @DesktopWidth / 2.1, @DesktopHeight / 3, -1, -1) GUICtrlSetBkColor(-1, 0x202020) GUICtrlSetColor(-1, 0xFFFFFF) GUISetFont(12) GUICtrlCreateButton("Place GUI Behind WorkerW", @DesktopWidth / 2.2, @DesktopHeight / 2, -1, -1) GUICtrlSetOnEvent(-1, "_dropBehind") GUICtrlSendMsg($idSlider1, $WM_CHANGEUISTATE, 65537, 0) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOWNOACTIVATE, $hGUI) While 1 $tPoint = _WinAPI_GetMousePos() $hMainWnd = _WinAPI_WindowFromPoint($tPoint) $hChildWnd = GetRealChild($hMainWnd) $hParentWnd = _WinAPI_GetAncestor(_WinAPI_WindowFromPoint($tPoint), $GA_ROOT) If $hChildWnd And $hMainWnd <> $hChildWnd Then $hMainWnd = $hChildWnd If $hMainWnd <> $hMainWnd_Old Then ToolTip("Parent: " & @TAB & _WinAPI_GetClassName($hParentWnd) & @CRLF & "Child: " & @TAB & _WinAPI_GetClassName($hMainWnd)) ;ConsoleWrite("Parent: " & _WinAPI_GetClassName($hParentWnd) & @CRLF) ;ConsoleWrite("Child: " & _WinAPI_GetClassName($hMainWnd) & @CRLF) ;$hMainWnd_Old = $hMainWnd EndIf Local $iRet = _IsPressed($aKeys, $hUser32, False) Switch $iRet Case 1 ; MouseClick Left $tPoint = _WinAPI_GetMousePos() $hWndCur = _WinAPI_GetAncestor(_WinAPI_WindowFromPoint($tPoint), $GA_ROOT) $sParent = _WinAPI_GetClassName($hWndCur) If $sParent = "Progman" Then $iTime = Round((_WinAPI_GetTickCount64() / 1000)) $iTimeDiff = $iTime - $iTimeLast ; ensure that it doesn't get hit more than once per second (approx.) If $iTime <> $iTimeLast Then ; do action here if needed ; ConsoleWrite("Desktop clicked at: " & HourAmPm(@HOUR & ":" & @MIN & ":" & @SEC) & @CRLF) $iTimeLast = $iTime EndIf EndIf EndSwitch Sleep(200) WEnd GUIDelete($hGUI) Func _dropBehind() _WinAPI_SetParent($hGUI, $hWorkerW) _WinAPI_SetWindowPos($hGUI, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE)) _WinAPI_SetWindowLong($hGUI, $GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong($hGUI, $GWL_EXSTYLE), $WS_EX_LAYERED, $WS_EX_TRANSPARENT)) _WinAPI_SetLayeredWindowAttributes($hGUI, 0, 180, $LWA_ALPHA) EndFunc Func _WinAPI_FindWindowEx($hParent, $hAfter, $sClass, $sTitle = "") Local $ret = DllCall("user32.dll", "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 Func GetPrimaryMonitorCoords() Local $tPoint = DllStructCreate("int x;int y") $tPoint.x = 0 $tPoint.y = 0 Local $hMonitor = _WinAPI_MonitorFromPoint($tPoint, $MONITOR_DEFAULTTOPRIMARY) If Not $hMonitor Then Return SetError(1, 0, 0) Local $tMI = DllStructCreate("dword cbSize;long rcMonitor[4];long rcWork[4];dword dwFlags") DllStructSetData($tMI, "cbSize", DllStructGetSize($tMI)) Local $aCall = DllCall("user32.dll", "bool", "GetMonitorInfoW", "handle", $hMonitor, "ptr", DllStructGetPtr($tMI)) If @error Or Not $aCall[0] Then Return SetError(2, 0, 0) Local $iLeft = $tMI.rcMonitor(1) Local $iTop = $tMI.rcMonitor(2) Local $iRight = $tMI.rcMonitor(3) Local $iBottom = $tMI.rcMonitor(4) Local $iWidth = $iRight - $iLeft Local $iHeight = $iBottom - $iTop Local $a[6] = [$iLeft, $iTop, $iRight, $iBottom, $iWidth, $iHeight] Return $a EndFunc ;==>GetPrimaryMonitorCoords Func GetDesktopOrigin() Local $minX = 0, $minY = 0, $x, $y Local $i = 0, $tDevice, $aRet, $tDevMode, $aED While True $tDevice = DllStructCreate("dword cb; char DeviceName[32]; char DeviceString[128]; dword StateFlags; char DeviceID[128]; char DeviceKey[128]") $tDevice.cb = DllStructGetSize($tDevice) $aRet = DllCall("user32.dll", "bool", "EnumDisplayDevicesA", "ptr", 0, "dword", $i, "ptr", DllStructGetPtr($tDevice), "dword", 0) If @error Or Not $aRet[0] Then ExitLoop If BitAND($tDevice.StateFlags, 1) Then $tDevMode = DllStructCreate( _ "byte dmDeviceName[32]; word dmSpecVersion; word dmDriverVersion; word dmSize; word dmDriverExtra; dword dmFields;" & _ "long dmPositionX; long dmPositionY; dword dmDisplayOrientation; dword dmDisplayFixedOutput;" & _ "short dmColor; short dmDuplex; short dmYResolution; short dmTTOption; short dmCollate; char dmFormName[32];" & _ "ushort dmLogPixels; dword dmBitsPerPel; dword dmPelsWidth; dword dmPelsHeight;" & _ "dword dmDisplayFlags; dword dmDisplayFrequency; dword dmICMMethod; dword dmICMIntent;" & _ "dword dmMediaType; dword dmDitherType; dword dmReserved1; dword dmReserved2; dword dmPanningWidth; dword dmPanningHeight") $tDevMode.dmSize = DllStructGetSize($tDevMode) $aED = DllCall("user32.dll", "bool", "EnumDisplaySettingsA", "str", $tDevice.DeviceName, "dword", -1, "ptr", DllStructGetPtr($tDevMode)) If Not @error And $aED[0] Then $x = $tDevMode.dmPositionX $y = $tDevMode.dmPositionY If $x < $minX Then $minX = $x If $y < $minY Then $minY = $y EndIf EndIf $i += 1 WEnd Local $a[2] = [$minX, $minY] Return $a EndFunc ;==>GetDesktopOrigin Func _Exit() GUIDelete($hGUI) Exit EndFunc Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tChange = DllStructCreate($tagTRBTHUMBPOSCHANGING, $lParam) If $tChange.IDfrom = $idSlider1 And $tChange.Code = $TRBN_THUMBPOSCHANGING Then GUICtrlSetData($idLabel1, GUICtrlRead($idSlider1)) ;If $tChange2.Pos <> $sWatchBlurColorIntensitySlider Then ; _SavedChangesStatus() ;EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY ; #FUNCTION# ==================================================================================================================== ; Name...........: HourAmPm ; Description....: Converts a time in 24-hour format to AM/PM format. ; Syntax.........: HourAmPm( $sDateTime [, $sAmPm = "AM|PM" [, $iTrimRight = 0]] ) ; Parameters.....: $sDateTime - The time (with date or not) string with "HH:" in it. ; $sAmPm - [optional] The AM/PM representation (default is "AM|PM"). ; $iTrimRight - [optional] The number of characters to trim from the right of the result (default is 0). ; $iNoDate - [optional] Whether to omit the date from the output. Defaults to False. ; Return values .: Success: Returns the formatted date and time in AM/PM format. ; Failure: None. ; Author ........: argumentum ; Modified ......: ; Remarks .......: This function takes a 24-hour time string, converts it to AM or PM format, and returns the result with optional trimming. ; Related .......: ; Link ..........: https://www.autoitscript.com/forum/index.php?showtopic=213061 ; Example .......: MsgBox(64, "Converted Time", HourAmPm("12/31/1999 18:59:59")) ; =============================================================================================================================== Func HourAmPm($sDateTime, $sAmPm = Default, $iTrimRight = Default, $iNoDate = Default) Local $aAmPm = StringSplit((StringInStr($sAmPm, "|") ? $sAmPm : "AM|PM"), "|"), $sFormat = $aAmPm[2] Local $iHourPos = StringInStr($sDateTime, ":"), $sHour = StringMid($sDateTime, $iHourPos - 2, 2) Local $sDate = StringLeft($sDateTime, $iHourPos - 3), $sTime = StringTrimLeft($sDateTime, $iHourPos - 1) If $sHour < 12 Then $sFormat = $aAmPm[1] ; https://www.autoitscript.com/forum/index.php?showtopic=213061 $sHour = Mod($sHour, 12) If Not $sHour Then $sHour = 12 Return StringTrimRight((Int($iNoDate) ? "" : $sDate) & StringRight('0' & $sHour, 2) & $sTime, Int($iTrimRight)) & " " & $sFormat EndFunc ;==>HourAmPm Func _WinAPI_RealChildWindowFromPoint($hWnd, $tPoint) Local $aRet = DllCall('user32.dll', 'hwnd', 'RealChildWindowFromPoint', 'hwnd', $hWnd, 'struct', $tPoint) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_RealChildWindowFromPoint Func GetRealChild($hWnd) Local $tPoint, $hRoot = _WinAPI_GetAncestor($hWnd, $GA_ROOT) If $hWnd = $hRoot Then $tPoint = _WinAPI_GetMousePos(True, $hWnd) Return _WinAPI_ChildWindowFromPointEx($hWnd, $tPoint) EndIf Local $hParent = _WinAPI_GetAncestor($hWnd, $GA_PARENT) Local $aChild = _WinAPI_EnumChildWindows($hParent) If @error Then Return 0 Local $hFound For $i = 1 To $aChild[0][0] $hParent = _WinAPI_GetParent($aChild[$i][0]) $tPoint = _WinAPI_GetMousePos(True, $hParent) $hFound = _WinAPI_RealChildWindowFromPoint($hParent, $tPoint) If $hFound = $aChild[$i][0] Then Return $hFound Next Return 0 EndFunc ;==>GetRealChil
argumentum Posted 14 hours ago Posted 14 hours ago 44 minutes ago, WildByDesign said: and @argumentum. me ?. Well thank you, but Global $hWorkerW = _WinAPI_FindWindowEx($hProgman, 0, "WorkerW", "") If $hWorkerW = 0 Then Exit MsgBox(16, "ERROR", "Couldn't find WorkerW under Progman", 30) didn't work for me so I had to Global $hWorkerW = _WinAPI_FindWindowEx($hProgman, 0, "WorkerW", "") If Not $hWorkerW Then ; dah Local $aEnumWindows = _WinAPI_EnumWindows(False) For $n = 1 To UBound($aEnumWindows) - 1 If $aEnumWindows[$n][1] <> "WorkerW" Then ContinueLoop If _WinAPI_GetParent($aEnumWindows[$n][0]) = $hProgman Then $hWorkerW = $aEnumWindows[$n][0] ExitLoop ; but is likely one at the end of the Z-order EndIf Next EndIf If $hWorkerW = 0 Then Exit MsgBox(16, "ERROR", "Couldn't find WorkerW under Progman", 30) to find it. So my only collaboration wasn't included !? 47 minutes ago, WildByDesign said: The goal of this thread is to see if there is any possible way to (at least momentarily) access controls in that GUI because you generally cannot click on them. Not really but you know that. You could use something to be aware of the wheel changing and use that to move the control if, condition are met ( you can come up with something am sure ). Also, after I closed the script, in the monitor that displayed the GUI, the wallpaper had to be reset. It was gone Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
ioa747 Posted 12 hours ago Posted 12 hours ago (edited) The example below can be exited by pressing F1 and then Escape expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> HotKeySet('{F1}', F1) ; <-- Global $idSlider, $idValueLabel, $iSliderValue = 50, $hSliderGUI, $bFlag Global $hGUI, $BkColor = 0x000000 Example() Func Example() Local $hWorkerW = _GetDesktopWorkerW() If @error Then Exit MsgBox(16, @ScriptName, "! Error - Couldn't find WorkerW under Progman", 30) ConsoleWrite("WorkerW = " & $hWorkerW & @CRLF) ; Overlay GUICreate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $hGUI = GUICreate("Overlay", @DesktopWidth, @DesktopHeight, -1, -1, $WS_POPUP, $WS_EX_TOOLWINDOW) GUISetBkColor($BkColor, $hGUI) Local $idLabelTime = GUICtrlCreateLabel("123456790", (@DesktopWidth - 400) / 2, (@DesktopHeight - 100) / 2, 400, 100, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetColor(-1, 0xFFD800) ; text GUICtrlSetFont(-1, 60, 700, 0, "consolas") _WinAPI_SetParent($hGUI, $hWorkerW) _WinAPI_SetWindowLong($hGUI, $GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong($hGUI, $GWL_EXSTYLE), $WS_EX_LAYERED)) _WinAPI_SetLayeredWindowAttributes($hGUI, $BkColor, $iSliderValue, $LWA_ALPHA) GUISetState(@SW_SHOWNOACTIVATE) ; SliderGUI GUICreate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $hSliderGUI = GUICreate("Slider Example", 250, 70, -1, @DesktopHeight * 0.6, $WS_POPUP) $idSlider = GUICtrlCreateSlider(10, 10, 230, 25) GUICtrlSetLimit(-1, 255, 0) GUICtrlSetData(-1, $iSliderValue) $idValueLabel = GUICtrlCreateLabel($iSliderValue, 10, 50, 230, 20, $SS_CENTER) GUISetState(@SW_HIDE, $hSliderGUI) GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL") Local $Tick, $sTime ;********************************** While 1 Switch GUIGetMsg() Case -3 ;$GUI_EVENT_CLOSE ExitLoop EndSwitch If $bFlag Then If Not IsMouseOverWin($hSliderGUI, 10) Then GUISetState(@SW_HIDE, $hSliderGUI) $bFlag = False EndIf EndIf If $Tick <> @SEC Then $sTime = @HOUR & ":" & @MIN & ":" & @SEC GUICtrlSetData($idLabelTime, $sTime) $Tick = @SEC EndIf WEnd ;********************************** EndFunc ;==>Example ;--------------------------------------------------------------------------------------- Func F1() $bFlag = Not $bFlag If $bFlag Then GUISetState(@SW_SHOW, $hSliderGUI) MouseMove(@DesktopWidth / 2, @DesktopHeight * 0.62, 1) EndIf EndFunc ;==>F1 ;--------------------------------------------------------------------------------------- Func IsMouseOverWin($hWnd, $iOffSet = 0) Local $aMPos = MouseGetPos() Local $aWPos = WinGetPos($hWnd) If $aMPos[0] > $aWPos[0] - $iOffSet _ And $aMPos[1] > $aWPos[1] - $iOffSet _ And $aMPos[0] < $aWPos[0] + $aWPos[2] + $iOffSet _ And $aMPos[1] < $aWPos[1] + $aWPos[3] + $iOffSet Then Return True EndIf Return False EndFunc ;==>IsMouseOverWin ;--------------------------------------------------------------------------------------- Func _GetDesktopWorkerW() Local $hProgman = _WinAPI_GetShellWindow() _WinAPI_SendMessageTimeout($hProgman, 0x052C, 0, 0, 3000, $SMTO_NORMAL) ; same as _SendMessage() Local $aEnumWindows = WinList("[CLASS:WorkerW]") For $n = 1 To $aEnumWindows[0][0] Local $hWnd = $aEnumWindows[$n][1] If _WinAPI_GetParent($hWnd) = $hProgman Then Return SetError(0, $hProgman, $hWnd) Next Return SetError(1, $hProgman, 0) EndFunc ;==>_GetDesktopWorkerW ;--------------------------------------------------------------------------------------- Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam Local $hControl = $lParam If $hControl = GUICtrlGetHandle($idSlider) Then $iSliderValue = GUICtrlRead($idSlider) _WinAPI_SetLayeredWindowAttributes($hGUI, $BkColor, $iSliderValue, $LWA_ALPHA) GUICtrlSetData($idValueLabel, $iSliderValue) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_HSCROLL ;--------------------------------------------------------------------------------------- Edited 11 hours ago by ioa747 improvement argumentum 1 I know that I know nothing
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