Popup to launch favorite Apps/Folders

Post your working scripts, libraries and tools for AHK v1.1 and older
jfsturtz
Posts: 4
Joined: 26 Mar 2020, 16:16

Popup to launch favorite Apps/Folders

27 Mar 2020, 20:18

This is a script I whipped up for myself a few months ago. I find I'm using it pretty frequently, so I thought I'd post it here.

Basically, it displays a pop-up window from which you can launch favorite applications or folders. There must be a zillion of these in existence, but I looked around awhile back and couldn't find one that exactly suited me, so I put this together.

Here's the script:

Code: Select all

;  ======================================================================
; | Initializations                                                      |
; |                                                                      |
; |                                                                      |
;  ======================================================================
#SingleInstance Force



;  ======================================================================
; | Hotkeys                                                              |
; |                                                                      |
; |                                                                      |
;  ======================================================================

    ;  -----------------------------------------------------------
    ; | Left mouse click
    ; | 
    ; | If on desktop, double-click displays GUI and single-click
    ; | clears it
    ;  -----------------------------------------------------------
    ~LButton Up::
        WinGetClass, Class, A
        If Class in Progman,WorkerW
        {
            KeyWait, LButton, D T0.1
            e := ErrorLevel
            if (e)
            {
                if (WinExist("ahk_class AutoHotkeyGUI"))
                    Remove()
            }
            else
            {
                KeyWait, LButton
                if (not WinExist("ahk_class AutoHotkeyGUI"))
                    Display()
            }
        }
        Return

    ;  -----------------------------------------------------------
    ; | Alt-Space
    ; | 
    ; | Toggle display
    ;  -----------------------------------------------------------
    !Space::
        if (WinExist("ahk_class AutoHotkeyGUI"))
            Remove()
        else
            Display()
        Return
    
    ^Esc::ExitApp



;  ======================================================================
; | Functions                                                            |
; |                                                                      |
; |                                                                      |
;  ======================================================================

    ;  -----------------------------------------------------------
    ; | Display
    ; |
    ; | Display GUI if it isn't already
    ;  -----------------------------------------------------------
    Display()
    {
        global

        Apps := []
        Folders := []
        Read_Config(Apps, Folders)
        MouseGetPos, xpos, ypos
        Create_GUI(xpos, ypos, Apps, Folders)
    }

    ;  -----------------------------------------------------------
    ; | Remove
    ; |
    ; | Remove GUI if it is displayed
    ;  -----------------------------------------------------------
    Remove()
    {
        Gui, Destroy
    }

    ;  -----------------------------------------------------------
    ; | Read_Config
    ; |
    ; | Read in config file
    ; | Format is:  <A|F><label><icon><cmd|loc>
    ; |
    ; | Results get stashed in Apps and Folders arrays
    ;  -----------------------------------------------------------
    Read_Config(Apps, Folders)
    {
        global

        local fs := chr(0x1f)
        local cfg := A_ScriptDir . "\cfg.txt"
        Loop, read, %cfg%
        {
            s := RegExReplace(A_LoopReadLine, "#.*$")
            if (RegExMatch(s, "^\s*$"))
                Continue
            local a := StrSplit(s, Chr(0x1f))
            if (a[1] = "A")
            {
                local obj := {label: a[2], icon: a[3], cmd: a[4], dir: a[5]}
                Apps.Push(obj)
            }
            else if (a[1] = "F")
            {
                local obj := {label: a[2], icon: a[3], loc: a[4]}
                Folders.Push(obj)
            }
        }
    }

    ;  -----------------------------------------------------------
    ; | Create_GUI
    ; |
    ; | Create GUI at coordinates (GUI_x, GUI_y), from data in 
    ; | Apps and Folders arrays
    ;  -----------------------------------------------------------
    Create_GUI(GUI_x, GUI_y, Apps, Folders)
    {
        global

        local group_margin  := 0
            , cell_width    := 96
            , cell_height   := 96
            , cells_per_row := 4
            , font := "Corbel"
        local width  := cell_width * cells_per_row

        ; Create Apps GroupBox
        local n_rows := ((Apps.Length() - 1) // cells_per_row) + 1
        local group_height := group_margin + (cell_height * n_rows) + group_margin
        Gui, Font, s12 w800 cNavy, %font%
        Gui, Add, GroupBox, Section xm ym w%width% h%group_height%, Apps
        Populate_Group(Apps, "Apps"
            , group_margin, cell_width, cell_height, cells_per_row)

        ; Create Folders GroupBox
        local y := group_height + 10
        local n_rows := ((Folders.Length() - 1) // cells_per_row) + 1
        local group_height := group_margin + (cell_height * n_rows) + group_margin
        Gui, Font, s12 w800 cNavy, %font%
        Gui, Add, GroupBox, Section xm ym+%y% w%width% h%group_height%, Folders
        Populate_Group(Folders, "Folders"
            , group_margin, cell_width, cell_height, cells_per_row)
            
        ; Determine width and height of gui
        Gui, -Caption +Border +alwaysontop
        Gui, Show, Hide
        Gui, +LastFound
        local w, h
        WinGetPos,,, w, h
        
        ; Scale back top/left location of GUI so it isn't off screen
        SysGet, Mon, Monitor
        GUI_x := Min(GUI_x, (MonRight - w))
        GUI_y := Min(GUI_y, (MonBottom - h))

        ; Display it
        Gui, Color, White
        Gui, Show, x%GUI_x% y%GUI_y%, Test
        
        OnMessage(0x0200,"WM_MOUSEMOVE")
        OnMessage(0x0205, "WM_RBUTTONUP")
    }

    ;  -----------------------------------------------------------
    ; | Populate_Group
    ; |
    ; | Populate GroupBox with icons and labels
    ;  -----------------------------------------------------------
    Populate_Group(Grp, grp_id, group_margin, cell_width, cell_height, cells_per_row)
    {
        global

        local icon_size    := 42
        r := 1
        c := 1
        Loop % Grp.Length()
        {

            ; Icon
            ico := A_ScriptDir . "\ico\" . Grp[A_Index]["icon"]
            id := Format("{1}_{2:02d}_{3:02d}", grp_id, r, c)
            x := (c - 1) * cell_width
                + ((cell_width - icon_size) / 2)
            y := group_margin + (r - 1) * cell_height
            if (r = 1)
            {
                y += ((cell_height - icon_size) / 2)
            }
            else
            {
                y += ((cell_height - icon_size) / 6)
            }
            Gui, Add, Picture
                , xs+%x% ys+%y% w%icon_size% h-1 v%id% hwnd%id% gClick
                , %ico%
            Grp[A_Index]["hwnd"] := %id%

            ; Label
            label := Grp[A_Index]["label"]
            x := (c - 1) * cell_width
            y += icon_size + 4
            Gui, Font, s11 w500 cNavy q5, %font%
            Gui, Add, Text
                , xs+%x% ys+%y% w%cell_width% Center BackgroundTrans
                , %label%

            ; Update row and column
            if (++c > cells_per_row)
            {
                r += 1
                c := 1
            }
        }

    }

    ;  -----------------------------------------------------------
    ; | Ctrl_Index
    ; |
    ; | ctrl is the windows handle for an object that was clicked
    ; | on.  Search for it in the Apps and Folders arrays.
    ; |
    ; | Return value is a 2-tuple.
    ; |   First item is either Apps or Folders
    ; |   Second item is the index in the array of the object
    ;  -----------------------------------------------------------
    Ctrl_Index(ctrl)
    {
        global Apps, Folders
        
        r := 0
        Loop % Apps.Length()
        {
            if (Apps[A_Index]["hwnd"] = ctrl)
            {
                r := [Apps, A_Index]
                break
            }
        }
        Loop % Folders.Length()
        {
            if (Folders[A_Index]["hwnd"] = ctrl)
            {
                r := [Folders, A_Index]
                break
            }
        }
        
        return r
    }

    ;  -----------------------------------------------------------
    ; | Click
    ; |
    ; | Handle mouse clicks.  Look up the handle of the object
    ; | that was clicked.
    ; |   If found in Apps, run the app.
    ; |   If found in Folders, open the folder.
    ;  -----------------------------------------------------------
    Click(CtrlHwnd, GuiEvent, EventInfo)
    {
        global Apps, Folders
        
        r := Ctrl_Index(CtrlHwnd)
        if (r)
        {
            grp := r[1], idx := r[2]
            if (grp = Apps)
            {
                exe := grp[idx]["cmd"]
                dir := grp[idx]["dir"]
                if (exe)
                    run, %exe%, %dir%
            }
            if (grp = Folders)
            {
                loc := grp[idx]["loc"]
                if (loc)
                    run, %loc%
            }
            Gui, Destroy
        }
    }

    ;  -----------------------------------------------------------
    ; | WM_RBUTTONUP
    ; |
    ; | Causes right mouse click on GUI to remove it.
    ;  -----------------------------------------------------------
    WM_RBUTTONUP()
    {
        Gui, Destroy
        return 0
    }

    ;  -----------------------------------------------------------
    ; | WM_MOUSEMOVE
    ; |
    ; | Triggered on WM_MOUSEMOVE message.
    ; | Causes cursor to become hand over icons.
    ;  -----------------------------------------------------------
    WM_MOUSEMOVE()
    {
        Gui, Submit, NoHide
        MouseGetPos,,,,ctrl, 2
        
        idx := Ctrl_Index(ctrl)
        if (idx)
        {
            hand := DllCall("LoadCursor", Uint, 0, Int, 32649)
            DllCall("SetCursor", "uint", hand)
            OnMessage(0x0020, "WM_SETCURSOR")
        }
        else
        {
            OnMessage(0x0020, "")
        }
    }

    ;  -----------------------------------------------------------
    ; | WM_SETCURSOR
    ; |
    ; | Triggered on WM_SETCURSOR message.  All this does is just
    ; | absorb the message so the HAND cursor doesn't change back
    ; | to the default cursor when the mouse moves over an icon.
    ;  -----------------------------------------------------------
    WM_SETCURSOR()
    {
        return true
    }

    ;  -----------------------------------------------------------
    ; | Console_Write
    ; |
    ; | Write a message to the SciTE console
    ;  -----------------------------------------------------------
    Console_Write(s)
    {
        stdout := FileOpen("*", "w")
        stdout.WriteLine(s)
    }



;  ======================================================================
; | Labels                                                               |
; |                                                                      |
; |                                                                      |
;  ======================================================================
GuiClose:
    Console_Write("Exiting.")
    Gui, Destroy
    return
There needs to be a file named cfg.txt in the directory where the script launches from, which contains information about what Apps and Folders to display in the pop-up. That directory should also contain a subdirectory named ico which contains the icon files (either .ico or .png) to display.

A minimal installation is contained in the attached zip file. It should work if you just unzip the zip, then run dtp.ahk from that location (assuming you have AutoHotkey installed, of course). This structure should display a pop-up that looks like the screenshot below.

As currently written, the script displays the pop-up if you double-click on empty desktop space, or hit Alt-Space (useful if the desktop is full of windows, and there isn't much empty desktop space). To open an App or Folder from the pop-up, click on an icon. To make the pop-up go away, either single-click on the empty desktop space outside the pop-up window, or right-click inside the pop-up window.
screenshot.png
screenshot.png (331.69 KiB) Viewed 1674 times
Attachments
dtp.zip
(234.49 KiB) Downloaded 116 times
Last edited by jfsturtz on 28 Mar 2020, 13:24, edited 1 time in total.
User avatar
huyaowen
Posts: 109
Joined: 28 Jul 2014, 01:15

Re: Popup to launch favorite Apps/Folders

28 Mar 2020, 00:26

Good job.Thanks!
If I change the cell's size,gui is shown in confusion.
, cell_width := 48
, cell_height := 48
User avatar
huyaowen
Posts: 109
Joined: 28 Jul 2014, 01:15

Re: Popup to launch favorite Apps/Folders

28 Mar 2020, 10:58

Missing an issue in readme as follow.
# <A|F><label><icon><cmd|loc><workingdir>
jfsturtz
Posts: 4
Joined: 26 Mar 2020, 16:16

Re: Popup to launch favorite Apps/Folders

28 Mar 2020, 13:09

huyaowen wrote:
28 Mar 2020, 00:26
Good job.Thanks!
If I change the cell's size,gui is shown in confusion.
, cell_width := 48
, cell_height := 48
Yeah, it's not quite that sophisticated. It makes some attempt to automatically adjust based on sizes of things, but it isn't that automatic.

If you're going to make cell_width and cell_height that small, you'll also need to decrease icon_size (line #186). It will also help keep the icons and the group borders from overlapping if you fiddle with the value of group_margin (line #133).

Also if you're going to make everything that small, you'll probably need to decrease the font size of the labels displayed below the icons (the s<n> parameter to the Gui call on line #215). It also doesn't automatically add vertical space if the label wraps to a second line, so if you're going to make the cell sizes that small, you may need to make the labels short enough to fit on one line.

By fiddling around with some values, you can maybe make it come out how you wish. See attached zip.
screenshot.png
screenshot.png (132.88 KiB) Viewed 1523 times
Attachments
dtp.zip
(98.12 KiB) Downloaded 68 times
jfsturtz
Posts: 4
Joined: 26 Mar 2020, 16:16

Re: Popup to launch favorite Apps/Folders

28 Mar 2020, 13:19

huyaowen wrote:
28 Mar 2020, 10:58
Missing an issue in readme as follow.
# <A|F><label><icon><cmd|loc><workingdir>
You are right. For Applications, you can specify a 5th item on the config file line that determines the working directory.

To be honest, I'd forgotten that was even possible. Thanks!

I don't suppose there's any way to go back and add it to the zip in the original post now ...
jfsturtz
Posts: 4
Joined: 26 Mar 2020, 16:16

Re: Popup to launch favorite Apps/Folders

28 Mar 2020, 13:27

huyaowen wrote:
28 Mar 2020, 10:58
Missing an issue in readme as follow.
# <A|F><label><icon><cmd|loc><workingdir>
Actually, it seems I can edit the original post and update the config file in the zip to reflect this. And I did.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 262 guests