There are now 4 additional options
- bEffectOpen + bEffectOpenTime
- bEffectClose + bEffectCloseTime
Enter one of the following options for show and hide GUI effect:
C=CENTER
B=BLEND
S=SLIDE
- For slide effect include SD for slide down or SR to slide from left to right or SU=up SL=slide right to left
Includes also a Fix for SciTE4AutoHotkey toolbar
I had to include SetFormat,integerfast,D in ListBoxAdjustHSB+GetListBoxItem
/* TheGood
TillaGoto - Go to functions and labels in your script
*/
;_________________________________
;CONFIGURATION
uHotkey := "F1" ;Specify the hotkey you want to use to call up the GUI
bUseMButton := True ;Set to True to enable the middle mouse button as a hotkey to call up the GUI.
;More importantly, this also allows you to go to a function/label simply by
;pressing the middle mouse button on the function/label name.
;Set to False to disable it.
iCancelWait := 300 ;Specify in milliseconds the amount of time the middle mouse button should be
;depressed while the GUI is showing for the GUI to close without selection.
;If the middle mouse button is pressed for any amount shorter than that, the
;selection is validated.
iGUIWidth := 250 ;Specify the width of the GUI
iGUIHeight := 15 ;Specify, in number of rows, the height of the listbox
iTransparency := 255 ;Specify the transparency of the GUI. Preferably divisible by 15. Put 255 for no
;transparency at all (consumes less resources). Put 0 to disable fade-in effect.
bQuickMode := True ;Set to True to make TillaGoto go straight to showing the GUI and exit on close.
bPosLeft := True ;Position left side instead right
bEffectOpen = SRD ;CENTER=C, BLEND=B, SLIDE=S (HOR_POSITIVE=L || HOR_NEGATIVE=R || VER_POSITIVE=D || VER_NEGATIVE=U)
bEffectTimeOpen := 200 ;Time for the effect when showing GUI
bEffectClose = SLU ;Same as for EffectOpten, for example SU or C or B
bEffectTimeClose := 100 ;Time for the effect when closing Gui
bMatchEverywhere := True ;Set to False for matching to occur only at the beginning of the label/function
;name. Set to True for matching to occur anywhere in the label/function name. As
;well, multiple words can be specified. For example, typing "Dog Cat" will match
;any label/function containing those words anywhere in their name. This is useful
;to search for functions (or labels) only by typing "() FunctionName".
sActiveWindow := "SciTE4AutoHotkey" ;Regular expression which should match the window of the editor
;containing the Scintilla control. Use "ahk - SciTE4AutoHotkey"
;for SciTE4AutoHotkey
sScintillaClass := "Scintilla" ;Class name of the Scintilla control. Exclude instance number.
;______________________________________
;DO NOT CHANGE ANYTHING BELOW THIS LINE
#Include %A_ScriptDir%\RemoteBuf.ahk
#EscapeChar @
#SingleInstance Force
SetTitleMatchMode, RegEx
;Create GUI
Gui, +AlwaysOnTop +Border +ToolWindow +LastFound -Caption
Gui, Font, s8, Courier New
Gui, Margin, 2, 2
Gui, Add, Edit, w%iGUIWidth% h20 vtxtSearch gtxtSearch_Event hwndhtxtsearch,
Gui, Add, ListBox, Sort wp r%iGUIHeight% vlblList glblList_Event hwndhlblList +HScroll,
hGui := WinExist()
;Get scrollbar width
SysGet, SM_CXVSCROLL, 2
;Catch WM_INPUT, WM_KEYDOWN and WM_MOUSEWHEEL
OnMessage(255, "GUIInteract")
OnMessage(256, "GUIInteract")
OnMessage(522, "GUIInteract")
;Register the mouse with RIDEV_INPUTSINK
HID_Register(1, 2, hGui, 0x00000100)
;Check if we're in quick mode
If bQuickMode {
;Check if Notepad++ is active
hNPP := WinActive(sActiveWindow)
If Not hNPP
If !WinActive("AHKToolbar4SciTE") {
ExitApp
} else {
WinActivate,%sActiveWindow%
hNPP:=WinExist(sActiveWindow)
}
If Not hNPP
ExitApp
bExitOnClose := True
Gosub SummonGUI
} Else bExitOnClose := False
;Main monitoring loop
Loop {
Sleep, 200
;Check if Notepad++ is active
h := WinActive(sActiveWindow)
;Skip the loop if Notepad++ is not active
If Not h And Not WinActive("ahk_id " hGui) {
;Turn off hotkeys
Hotkey, %uHotkey%, SummonGUI, Off
;Hide GUI if showing
If bShowing
Gosub, GuiEscape
hNPP := 0 ;Reset value
Continue
;Check if we just found a new window
} Else If (h <> hNPP) And Not WinActive("ahk_id " hGui) {
;Remember the newfound Notepad++ window and script
hNPP := h
;Turn on hotkeys
Hotkey, %uHotkey%, SummonGUI, On
}
}
;------------\
;GUI related |
;------------/
;User summoned the GUI
SummonGUI:
;Check if we're already showing
If bShowing {
If bWheeled
Goto SelectItem
bWheeled := True ;So that if the user presses the hotkey again,
;the first item selected will be validated
ControlFocus,, ahk_id %htxtSearch%
Return
}
;Get handle to focused control
ControlGetFocus, cSci, ahk_id %hNPP%
;Check if it fits the class name
If InStr(cSci, sScintillaClass)
ControlGet, hSci, Hwnd,, %cSci%, ahk_id %hNPP%
Else Return
Gosub, AnalyseScript
;Check if we're doing CheckOnClick
If bCheckClick {
bCheckClick := False
If CheckTextClick(clickX, clickY)
Return
}
;Check if text is selected
s := Sci_GetSelText(hSci)
If (s <> "") And Not InStr(s, "@n") {
;Copy the selected text in the textbox
GuiControl,, txtSearch, %s%
;Create a list based on sel
CreateList(s)
;Check if it's just one match. If so, go to it. LB_GETCOUNT.
SendMessage, 395, 0, 0,, ahk_id %hlblList%
If (ErrorLevel = 1)
Goto SelectItem
;Select all. EM_SETSEL
SendMessage, 177, 0, -1,, ahk_id %htxtSearch%
} Else { ;Otherwise, empty the textbox and show the whole list
GuiControl,, txtSearch,
CreateList()
}
;Get window info
WinGetPos, iX, iY,,, ahk_id %hNPP%
ControlGetPos, sX, sY, sW, sH, %cSci%, ahk_id %hNPP%
iX += sX + sW - (iGUIWidth + 6) - SM_CXVSCROLL
iY += sY + 2
If bPosLeft
Gui, Show, Hide AutoSize x5 y%iY%
else
Gui, Show, Hide AutoSize x%iX% y%iY%
bShowing := True
AnimateWindow(hGui,bEffectTimeOpen,"A" . bEffectOpen)
If Not iTransparency Or (iTransparency = 255) ;Turn off if opaque
WinSet, Transparent, OFF, ahk_id %hGui%
Else
WinSet, Transparent, %iTransparency%, ahk_id %hGui%
WinActivate, ahk_id %hGui%
ControlFocus,, ahk_id %htxtSearch%
Return
GuiEscape:
bShowing := False
bWheeled := False
AnimateWindow(hGui,bEffectTimeClose,"H". bEffectClose)
Gui, Show, w0 h0
Gui,Cancel
Gui,Hide
If bExitOnClose
ExitApp
EmptyMem()
Return
;Incremental searching
txtSearch_Event:
If bShowing {
GuiControlGet, s,, txtSearch
CreateList(s)
}
Return
lblList_Event:
If (A_GuiEvent <> "DoubleClick")
Return
SelectItem:
;Get selected item index. LB_GETCURSEL
SendMessage, 0x188, 0, 0,, ahk_id %hlblList%
s := GetListBoxItem(hlblList, ErrorLevel)
;Check if it's a label or a function
StringRight, t, s, 1
If (t = ":") {
Loop %sLabels0% {
If (sLabels%A_Index% = s) {
l := sLabels%A_Index%_Line
Break
}
}
} Else {
Loop %sFuncs0% {
If (sFuncs%A_Index% = s) {
l := sFuncs%A_Index%_Line
Break
}
}
}
;Call up the line in the Scintilla control
ShowLine(l)
Goto GuiEscape ;Done
Return
AnimateWindow(hwnd,time,options){
local H:=0x10000, A:=0x20000,C:=0x10, B:= 0x80000,S:=0x40000,R:= 0x1, L:=0x2, D:=0x4, U:=0x8,O:="HACBSLURD",opt:="",Format:=""
format:=A_FormatInteger
SetFormat, IntegerFast, Hex
opt := 0x0 + 0
Loop,parse,Options
If InStr(O,A_LoopField)
opt |= %A_LoopField%
If opt
DllCall("AnimateWindow", "UInt", hwnd, "Int", time, "UInt", opt)
SetFormat, IntegerFast,%A_FormatInteger%
}
GUIInteract(wParam, lParam, msg, hwnd) {
Local iCount, flags, bDown, bUp, sControl, cX, cY
Static bIgnoreUp := False
Critical
;Check which message it is
If (msg = 256) { ;WM_KEYDOWN
IfEqual wParam, 13, Gosub SelectItem ;Enter
;Check if it's the textbox
If (hwnd = htxtSearch) {
If (wParam = 38) {
ControlFocus,, ahk_id %hlblList%
If Not WrapSel(True)
SendInput {Up}
} Else If (wParam = 40) {
ControlFocus,, ahk_id %hlblList%
If Not WrapSel(False)
SendInput {Down}
}
} Else If (hwnd = hlblList) { ;Make up/down wrap around
If (wParam = 38) Or (wParam = 40)
Return WrapSel(wParam = 38) ? True : ""
}
} Else If (msg = 522) And (hwnd = htxtSearch) { ;WM_MOUSEWHEEL
bWheeled := True
;Sign it if needed
wParam := wParam > 0x7FFFFFFF ? -(~wParam) - 1 : wParam
;Get notches turned
wParam := (wParam >> 16) / 120
If (wParam > 0) {
Loop % Abs(wParam) { ;%
If Not WrapSel(True)
ControlSend,, {Up}, ahk_id %hlblList%
}
} Else {
Loop % Abs(wParam) { ;%
If Not WrapSel(False)
ControlSend,, {Down}, ahk_id %hlblList%
}
}
} Else If (msg = 255) { ;WM_INPUT
;Get flags
flags := HID_GetInputInfo(lParam, 20 | 0x0100)
;Check if middle mouse button is down/up
bDown := flags & 0x0010
bUp := flags & 0x0020
;To save time for most cases this branch will be executed
If Not (bDown Or bUp)
Return
If bDown And bShowing {
bIgnoreUp := True
SetTimer, GuiEscape, -%iCancelWait%
} Else If bUp And bShowing
Gosub SelectItem
Else If bUp And bUseMButton And Not bIgnoreUp And WinActive(sActiveWindow) {
;Get mouse data
MouseGetPos, clickX, clickY,, sControl
If InStr(sControl, sScintillaClass) {
ControlGet, hSci, Hwnd,, %sControl%, ahk_id %hNPP%
ControlGetPos, cX, cY,,, %sControl%, ahk_id %hNPP%
clickX -= cX, clickY -= cY
bCheckClick := True
}
Critical Off
Gosub SummonGUI
}
If bUp And bIgnoreUp
bIgnoreUp := False
}
}
WrapSel(bUp) {
Local iCount, iSel
;Get selected item index and count. LB_GETCOUNT. LB_GETCURSEL.
SendMessage, 395, 0, 0,, ahk_id %hlblList%
iCount := ErrorLevel
SendMessage, 392, 0, 0,, ahk_id %hlblList%
iSel := ErrorLevel
;Select the first/last item. LB_SETCURSEL
If bUp And (iSel = 0) {
SendMessage 390, iCount - 1, 0,, ahk_id %hlblList%
Return 1
} Else If Not bUp And (iSel = iCount - 1) {
SendMessage 390, 0, 0,, ahk_id %hlblList%
Return 1
}
Return 0
}
;-------------------\
;Scanning Functions |
;-------------------/
;Retrieves labels and functions of the script
AnalyseScript:
;Get full text
sScript := Sci_GetText(hSci)
;Prep it
BlankOutComments(sScript)
;Get labels and functions
GetScriptLabels(sScript)
GetScriptHotkeys(sScript)
GetScriptFunctions(sScript)
Return
;This sub analyses the script and add the labels in it to the array
GetScriptLabels(ByRef s) {
Local i, t
;Reset counter
sLabels0 := 0
i := 1
Loop {
;Get next label
i := RegExMatch(s, "m)^[[:blank:]]*\K[a-zA-Z0-9#_@\$\?\[\]]+:[[:blank:]]*$", t, i)
;Make sure we found something
If Not i
Break
;We found a label. Trim everything after the last colon
StringLeft t, t, InStr(t, ":", False, 0)
sLabels0 += 1 ;Increase counter
sLabels%sLabels0% := t ;Add to array
;Get line from pos
sLabels%sLabels0%_Line := LineFromPos(i)
;Set i to the beginning of the next line
i := InStr(s, "@n", False, i) + 1
If (i = 1)
Break
}
}
;This sub analyses the script and add the hotkeys in it to the array (uses the same array as labels)
GetScriptHotkeys(ByRef s) {
Local i, t
i := 1
Loop {
;Get next hotkey
i := RegExMatch(s, "m)^[[:blank:]]*\K[[:blank:]a-zA-Z0-9\Q#!^+&<>*~$`-=\[]';/\.,\E]+::", t, i)
;Make sure we found something
If Not i
Break
;We found a hotkey.
sLabels0 += 1 ;Increase counter
sLabels%sLabels0% := t ;Add to array
;Get line from pos
sLabels%sLabels0%_Line := LineFromPos(i)
;Set i to the beginning of the next line
i := InStr(s, "@n", False, i) + 1
If (i = 1)
Break
}
}
;This sub analyses the script and add the functions in it to the array
GetScriptFunctions(ByRef s) {
Local i, t
;Loop through the functions
sFuncs0 := 0 ;Prep counter
i := 1
Loop {
;Get the next function
i := RegExMatch(s, "m)^[[:blank:]]*\K[a-zA-Z0-9#_@\$\?\[\]]+(?=\(.*?\)\s*?\{)", t, i)
;Check if we found something
If (i = 0)
Break
;Make sure it's a valid function
If t Not In If,While
{ ;Increment counter
sFuncs0 += 1
sFuncs%sFuncs0% := t "()" ;Add the ()
sFuncs%sFuncs0%_Line := LineFromPos(i)
}
;Get the next function
i := InStr(s, "@n", False, i) + 1
If (i = 1)
Break
}
}
BlankOutComments(ByRef s) {
i := 0
Loop {
;Get next block
i := RegExMatch(s, "Psm)^[[:blank:]]*\K/\*.*?\r\s*\*/", len, i + 1)
;Check if we found anything
If Not i
Break
;Blank out comment
VarSetCapacity(blank, len, 32)
DllCall("RtlMoveMemory", UInt, &s + (i - 1), UInt, &blank, UInt, len)
}
;Get the comment flag used
i := RegExMatch(s, "m)^[[:blank:]]*#CommentFlag\K.*?(?=\r)", sCommentFlag)
If Not i
sCommentFlag := ";"
Else sCommentFlag = %sCommentFlag%
;Check if the very first line is a comment
If (SubStr(s, 1, StrLen(sCommentFlag)) = sCommentFlag) {
len := InStr(s, "@r") - 1
VarSetCapacity(blank, len, 32)
DllCall("RtlMoveMemory", UInt, &s, UInt, &blank, UInt, len)
}
i := 0
Loop {
;Get next comment
i := RegExMatch(s, "P)\s+\K\Q" sCommentFlag "\E.*?(?=\r)", len, i + 1)
;Check if we found anything
If Not i
Break
;Blank out comment
VarSetCapacity(blank, len, 32)
DllCall("RtlMoveMemory", UInt, &s + (i - 1), UInt, &blank, UInt, len)
}
}
;------------------\
;ListBox Functions |
;------------------/
CreateList(filter = "") {
Global sLabels0, sFuncs0, bMatchEverywhere, hlblList
;Clear
GuiControl,, lblList,|
;Disable redraw
GuiControl, -Redraw, lblList
;Autotrim
filter = %filter%
If (filter = "") { ;Split cases for speed
Loop %sLabels0%
GuiControl,, lblList, % sLabels%A_Index%
Loop %sFuncs0%
GuiControl,, lblList, % sFuncs%A_Index%
} Else {
;Split cases for speed
If bMatchEverywhere {
;Parse words
StringSplit, words, filter, %A_Space%
;Split cases for speed
If (words0 > 1) {
Loop %sLabels0% {
bMatch := True
i := A_Index
Loop %words0% {
bMatch := bMatch And InStr(sLabels%i%, words%A_Index%)
If Not bMatch
Break
}
If bMatch
GuiControl,, lblList, % sLabels%A_Index%
}
Loop %sFuncs0% {
bMatch := True
i := A_Index
Loop %words0% {
bMatch := bMatch And InStr(sFuncs%i%, words%A_Index%)
If Not bMatch
Break
}
If bMatch
GuiControl,, lblList, % sFuncs%A_Index%
}
;It's one word
} Else {
Loop %sLabels0%
If InStr(sLabels%A_Index%, filter)
GuiControl,, lblList, % sLabels%A_Index%
Loop %sFuncs0%
If InStr(sFuncs%A_Index%, filter)
GuiControl,, lblList, % sFuncs%A_Index%
}
} Else {
Loop %sLabels0%
If (InStr(sLabels%A_Index%, filter) = 1)
GuiControl,, lblList, % sLabels%A_Index%
Loop %sFuncs0%
If (InStr(sFuncs%A_Index%, filter) = 1)
GuiControl,, lblList, % sFuncs%A_Index%
}
}
;Add hscrollbar if necessary
ListBoxAdjustHSB(hlblList)
;Select the first item. LB_SETCURSEL
SendMessage 390, 0, 0,, ahk_id %hlblList%
;Redraw
GuiControl, +Redraw, lblList
}
ListBoxAdjustHSB(hLB) {
SetFormat,IntegerFast,D
;Declare variables (for clarity's sake)
dwExtent := 0
dwMaxExtent := 0
hDCListBox := 0
hFontOld := 0
hFontNew := 0
VarSetCapacity(lptm, 53)
;Use GetDC to retrieve handle to the display context for the list box and store it in hDCListBox
hDCListBox := DllCall("GetDC", "Uint", hLB)
;Send the list box a WM_GETFONT message to retrieve the handle to the
;font that the list box is using, and store this handle in hFontNew
SendMessage 49, 0, 0,, ahk_id %hLB%
hFontNew := ErrorLevel
;Use SelectObject to select the font into the display context.
;Retain the return value from the SelectObject call in hFontOld
hFontOld := DllCall("SelectObject", "Uint", hDCListBox, "Uint", hFontNew)
;Call GetTextMetrics to get additional information about the font being used
;(eg. to get tmAveCharWidth's value)
DllCall("GetTextMetrics", "Uint", hDCListBox, "Uint", &lptm)
tmAveCharWidth := NumGet(lptm, 20)
;Get item count using LB_GETCOUNT
SendMessage 395, 0, 0,, ahk_id %hLB%
;Loop through the items
Loop %ErrorLevel% {
;Get list box item text
s := GetListBoxItem(hLB, A_Index - 1)
;For each string, the value of the extent to be used is calculated as follows:
DllCall("GetTextExtentPoint32", "Uint", hDCListBox, "str", s, "int", StrLen(s), "int64P", nSize)
dwExtent := (nSize & 0xFFFFFFFF) + tmAveCharWidth
;Keep if it's the highest to date
If (dwExtent > dwMaxExtent)
dwMaxExtent := dwExtent
}
;After all the extents have been calculated, select the old font back into hDCListBox and then release it:
DllCall("SelectObject", "Uint", hDCListBox, "Uint", hFontOld)
DllCall("ReleaseDC", "Uint", hLB, "Uint", hDCListBox)
;Adjust the horizontal bar using LB_SETHORIZONTALEXTENT
SendMessage 404, dwMaxExtent, 0,, ahk_id %hLB%
}
GetListBoxItem(hLB, i) {
SetFormat,IntegerFast,D
;Get length of item. 394 = LB_GETTEXTLEN
SendMessage 394, %i%, 0,, ahk_id %hLB%
;Check for error
If (ErrorLevel = 0xFFFFFFFF)
Return ""
;Prepare variable
VarSetCapacity(sText, ErrorLevel, 0)
;Retrieve item. 393 = LB_GETTEXT
SendMessage 393, %i%, &sText,, ahk_id %hLB%
;Check for error
If (ErrorLevel = 0xFFFFFFFF)
Return ""
;Done
Return sText
}
;--------------------\
;Scintilla Functions |
;--------------------/
Sci_GetText(hSci) {
;Used constants
SCI_GETLENGTH := 2006
SCI_GETTEXT := 2182
;Retrieve text length
SendMessage SCI_GETLENGTH, 0, 0,, ahk_id %hSci%
iLength := ErrorLevel
;Open remote buffer (add 1 for 0 at the end of the string)
RemoteBuf_Open(hBuf, hSci, iLength + 1)
;Fill buffer with text
SendMessage SCI_GETTEXT, iLength + 1, RemoteBuf_Get(hBuf),, ahk_id %hSci%
;Read buffer
VarSetCapacity(sText, iLength)
RemoteBuf_Read(hBuf, sText, iLength + 1)
;We're done with the remote buffer
RemoteBuf_Close(hBuf)
Return sText
}
Sci_GetSelText(hSci) {
;Used constants
SCI_GETSELTEXT := 2161
;Get length
SendMessage SCI_GETSELTEXT, 0, 0,, ahk_id %hSci%
iLength := ErrorLevel
;Check if it's none
If (iLength = 1)
Return ""
;Open remote buffer
RemoteBuf_Open(hBuf, hSci, iLength)
;Fill buffer
SendMessage, SCI_GETSELTEXT, 0, RemoteBuf_Get(hBuf),, ahk_id %hSci%
;Prep var
VarSetCapacity(sText, iLength)
RemoteBuf_Read(hBuf, sText, iLength)
;Done
RemoteBuf_Close(hBuf)
Return sText
}
Sci_GetLineText(hSci, iLine) {
;Used constants
SCI_GETLINE := 2153
SCI_LINELENGTH := 2350
;Retrieve line length
SendMessage SCI_LINELENGTH, iLine, 0,, ahk_id %hSci%
iLength := ErrorLevel
;Open remote buffer (add 1 for 0 at the end of the string)
RemoteBuf_Open(hBuf, hSci, iLength + 1)
;Fill buffer with text
SendMessage SCI_GETLINE, iLine, RemoteBuf_Get(hBuf),, ahk_id %hSci%
;Read buffer
VarSetCapacity(sText, iLength)
RemoteBuf_Read(hBuf, sText, iLength + 1)
;We're done with the remote buffer
RemoteBuf_Close(hBuf)
;Trim off ending characters
sText := RegExReplace(sText, "\R")
Return sText
}
LineFromPos(pos) {
Global
;SCI_LINEFROMPOSITION
SendMessage, 2166, pos - 1, 0,, ahk_id %hSci%
Return ErrorLevel + 1
}
CheckTextClick(x, y) {
Local pos, line, linetext, i
;SCI_POSITIONFROMPOINTCLOSE
SendMessage, 2023, x, y,, ahk_id %hSci%
pos := ErrorLevel
;Check for error
If (pos = -1)
Return False
Else {
;SCI_LINEFROMPOSITION
SendMessage, 2166, pos, 0,, ahk_id %hSci%
line := ErrorLevel
;SCI_POSITIONFROMLINE
SendMessage, 2167, line, 0,, ahk_id %hSci%
pos -= ErrorLevel
;Get line text
linetext := Sci_GetLineText(hSci, line)
;Trim after the first illegal character
i := RegExMatch(linetext, "[^a-zA-Z0-9#_@\$\?\[\]]", "", pos + 1)
If i
StringLeft, linetext, linetext, i - 1
;Trim before the first illegal character
i := RegExMatch(StringReverse(linetext), "[^a-zA-Z0-9#_@\$\?\[\]]", "", StrLen(linetext) - pos + 1)
If i
StringTrimLeft, linetext, linetext, StrLen(linetext) - i + 1
;Check if it's a clean match
linetext .= "()"
Loop %sFuncs0% {
If (linetext = sFuncs%A_Index%) {
ShowLine(sFuncs%A_Index%_Line)
Return True
}
}
StringTrimRight, linetext, linetext, 2
linetext .= ":"
Loop %sLabels0% {
If (linetext = sLabels%A_Index%) {
ShowLine(sLabels%A_Index%_Line)
Return True
}
}
}
Return False
}
StringReverse(s) {
Loop, Parse, s
ret := A_LoopField ret
Return ret
}
ShowLine(line) {
Global
;Get the first visible line
SendMessage, 2152, 0, 0,, ahk_id %hSci%
If (ErrorLevel < line - 1) {
;Get the number of lines on screen. SCI_LINESONSCREEN
SendMessage, 2370, 0, 0,, ahk_id %hSci%
;Go to the line wanted + lines on screen. SCI_GOTOLINE
SendMessage, 2024, line - 1 + ErrorLevel, 0,, ahk_id %hSci%
}
SendMessage, 2024, line - 1, 0,, ahk_id %hSci%
}
;--------------\
;HID Functions |
;--------------/
HID_Register(UsagePage = False, Usage = False, Handle = False, Flags = 0) {
RIDEV_REMOVE := 0x00000001
RIDEV_EXCLUDE := 0x00000010
;Prep var
VarSetCapacity(uDev, 12)
;Check if hwnd needs to be null
bNull := (Flags & RIDEV_REMOVE) Or (Flags & RIDEV_EXCLUDE)
NumPut(UsagePage, uDev, 0, "UShort")
NumPut(Usage, uDev, 2, "UShort")
NumPut(Flags, uDev, 4)
NumPut(bNull ? 0 : Handle, uDev, 8)
;Call
r := DllCall("RegisterRawInputDevices", "UInt", &uDev, "UInt", 1, "UInt", 12)
;Check for error
If Not r {
MsgBox RegisterRawInputDevices call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return -1
}
Return 0
}
HID_GetInputInfo(InputHandle, Flag) {
Static uRawInput, iLastHandle := 0
RID_INPUT := 0x10000003
;Check if it's the same handle
If (InputHandle = iLastHandle) ;We can retrieve the data without having to call again
Return NumGet(uRawInput, Flag, HID_NumIsShort(Flag) ? (HID_NumIsSigned(Flag) ? "Short" : "UShort") : (HID_NumIsSigned(Flag) ? "Int" : "UInt"))
Else { ;We need to get a fresh copy
;Get raw data size
r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", RID_INPUT, "UInt", 0, "UInt*", iSize, "UInt", 16)
If (r = -1) Or ErrorLevel {
MsgBox GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
Return -1
}
;Prep var
VarSetCapacity(uRawInput, iSize)
;Get raw data
r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", RID_INPUT, "UInt", &uRawInput, "UInt*", iSize, "UInt", 16)
If (r = -1) Or ErrorLevel {
MsgBox GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
ErrorLevel := -1 ;Set errorlevel to fail
Return -1
} Else If (r <> iSize) {
MsgBox GetRawInputData did not return the correct size.`nSize returned: %r%`nSize allocated: %iSize%
ErrorLevel := -1 ;Set errorlevel to fail
Return -1
}
;Keep handle reference of current uRawInput
iLastHandle := InputHandle
;Retrieve data
Return NumGet(uRawInput, Flag, HID_NumIsShort(Flag) ? (HID_NumIsSigned(Flag) ? "Short" : "UShort") : (HID_NumIsSigned(Flag) ? "Int" : "UInt"))
}
Return 0
}
;Internal use only
HID_NumIsShort(ByRef Flag) {
If (Flag & 0x0100) {
Flag ^= 0x0100 ;Remove it
Return True
} Return False
}
;Internal use only
HID_NumIsSigned(ByRef Flag) {
If (Flag & 0x1000) {
Flag ^= 0x1000 ;Remove it
Return True
} Return False
}
;EmptyMem() by heresy
;http://www.autohotkey.com/forum/viewtopic.php?t=32876
EmptyMem(PID="AHK Rocks"){
pid:=(pid="AHK Rocks") ? DllCall("GetCurrentProcessId") : pid
h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
DllCall("CloseHandle", "Int", h)
}