Jump to content

MenuBarLauncher


lod3n
 Share

Recommended Posts

This is my MenuBarLauncher, which I personally use instead of the Window's QuickLaunch Bar. You just create a bunch of shortcuts (or .urls, or whatever) in the subfolders within the included Shortcuts folder, and run it. It then generates a nice dropdown menu at the top of your screen with a menu for each subfolder, with a link to each item in that subfolder.

My favorite part of this is that it uses SHGetFileInfo to figure out exactly what Icon to show for the item, instead of mucking about in the registry (which doesn't account for all kinds of files very well). Much thanks to Holger for providing the MenuIcons demo, and for helping me figure out SHGetFileInfo.

Edit: Here is an updated version, which will only activate the menu if you set your mouse at the top within it's left and right borders, as per a suggestion below:

Edit: Now handles resizing using the edge anchors, and saves your desired xPosition and width in an INI file. Added a Regenerate menu command in case you modify the Shortcuts folder and want to see the changes reflected. Next I want to work on handling subdirectories in the shortcuts folder.

Edit: Updated code shown below supports subdirectories of any depth.

Edit: Fixed creeping width bug on regenerate, cleaned up mouse detection code using WindowFromPoint (via Larry's code).

Edit: Fixed the issue where it would not honor the Exit function, or load any item clicked on. It turns out that I had the menu item array hard coded to 100 items. This has since been resolved. Added a function to extract the correct icon for SUBFOLDERS too, if you customize your folder icons (I do), you will like it.

_linenums:0'>
; This is the updated version of MenuBarLauncher.au3, revision 6
; To use this, download the zip file below, and replace the contents of MenuBarLauncher.au3 with this code

TraySetIcon ( "shell32.dll", 39)
opt("ExpandEnvStrings",1)
#include <Array.au3>
#include <GUIConstants.au3>
#include <Process.au3>
#include <Constants.au3>
#include <Misc.au3>
#include "_Holger_MenuIcons.au3"
; most of this is ripped directly from Holger's Menu Icons demo

if _Singleton("MenuBarLauncher",1) = 0 Then
    sleep(1000) 
    if _Singleton("MenuBarLauncher",1) = 0 Then
        Exit
    EndIf
EndIf

; You have to set the menuWidth here, until I figure out a good way to determine
; the proper width automatically
global $menuWidth = IniRead("MenuBarLauncher.ini","values","menuWidth",400)

; you have to set the position here, use -1 to keep it centered on the monitor
; perhaps I will develop a configuration menu for this
global $xPosition = IniRead("MenuBarLauncher.ini","values","xPosition",-1)

ToolTip("MenuBarLauncher reading shortcuts...",$xPosition,0)

$oMenus = ObjCreate("Scripting.Dictionary")
$oDict = ObjCreate("Scripting.Dictionary")
$oShell= ObjCreate("Shell.Application")

; build the array of parent directories, *. ought to do it.
$shortcutdir = @scriptdir & "\shortcuts"
$foo = Run(@ComSpec & " /c dir *. /s /b", $shortcutdir, @SW_HIDE,$STDOUT_CHILD)
$output = ""
While 1
    $output &= StdoutRead($foo)
    If @error Then ExitLoop
Wend
$output = StringReplace($output,$shortcutdir,"")
$output = StringStripWS($output,3)
$aOutputD = StringSplit($output,@crlf,1)
_ArraySort ($aOutputD , 0 ,1)
;_ArrayDisplay($aOutputD,"Dirs")


; build the array of shortcut items
$shortcutdir = @scriptdir & "\shortcuts"
$foo = Run(@ComSpec & " /c dir *.* /s /b", $shortcutdir, @SW_HIDE,$STDOUT_CHILD)
$output = ""
While 1
    $output &= StdoutRead($foo)
    If @error Then ExitLoop
Wend
$output = StringReplace($output,$shortcutdir,"")
$output = StringStripWS($output,3)
$aOutput = StringSplit($output,@crlf,1)
_ArraySort ($aOutput , 0 ,1)


Dim $arMenuItems[$aOutputD[0]+$aOutput[0]][4] ; this had previously been hard coded to 100!
$arMenuItems[0][0] = 0
Dim $hMenuImageList = ImageList_Create(16, 16, BitOr($ILC_MASK, $ILC_COLOR32), 0, 1)


Dim $hGUI      = GUICreate('MenuBarLauncher', $menuWidth, 20,$xPosition,-5,BitOr($WS_POPUP,$WS_DLGFRAME,$WS_SIZEBOX),$WS_EX_TOOLWINDOW)
Dim $hMenuFont  = CreateMenuFont('MS Sans Serif')  ; Create a usable font for using in ownerdrawn menus
global $oldpos, $isresizing = false, $waithide = true
dim $oldpos[2]

#include "_gafrost_WinAnimate.au3"
#include "_MenuBar_Functions.au3"

; Register the messages for building and drawing ownerdrawn items
GUIRegisterMsg($WM_MEASUREITEM, 'MY_WM_MEASUREITEM')    ; Called by system at first for presetting the item properties
GUIRegisterMsg($WM_DRAWITEM, 'MY_WM_DRAWITEM')      ; Called by system to paint our items

; build the menu
global $menucount = 0
dim $Menus[1]
global $menuItemCount = 0
dim $MenuItems[1]

; create menus and menu subdirs
for $i = 1 to ubound($aOutputD)-1
    ;ConsoleWrite($aOutputD[$i] & @crlf)
    $aDirParts = StringSplit($aOutputD[$i],"\")
    $item = $aDirParts[$aDirParts[0]]
    $parentID = StringTrimRight($aOutputD[$i],stringLen($item))

    $menuID = $aOutputD[$i] & "\"
    if $parentID = "\" then
        ;ConsoleWrite("+[" & $menuID &"]" & @crlf)
        $oMenus.add($menuID,GUICtrlCreateMenu($item))
    Else
        ;ConsoleWrite("++[" & $parentID &"]["& $menuID &"]" &  @crlf)
        ;$oMenus.add($menuID,MY_GUICtrlCreateMenu($item, $oMenus.item($parentID), "shell32.dll", 3))
        $oMenus.add($menuID,MY_GUICtrlCreateMenu2($item, $oMenus.item($parentID), $shortcutdir&$aOutputD[$i]))
    EndIf
Next

;create menu items
for $i = 1 to ubound($aOutput)-1
    ;ConsoleWrite($shortcutdir&$aOutput[$i] & @crlf)
    
    $aDirParts = StringSplit($aOutput[$i],"\")
    $item = $aDirParts[$aDirParts[0]]
    $parentID = StringTrimRight($aOutput[$i],stringLen($item))
    
    if not $oMenus.exists($item) and $parentID <> "\" then
        $item = StringLeft($item,StringInStr($item,".",0,-1)-1)
        if $item <> "" then 
            ;ConsoleWrite("MenuItem: [" & $parentID &"]" & $item & @crlf)
            $newitem = MY_GUICtrlCreateMenuItem2($item, $oMenus.item($parentID), $shortcutdir&$aOutput[$i])
            $oDict.add($newitem,$shortcutdir&$aOutput[$i])
        EndIf
    EndIf
Next

$configmenu = GUICtrlCreateMenu("?")
$editItem = MY_GUICtrlCreateMenuItem("Edit", $configmenu, "shell32.dll", 21)
$regenItem = MY_GUICtrlCreateMenuItem("Regenerate", $configmenu, "shell32.dll", 146)
$exitItem = MY_GUICtrlCreateMenuItem("Exit", $configmenu, "shell32.dll", 27)

ToolTip("")
GUISetState(@SW_SHOW)
winmove($hGUI,"",$xPosition,-5,$menuWidth,26)


;********************************************************************
; The GUI Main Loop
;********************************************************************

While 1
    $nMsg = GUIGetMsg()
   
    Switch $nMsg
        Case $GUI_EVENT_CLOSE 
            quitter()
        Case $exitItem
            quitter()
        case $editItem
            ShellExecute($shortcutdir)
        case $regenItem
            $oShell.shellExecute(@ScriptFullPath,"","","","open")
            quitter()
    EndSwitch
   
    if $nMsg > 0 then
        ;ConsoleWrite($nMsg & @crlf)
        if $oDict.exists($nMsg) Then
            $oShell.shellExecute($oDict.item($nMsg),"","","","open")
            ;AutoIt's ShellExecute doesn't work here for all items. Don't know why.
        EndIf
    EndIf   
   
    ; sense the mouse position, pop up the menu if required
    MouseActivation($hGUI)
   
WEnd


quitter()

func quitter()
    ; Free's memory
    ImageList_Destroy($hMenuImageList)
    DeleteObject($hMenuFont)
    Exit
EndFunc

func MouseActivation($winHandle)
    $MousePos = MouseGetPos()
    if $MousePos[0] <> $oldpos[0] or $MousePos[1] <> $oldpos[1] then
        $oldpos[0] = $MousePos[0]
        $oldpos[1] = $MousePos[1]
        
        $WinPos = WinGetPos($winHandle)
        $state = WinGetState($winHandle)

        ;ConsoleWrite("Checking..." & TimerInit() & @crlf)
        if not BitAnd($state, 2) Then
            if $MousePos[1] = 0 and $MousePos[0] > $WinPos[0] and $MousePos[0] < $WinPos[0]+$WinPos[2]  then
                fadein($winHandle)
                fixPos($winHandle,$WinPos)
            EndIf
        else
            $hWinUnderMouse = DLLCall("user32.dll", "hwnd", "WindowFromPoint", "int", $MousePos[0], "int", $MousePos[1]) ; thanks Larry!
            if $hWinUnderMouse[0] <> $winHandle and $waithide = false Then
                fixPos($winHandle,$WinPos)
                fadeout($winHandle)
            EndIf
        EndIf   
        if $MousePos[0] > $WinPos[0] and $MousePos[0] < $WinPos[0]+$WinPos[2] and $MousePos[1] = 0 Then
            $waithide = False
        EndIf
        
    endif
EndFunc

func fixPos($handle,$pos)
    if $pos[2] <> $menuWidth Then 
        $menuWidth = $pos[2]
        IniWrite("MenuBarLauncher.ini","values","menuWidth",$pos[2])
    EndIf
    if $pos[0] <> $xPosition Then 
        $xPosition = $pos[0]
        IniWrite("MenuBarLauncher.ini","values","xPosition",$pos[0])
    EndIf
    winmove($handle,"",$pos[0],-5,$pos[2],26)
EndFunc


;********************************************************************
; Create a menu and set its style to OwnerDrawn
;********************************************************************
; this modification will allow setting a folder's icon correctly
Func MY_GUICtrlCreateMenu2($sMenuText, $nParentMenuID, $WhichFile)
    Local $MenuID = GUICtrlCreateMenu($sMenuText, $nParentMenuID)
    
    $arMenuItems[0][0] += 1
    
    $hMenu = GUICtrlGetHandle($nParentMenuID)
    
    $arMenuItems[$arMenuItems[0][0]][0] = $MenuID
    $arMenuItems[$arMenuItems[0][0]][1] = $sMenuText
    
        $hIcon  = getIconHandleByFile($WhichFile)
    $arMenuItems[$arMenuItems[0][0]][2] = ImageList_AddIcon($hMenuImageList, $hIcon)
        DestroyIcon($hIcon)
    
    ;$arMenuItems[$arMenuItems[0][0]][2] = AddMenuIcon($sIconFile, $nIconID)
    $arMenuItems[$arMenuItems[0][0]][3] = $hMenu
    
    SetOwnerDrawn($hMenu, $MenuID, $sMenuText)
    
    Return $MenuID
EndFunc

MenuIcons.zip

post-14785-1168988695_thumb.jpg

Edited by lod3n

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

Love the program, very cool idea.

Feature ideas:

-How about an option, like a context menu, that will allow it to be moved along the top of the screen?

-I think it might be nice if it would only pop down when the mouse is in that screen area, not if the mouse is just at the top of the screen.

Bugs:

-I'm assuming the ?->Exit is supposed to exit, but it doesn't for me (I am running latest beta)

-This could be because of a custom theme I'm running, but when I put my mouse to the top of the screen by a windows minimize/restore/or exit buttons, the mouse seems to do a "virtual click" and the window performs the action that the mouse is over (minimize/restore/exit). I hope that makes sense :)

Love it though, keep it up!

Link to comment
Share on other sites

I am running the latest.

I also have the issue of having to kill it with task manager to shut it down.

hitting "ESC" while I have it selected works for me, just not the Exit button.

Link to comment
Share on other sites

@webmedic, you're sure you're running the latest versions, as in AutoUpdateIt says so?

C:\Program Files\AutoIt3\beta\Extras\AutoUpdateIt\AutoUpdateIt.au3

As for the inability to quit, I don't know, I can't replicate that issue. Try switch statement to this:

Switch $nMsg
        Case $GUI_EVENT_CLOSE
            ExitLoop
        case $exitItem
            Msgbox(0,"","Testing, trying to quit")
            Exit
        case $editItem
            ShellExecute($shortcutdir)
    EndSwitch

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

@fisofo, in _MenuBar_Functions.au3 there is a function, fadeIn(), which does a MouseClick() to drop the menu after the window is activated. Why it's doing what you're describing, I have no idea. I don't have access to your custom theme, so I can't replicate your environment.

I did one of your suggestions though, see the first post for an updated version.

@frontmill, yes, it's always on the foreground, but it's hidden until you put your mouse in it's area at the top of the screen.

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

ok after much trouble shooting. I'm currently running 3.2.2.0 which is newer then the last beta so the beta does not matter right now. I have been running 3.2.2.0 since about a day or two after it hit the net. The only reason it was not sooner is becuase of the server overload I was unable to download it.

current beta is only 3.2.1.14.

I found the issue though it's that

$nMsg = GUIGetMsg()

is never getting any information other than 0 and some negative values. It is never returning the handle of any of the controls. This not only includes the exit and edit but every single menu item. Clicking on anything does nothing. The icons show up properly running the latest release but when compiled with the latest release the icons do not show up.

If there is naything else you would like to know just ask. Thanks.

Oh and in my debuging I already messed with the switch to see what was going on. Thats how I discovered that no handles were being returned.

So far many other things I do work fine and I have not had any of these issues so I'm kind of at a loss as to know why this one app acts like this. If I have time today I'll see if I can but hunt a little more.

If you would like like my version that outputs debuging info let me know and I'll post it here.

Link to comment
Share on other sites

Thanks for the info, I will try it with 3.2.2.0 and see what I can come up with. Perhaps there is a issue with 3.2.2.0 affecting ownerdrawn controls. I am not suprised to see an issue with this; I haven't seen much that's using Holger's menu icon stuff yet, and the SHGetFileInfo function has never before been implemented in AutoIt that I know of. I'm actually relieved that it works as well as it does. :)

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

@webmedic: If you could try out the updated code, I think your problem is fixed. I am guessing you added a bunch of items to the Shortcuts folder prior to running it? After I added a bunch more myself, I started running into what sounded like the same issue you were having. Hopefully it's sorted out now, but let me know if not.

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...