- Joined
- Jan 20, 2004
- Location
- Saltirelandia
Bryan recently put up a really cool blog post (Link Outdated / Removed), here's a sneak peek:
Anyway, I got to thinking, might be a cool topic for general discussion. So, voila!, this is what I've been doing in my spare time lately:
Scary huh? My wife thinks I'm having some kind of mid-life crisis.
Anyway, I got to thinking, might be a cool topic for general discussion. So, voila!, this is what I've been doing in my spare time lately:
Code:
; Stringbox.AHK: use specific hotstrings to open a listbox of associated text strings,
; choosing from the listbox will paste the selected string into the
; user's workspace.
;
; - fwiw, default listbox behaviour is perfectly adequate for general use.
;
; things to do:
; - ??? load hotstrings and/or string sets from an ini file. ???
; - ??? allow user to edit hotstring sets. ???
; - offer a "temp" list, user can add/remove items.
; - try key-value arrays for larger/less readable texts (eg. sign-offs, etc).
#SingleInstance Ignore ; won't start a new instance, the old instance rules.
#NoEnv
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Include LBLib.ahk ; low-level LB_*() functions to query and manipulate listboxes
Menu, Tray, NoStandard
Menu, Tray, Add , Pause, MyPause
Menu, Tray, Add , Suspend, MySuspend
Menu, Tray, Add , Reload, MyReload
Menu, Tray, Add , Exit, MyExit
Menu, Tray, Default, Pause
Menu, Tray, Click, 1 ; single-click on the tray icon will trigger the default action
Menu, Tray, Icon , t:\bin\AutoHotkey\_scripts\stringboxico.dll, 2, 1 ; green for Normal
Menu, Tray, Tip, Stringbox`nClick to Pause/unPause
CoordMode, Caret, Screen ; use absolute screen coordinates for the caret, since Gui also uses screen coord.
;
; globals and (faux) constants.
;
guiTitle := "Stringbox Items"
guiVarName := "MyLBox"
guiGosub := "MyLBoxGosub"
triggerText := ""
clipArray := [] ; a queue of recent Clipboard saves (see "OnClipboardChange:").
CONST_MAXCLIPS := 10 ; a faux constant to tell us the max number of clipboard items to remember.
firstPass := true ; some things are run once when the script is loaded, in the case of certain events
; this means the event handler is run at the beginning without the event actually having
; happened. this global tells us whether we've been through once before (since loading).
; MakeListbox: create, load and display a listbox.
; - we assume it is for temporary use, that it will be destroyed once
; the user is finished with it (a selection has been made or the user
; has cancelled out of it).
;
MakeListbox( arrayObj, sorted)
; arrayObj in assumed to be pre-loaded with strings that will be used to load a listbox
; sorted is a boolean: true = make it a sorted list, false = not sorted.
{
global
local lbNum := 0
local lbPixelW := 0
local longest := 0
local sortLB := ""
local xPos := 0
local yPos := 0
; place the listbox/ToolTip near the caret (in the user's workspace)
xPos := A_CaretX
yPos := A_CaretY + 10 ; seems to look better if we nudge it down a little
lbNum := arrayObj.MaxIndex()
; alert the user if there is nothing to put in a listbox.
if (lbNum = 0)
{
ToolTip , "Nothing to choose from!", %xPos%, %yPos%
Sleep , 2000
ToolTip
return
}
; for the purposes of sizing the listbox, find the length of the longest item to be displayed.
Loop , %lbNum%
{
loopFieldLen := StrLen( arrayObj[A_Index])
longest := (loopFieldLen > longest) ? loopFieldLen : longest
}
; calculate the list box width based on the StrLen of the longest element.
; 35 is (arbitrary) max chars to display,
; 8 is (assumed) number of pixels per character,
; so 35*8=280 is (arbitrary) max pixel width.
lbPixelW := (longest < 35) ? (longest * 8) : 280
sortLB := sorted ? "Sort" : ""
; have seen instances where we were trying to create a second listbox, don't.
IfWinNotExist , %GUITitle%
{
Gui, Margin , 1, 1
Gui -Caption +ToolWindow -Border
Gui, Font, s8, Verdana ; just hacking this in, makes the width calc'n more meaningful.
Gui, Color,, FFFFAA ; make it a contrasty colour so it stands out.
Gui, Add, ListBox, r%lbNum% w%lbPixelW% v%guiVarName% g%guiGosub% %sortLB%
}
Gui, Show, AutoSize x%xPos% y%yPos%, %GUITitle% ; x&y only work properly here if CoordMode for caret is Screen
SetListboxFromArrayObj( arrayObj)
LB_Set() ; defaults to selecting the first item.
}
MyLBoxGosub: ; see %guiGosub%
if A_GuiEvent = DoubleClick
{
ShowAndDie()
}
return
ShowAndDie()
; Send the current list selection back to the user and kill the listbox
; - needs "global" iot access the listbox.
{
global
Gui, Submit
Send , % %guiVarName% ; "%" forces expression evaluation
; done with the listbox now.
Gui, Destroy
}
; Esc to leave the listbox w/o selecting from it, in other words abort
;
GuiEscape:
IfWinExist , %GUITitle%
Gui, Destroy
; replace the text that triggered the listbox.
; (by default it is yoinked from the user's window when the hotstring fired)
Send , %triggerText%
return
; ----------------------------------------------------------------
; ----------- hotstrings sets get defined here -------------------
; ----------------------------------------------------------------
:c*:bbb:: ;case sensitive, auto-trigger
triggerText := "bbb" ; would have used "www" here but that's too commonly used elsewhere
localArray := []
;
; doing various work-related sign-off ("bye") strings
;
localArray.Insert( 1, "Regards,{enter}Max."
, "Regards,{enter}Max, Casinomeister.com"
, "Regards,{enter}Max Drayman{enter}Casinomeister.com, Player Complaints Manager and Forum Moderator")
MakeListbox( localArray, false)
return
:c*:ccc:: ;case sensitive, auto-trigger
triggerText := "ccc"
;
; listbox the current current contents of clipArray, our queue of the last CONST_MAXCLIPS clipboard items.
;
MakeListbox( clipArray, false)
return
:c*:ddd:: ;case sensitive, auto-trigger
triggerText := "ddd"
tStr := ""
localArray := []
nowDT := A_Now
;
; doing various useful date formats
;
FormatTime, tStr, nowDT, yyyy-MMM-dd
StringUpper, tStr, tStr
localArray.Insert( tStr)
FormatTime, tStr, nowDT, yyyy-MMM-dd-HH:mm
StringUpper, tStr, tStr
localArray.Insert( tStr)
FormatTime, tStr, nowDT, yyyyMMdd
localArray.Insert( tStr)
FormatTime, tStr, nowDT, yyyyMMdd-HH:mm
localArray.Insert( tStr)
MakeListbox( localArray, false)
return
:c*:jjj:: ;case sensitive, auto-trigger
triggerText := "jjj"
localArray := []
;
; doing casino licence jurisdictions
;
localArray.Insert( 1, "UK", "Panama", "Malta", "Kahnawake", "Isle of Man", "Gibraltar", "Cyprus", "Curaçao", "Costa Rica", "Belize", "Antigua-Barbuda", "Alderney")
MakeListbox( localArray, true)
return
:c*:sss:: ;case sensitive, auto-trigger
triggerText := "sss"
localArray := []
;
; doing casino software providers
;
localArray.Insert( 1, "Chartwell", "Boss Media", "Crypto", "OnGame", "NetEnt", "misc", "Proprietary", "Microgaming", "TopGame", "RTG", "Rival")
MakeListbox( localArray, true)
return
:c*:vvv:: ;case sensitive, auto-trigger
triggerText := "vvv" ; would have used "www" here but that's too commonly used elsewhere
localArray := []
;
; doing various work-related strings
;
localArray.Insert( 1, "Casinomeister","Casinomeister.com","Pitch-A-Bitch","bryan@casinomeister.com","max.drayman@casinomeister.com")
MakeListbox( localArray, false)
return
#IfWinExist, Stringbox Items ; turns on context-sensitivity for the following hotkeys (and hotstrings)
; - have to provide the actual text here because %GUITitle% isn't processed.
; catch {Enter} as a selection key, show it and quit the listbox.
~Enter::
ShowAndDie()
return
; Up and Down logic yoinked from SoLong&Thx4AllTheFish's post,
; "Endless scrolling in a listbox" ([url]http://www.autohotkey.com/forum/topic31618.html[/url])
;
Up::
oldPos := LB_Get() + 1
itemsInList := LB_GetCount()
ControlSend, ListBox1, {Up}, %GUITitle%
newPos := LB_Get() + 1
If (newPos = oldPos)
; the Up didn't change our position => we're at the top, wrap-around
LB_Set( LB_GetCount() - 1)
Return
Down::
oldPos := LB_Get() + 1
itemsInList := LB_GetCount()
ControlSend, ListBox1, {Down}, %GUITitle%
newPos := LB_Get() + 1
If (newPos = oldPos)
; the Down didn't change our position => we're at the bottom, wrap-around
LB_Set() ; defaults to position 'one'
Return
#IfWinExist ; turns off context-sensitivity for hotkeys and hotstrings
OnClipboardChange:
; docs say "The label also runs once when the script first starts", so looks like we need
; to know if this is the first time we've been here in order to avoid dropping something
; in the queue of saved clips that doesn't belong there.
if firstPass
{
firstPass := false
return
}
if (A_EventInfo = 1)
{
; Clipboard has some text (presumably new),
; append it to our saved list (adds to the end of the "queue").
clipArray.Insert( clipboard)
; limit the clipArray to a pre-specified number of items
if (clipArray.MaxIndex() > CONST_MAXCLIPS)
; toss the oldest item in our saved clips "queue".
clipArray.Remove( 1)
}
return
!Pause::
MySuspend:
Suspend , Toggle
if (A_IsSuspended)
{
Menu, Tray, Icon , %A_IconFile%, 1, 1 ; blue for Suspended
Menu, Tray, Tip, Stringbox (Suspended)`nclick to Pause/unPause
}
Else
{
Menu, Tray, Icon , %A_IconFile%, 2, 1 ; green for Normal
Menu, Tray, Tip, Stringbox`nclick to Pause/unPause
}
Return
; - some very strange stuff happens with the Pause key and/or when the script is Paused:
; to make a long story short it seems that whatever key(s) are used to Pause the script
; are not seen by a Paused script, iow you need to use something else to un-Pause. ???
;
; - ^Pause seems to cause "Process failed to respond; forcing abrupt termination...", sometimes. ???
MyPause:
if (A_IsPaused)
gosub , doPauseOff
Else
gosub , doPauseOn
Return
Pause:: ; ??? _sometimes_ it doesn't *@%£$%# work! behaves as if it never happened.
doPauseOn:
Menu, Tray, Icon , %A_IconFile%, 3, 1 ; red for Paused
Menu, Tray, Tip, Stringbox (Paused)`nclick to Pause/unPause
Pause, On
return
+Pause::
doPauseOff:
Pause, Off
Menu, Tray, Icon , %A_IconFile%, 2, 1 ; green for Normal
Menu, Tray, Tip, Stringbox`nclick to Pause/unPause
return
MyReload:
Reload
Return
F12::ListVars
^Escape::
MyExit:
ExitApp ; Kill the script if it gets too Scary.
Return
Scary huh? My wife thinks I'm having some kind of mid-life crisis.