doing a 'launchy'... how to grab a hotkey

Just starting out? Need help? Post your questions and find answers here.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

doing a 'launchy'... how to grab a hotkey

Post by blueznl »

Tools like Enso and Launchy 'steal' a hotkey, and I would like to copy that behaviour, ie.

If the user presses [Alt]+[Space] I want my program to pop up, no matter what else is going on, just like Launchy does. How can I do that?

What I plan to write (and if you already know about a tool that does this then please tell me so I don't have to write it myself :-)) is a small application launcher, in the style of launchy, however with a twist.

If pressing [Alt]+[Space] it should bring up a menu, ie. a screen with multiple Single key shortcuts. Thus, to quickly launch a browser, one would do [Alt]+[Space] followed by, for example, [F]. To enter more complex 'Launchy' style commands one would launch the tool using [Alt]+[2xSpace].

It's easier to talk about it than to write it I guess :-)

One of the things that I did NOT like about Launchy etc. is how much memory those things consume. Why should a keyboard launcher consume 10 MB (!) for a simple execute program call or pop up window call? Not a good thing on netbooks (like the one I'm typing this on right now :-)) so PureBasic to the rescue?

Suggestions welcome.
Last edited by blueznl on Tue Nov 02, 2010 8:33 am, edited 3 times in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
LuCiFeR[SD]
666
666
Posts: 1033
Joined: Mon Sep 01, 2003 2:33 pm

Re: Grabbing a hotkey (how to do a 'launchy')

Post by LuCiFeR[SD] »

I've got a bit of code from RASHAD IIRC :), should find it on here with a search "Global Keyboard Hook" I think

Code: Select all

Procedure CheckForHotKey(Delete.i = #True)
  Message.MSG
  If Delete
    If PeekMessage_(@Message, -1, #WM_HOTKEY,#WM_HOTKEY, #PM_REMOVE)
      ProcedureReturn Message\wParam
    EndIf  
  Else
    If PeekMessage_(@Message, -1, #WM_HOTKEY,#WM_HOTKEY, #PM_NOREMOVE)
      ProcedureReturn Message\wParam
    EndIf  
  EndIf

  ProcedureReturn #False
EndProcedure

#PB_Event_ShortCut = 1337

Procedure WindowEventHook(Wait.i = #False)
  Message.MSG
  If CheckForHotKey(#False)
    ProcedureReturn #PB_Event_ShortCut
  EndIf
  
  If Wait
    ProcedureReturn WaitWindowEvent()  
  Else 
    ProcedureReturn WindowEvent()
  EndIf
EndProcedure

Macro WindowEvent()
  WindowEventHook()
EndMacro

Macro WaitWindowEvent()
  WindowEventHook(#True)
EndMacro

Procedure RegisterSystemHotkey(ID.i, Key1.i, Key2.i)
  RegisterHotKey_(0,ID, Key1, Key2)  
EndProcedure

Procedure UnregisterSystemHotkey(ID.i)
  UnregisterHotKey_(0,ID)
EndProcedure

RegisterSystemHotkey(1,#MOD_CONTROL, #VK_SPACE) ;CTRL + Space
RegisterSystemHotkey(2,#MOD_CONTROL, #VK_Q) ;CTRL + Q


OpenWindow(0,0,0,300,300,"TestWindow")

Repeat
  Delay(1)
  Event = WindowEvent()
  If Event = #PB_Event_ShortCut
    Hotkey = CheckForHotKey()
    If Hotkey = 1
      Debug "CTRL + Space"
    ElseIf Hotkey = 2
      Debug "CTRL + Q pressed"
    EndIf
  ElseIf Event = #PB_Event_CloseWindow
    End
  EndIf
ForEver
This should get you started :P
User avatar
idle
Always Here
Always Here
Posts: 5903
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Grabbing a hotkey (how to do a 'launchy')

Post by idle »

Just use a use a low level keyboard hook with a timer to queue the key sequences
If that doesn't work properly all the time or some other app responds to the keys then you could try eating the keys triggered on the alt key by setting a timer and store the key messages and if after x milliseconds the sequence doesn't match a target pattern flush the stored keys back into the system.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by blueznl »

Ah! GlobalKeyboardHook, I knew it was there somewhere! Thanks, let's see how large my own 'launchy' will be, I bet it's going to be quite a bit short of 10 Mb :-)

(Though, to be honest, even WallX takes 5 Mb when running, even though the code is so silly small it's amazing how Windows manages to blow it up :-))
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Vera
Addict
Addict
Posts: 858
Joined: Tue Aug 11, 2009 1:56 pm
Location: Essen (Germany)

Re: Grabbing a hotkey (how to do a 'launchy')

Post by Vera »

The smallest (87.5kb)
and best launcher I've ever come across, is written in pure PureBasic ~ PopSel by Horst.

Now - can this be a challenge :mrgreen:

And I'm already anxious what it'll be going to be - in case we'll get a look one day :D

greetings ~ Vera
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: Grabbing a hotkey (how to do a 'launchy')

Post by Mistrel »

User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by blueznl »

Lucifer's code seems to be a bit complex, wouldn't the next snippet pretty much do the same, or am I overlooking something?

Code: Select all

Enumeration
  #w_main_nr
  #hk_altspace
  #hk_ctrlspace
EndEnumeration
;
w_main_h = OpenWindow(#w_main_nr,300,300,300,300,"Thype",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
hk_altspace = RegisterHotKey_(w_main_h,#hk_altspace,#MOD_ALT,#VK_SPACE)
hk_ctrlspace = RegisterHotKey_(w_main_h,#hk_ctrlspace,#MOD_CONTROL,#VK_SPACE)
;
Repeat
  event = WaitWindowEvent()
  Select event
  Case #PB_Event_CloseWindow
  Case #PB_Event_MoveWindow
  Case #WM_HOTKEY
    Select EventwParam()
    Case #hk_altspace
      Debug "alt"
    Case #hk_ctrlspace
      Debug "ctrl"
    EndSelect
  EndSelect
Until event = #PB_Event_CloseWindow
;
UnregisterHotKey_(w_main_h,hk_altspace)
UnregisterHotKey_(w_main_h,hk_ctrlspace)
Slightly improved version (seems to work fine though :-))

Code: Select all

Enumeration
  #w_invisible_nr
  #w_main_nr
  #hk_altspace
EndEnumeration
;
w_invisible_h = OpenWindow(#w_invisible_nr,300,300,300,300,"Thype",#PB_Window_Invisible)
hk_altspace = RegisterHotKey_(w_invisible_h,#hk_altspace,#MOD_ALT,#VK_SPACE)
;
Repeat
  event = WaitWindowEvent()
  window = EventWindow()
  ;
  Select window
  Case #w_invisible_nr
    Select event
    Case #WM_HOTKEY
      Select EventwParam()
      Case #hk_altspace
        If Not IsWindow(#w_main_nr)
          w_main_h = OpenWindow(#w_main_nr,300,300,300,300,"Thype",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
        Else
        EndIf
      EndSelect
    EndSelect
  Case #w_main_nr
    Select event
    Case #PB_Event_CloseWindow
      CloseWindow(#w_main_nr)
    EndSelect
  EndSelect
Until event = 1234
;
hk_altspace = RegisterHotKey_(w_invisible_h,#hk_altspace,#MOD_ALT,#VK_SPACE)
Edit: Mistrel, I checked your email after I worked out my own code. Question: why are you not using the regular WindowEvent() messages in your example?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: Grabbing a hotkey (how to do a 'launchy')

Post by Mistrel »

blueznl wrote:Question: why are you not using the regular WindowEvent() messages in your example?
Because my code isn't using any windows.
marc_256
Addict
Addict
Posts: 842
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by marc_256 »

hi,

if I try to download the 'PopSel by Horst'
I receive a VIRUS warning by NOD32 anti-virus program.

Is there someone else who have this warning ??

Marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by Michael Vogel »

Not sure if you found already a solution, I did a launcher which uses "only" a key combination with the windows. This can be done easily with something like this which results in WM_HOTKEY events:

Code: Select all

Procedure ActivateHotkeys()
    If OptHotkeyFlag
        If OptHotkey<#HotKeyAlternateSet
            RegisterHotKey_(HandleMyWin,$9999,#MOD_WIN,#VK_A+OptHotkey)
            RegisterHotKey_(HandleMyWin,$9898,#MOD_WIN|#MOD_SHIFT,#VK_A+OptHotkey)
        Else
            RegisterHotKey_(HandleMyWin,$9999,#MOD_CONTROL|#MOD_SHIFT,#VK_A+OptHotkey-#HotKeyAlternateSet)
            RegisterHotKey_(HandleMyWin,$9898,#MOD_ALT|#MOD_SHIFT,#VK_A+OptHotkey-#HotKeyAlternateSet)
        EndIf
    EndIf
EndProcedure
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by blueznl »

Got a bit further, here's my current code:

Code: Select all

; thype v0.1

EnableExplicit
Declare init()
Declare main()
init()
main()

Procedure init()
  ;
  ; *** setup constants, structures and global variables
  ;
  Enumeration
    ;
    ; windows
    ;
    #w_invisible_nr   ; window used to capture hk_launch events
    #w_visible_nr     ; main window nr when visible
    ;
    ; gadgets
    ;
    #g_command        ; gadget to input launch string
    ;
    ; hotkeys
    ;
    #hk_launch        ; constant identifying hk_launch in use
    ;
    ; actions
    ;
    #f_none           ; do nothing
    #f_exit           ; exit program
    #f_escape         ; escape, abort
    #f_enter          ; confirm selection
    ;
  EndEnumeration
  ;
  ; *** globals
  ;
  ; gui elements
  ;
  Global w_invisible_h.i
  Global w_visible_h.i
  ;
  ; shortcuts
  ;
  Global hk_launch.i
  ;
  ; events
  ;
  Global action.i
  Global event.i
  Global event_window.i
  Global event_menu.i
  ;
  ; other
  ;
  Global mode.i
  Global command.s
  ;
EndProcedure

Procedure draw(mode.i)
  ;
  ; *** draw window
  ;
  Select mode
  Case 0
    ;
    ; mode 0 brings up single key shortcuts
    ;
  Case 1
    ;
    ; mode 1 allows typing multiple letters
    ;
    StringGadget(#g_command,10,10,280,20,"")
    SetActiveGadget(#g_command)
    AddKeyboardShortcut(#w_visible_nr,#PB_Shortcut_Escape,#f_escape)
    AddKeyboardShortcut(#w_visible_nr,#PB_Shortcut_Return,#f_enter)
    ;
  EndSelect
  ;
EndProcedure

Procedure main()
  ;
  ; *** main routine
  ;
  w_invisible_h = OpenWindow(#w_invisible_nr,300,300,300,300,"Thype",#PB_Window_Invisible)
  hk_launch = RegisterHotKey_(w_invisible_h,#hk_launch,#MOD_ALT,#VK_SPACE)
  ;
  ; *** event loop
  ;
  Repeat
    action = #f_none
    ;
    event = WaitWindowEvent()
    event_window = EventWindow()
    event_menu = EventMenu()
    ;
    Select event_window
    Case #w_invisible_nr
      ;
      ; *** process all events arriving at the invisible window
      ;
      Select event
      Case #WM_HOTKEY
        Select EventwParam()
        Case #hk_launch
          If Not IsWindow(#w_visible_nr)
            ;
            ; open the visible window
            ;
            w_visible_h = OpenWindow(#w_visible_nr,300,300,300,300,"Thype",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
            mode = 0
            draw(mode)
            ;
          Else
            ;
            ; visible window is open, toggle mode
            ;
            ; mode 0 brings up a single key menu, ie. [Alt]+[Space] then [W] should launch 'word' etc.
            ; mode 1 allows entering a text, ie. [Alt]+[Space] then [W][O][R][D] should launch 'word'
            ;
            mode = 1 - mode
            draw(mode)
            ;
          EndIf
        EndSelect
      Case #PB_Event_CloseWindow
        ;
        ; close window / exit program message
        ;
        action = #f_exit
      EndSelect
      ;
    Case #w_visible_nr
      ;
      ; *** process all events arriving at the visible window
      ;
      Select event
      Case #PB_Event_Menu
        ;
        ; process menu events and shortcut keys
        ;
        Select event_menu
        Case #f_escape
          ;
          ; hitting the escape key aborts the sequence and closes the window
          ;
          CloseWindow(#w_visible_nr)
        Case #f_enter
          ;
          ; hitting enter confirms the input
          ;
          command = LCase(GetGadgetText(#g_command))
          Select command
          Case "quit"
            action = #f_exit
          EndSelect
          ;
        EndSelect
        ;
      Case #PB_Event_CloseWindow
        ;
        ; close the visible window
        ;
        CloseWindow(#w_visible_nr)
        ;
      Default
        ;
        ; all other events (debugging)
        ;
      EndSelect
      ;
    EndSelect
  Until action = #f_exit
  ;
  ; *** all completed, free up, close, exit
  ;
  hk_launch = UnregisterHotKey_(w_invisible_h,#hk_launch)
  ;
EndProcedure
It's the basic framework for a 'launchy' style of application. On we go... next challenge: search through the start menu. Suggestions? :-)

http://www.purebasic.fr/english/viewtop ... 13&t=44151
Last edited by blueznl on Tue Nov 02, 2010 2:03 pm, edited 1 time in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
horst
Enthusiast
Enthusiast
Posts: 197
Joined: Wed May 28, 2003 6:57 am
Location: Munich
Contact:

Re: Grabbing a hotkey (how to do a 'launchy')

Post by horst »

marc_256 wrote: if I try to download the 'PopSel by Horst'
I receive a VIRUS warning by NOD32 anti-virus program.
This is the full :!: source code of the "program" RunDemo.exe that caused the alert (tested with Jotti: about half a dozen scanners reported positive).

Code: Select all

ShellExecute_(0,0,"PopSel.exe","Demo.lst",0,#SW_SHOWNORMAL)
I compiled it again with PB 4.51, and all but one ("VBA32") scanner reported "found nothing".
Download archive updated; new "official" version soon.

Sorry, if off topic
Horst.
marc_256
Addict
Addict
Posts: 842
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: doing a 'launchy'... how to grab a hotkey

Post by marc_256 »

To Horst,

Thanks,
all the downloads are ok now.
No virus detection anymore...

Marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
idle
Always Here
Always Here
Posts: 5903
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: doing a 'launchy'... how to grab a hotkey

Post by idle »

An idea to facilitate blueznl mode 1
mode 1 allows entering a text, ie. [Alt]+[Space] then [W][O][R][D] should launch 'word'

Notes

It will save a file "launchy.lbn" where ever you run it from.
Either let is scan all drives or scan a drive
start to type in an exe name list will populate
click on an item in the list to run

Questions

should it be trawling the drives for exe's or the registry?
how can you tell the difference between a windows and console application? read the PE header I suppose
how can you tell if an app is a worker app of some other app?

Code: Select all


;an idea for to facilitate blueznl mode 1  
;mode 1 allows entering a text, ie. [Alt]+[Space] then [W][O][R][D] should launch 'word'

;quick hacky launchy app - code at line 197
Structure edge
   edge.i[256] 
EndStructure

Structure TrieNode;
   Value.i;
   Count.i;
   Vertex.edge
EndStructure;

Structure Trie
  *vt.i
  *root.TrieNode;
EndStructure;

Declare FreeNodes(*node.TrieNode)
Declare NewTrie(*obj.Trie)
Declare FreeTrie(*this.Trie)
Declare AddTrie(*this.Trie,key.s,value.i=1)
Declare lookupTrie(*this.Trie,key.s)
Declare iEnumTrie(*this.Trie,*node.TrieNode,key.s,*fn)
Declare EnumTrie(*this.Trie,key.s,*fn.i)

Interface clsTrie
  Free()
  Add(key.s,item.i=1)
  LookUp(key.s)
  Enum(key.s,*fn.i)
EndInterface   


Procedure FreeNodes(*node.TrieNode)
  ;Free all Trie Nodes
  Protected a.i
   If Not *node
      ProcedureReturn;
   EndIf
   
   For a=0 To 255
      FreeNodes(*node\Vertex\edge[a]);
   Next
   
   If *node
     FreeMemory(*node)
   EndIf 
   
EndProcedure

Procedure NewTrie(*obj.Trie)
  *obj = AllocateMemory(SizeOf(Trie))
  If *obj
   *obj\vt=?vt_Trie
  EndIf
  *obj\root = AllocateMemory(SizeOf(TrieNode))
 
  ProcedureReturn *obj
EndProcedure

Procedure FreeTrie(*this.Trie)
  ;free the Trie
  FreeNodes(*this\root)
  FreeMemory(*this)
 
EndProcedure

Procedure AddTrie(*this.Trie,key.s,value.i=1)
  ;Add item to the Trie, value is optional
  Protected *tnode.TrieNode,*node.TrieNode,len.i,tkey.i,lkey.i,pos.i
  len = Len(key)
   lkey.i
   
   If Not len
     ProcedureReturn;
   EndIf

   *node = *this\root;
   
   While pos < Len+1
    
     tkey = PeekB(@key+pos) & $FF
    
     If Not *node          
      *node = AllocateMemory(SizeOf(TrieNode))
        *tnode\Vertex\edge[lkey] = *node
      EndIf

      *node\count + 1
        
     If pos = len 
       *node\value = value
      EndIf
      
      *tnode = *node
      *node = *node\Vertex\edge[tkey]
      lkey = tkey
      pos+1
      
   Wend
   
EndProcedure

Procedure lookupTrie(*this.Trie,key.s)
  ;Find the value of the key returns the value or 0
  Protected *node.TrieNode,*bkey.byte,result.i   
    
  *node = *this\root
  *bkey = @key 
  *node = *node\Vertex\edge[*bkey\b & $FF]
 
  While *bkey\b <> 0 
   
      If Not *node
         ProcedureReturn 0
      EndIf
      *bkey+1
      result = *node\value
      *node = *node\Vertex\edge[*bkey\b & $FF]
      
   Wend
   
   ProcedureReturn result
   
EndProcedure

Procedure iEnumTrie(*this.Trie,*node.TrieNode,key.s,*fn)
  ;internal Enum trie 
  Protected a.i,tkey.s
 
  If Not *node
      ProcedureReturn;
   EndIf
   
   ;build the key   
   For a=0 To 255
     If *node\Vertex\edge[a]
       tkey = key + Chr(a)
       iEnumTrie(*this,*node\Vertex\edge[a],tkey,*fn);
     Else
       tkey = key
     EndIf 
   Next
   
   ;lookup the key
   If lookupTrie(*this,tkey)
     CallFunctionFast(*fn,@tkey)
     key=tkey
     ProcedureReturn *node
   EndIf   
      
EndProcedure

Procedure EnumTrie(*this.Trie,key.s,*fn.i)
  ;enumerate all the entries below given root key
  Protected *node.TrieNode,*tnode.TrieNode,tkey.i,len.i,pos.i
 
  *node = *this\root;
  tkey = PeekB(@key) & $FF;
  len = Len(key)
  *node = *node\Vertex\edge[tkey]
 
  ;find the root   
  While *node
   
    If *node
       *tnode =*node
     EndIf
    
     pos+1
     tkey = PeekB(@key+pos) & $FF
     *node = *node\Vertex\edge[tkey]
        
   Wend
   ;enum the root
   While *tnode
    
     *tnode = iEnumTrie(*this,*tnode,key,*fn)
     tkey = PeekB(@key+pos) & $FF
    
     If *tnode
      *tnode = *tnode\Vertex\edge[tkey]
     EndIf   
    
   Wend
   
EndProcedure

DataSection: vt_Trie:
  Data.i @FreeTrie()
  Data.i @AddTrie()
  Data.i @lookupTrie()
  Data.i @EnumTrie()
EndDataSection   



; Hacky Test code_____________________________________________________________________
 Global result.s 
 Procedure MyTreeCallBack(*item)
;    
   result + PeekS(*item) + " "  
;  
 EndProcedure   
; 
Global mt.clsTrie = NewTrie(@mt)
Global Dim gApps.s(100)
Global gAppCnt,gScanDone,gappSize
Global gWinScan,gKillScan,gScanDone,gscanpos,gloaded,gTotalDriveSize.q,gScanSum.q,gmwind,gmvis
Structure fDat 
  file.s{256} 
  app.s {64}
EndStructure   
Structure scaninf
  mode.i 
  dir.s 
EndStructure 

Enumeration
  #Window_Media
  #LV_APPS
  #S_APP
   
  #M_ReScan
  #PBar
  #TDrive
  #TFile
  #TCount
  #M_Help
  #M_About
  #M_port 
EndEnumeration

Procedure addapp(filePath.s,name.s,fn)
  
  If Not mt\LookUp(name) 
    If gAppCnt >= gAppSize 
      gAppSize + 100 
      ReDim gapps.s(gAppSize) 
    EndIf   
    
    gapps(gAppCnt) = filepath 
    mt\Add(name,gAppCnt)
    gAppCnt+1
    If IsFile(fn)
      dat.fDat
      dat\app = name
      dat\file = filePath 
      FileSeek(fn,Lof(fn))
      WriteData(fn,@dat,SizeOf(fdat))
    EndIf 
  EndIf
  
EndProcedure   

Procedure.s dirlist(dir.s,bRec,ofn):
  Static strFiles.s,ct1
  Protected sumf.f,tot.f
  mDir=ExamineDirectory(#PB_Any,dir,"*.*")  
  
  If mDir ;And Not gKillScan
    While NextDirectoryEntry(mDir)
      gScanSum + DirectoryEntrySize(mDir)
      If gTotalDriveSize <> 0 And gScanSum <> 0 And gWinScan  
        sumf = gScanSum
        tot = gTotalDriveSize
        Scanpos = Int((sumf / tot) * 100.0) 
        SetGadgetState(#pbar,Scanpos)
      EndIf  
      If DirectoryEntryType(mDir)=#PB_DirectoryEntry_File
        FN.s=DirectoryEntryName(mDir):
        exe.s = GetExtensionPart(FN)
        If exe = "exe"   
           FFN.s= dir+"\"+FN
           If IsWindow(gWinScan)
             SetGadgetText(#Tfile,FFN)
           EndIf  
           ts.s = LCase(Left(FN,Len(FN)-4))
           addApp(FFN,ts,ofn)
           ct1+1
         EndIf
       Else
         td$=DirectoryEntryName(mDir)
         If td$<>"." And td$<>".."
           If bRec=0
             dirlist(Dir+"\"+td$,bRec,ofn)
           EndIf
         EndIf
      EndIf
    Wend
    FinishDirectory(mDir)
  EndIf
EndProcedure:


Procedure AddToDB(*scan.scaninf)
  Protected filn,fn.i,ts.s,dir.s
  Protected fb.q,tb.q,tfb.q,titlecount.i 
    
  dir=*scan\dir
  
   
  SetErrorMode_(#SEM_FAILCRITICALERRORS)
  

  
  If *scan\mode=1 Or *scan\mode=2
    
    fn = OpenFile(-1,"launchy.lbn")
    
    If dir = "\"
          
      For d = 'A' To 'Z' 
        gScanSum=0
        dir = Chr(d) + ":\"
        SetGadgetText(#TDrive,dir)
        GetDiskFreeSpaceEx_(dir,@fb,@TB,@TFB)
        gTotalDriveSize = (TB - TFB) 
        dirlist(dir,0,fn)
      Next  
     
    Else 
             
      drive.s  = Left(dir,3)
      
      GetDiskFreeSpaceEx_(drive,@fb,@TB,@TFB)
      gTotalDriveSize = (TB - TFB) 
      SetGadgetText(#TDrive,drive)
      dirlist(dir,0,fn)
    EndIf   
     
  ElseIf *scan\mode=0 
    fn=ReadFile(#PB_Any,"launchy.lbn")
    If fn
      While Not Eof(fn)
        indat.fdat ;ts=Space(512)
        ReadData(fn,@indat,SizeOf(fdat))
        addapp(indat\file,indat\app,0)
      Wend
      If IsFile(fn)
       CloseFile(fn)
      EndIf   
    EndIf 
 EndIf
  gScanDone = 1
  
  SetErrorMode_(0)
  
EndProcedure  

Procedure Open_ScanGui(mode)
 Protected title.s,evs.i,dir.s,scan.scaninf,result 
 title = "Launchy Scaner"  
 fn = OpenFile(-1,"launchy.lbn")
 homedir.s = Left(GetCurrentDirectory(),3)
 
  
 tlen = Lof(fn) 
 CloseFile(fn)
 
 If tlen = 0 Or mode   
   
   If tlen = 0 
     result = MessageRequester("Launcy Scan - Add Links","Would like to scan your entire system?",#PB_MessageRequester_YesNo)
     If result = #PB_MessageRequester_Yes
       bScanAll=1
       dir = "\"
     EndIf
     mode=1
   EndIf   
     
   If Not bScanAll 
      dir.s = PathRequester("Please choose a directory To scan", InitialPath$)
      ;dir = Left(dir,Len(dir)-1)
   EndIf     
   
   scan\mode = mode
   scan\dir = dir 
   
   If dir <> ""
   
   gWinScan = OpenWindow(-1, 354, 253, 492, 126, Title, #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
   
    If gWinScan
       ProgressBarGadget(#PBar, 5, 85, 480, 35, 0, 100, #PB_ProgressBar_Smooth)
       TextGadget(#TDrive, 10, 10, 90, 30, "")
       TextGadget(#TFile, 10, 50, 475, 30, "")
       TextGadget(#TCount, 100, 10, 200,30,"")
    EndIf
    
    If dir <> ""
         
      
      gScanDone=0
      CreateThread(@AddToDB(),@scan)
 
      Repeat 
 
         evs=WindowEvent()
         Delay(0)
 
       Until gScanDone Or evs=#WM_CLOSE  
    Else 
      If IsWindow(gWinScan)
        CloseWindow(gWinScan)
      EndIf   
       gWinScan=0
    EndIf    
    If gScanDone
      If IsWindow(gWinScan)
        CloseWindow(gWinScan)
      EndIf   
      gWinScan=0
    EndIf
    
    EndIf 
    
 Else 
   scan\mode = 0
   scan\dir = ""
   
   AddToDB(@scan)

   
EndIf  
 
EndProcedure

Procedure UpdateList(*item)
  If *item  
     item.s = PeekS(*item)
     AddGadgetItem(#LV_APPS,-1,item) 
     SetGadgetState(#LV_APPS,0)  
   EndIf 
 EndProcedure   


mod.scaninf 
mod\dir = "\"
mod\mode = 0 
AddToDB(@mod)
;Open_ScanGui(1)
Global gpt
gmwind = OpenWindow(-1,300,300,300,300,"Runner", #PB_Window_SystemMenu)

StringGadget(#S_APP,5,5,290,20,"")
ListViewGadget(#LV_APPS,5,30,290,260)

If CreateMenu(0, WindowID(gmwind))  ; 
  MenuTitle("Apps")
  MenuItem(#M_ReScan, "Add Apps")
EndIf 

AddKeyboardShortcut(gmwind, #PB_Shortcut_Down,10)
AddKeyboardShortcut(gmwind, #PB_Shortcut_Up,11)
AddKeyboardShortcut(gmwind, #PB_Shortcut_Return,12)

SetActiveGadget(#S_APP)

 Repeat 
      
      EV = WaitWindowEvent()
      EVG = EventGadget()
      EVT = EventType()
      EVW=EventWindow()
       
      If ev  
      If EVW=gmwind
        If EV = #PB_Event_Menu
           mev = EventMenu()
           Select mev 
            Case #M_ReScan 
               Open_ScanGui(2)
             Case 10 
               If gpt < CountGadgetItems(#LV_APPS)
                  gpt+1 
                EndIf        
                SetGadgetState(#LV_APPS,gpt)
             Case 11 
               If gpt > 0 
                gpt-1
              EndIf 
              SetGadgetState(#LV_APPS,gpt)
             Case 12  
               pos = GetGadgetState(#LV_APPS)
                If pos >= 0 
                  tapp.s = GetGadgetItemText(#LV_APPS,pos)
                  res = mt\LookUp(tapp.s)
                  If res 
                    RunProgram(gapps(res))
                    SetActiveGadget(#S_APP)
                  EndIf
                EndIf 
          EndSelect 
        
        ElseIf EV = #PB_Event_Gadget 
          Select EVG 
              Case #LV_APPS 
                If evt = #PB_EventType_LeftDoubleClick 
                pos = GetGadgetState(#LV_APPS)
                tapp.s = GetGadgetItemText(#LV_APPS,pos)
                res = mt\LookUp(tapp.s)
                If res 
                  RunProgram(gapps(res))
                  SetActiveGadget(#S_APP)
                EndIf
                EndIf 
              Case #S_APP 
                tapp.s = GetGadgetText(#S_APP) 
                If Len(tapp) > 1 
                  ClearGadgetItems(#LV_APPS)
                  mt\Enum(tapp,@UpdateList())
                EndIf 
            EndSelect        
          EndIf
        EndIf
      EndIf 
            
Until EV = #WM_CLOSE            
Windows 11, Manjaro, Raspberry Pi OS
Image
Post Reply