WildByDesign Posted 8 hours ago Posted 8 hours ago In the Files Au3 project, I have implemented IFileOperation to allow copying, deleting, renaming, etc. files and folders on disk. It is all working beautifully right now. The only (important) thing missing is Undo. The great thing about using IFileOperation for all of these file management ops is that the Shell (explorer.exe) keeps track of all of the Undo stack information. For example, if I delete, copy or rename something in Files Au3, I can either open File Explorer and press Ctrl+Z to undo the file op performed in Files Au3 or alternatively I can click on the Desktop and press Ctrl+Z. Since File Explorer itself is not always running (CabinetWClass class), the Desktop most certainly is. So my thought is somehow sending the Ctrl+Z key combo to the Desktop but I don't have much experience with that. Does anyone know how this could be done? I don't know whether the key combo would/should be sent to the Progman class, SysListView32 (of the desktop) or if it just gets sent to explorer.exe in general. I know how to get the handle for those classes but I'm just not sure how or where to send Ctrl+Z. I've never sent any key combinations before in any of my previous projects. Thank you for your time. SOLVE-SMART 1
WildByDesign Posted 5 hours ago Author Posted 5 hours ago I am still stuck on this. I've got the handles for the desktop Progman, SHELLDLL_DefView and SysListView32. Example: #include <WinAPISysWin.au3> Local $hProgman = WinGetHandle("[CLASS:Progman]") ConsoleWrite("Progman hWnd: " & $hProgman & @CRLF) Local $hSHELLDLL_DefView = _WinAPI_FindWindowEx($hProgman, 0, "SHELLDLL_DefView", "") ConsoleWrite("SHELLDLL_DefView hWnd: " & $hSHELLDLL_DefView & @CRLF) Local $aEnumWindows = _WinAPI_EnumWindows(False) For $n = 1 To UBound($aEnumWindows) - 1 If $aEnumWindows[$n][1] <> "SysListView32" Then ContinueLoop If _WinAPI_GetParent($aEnumWindows[$n][0]) = $hSHELLDLL_DefView Then $hSysListView32 = $aEnumWindows[$n][0] ExitLoop EndIf Next ConsoleWrite("Desktop SysListView32 hWnd: " & $hSysListView32 & @CRLF) ;ControlSend($hProgman, "", "[CLASS:SysListView32]", "^z") ControlSend($hSysListView32, "", ControlGetFocus($hSysListView32), "^z") 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
WildByDesign Posted 5 hours ago Author Posted 5 hours ago It looks like what I have does work if the desktop is in focus. But I was hoping to avoid having to switch windows. I even tried using _WinAPI_SetFocus() but it wasn't enough. It looks like I'm going to have to find a better way to do this from what I can tell.
WildByDesign Posted 4 hours ago Author Posted 4 hours ago Here we go. This will undo any Copy, Rename, Delete, etc. whether it is from Files Au3, File Explorer, etc. We do lose focus though but that can easily be brought back. #include <WinAPISysWin.au3> Local $hProgman = WinGetHandle("[CLASS:Progman]") ConsoleWrite("Progman hWnd: " & $hProgman & @CRLF) Local $hSHELLDLL_DefView = _WinAPI_FindWindowEx($hProgman, 0, "SHELLDLL_DefView", "") ConsoleWrite("SHELLDLL_DefView hWnd: " & $hSHELLDLL_DefView & @CRLF) Local $aEnumWindows = _WinAPI_EnumWindows(False) For $n = 1 To UBound($aEnumWindows) - 1 If $aEnumWindows[$n][1] <> "SysListView32" Then ContinueLoop If _WinAPI_GetParent($aEnumWindows[$n][0]) = $hSHELLDLL_DefView Then $hSysListView32 = $aEnumWindows[$n][0] ExitLoop EndIf Next ConsoleWrite("Desktop SysListView32 hWnd: " & $hSysListView32 & @CRLF) _WinAPI_SetForegroundWindow($hSysListView32) _WinAPI_SetFocus($hSysListView32) ControlSend($hSHELLDLL_DefView, "", "[CLASS:SysListView32]", "^z") ;ControlSend($hSysListView32, "", ControlGetFocus($hSysListView32), "^z") 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
Solution Nine Posted 4 hours ago Solution Posted 4 hours ago FWIW, you could simply : Local $hProgman = WinGetHandle("[CLASS:Progman]") Local $hCurrent = WinGetHandle("[ACTIVE]") WinActivate($hProgman) ControlSend($hProgman, "", "", "^a") WinActivate($hCurrent) “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 4 hours ago Author Posted 4 hours ago 6 minutes ago, Nine said: FWIW, you could simply : That is nice! Thank you. The same goal is achieved but with something like 90% less lines of code. Works perfectly. That also reminds me that I really need to stop overlooking the built-in AutoIt functions.
SOLVE-SMART Posted 4 hours ago Posted 4 hours ago (edited) Sorry but both variants don't work for me (for my system). German Windows 11 (newest). Maybe I did something wrong, but what is did is the following: Open a Windows Explorer window Move a file from one folder into another Test by CTRL+Z and CTRL+Y within the Windows Explorer window - works fine Repeat 1. + 2. Use the scripts - without success I checked the classes for Desktop which is "Progman". I also used the taskbar "Shell_TrayWnd" which should also work (as my understanding is), but no it doesn't. What could cause the issue? I don't believe it depends on Windows 11 language version. I also tested it on a "Windows Server 2019 Datacenter" without success 😒 . Best regards Sven Edited 4 hours ago by SOLVE-SMART ==> AutoIt related: 🔗 Organization AutoIt Community, 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet, 🔗 autoit-webdriver-boilerplate Spoiler 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
WildByDesign Posted 3 hours ago Author Posted 3 hours ago 8 minutes ago, SOLVE-SMART said: Open a Windows Explorer window Move a file from one folder into another Test by CTRL+Z and CTRL+Y within the Windows Explorer window - works fine Repeat 1. + 2. Use the scripts - without success Can you try to move the file into another folder again, then minimize or close File Explorer, click anywhere on the desktop background and press Ctrl+Z? Let me know if that works. It's definitely something that we need to figure out. Although since it uses class names, those are the same on all languages so I'm not exactly sure why it isn't working on yours.
SOLVE-SMART Posted 3 hours ago Posted 3 hours ago Update: I recognized a non-deterministic behavior. I believe it is a timing based issue. Your suggestion worked three times in a raw, then not at all, then sometimes again. I try several Sleep command combination to get to the point where the issue is, but so far only your @WildByDesign variant works sometimes. The code snippets of @Nine doesn't work so far, but I try it on the different Windows System (server system) to confirm my observation. I will let you know when I found the issue. Best regards Sven WildByDesign 1 ==> AutoIt related: 🔗 Organization AutoIt Community, 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet, 🔗 autoit-webdriver-boilerplate Spoiler 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
WildByDesign Posted 3 hours ago Author Posted 3 hours ago (edited) 23 minutes ago, SOLVE-SMART said: I recognized a non-deterministic behavior. I believe it is a timing based issue. Your suggestion worked three times in a raw, then not at all, then sometimes again. I try several Sleep command combination to get to the point where the issue is, but so far only your @WildByDesign variant works sometimes That is very interesting behavior. We definitely need to get this sorted out. Does the script get the handles in the ConsoleWrite 100% of the time? Or does it sometimes fail to return a handle? Edited 3 hours ago by WildByDesign
WildByDesign Posted 3 hours ago Author Posted 3 hours ago Also keep in mind that this can walk the entire Windows undo stack many steps back. For example, if you run the script 12 times, it will go back 12 undo steps.
SOLVE-SMART Posted 3 hours ago Posted 3 hours ago I restarted my computer. Now I don't have any issue anymore 😤 - welcome to Windows 😅 . @Nines approach is still not working, but the WinAPI way works so far without any additional "Sleep" actions. Still strange, that it doesn't worked on the Windows Server system, but this one is within a Citrix VDI (virtual desktop infrastructure). Maybe there was a correlation between my system and the virtualized one, before I restarted my system/computer. No it works on both OS variants. I knwo that I can undo or redo several steps and this also works fine, thankfully now. Best regards Sven ==> AutoIt related: 🔗 Organization AutoIt Community, 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet, 🔗 autoit-webdriver-boilerplate Spoiler 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
WildByDesign Posted 2 hours ago Author Posted 2 hours ago 15 minutes ago, SOLVE-SMART said: @Nines approach is still not working, but the WinAPI way works so far without any additional "Sleep" actions. This could be because on his you have to switch ^a to ^z likely as he was being careful.
Nine Posted 2 hours ago Posted 2 hours ago Strange. I am using ^a (instead of ^z) so I do not have to delete things (or other stuff). You should see all icons get selected. You could try to run it x64. “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
SOLVE-SMART Posted 2 hours ago Posted 2 hours ago I did both. Playing around with ^a (select all) and ^z (undo). Non of them works in the short version (Nine). But I am quite sure, this must have be related to my system, because the AutoIt code is okay and make sence. I usually run x64, so I am still confused a bit. Today I cannot further investigate, but tomorrow I will have a fresh look. Best regards Sven ==> AutoIt related: 🔗 Organization AutoIt Community, 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet, 🔗 autoit-webdriver-boilerplate Spoiler 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
Nine Posted 9 minutes ago Posted 9 minutes ago Try that Sven : Local $hProgman = WinGetHandle("[CLASS:Progman]") Local $hCurrent = WinGetHandle("[ACTIVE]") WinActivate($hProgman) WinWaitActive($hProgman) Send("^a") WinActivate($hCurrent) I know Send is misliked. It is just a cultural bias on the forum. When you know that a specific window is active, Send is a more robust way to transmit characters. Some windows will not accept KB messages, but will accept LLKB. Notice that the last WinActivate will temporarily hide the selection. You can comment it out if you wish to. “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
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