Reopen Last closed window script (v1 -> v2) Topic is solved
Reopen Last closed window script (v1 -> v2)
Dear Team, I am looking for a script to "simply" reopen the last closed explorer window via hotkey.
Found this v1 script dated Q3/2022 by @teadrinker : viewtopic.php?p=484659#p484659
Has anybody successfully ported this to v2 already? Thanks for sharing!
Found this v1 script dated Q3/2022 by @teadrinker : viewtopic.php?p=484659#p484659
Has anybody successfully ported this to v2 already? Thanks for sharing!
Re: Reopen Last closed window script (v1 -> v2)
Hallo,
only If your Explorer shows full path in Address Bar!
https://www.thewindowsclub.com/make-win ... 0then%20OKEdit: or HSHELL_REDRAW
only If your Explorer shows full path in Address Bar!
https://www.thewindowsclub.com/make-win ... 0then%20OK
Code: Select all
#Requires AutoHotkey v2.0
PreviousExplorerTitle := False
DllCall("RegisterShellHookWindow", "UInt", A_ScriptHwnd)
OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), WinActivated)
q:: {
Global PreviousExplorerTitle
IF !PreviousExplorerTitle
MsgBox "No Previous Explorer"
Else IF WinExist(PreviousExplorerTitle)
WinActivate
Else Run PreviousExplorerTitle
}
WinActivated(wParam, lParam, msg, hWnd)
{
Global PreviousExplorerTitle
; ToolTip Format("0x{:04X}",wParam)
If (wParam = 0x4 OR wParam = 0x8004 OR wParam = 0x6)
; WINDOWACTIVATED or HSHELL_REDRAW
And WinActive("ahk_class CabinetWClass ahk_exe explorer.exe")
PreviousExplorerTitle := WinGetTitle("A")
}
Last edited by Rohwedder on 20 May 2024, 10:19, edited 1 time in total.
- Noitalommi_2
- Posts: 321
- Joined: 16 Aug 2023, 10:58
Re: Reopen Last closed window script (v1 -> v2)
Hi.
I went through teadrinker's v1 script and here is the v2 result.
I haven't tested it for to long but it opens the last closed explorer window as expected.
And I noticed that the Shell_NavigateComplete2 function is not used in the script, so i commented it out.
As it turns out, this is important.
I went through teadrinker's v1 script and here is the v2 result.
I haven't tested it for to long but it opens the last closed explorer window as expected.
As it turns out, this is important.
Code: Select all
#Requires AutoHotkey 2.0
#SingleInstance
ExistingWindows := Map()
CollectExistingWindows()
Hook := ShellHook(ShellProc)
!e:: {
if !ExistingWindows.Has("lastClosed")
MsgBox "No Explorer Window closed since script has been run."
else
OpenShellWindow(ExistingWindows["lastClosed"])
}
CollectExistingWindows() {
for window in ComObject("Shell.Application").Windows {
ExistingWindows[window.hwnd] := {currentPath: window.Document.Folder.Self.Path, window: window}
ComObjConnect(window, "Shell_")
}
}
ShellProc(nCode, wParam, *) {
static HSHELL_WINDOWCREATED := 1, HSHELL_WINDOWDESTROYED := 2
if (nCode = HSHELL_WINDOWCREATED) {
winClass := WinGetClass("ahk_id" wParam)
if (winClass != "CabinetWClass")
return
for window in ComObject("Shell.Application").Windows {
if (wParam = window.hwnd) {
ExistingWindows[window.hwnd] := {currentPath: window.Document.Folder.Self.Path, window: window}
ComObjConnect(window, "Shell_")
break
}
}
}
if (nCode = HSHELL_WINDOWDESTROYED && ExistingWindows.Has(wParam)) {
ComObjConnect(ExistingWindows[wParam].window)
ExistingWindows["lastClosed"] := ExistingWindows.Delete(wParam).currentPath
}
}
OpenShellWindow(folderPath) {
for window in ComObject("Shell.Application").Windows {
if (window.Document.Folder.Self.Path = folderPath && found := window.hwnd)
break
}
if found ?? 0
WinActivate "ahk_id" . found
else
Run folderPath
}
Shell_NavigateComplete2(Window, &URL, *) {
ExistingWindows[Window.Hwnd].CurrentPath := URL
}
class ShellHook {
__New(shellProc) {
DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
OnMessage(this.msg := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), this.shellProc := shellProc)
}
__Delete() {
if IsObject(this.shellProc)
OnMessage(this.msg, this.shellProc, 0)
else
OnMessage(this.msg, "")
DllCall("DeregisterShellHookWindow", "Ptr", A_ScriptHwnd)
}
}
Last edited by Noitalommi_2 on 21 May 2024, 16:19, edited 2 times in total.
Re: Reopen Last closed window script (v1 -> v2) Topic is solved
Shell_NavigateComplete2() is used to update the current path after navigating in an existing explorer window.
My attempt:
My attempt:
Code: Select all
#Requires AutoHotkey v2.0
Shell := ComObject("Shell.Application")
ExistingWindows := Map("LastClosed", "")
CollectExistingWindows()
Hook := ShellHook(ShellHookProc)
!e:: {
If !ExistingWindows["LastClosed"]
MsgBox("No Explorer Window closed since script has been run.")
Else
OpenShellWindow(ExistingWindows["LastClosed"])
}
OpenShellWindow(FolderPath) {
MsgBox(FolderPath)
Local Hwnd := 0
For Window In Shell.Windows {
If (Window.Document.Folder.Self.Path = FolderPath) && (Hwnd := Window.Hwnd)
Break
}
If Hwnd
WinActivate(Hwnd)
Else
Run((SubStr(FolderPath, 1, 3) = "::{" ? "Shell:" : "") . FolderPath)
}
CollectExistingWindows() {
For Window in Shell.Windows {
ExistingWindows[Window.Hwnd] := {CurrentPath: Window.Document.Folder.Self.Path, Window: Window}
ComObjConnect(Window, "Shell_")
}
}
ShellHookProc(nCode, wParam, *) {
Static HSHELL_WINDOWCREATED := 1, HSHELL_WINDOWDESTROYED := 2
Switch nCode {
Case HSHELL_WINDOWCREATED:
If (WinGetClass(wParam) != "CabinetWClass")
Return
For Window In Shell.Windows {
If (wParam = Window.Hwnd) {
ExistingWindows[Window.Hwnd] := {CurrentPath: Window.Document.Folder.Self.Path, Window: Window}
ComObjConnect(Window, "Shell_")
Break
}
}
Case HSHELL_WINDOWDESTROYED:
If ExistingWindows.Has(wParam) {
ComObjConnect(ExistingWindows[wParam].Window)
ExistingWindows["LastClosed"] := ExistingWindows.Delete(wParam).CurrentPath
}
}
}
Shell_NavigateComplete2(Window, &URL, *) {
ExistingWindows[Window.Hwnd].CurrentPath := URL
}
Class ShellHook {
Static Msg := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK", "UInt")
__New(ShellProc) {
DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
This.ShellProc := ShellProc
OnMessage(ShellHook.Msg, This.ShellProc)
}
; ---------------------------------------------------------------------------
__Delete() {
If IsObject(This.ShellProc)
OnMessage(ShellHook.Msg, This.ShellProc, 0)
DllCall("DeregisterShellHookWindow", "Ptr", A_ScriptHwnd)
}
}
- Noitalommi_2
- Posts: 321
- Joined: 16 Aug 2023, 10:58
Re: Reopen Last closed window script (v1 -> v2)
Code: Select all
ComObjConnect(Window, "Shell_")
Re: Reopen Last closed window script (v1 -> v2)
Thanks @just me - confirmed working! Brilliant.
- Noitalommi_2
- Posts: 321
- Joined: 16 Aug 2023, 10:58
Re: Reopen Last closed window script (v1 -> v2)
Ah, ok. I thought this was a leftover without a caller, so i commented it out. But somehow the script throws no error and works regardless? Anyway, there would probably an error at some point.just me wrote: ↑20 May 2024, 12:18It's called for NavigateComplete2 events for connected shell windows (https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa768285(v=vs.85)).Code: Select all
ComObjConnect(Window, "Shell_")
-
- Posts: 4411
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Reopen Last closed window script (v1 -> v2)
If you run your variant, open any folder with other folders inside it, and in the same window go to another folder, then close that window, then try to open the last closed one by hotkey - you will see what the problem is.Noitalommi_2 wrote: ↑But somehow the script throws no error and works regardless?
I'd also wrap all of this into a class, since we have an object-oriented approach now:
Code: Select all
#Requires AutoHotkey v2
!e:: {
if !LastClosedExplorerWindow.OpenLastClosed() {
MsgBox 'No explorer window is closed after running the script'
}
}
class LastClosedExplorerWindow
{
static __New() {
this.existingWindows := Map()
this.EnumShellWindows(wnd => this.AddWindow(wnd))
this.hook := ShellHook(ObjBindMethod(this, 'ShellProc'))
}
static OpenLastClosed() {
if !this.existingWindows.Has('lastClosed') {
return false
}
folderPath := this.existingWindows['lastClosed']
if !this.EnumShellWindows(wnd => wnd.Document.Folder.Self.Path = folderPath && (WinActivate(wnd), true)) {
Run(folderPath)
}
return true
}
static ShellProc(nCode, wParam, *) {
static HSHELL_WINDOWCREATED := 1, HSHELL_WINDOWDESTROYED := 2
if nCode = HSHELL_WINDOWCREATED && WinGetClass(wParam) = 'CabinetWClass' {
this.EnumShellWindows(wnd => wParam = wnd.hwnd && (this.AddWindow(wnd), true))
}
if nCode = HSHELL_WINDOWDESTROYED && this.existingWindows.Has(wParam) {
ComObjConnect(this.existingWindows[wParam]['window'])
this.existingWindows['lastClosed'] := this.existingWindows.Delete(wParam)['currentPath']
}
}
static AddWindow(window) {
this.existingWindows[window.hwnd] := Map('currentPath', window.Document.Folder.Self.Path, 'window', window)
ComObjConnect(window, this)
}
static EnumShellWindows(fn) {
for window in ComObject('Shell.Application').Windows {
res := fn(window)
} until res
return res ?? false
}
static NavigateComplete2(window, &url, *) => this.existingWindows[window.hwnd]['currentPath'] := url
}
class ShellHook
{
__New(shellProc) {
DllCall('RegisterShellHookWindow', 'Ptr', A_ScriptHwnd)
this.msg := DllCall('RegisterWindowMessage', 'Str', 'SHELLHOOK')
OnMessage(this.msg, this.shellProc := shellProc)
}
__Delete() {
OnMessage(this.msg, this.shellProc, 0)
DllCall('DeregisterShellHookWindow', 'Ptr', A_ScriptHwnd)
}
}
Code: Select all
#Requires AutoHotkey v2
!e:: {
if !LastClosedExplorerWindow.OpenLastClosed() {
MsgBox 'No explorer window is closed after running the script'
}
}
class LastClosedExplorerWindow
{
static __New() {
this.existingWindows := Map()
this.EnumShellWindows(wnd => (this.AddWindow(wnd), false))
this.hook := ShellHook(ObjBindMethod(this, 'ShellProc'))
}
static OpenLastClosed() {
if !this.existingWindows.Has('lastClosed') {
return false
}
folderPath := this.existingWindows['lastClosed']
if !this.EnumShellWindows(wnd => wnd.Document.Folder.Self.Path = folderPath && (WinActivate(wnd), true)) {
Run(folderPath)
}
return true
}
static EnumShellWindows(fn) {
for window in ComObject('Shell.Application').Windows {
res := fn(window)
} until res
return res ?? false
}
static AddWindow(window) => this.existingWindows[window.hwnd] := this.ShellWindow(this.existingWindows, window)
static ShellProc(nCode, wParam, *) {
static HSHELL_WINDOWCREATED := 1, HSHELL_WINDOWDESTROYED := 2
if nCode = HSHELL_WINDOWCREATED && WinGetClass(wParam) = 'CabinetWClass' {
this.EnumShellWindows(wnd => wParam = wnd.hwnd && this.AddWindow(wnd))
}
if nCode = HSHELL_WINDOWDESTROYED && this.existingWindows.Has(wParam) {
this.existingWindows.Delete(wParam)
}
}
class ShellWindow
{
__New(list, wnd) {
this.map := list
this.wnd := wnd
this.path := wnd.Document.Folder.Self.Path
ComObjConnect(wnd, this)
ObjRelease(ObjPtr(this))
}
NavigateComplete2(window, &url, *) => this.path := url
__Delete() {
ObjAddRef(ObjPtr(this))
ComObjConnect(this.wnd)
this.map['lastClosed'] := this.path
}
}
}
class ShellHook
{
__New(shellProc) {
DllCall('RegisterShellHookWindow', 'Ptr', A_ScriptHwnd)
this.msg := DllCall('RegisterWindowMessage', 'Str', 'SHELLHOOK')
OnMessage(this.msg, this.shellProc := shellProc)
}
__Delete() {
OnMessage(this.msg, this.shellProc, 0)
DllCall('DeregisterShellHookWindow', 'Ptr', A_ScriptHwnd)
}
}
- Noitalommi_2
- Posts: 321
- Joined: 16 Aug 2023, 10:58
Re: Reopen Last closed window script (v1 -> v2)
Ah ok, it wouldn't open the last closed window but the one before it.teadrinker wrote: ↑20 May 2024, 20:13If you run your variant, open any folder with other folders inside it, and in the same window go to another folder, then close that window, then try to open the last closed one by hotkey - you will see what the problem is.Noitalommi_2 wrote: ↑But somehow the script throws no error and works regardless?