Komisch...
Ich bin mir auch nicht sicher, dass nicht irgendwelche Benutzereingaben und Programaufrufe die Reihenfolge der Fenster durcheinanderbringen.
Zum Beispiel macht WIN+Tab den Desktop wieder richtig.
Ich habe noch ein "aktives" Beispiel "Fenster mit CountDown" gebastelt.
Code: Alles auswählen
;' File : DrawToDesktopBehindIcons.pb
;' based on C#/C++ Code
;' LINK: https://www.codeproject.com/Articles/856020/Draw-Behind-Desktop-Icons-in-Windows-plus
;'
EnableExplicit
;' Debugging helpers
Macro DQ
"
EndMacro
Macro InspectRect(rcVar)
DQ#rcVar#DQ+" = "+Str(rcVar\left)+", "+Str(rcVar\top)+", "+Str(rcVar\right)+", "+Str(rcVar\bottom)+" "
EndMacro
Macro InspectVar(iVar)
DQ#iVar#DQ+" = 0x"+Hex(iVar)+" ("+Str(iVar)+") "
EndMacro
;' EnumWindows that will be called for each window...
Procedure __EnumWindowsProc(hWnd, *Param.INTEGER) ;' returns the found hWnd as *Param
Protected h, hworker
h = FindWindowEx_(hWnd, 0, @"SHELLDLL_DefView", 0) ;' gets first child
If h :Debug "SHELLDLL_DefView: "+InspectVar(h)
hworker = FindWindowEx_(0, hWnd, @"WorkerW", 0) ;' gets the WorkerW Window after the current one.
If hworker :Debug "WorkerW: "+InspectVar(hworker)
*Param\i = hworker ;' return this by Argument
EndIf
EndIf
ProcedureReturn 1 ; returning <> 0 will continue till all windows are searched
EndProcedure ;()
Procedure.i GetWallpaperWindow() ;' returns handle of WorkerW or zero
Protected hwndWallpaper, hwndProgMan
;' fetch the Progman window
hwndProgMan = FindWindowEx_(0, 0, @"Progman", 0) :Debug " "+InspectVar(hwndProgMan)
;' check - not needed, doesn't hurt
If SendMessageTimeout_(hwndProgMan, #WM_NULL, #Null, #Null, #SMTO_ABORTIFHUNG, 1000, #Null)
Debug "We can still communicate with the window..."
;' Send 0x052C to Progman. This message directs Progman to spawn a
;' WorkerW behind the desktop icons. If it is already there, nothing happens.
;' MSDN: LRESULT SendMessageTimeoutW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult);
;'
;' HINT: SendMessage with 0x52c, 0xD, 0x1 (or 0) allows the Worker window with high resolution ??
;'
If SendMessageTimeout_(hwndProgMan, $052C, #Null, #Null, #SMTO_NORMAL, 1000, #Null) = 0
Debug "Error " + GetLastError_()
;If GetLastError_() <> #error_timeout
; to get extended error information, call GetLastError.
; If GetLastError returns ERROR_TIMEOUT, then the function timed out.
Else
Debug "Look for the wallpaper window, now "
;' We enumerate all Windows, until we find one, that has the SHELLDLL_DefView as a child.
;' If we found that window, we take its next sibling and assign it to workerw.
; HWND wallpaper_hwnd = nullptr;
; EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
hwndWallpaper = 0
EnumWindows_(@__EnumWindowsProc(), @hwndWallpaper) ;' the hwndWallpaper will get the window handle
If hwndWallpaper <> 0
Debug "found "+InspectVar(hwndWallpaper)
EndIf
EndIf
EndIf
;' return the handle you're looking for.
ProcedureReturn hwndWallpaper
EndProcedure ;()
Procedure Test(State=0)
Static hwndWallpaper, hWnd = 0
Protected r, hdc, hBrush, clientRect.RECT
If State = 0 ;' find the Wallpaper
hwndWallpaper = GetWallpaperWindow()
If hwndWallpaper <> 0 :Debug " "+InspectVar(hwndWallpaper)
; hdc = GetDCEx_(hwndWallpaper, 0, $403)
; ; hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_BTNFACE))
; hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_INFOBK))
;
GetClientRect_(hwndWallpaper, @clientRect) :Debug " "+InspectRect(clientRect)
; FillRect_(hdc, @clientRect, hBrush)
; ReleaseDC_(hwndWallpaper, hdc)
r = SetParent_(WindowID(1), hwndWallpaper) :Debug " SetParent return "+r
EndIf
ElseIf State = 1 ;' get away from this
If hwndWallpaper <> 0
r = SetParent_(WindowID(1), 0) :Debug " SetParent return "+r
; r = SendMessage_(hwndWallpaper, #WM_CLOSE, 0, 0) :Debug " WM_CLOSE return code = "+r
GetClientRect_(hwndWallpaper, @clientRect) :Debug " "+InspectRect(clientRect)
; RedrawWindow_(hwndWallpaper, @clientRect, 0, #RDW_INVALIDATE| #RDW_ERASE | #RDW_UPDATENOW)
; SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero);
;
; If SendMessageTimeout_(#HWND_BROADCAST, #WM_SETTINGCHANGE, #Null, #Null, #SMTO_ABORTIFHUNG, 1000, #Null)
; If SendMessageTimeout_(hwndWallpaper, #WM_SETTINGCHANGE, #Null, #Null, #SMTO_ABORTIFHUNG, 1000, #Null)
; Debug "refresh ..."
; EndIf
; hWnd = GetWindow_(hwndWallpaper, #GW_HWNDPREV)
; If hWnd <> 0
; SetWindowPos_(hwndWallpaper, hWnd, 0, 0, 0, 0, #SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOACTIVATE)
; EndIf
;; SystemParametersInfo_(#SPI_SETDESKWALLPAPER, 0, tempPath, #SPIF_UPDATEINIFILE | #SPIF_SENDWININICHANGE);
EndIf
; SHChangeNotify_($8000000, $1000, 0, 0)
EndIf
EndProcedure ;()
Procedure x_Test()
; Protected hWorkW
; Protected hWnd, hdc, hBrush, clientRect.RECT
;
; hWnd = FindWindowEx_(0, 0, @"Progman", 0) :Debug "Progman - hwnd = "+hwnd
;
; ;LRESULT SendMessageTimeoutW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult);
; If SendMessageTimeout_(hWnd, #WM_NULL, #Null, #Null, #SMTO_ABORTIFHUNG, 1000, #Null)
; Debug "We can still communicate with the window..."
;
; If SendMessageTimeout_(hWnd, $052C, #Null, #Null, #SMTO_NORMAL, 1000, #Null) = 0
; Debug "Error " + GetLastError_()
; ;If GetLastError_() <> #error_timeout
; ; to get extended error information, call GetLastError.
; ; If GetLastError returns ERROR_TIMEOUT, then the function timed out.
; Else
; Debug "Look for windows "
; EnumWindows_(@EnumProcedure(), @hWorkW) ; the hWorkW will receive the right window handle in the procedure
; Debug "Compare "+hWorkerW+" == "+hWorkW : If hWorkerW = hWorkW : Debug " +--> yes that works." : EndIf
;
; If hWorkerW <> 0 :Debug "hWorkerW "
; hdc = GetDCEx_(hWorkerW, 0, $403)
; ; hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_BTNFACE))
; hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_INFOBK))
;
; GetClientRect_(hWorkerW, @clientRect) :Debug " "+InspectRect(clientRect)
; FillRect_(hdc, @clientRect, hBrush)
;
; ReleaseDC_(hWorkerW, hdc)
; EndIf
; EndIf
; EndIf
; ; EnumWindows_(@EnumProcedure(), 0) ; the 0 will be passed in Paremeter.l to the procedure
EndProcedure
Procedure MoveSecondWindow()
ResizeWindow(1, WindowX(0), WindowY(0)-WindowHeight(1)-20, #PB_Ignore, #PB_Ignore)
EndProcedure
Procedure Main()
Protected Event, CountDown = 10
If OpenWindow(1, 80, 80, 230, 80, "Example...", #PB_Window_SystemMenu|#PB_Window_BorderLess)
SetWindowLongPtr_(WindowID(1), #GWL_STYLE, GetWindowLongPtr_(WindowID(1), #GWL_STYLE) & ~#WS_CAPTION)
TextGadget(0, 0, 10, 230, 60, "count down", #PB_Text_Center)
SetGadgetFont(0, LoadFont(0, "Arial", 48))
EndIf
If OpenWindow(0, 80, 180, 230, 200, "Example...", #PB_Window_SystemMenu )
ButtonGadget (1, 10, 10, 200, 20, "Find Wallpaper")
ButtonGadget (2, 10, 40, 200, 20, "Reset Countdown")
ButtonGadget (3, 10, 70, 200, 20, " Wallpaper ?")
; Protected hwndMain = GetWindowLongPtr_(WindowID(0), #GWL_HWNDPARENT) :Debug InspectVar(hwndMain)
; Protected hwndForm = GetWindowLongPtr_(WindowID(1), #GWL_HWNDPARENT) :Debug InspectVar(hwndForm)
BindEvent(#PB_Event_MoveWindow, @MoveSecondWindow(), 0)
AddWindowTimer(1, 1, 1000)
Repeat
Event = WaitWindowEvent(20)
Select Event
Case #PB_Event_Timer
If EventTimer() = 1
SetGadgetText(0, Str(CountDown))
CountDown - 1
EndIf
If CountDown < 0
CountDown = 10
; event = #PB_Event_CloseWindow
EndIf
Case #PB_Event_MoveWindow ;:Debug "moving window "
ResizeWindow(1, WindowX(0), WindowY(0)-WindowHeight(1)-20, #PB_Ignore, #PB_Ignore)
; SetWindowPos_(hwndWallpaper, hWnd, 0, 0, 0, 0, #SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOACTIVATE)
Case #PB_Event_Gadget
Select EventGadget()
Case 1 : Test(0) ; find wallpaper
Case 2 : CountDown = 10 ; reset count down
Case 3 : Test(1) ; get rid of it -- TODO not working at this time
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
RemoveWindowTimer(1, 1)
; SHChangeNotify_($8000000, $1000, 0, 0) ;' not figured out what this constants mean
EndIf
EndProcedure
End Main()