Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ShowMenu: based on folder and textfiles
#1
If I have the following directory:
d:\menu_qm

Which has the following tree structure


Code:
Copy      Help
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.
#2
Function ShowMenuStringFromFilesInFolder
Code:
Copy      Help
;/
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
Code:
Copy      Help
;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
#3
This is downright beautiful!!
Thank you very very much!!
#4
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)
#5
GetCaretXY.
ShowMenu flag 1.

Macro Macro2461
Code:
Copy      Help
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]
#6
I didnt know about "GetCaretXY"!!
Thank you!
#7
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
Code:
Copy      Help
;/
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
#8
Not easy. I would probably spend half day with it.
#9
Ok! I expected it would be a time consuming subject.
No problem, thanks for feedback!
#10
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:
 
Code:
Copy      Help
 >sub_menu    <=========== NO ID
     8 Normal2
     <

What I request:
 
Code:
Copy      Help
 >7 sub_menu     <=========== WITH ID
     8 Normal2
     <

I did several attempts but I can't get the incremental numbering right.


Forum Jump:


Users browsing this thread: 1 Guest(s)