Is there an "open folder" event Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
superpeter
Posts: 115
Joined: 18 Dec 2020, 05:17

Re: Is there an "open folder" event

27 Feb 2021, 14:11

Oh, there's no folder path since I just wanted to check if a particular file was opened. I'd use your solution to check if a folder was opened.
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there an "open folder" event

27 Feb 2021, 14:29

If the folder has been opened this doesn't mean that the file has been launched from that folder. :)
superpeter
Posts: 115
Joined: 18 Dec 2020, 05:17

Re: Is there an "open folder" event

27 Feb 2021, 18:23

You're right!

I think the answer is somewhere here: https://www.autohotkey.com/boards/viewtopic.php?p=120546#p120546

But it's way above my pay grade lol.
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there an "open folder" event

27 Feb 2021, 18:59

If you mean reading the command line of the process, this is an option, but the command line does not have to contain the path to the currently open file.
AutoGiraffe
Posts: 4
Joined: 27 Jul 2021, 14:30

Re: Is there an "open folder" event

27 Jul 2021, 14:40

teadrinker wrote:
27 Sep 2020, 08:22

Code: Select all

#Persistent
global EVENT_OBJECT_SHOW       := 0x8002
     , EVENT_OBJECT_NAMECHANGE := 0x800C

folderPath := "C:\Program Files"
WatchFolders := Func("IsMyFolderOpened").Bind(folderPath)

Hook := new WinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_NAMECHANGE, "HookProc", Object(WatchFolders))

IsMyFolderOpened(folderPath, hWnd) {
   openedFolderPath := GetFolderPath(hWnd)
   if InStr(openedFolderPath, folderPath . "\") || openedFolderPath = folderPath
      MsgBox, Folder %openedFolderPath% was opened
}

HookProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
   static OBJID_WINDOW := 0, CallBack, prevTime := 0
   (!CallBack && CallBack := Object(A_EventInfo))
   if (idObject != OBJID_WINDOW)
      Return
   if !(event = EVENT_OBJECT_SHOW || event = EVENT_OBJECT_NAMECHANGE)
      Return
   WinGetClass, winClass, ahk_id %hwnd%
   if (winClass != "CabinetWClass")
      Return
   if (A_TickCount - prevTime < 300)
      Return
   prevTime := A_TickCount
   CallBack.(hwnd)
}

GetFolderPath(hWnd := "") {
   (!hWnd && hWnd := WinExist("A"))
   WinGetClass, winClass, ahk_id %hWnd%
   if !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
      Return
   
   if (winClass ~= "Progman|WorkerW")
      Return A_Desktop
   
   for window in ComObjCreate("Shell.Application").Windows {
      if (hWnd = window.HWND && dirPath := window.Document.Folder.Self.Path)
         break
   }
   Return dirPath
}

class WinEventHook
{
   __New(eventMin, eventMax, hookProc, eventInfo := 0, idProcess := 0, idThread := 0, dwFlags := 0) {
      this.pCallback := RegisterCallback(hookProc, "F",, eventInfo)
      this.hHook := DllCall("SetWinEventHook", "UInt", eventMin, "UInt", eventMax, "Ptr", 0, "Ptr", this.pCallback
                                             , "UInt", idProcess, "UInt", idThread, "UInt", dwFlags, "Ptr")
   }
   __Delete() {
      DllCall("UnhookWinEvent", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.pCallback, "Ptr")
   }
}
If the Program Files folder or its subfolder is open, a message will appear.
Thank you so much for this. What if one wants to change the monitored folder (while the script is already running)? Or in another case, turning off the folder monitoring completely without exiting the script. Is there a way to do these?
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there an "open folder" event

27 Jul 2021, 19:31

AutoGiraffe wrote: Is there a way to do these?
Of course.

Code: Select all

#Persistent
global EVENT_OBJECT_SHOW       := 0x8002
     , EVENT_OBJECT_NAMECHANGE := 0x800C

WatchFolders := Func("IsMyFolderOpened").Bind(folderPathObj := [])
pObj := Object(WatchFolders)
Return

$F1:: folderPathObj[1] := SelectFolderEx(, "Select the folder to monitor")
$F2::
   if !InStr( FileExist(folderPathObj[1]), "D" )
      MsgBox, No folder chosen
   else
      Hook := new WinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_NAMECHANGE, "HookProc", pObj)
   Return

$F3:: Hook := ""

IsMyFolderOpened(obj, hWnd) {
   openedFolderPath := GetFolderPath(hWnd)
   if InStr(openedFolderPath, obj[1] . "\") || openedFolderPath = obj[1]
      MsgBox, Folder %openedFolderPath% was opened
}

HookProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
   static OBJID_WINDOW := 0, CallBack, prevTime := 0
   (!CallBack && CallBack := Object(A_EventInfo))
   if (idObject != OBJID_WINDOW)
      Return
   if !(event = EVENT_OBJECT_SHOW || event = EVENT_OBJECT_NAMECHANGE)
      Return
   WinGetClass, winClass, ahk_id %hwnd%
   if (winClass != "CabinetWClass")
      Return
   if (A_TickCount - prevTime < 300)
      Return
   prevTime := A_TickCount
   CallBack.(hwnd)
}

GetFolderPath(hWnd := "") {
   (!hWnd && hWnd := WinExist("A"))
   WinGetClass, winClass, ahk_id %hWnd%
   if !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
      Return
   
   if (winClass ~= "Progman|WorkerW")
      Return A_Desktop
   
   for window in ComObjCreate("Shell.Application").Windows {
      if (hWnd = window.HWND && dirPath := window.Document.Folder.Self.Path)
         break
   }
   Return dirPath
}

class WinEventHook
{
   __New(eventMin, eventMax, hookProc, eventInfo := 0, idProcess := 0, idThread := 0, dwFlags := 0) {
      this.pCallback := RegisterCallback(hookProc, "F",, eventInfo)
      this.hHook := DllCall("SetWinEventHook", "UInt", eventMin, "UInt", eventMax, "Ptr", 0, "Ptr", this.pCallback
                                             , "UInt", idProcess, "UInt", idThread, "UInt", dwFlags, "Ptr")
   }
   __Delete() {
      DllCall("UnhookWinEvent", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.pCallback, "Ptr")
   }
}

SelectFolderEx(StartingFolder := "", Prompt := "", OwnerHwnd := 0, OkBtnLabel := "") {
   static OsVersion := DllCall("GetVersion", "UChar")
        , IID_IShellItem := 0
        , InitIID := VarSetCapacity(IID_IShellItem, 16, 0)
                  & DllCall("Ole32.dll\IIDFromString", "WStr", "{43826d1e-e718-42ee-bc55-a1e261c37bfe}", "Ptr", &IID_IShellItem)
        , Show := A_PtrSize * 3
        , SetOptions := A_PtrSize * 9
        , SetFolder := A_PtrSize * 12
        , SetTitle := A_PtrSize * 17
        , SetOkButtonLabel := A_PtrSize * 18
        , GetResult := A_PtrSize * 20
   SelectedFolder := ""
   if (OsVersion < 6) { ; IFileDialog requires Win Vista+, so revert to FileSelectFolder
      FileSelectFolder, SelectedFolder, *%StartingFolder%, 3, %Prompt%
      Return SelectedFolder
   }
   OwnerHwnd := DllCall("IsWindow", "Ptr", OwnerHwnd, "UInt") ? OwnerHwnd : 0
   if !(FileDialog := ComObjCreate("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}", "{42f85136-db7e-439c-85f1-e4075d135fc8}"))
      Return ""
   VTBL := NumGet(FileDialog + 0, "UPtr")
   ; FOS_CREATEPROMPT | FOS_NOCHANGEDIR | FOS_PICKFOLDERS
   DllCall(NumGet(VTBL + SetOptions, "UPtr"), "Ptr", FileDialog, "UInt", 0x00002028, "UInt")
   if (StartingFolder <> "")
      if !DllCall("Shell32.dll\SHCreateItemFromParsingName", "WStr", StartingFolder, "Ptr", 0, "Ptr", &IID_IShellItem, "PtrP", FolderItem)
         DllCall(NumGet(VTBL + SetFolder, "UPtr"), "Ptr", FileDialog, "Ptr", FolderItem, "UInt")
   if (Prompt <> "")
      DllCall(NumGet(VTBL + SetTitle, "UPtr"), "Ptr", FileDialog, "WStr", Prompt, "UInt")
   if (OkBtnLabel <> "")
      DllCall(NumGet(VTBL + SetOkButtonLabel, "UPtr"), "Ptr", FileDialog, "WStr", OkBtnLabel, "UInt")
   if !DllCall(NumGet(VTBL + Show, "UPtr"), "Ptr", FileDialog, "Ptr", OwnerHwnd, "UInt") {
      if !DllCall(NumGet(VTBL + GetResult, "UPtr"), "Ptr", FileDialog, "PtrP", ShellItem, "UInt") {
         GetDisplayName := NumGet(NumGet(ShellItem + 0, "UPtr"), A_PtrSize * 5, "UPtr")
         if !DllCall(GetDisplayName, "Ptr", ShellItem, "UInt", 0x80028000, "PtrP", StrPtr) ; SIGDN_DESKTOPABSOLUTEPARSING
            SelectedFolder := StrGet(StrPtr, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "Ptr", StrPtr)
         ObjRelease(ShellItem)
   }  }
   if (FolderItem)
      ObjRelease(FolderItem)
   ObjRelease(FileDialog)
   Return SelectedFolder
}
By F1 you can choose a folder, by F2 start monitoring, by F3 stop monitoring.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 335 guests