Posts: 769
Threads: 263
Joined: Jul 2012
If I have the following directory:
d:\menu_qm
Which has the following tree structure
menu_qm
|
|--qm.txt
|--qm.docx
|
|--regexes
| |
| |--findrx_basic.txt
| |--regex.docx
|
|
|--arrays
|
|--multidim.txt
|--array.docx
menu_qm = rootfolder
regexes=subfolder
arrays=subfolder
I want to create a sort of dynamic pop-up menu based on a folder, in this case "d:\menu_qm".
It should show all the folders/subfolders and only show the textfiles.
So the menu should exactly be like depicted above without the .docx files.
Also the root items should be shown but they also must be .txt files.
Once a menu item is clicked the contents of that text file should be read and then that text should be send to whatever window the user was focussed on. The menu should appear at mouse pointer position and it must work in .exe format.
This means once the executable is run, it stays running in the background waiting for a key combination (for example when user presses [SHIFT]+[F1].
Any help on this would be greatly appreciated.
Posts: 12,092
Threads: 142
Joined: Dec 2002
Function ShowMenuStringFromFilesInFolder
;/
function $folderFiles str&sm ARRAY(str)&aPaths
;Creates string for ShowMenu from matching files in a folder and its subfolders.
;folderFiles - folder and filename wildcard string. See example.
;sm - receives string that can be passed to ShowMenu.
;aPaths - receives full paths of matching files.
;EXAMPLE
;str sm; ARRAY(str) a
;ShowMenuStringFromFilesInFolder "$documents$\*.txt" sm a
;int i=ShowMenu(sm)-1; if(i<0) ret
;out a[i]
sm.all
aPaths=0
int k level; str rel relPrev
Dir d
foreach(d folderFiles FE_Dir 4)
,rel=d.RelativePath
,k=d.Level
,;out "%i %s" k rel
,
,;end submenu if need (insert "<" line)
,if level
,,for(level level k -1) sm.formata("%.*m<[]" level 9)
,,;may be in other folder
,,for level level 0 -1
,,,if(!StrCompareN(rel relPrev findt(rel level "\"))) break
,,,sm.formata("%.*m<[]" level 9)
,relPrev=rel
,
,;begin submenu if need (insert ">Folder" line)
,for level level k
,,_s.gett(rel level "\")
,,sm.formata("%.*m>%s[]" level 9 _s)
,
,;add normal item, with id = aPaths index + 1
,aPaths[]=d.FullPath
,sm.formata("%.*m%i %s[]" k 9 aPaths.len _s.getfilename(rel))
rep(level) sm.formata("%.*m<[]" level 9); level-1
To wait for a hotkey, use __RegisterHotKey class. Example:
Macro __RegisterHotKey example
;Shows how to use __RegisterHotKey to use hotkeys in a windowless thread.
;This should be function, not macro, because runs all the time.
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT VK_F5)
;also can register more hotkeys, for example
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL 'B')
;...
MSG m
rep
,if(GetMessage(&m 0 0 0)<1) break
,sel m.message
,,case WM_HOTKEY
,,sel m.wParam
,,,case 1 ;;Ctrl+Shift+F5 pressed
,,,mac "Function_that_does_something_on_Ctrl_Shift_F5"
,,,
,,,case 2
,,,out "Ctrl+B"
,,,
,,,;...
,,,
,DispatchMessage &m
Posts: 769
Threads: 263
Joined: Jul 2012
This is downright beautiful!!
Thank you very very much!!
Posts: 769
Threads: 263
Joined: Jul 2012
EDIT:
Sorry I overlooked the following flag:
1 enable keyboard
The below question is solved by the 'flag 1 (enable keyboard)'
Is the following technically possible?
If the user is in an text editor for example notepad, and the user is editing text and when the user presses a hotkey the menu is rendered.
(the code is exact as the code explained above in your example).
So far it works perfectly, but is it possible to render the menu at the cursor position (where the user is typing) and immediately after the menu is rendered it is activated.
What I mean with this: When the user presses a hotkey while typing in the text editor the menu is rendered correctly but not active, when the user presses the RIGHT arrow it moves the cursor in the text-editor to the right (which is as it's expected).
It would be very nice if the focus was set on the rendered menu and thus when the user presses RIGHT arrow it would begin navigating the menu.
I could simulate this, but I need to how to put the mouse-pointer at the blinking cursur in the text editor.
(I guess this is very difficult)
Posts: 12,092
Threads: 142
Joined: Dec 2002
GetCaretXY.
ShowMenu flag 1.
Macro Macro2461
str sm; ARRAY(str) a
ShowMenuStringFromFilesInFolder "$documents$\*.txt" sm a
POINT p; GetCaretXY p.x p.y; p.y+20
int i=ShowMenu(sm 0 p 1)-1; if(i<0) ret
out a[i]
Posts: 769
Threads: 263
Joined: Jul 2012
I didnt know about "GetCaretXY"!!
Thank you!
Posts: 769
Threads: 263
Joined: Jul 2012
A final hurdle I need to take is the sorting of the generated menu.
Is it possible to sort the menu just like windows sorts it's folder contents on name:
- First display at the top folders (From a to z)
- Then below the folders, display the files (From a to z)
I hoped the below code would get me somewhere but it does not work like I wished it would.
Is it even possible? I can imagine this is very complex.
Function ShowMenuStringFromFilesInFolder
;/
function $folderFiles str&sm ARRAY(str)&aPaths
;Creates string for ShowMenu from matching files in a folder and its subfolders.
;folderFiles - folder and filename wildcard string. See example.
;sm - receives string that can be passed to ShowMenu.
;aPaths - receives full paths of matching files.
;EXAMPLE
;str sm; ARRAY(str) a
;ShowMenuStringFromFilesInFolder "$documents$\*.txt" sm a
;int i=ShowMenu(sm)-1; if(i<0) ret
;out a[i]
sm.all
aPaths=0
int k level; str rel relPrev
// ---- ORIGINAL
;Dir d
;foreach(d folderFiles FE_Dir 4)
// ----
//---- REPLACED
ARRAY(str) a; int i
GetFilesInFolder a "$desktop$" "*.rtf" 4
a.sort(8)
for i 0 a.len
,Dir d.dir(a[i])
//----
,rel=d.RelativePath
,k=d.Level
,;out "%i %s" k rel
,
,;end submenu if need (insert "<" line)
,if level
,,for(level level k -1) sm.formata("%.*m<[]" level 9)
,,;may be in other folder
,,for level level 0 -1
,,,if(!StrCompareN(rel relPrev findt(rel level "\"))) break
,,,sm.formata("%.*m<[]" level 9)
,relPrev=rel
,
,;begin submenu if need (insert ">Folder" line)
,for level level k
,,_s.gett(rel level "\")
,,sm.formata("%.*m>%s[]" level 9 _s)
,
,;add normal item, with id = aPaths index + 1
,aPaths[]=d.FullPath
,sm.formata("%.*m%i %s[]" k 9 aPaths.len _s.getfilename(rel))
rep(level) sm.formata("%.*m<[]" level 9); level-1
Posts: 12,092
Threads: 142
Joined: Dec 2002
Not easy. I would probably spend half day with it.
Posts: 769
Threads: 263
Joined: Jul 2012
Ok! I expected it would be a time consuming subject.
No problem, thanks for feedback!
Posts: 769
Threads: 263
Joined: Jul 2012
Is it possible the script could be modified to alllow subfolders also get an ID, this way I also can assign an icon to the subfolder.
Currently:
>sub_menu <=========== NO ID
8 Normal2
<
What I request:
>7 sub_menu <=========== WITH ID
8 Normal2
<
I did several attempts but I can't get the incremental numbering right.
|