I don't know if anyone's made one of these yet, but it was a good learning experience nevertheless.
This script monitors your Windows explorer navigation and keeps a log of folders you visit (and spend more than a few seconds in, to eliminate logging 'pass-thru' folders on your way deeper into the path structure). The list of most recently visited places is stored in a menu which can be accessed via the tray or by pressing Win-LeftMouseButton.
On exit, it will write your list of recent folders to a file called 'Recent Folders lists.log' so it can remember the list from session to session.
The script can be exited quickly with a double-click on the tray icon.
Thanks to Rajat for alerting me to the %A_ThisMenuItem% variable as a means to keep track of an ever-changing menu.
Comments and suggestions welcome.
Code:
;CONFIG
rf_foldernum=10 ;set this value to the maximum number of folders you want remembered
rf_timer=2000 ;this is the period of the timer that checks the current window.
;Experiment to find something that works for you
;Too long = quick-access folders won't be picked up
;Too short = too many 'pass-thru' folders will be logged.
Process, Priority,, High ;This is necessary on my PC, but can probably be disabled on most modern, fast PCs.
;load current folder list from file
Loop, Read, Recent Folders list.log
{
If A_LoopReadLine=
break
rf_folder%A_Index%=%A_LoopReadLine%
}
;Get display names for those folder paths
Loop
{
If rf_folder%A_Index%=
break
StringSplit, temp_path_split, rf_folder%A_Index%,\,
rf_display%A_Index%:=temp_path_split%temp_path_split0%
}
;Launch initial menu items
Menu, Tray, NoStandard
;Menu, Tray, Icon, folders.ico ;add your own icon here, and de-comment this line.
Menu, Tray, Add, Exit Recent Folders, rf_close
menu, tray, Add ; separator
Menu, Tray, Default, Exit Recent Folders
Loop, %rf_foldernum%
{
temp_display:=rf_display%A_Index%
If temp_display<>
Menu, Tray, Add, %temp_display%, rf_launch
}
;load filter list
Loop, Read, Recent Folders filter.log
{
rf_filter%A_Index% = %A_LoopReadLine%
rf_filternum = %A_Index%
}
SetTimer, rf_trackfolders, %rf_timer%
#LButton:: Menu, Tray, Show ;Shows the menu wherever the mouse is. Key can be changed to whatever you like.
rf_trackfolders: ;monitors windows and updates the script with any folder windows.
WinGetActiveTitle, rf_current_win
WinGetClass, rf_class, %rf_current_win%
If rf_class = CabinetWClass
{
;Acquires folder path from window
SetTitleMatchMode, Slow
WinGetText, rf_win_info, %rf_current_win%, %rf_current_win%,
StringSplit, rf_new_folder, rf_win_info,`n
rf_new_folder= %rf_new_folder1%
StringTrimRight, rf_new_folder, rf_new_folder, 1
if rf_new_folder = %rf_last_folder% ;makes sure folder window has had focus for at least 1 complete cycle of timer
{
;check folder against filter list.
Loop, %rf_filternum%
{
temp_filter := rf_filter%A_Index%
If rf_current_win = %temp_filter%
{
rf_skip=1
break
}
}
;Begin re-sort menu - checks for a match to an existing item
If rf_skip<>1
{
Loop
{
temp_hold := rf_folder%A_Index%
If rf_new_folder = %temp_hold%
{
match=1
If rf_display%A_Index%<>%rf_foldernum%
{
rf_slot_number=%A_Index%
Gosub, rf_reshuffle_match
break
}
}
If rf_folder%A_Index%=
{
rf_first_empty=%A_Index%
break
}
}
If match<>1 ;adds new folder to empty slot
{
StringSplit, temp_path_split, rf_new_folder,\
If rf_first_empty <= %rf_foldernum%
{
rf_folder%rf_first_empty% = %rf_new_folder%
rf_display%rf_first_empty% :=temp_path_split%temp_path_split0%
temp_display :=rf_display%rf_first_empty%
Menu, Tray, Add, %temp_display%, rf_launch
}
else ;what happens when all slots are full - shuffles them all down 1
{
Menu, Tray, Delete, %rf_display1%
Loop
{
plus_count=%A_Index%
plus_count += 1
If A_Index > %rf_foldernum%
{
rf_folder%rf_foldernum% = %rf_new_folder%
rf_display%rf_foldernum% :=temp_path_split%temp_path_split0%
temp_display := rf_display%rf_foldernum%
Menu, Tray, Add, %temp_display%, rf_launch
break
}
rf_folder%A_Index% := rf_folder%plus_count%
rf_display%A_Index% := rf_display%plus_count%
}
}
match=
}
}
rf_last_folder=
}
else
rf_last_folder = %rf_new_folder%
}
match=
rf_skip=
return
rf_launch:
Loop ;checks which menu item folder to launch
{
If rf_display%A_Index% = %A_ThisMenuItem%
{
rf_open_folder := rf_folder%A_Index%
If rf_open_folder=Desktop ;these exceptions take care of some of the special folders - more to do.
{
Run, %A_Desktop%
break
}
If rf_open_folder=My Documents
{
Run, %A_MyDocuments%
break
}
Run, %rf_open_folder%
}
If A_Index > %rf_foldernum%
break
}
return
rf_reshuffle_match:
temp_tray := rf_display%rf_slot_number%
Menu, Tray, Delete, %temp_tray%
StringSplit, temp_path_split, rf_new_folder,\
rf_count=%rf_slot_number%
Loop
{
plus_count=%rf_count%
plus_count += 1
If rf_count = %rf_foldernum%
{
rf_folder%rf_foldernum% = %rf_new_folder%
rf_display%rf_foldernum% :=temp_path_split%temp_path_split0%
temp_display := rf_display%rf_foldernum%
Menu, Tray, Add, %temp_display%, rf_launch
break
}
rf_folder%rf_count% := rf_folder%plus_count%
rf_display%rf_count% := rf_display%plus_count%
rf_count++
}
return
rf_close: ;writes current folder list to file on exit
FileDelete, Recent Folders list.log
Loop
{
If rf_display%A_Index% =
break
rf_write_string := rf_folder%A_Index%
FileAppend, %rf_write_string%`n, Recent Folders list.log
}
ExitApp
Cheers,
C
Edit: Updated script with the changes listed in subsequent posts.