Advertisement
pk3456

Ahk text expander 1.0

Apr 27th, 2023
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #SingleInstance, Force
  2.  
  3. #Hotstring *1 B0
  4. #LTrim
  5.  
  6. ::shape::
  7.     TextExpandList("
  8.    (
  9.        triangle
  10.        square
  11.        pentagon
  12.        hexagon
  13.        heptagon
  14.        octagon
  15.        nonagon
  16.        decagon
  17.        item 9
  18.        item 10
  19.        item 11
  20.        item 12
  21.        item 13
  22.        item 14
  23.        item 15
  24.        item 16
  25.        item 17
  26.        item 18
  27.        item 19
  28.        item 20
  29.    )")
  30. Return
  31.  
  32. ; example
  33. ::Num::
  34.     TextExpandList("
  35.    (
  36.        one
  37.        two
  38.        three
  39.        four
  40.        five
  41.        six
  42.    )")
  43. Return
  44.  
  45. #Hotstring *0 B1
  46. #LTrim Off
  47.  
  48. ; ----------------------------------------------------------------------------------------
  49.  
  50. #If WinExist("ahk_id" TextExpandList.GuiHwnd)
  51.  
  52.     Tab::TextExpandList.SelectDown(10)
  53.     +Down::TextExpandList.SelectDown(5)
  54.  
  55.     NumpadDown::
  56.     Down::
  57.         TextExpandList.SelectDown(1)
  58.     Return
  59.  
  60.     +Tab::TextExpandList.SelectUp(10)
  61.     +Up::TextExpandList.SelectUp(5)
  62.  
  63.     NumpadUp::
  64.     Up::
  65.         TextExpandList.SelectUp(1)
  66.     Return
  67.  
  68.     Enter::TextExpandList.Submit()
  69.  
  70.     Esc::TextExpandList.HideGui()
  71.  
  72. #If
  73.  
  74. TextExpandList(MatchList) {
  75.     TextExpandList.ShowGui(MatchList)
  76. }
  77.  
  78. ; ----------------------------------------------------------------------------------------
  79. class TextExpandList {
  80.  
  81.     static  Title := "Custom Text Expander"
  82.           , TypeSize := 12
  83.           , TypeFace := "Segoe UI"
  84.           , AutoInsertSpace := True
  85.  
  86.     ShowGui(MatchList) {
  87.         static GuiCreated, ItemHeight
  88.  
  89.         ; Make new gui if not created yet
  90.         if !GuiCreated {
  91.             static WS_EX_COMPOSITED    := 0x2000000
  92.             static WS_EX_LAYERED       := 0x0080000
  93.             static DOUBLE_BUFFER       := WS_EX_COMPOSITED | WS_EX_LAYERED
  94.             Gui New, -Caption +ToolWindow +AlwaysOnTop +hwndGuiHwnd -DPIScale +E%DOUBLE_BUFFER%, % this.Title
  95.             ; hwnd of Gui root window
  96.             this.GuiHwnd := GuiHwnd
  97.             Gui font, % "s" this.TypeSize, % this.TypeFace
  98.             Gui Margin, 0, 0
  99.             ; AltSubmit makes listbox save position instead of name
  100.             Gui Add, ListBox, VScroll x0 y0 +hwndHLB +AltSubmit
  101.             ; hwnd to listbox
  102.             this.HLB := HLB
  103.             ; get height of a single item in listbox
  104.             ItemHeight := this.LB_GetItemHeight(this.HLB)
  105.             GuiCreated := True
  106.  
  107.             ih := this.KeyHook := InputHook("V")
  108.             ih.KeyOpt("{All}", "+E")
  109.             ih.KeyOpt("1234567890", "-E +SN")
  110.             ih.KeyOpt("{LCtrl}{RCtrl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{NumLock}{CapsLock}{ScrollLock}{PrintScreen}", "-NE")
  111.             ih.OnKeyDown := ObjBindMethod(TextExpandList, "OnKeyDown_TextExpandLB")
  112.             ih.OnEnd := ObjBindMethod(TextExpandList, "OnEnd_TextExpandLB")
  113.         }
  114.  
  115.         Gui % this.GuiHwnd ":Default"
  116.         ; remember the hotstring used to trigger this function, remove the options and colons at the front
  117.         this.HotstringText := RegExReplace(A_ThisHotkey, "^:.*:")
  118.  
  119.         ; Add numbers
  120.         newList := ""
  121.         Loop Parse, MatchList, `n, `r
  122.         {
  123.             ; put | between each item
  124.             (newList != "") && newList .= "|"
  125.  
  126.             ; put the pos number in front of the current item
  127.             newList .= A_Index (A_Index < 10 ? "     " : "   ")
  128.  
  129.             ; append each item
  130.             newList .= A_LoopField
  131.  
  132.             ; pre-select the first item by adding a second |
  133.             (A_Index = 1) && newList .= "|"
  134.         }
  135.  
  136.         ; modify ListBox content
  137.         ; you need the leading | to replace the content
  138.         GuiControl, , % this.HLB, |%newList%
  139.  
  140.         ; get width
  141.         MaxWidth := 0
  142.         Loop Parse, newList, |
  143.         {
  144.             Width := this.TextWidth(A_LoopField, this.TypeFace, this.TypeSize)
  145.             MaxWidth := Max(Width, MaxWidth)
  146.         }
  147.         ; add a little room to the end of the item
  148.         MaxWidth += 20
  149.  
  150.         ; get height
  151.         GuiControlGet, List, Pos, % this.HLB
  152.         Items := this.LB_GetCount(this.HLB)
  153.         ClientHeight := this.GetClientHeight(this.HLB)
  154.         VisibleItems := ClientHeight // ItemHeight
  155.         if (Items > 10) {
  156.             Items := 10
  157.             MaxWidth += 15
  158.         }
  159.         ListH += (Items - VisibleItems) * ItemHeight
  160.  
  161.         ; resize control
  162.         GuiControl Move, % this.HLB, h%ListH% w%MaxWidth%
  163.  
  164.         caret := this.GetCaret()
  165.         Gui Show, % "NA AutoSize x" caret.x " y" caret.y + 40
  166.  
  167.         this.KeyHook.Start()
  168.         WinWaitClose % "ahk_id" this.GuiHwnd
  169.         (this.KeyHook.InProgress) && this.KeyHook.Stop()
  170.     }
  171.     ; ----------------------------------------------------------------------------------------
  172.     OnKeyDown_TextExpandLB(InputHook, VK, SC) {
  173.         static chooseNum := ""
  174.         static timeSinceLastKey := ""
  175.         key := GetKeyName(Format("vk{:x}", VK) Format("sc{:x}", SC))
  176.  
  177.         if (A_TickCount - timeSinceLastKey < 400)
  178.             chooseNum .= key
  179.         else
  180.             chooseNum := key
  181.  
  182.         LastItem := this.LB_GetCount(this.HLB)
  183.         if (chooseNum > 0 && chooseNum <= LastItem)
  184.             GuiControl Choose, % this.HLB, % chooseNum
  185.         else if (chooseNum = 0) ; 0 chooses 10
  186.             GuiControl Choose, % this.HLB, 10
  187.  
  188.         timeSinceLastKey := A_TickCount
  189.     }
  190.     OnEnd_TextExpandLB(InputHook) {
  191.         this.HideGui()
  192.     }
  193.     ; ----------------------------------------------------------------------------------------
  194.     ; function when item is selected
  195.     Submit() {
  196.         Gui % this.GuiHwnd ":Default"
  197.         ; remove AltSubmit to get text instead of pos
  198.         GuiControl -AltSubmit, % this.HLB
  199.         GuiControlGet, LBText,, % this.HLB
  200.         GuiControl +AltSubmit, % this.HLB
  201.         GuiControlGet LBPos,, % this.HLB
  202.         this.HideGui()
  203.  
  204.         ; use length of hotstring trigger to delete the hotstring word
  205.         SendInput % "{BS " StrLen(this.HotstringText) "}"
  206.  
  207.         ; send the item selected from listbox
  208.         ClipSend(RegExReplace(LBText, "^\d+ +"))
  209.  
  210.         if (this.AutoInsertSpace)
  211.             SendInput % A_Space
  212.     }
  213.     ; ----------------------------------------------------------------------------------------
  214.     ; function for selecting previous item
  215.     ; item selection wraps around to last item if first item is selected when pressing up
  216.     SelectUp(steps := 10) {
  217.         Gui % this.GuiHwnd ":Default"
  218.         GuiControlGet ItemPos,, % this.HLB
  219.         LastItem := this.LB_GetCount(this.HLB)
  220.         newPos := itemPos - steps
  221.         if (newPos < 1)
  222.             newPos := LastItem + 1 - steps
  223.         GuiControl Choose, % this.HLB, % newPos
  224.     }
  225.     ; ----------------------------------------------------------------------------------------
  226.     ; function for selecting next item
  227.     ; item selection wraps around to first item if last item is selected when pressing up
  228.     SelectDown(steps := 10) {
  229.         Gui % this.GuiHwnd ":Default"
  230.         GuiControlGet itemPos,, % this.HLB
  231.         LastItem := this.LB_GetCount(this.HLB)
  232.         newPos := itemPos + steps
  233.         if (newPos > LastItem)
  234.             newPos -= LastItem
  235.         GuiControl Choose, % this.HLB, % newPos
  236.     }
  237.     ; ----------------------------------------------------------------------------------------
  238.     HideGui() {
  239.         Gui % this.GuiHwnd ":Hide"
  240.         Hotstring("Reset")
  241.     }
  242.     ; ----------------------------------------------------------------------------------------
  243.     GetClientHeight(HWND) { ; Retrieves the height of the client area.
  244.         VarSetCapacity(RECT, 16, 0)
  245.         DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RECT)
  246.         Return NumGet(RECT, 12, "Int")
  247.     }
  248.     ; ----------------------------------------------------------------------------------------
  249.     LB_GetItemHeight(HLB) { ; Retrieves the height of a single list box item.
  250.     ; LB_GETITEMHEIGHT = 0x01A1
  251.     SendMessage, 0x01A1, 0, 0, , ahk_id %HLB%
  252.     Return ErrorLevel
  253.     }
  254.     ; ----------------------------------------------------------------------------------------
  255.     LB_GetCount(HLB) { ; Retrieves the number of items in the list box.
  256.         ; LB_GETCOUNT = 0x018B
  257.         SendMessage, 0x018B, 0, 0, , ahk_id %HLB%
  258.         Return ErrorLevel
  259.     }
  260.     ; ----------------------------------------------------------------------------------------
  261.     TextWidth(String, Typeface:="Segoe UI", Size:=12)
  262.     {
  263.         static hDC, hFont := 0, Extent
  264.         If !hFont
  265.         {
  266.             hDC := DllCall("GetDC","UPtr",0,"UPtr")
  267.             Height := -DllCall("MulDiv","Int",Size,"Int",DllCall("GetDeviceCaps","UPtr",hDC,"Int",90),"Int",72)
  268.             hFont := DllCall("CreateFont","Int",Height,"Int",0,"Int",0,"Int",0,"Int",400,"UInt",False,"UInt",False,"UInt",False,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"Str",Typeface)
  269.             hOriginalFont := DllCall("SelectObject","UPtr",hDC,"UPtr",hFont,"UPtr")
  270.             VarSetCapacity(Extent,8)
  271.         }
  272.         DllCall("GetTextExtentPoint32","UPtr",hDC,"Str",String,"Int",StrLen(String),"UPtr",&Extent)
  273.         Return, NumGet(Extent,0,"UInt")
  274.     }
  275.     ; ----------------------------------------------------------------------------------------
  276.     GetCaret() {
  277.         oc := A_CoordModeCaret
  278.         CoordMode Caret, Screen
  279.         ; get caret using A_CaretX and A_CaretY
  280.         ; if A_CaretX and A_CaretY cannot be found, use acc method
  281.         if (A_CaretX) {
  282.             caret := { x: A_CaretX, y: A_CaretY }
  283.         } else {
  284.             Sleep 20
  285.             activeHwnd := WinExist("A")
  286.             oAcc := this.Acc_ObjectFromWindow(activeHwnd, OBJID_CARET := 0xFFFFFFF8)
  287.             oAccCaret := this.Acc_Location(oAcc)
  288.             caret := { x: oAccCaret.x, y: oAccCaret.y }
  289.         }
  290.         ; revert caret coordmode to original
  291.         CoordMode Caret, % oc
  292.  
  293.         WinGetPos, X, Y, W, H, % "ahk_id " WinActive("A")
  294.  
  295.         ; no caret found?
  296.         ; try using the location of the focused acc
  297.         if (caret.x = 0) && (caret.y = 0) {
  298.             oAcc := this.Acc_Location(this.Acc_Focus(activeHwnd))
  299.             caret := {x: oAcc.x, y: oAcc.y}
  300.         }
  301.  
  302.         return caret
  303.     }
  304.     ; ----------------------------------------------------------------------------------------
  305.     ; https://www.autohotkey.com/boards/viewtopic.php?p=404749#p404749
  306.     ; the accFocus "call" returns an Object if successful and an error code if not.
  307.     ; So the while loop returns the last object were the accFocus call returns successfully.
  308.     Acc_Focus(hWnd)
  309.     {
  310.         Acc := this.Acc_ObjectFromWindow(hWnd)
  311.         While IsObject(Acc.accFocus)
  312.             Acc := Acc.accFocus
  313.  
  314.         return Acc
  315.     }
  316.     ; ----------------------------------------------------------------------------------------
  317.     Acc_WindowFromObject(pacc)
  318.     {
  319.         If  DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
  320.         Return  hWnd
  321.     }
  322.     ; ----------------------------------------------------------------------------------------
  323.     Acc_ObjectFromWindow(hWnd, idObject = -4)
  324.     {
  325.         static h := DllCall("LoadLibrary","Str","oleacc","Ptr")
  326.         If  DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
  327.         Return ComObjEnwrap(9,pacc,1)
  328.     }
  329.     ; ----------------------------------------------------------------------------------------
  330.     Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
  331.         try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
  332.         catch
  333.             return
  334.         Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
  335.         return {x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
  336.     }
  337. }
  338.  
  339. ClipSend(toSend) {
  340.     static prevClip := ""
  341.     prevClip := ClipboardAll
  342.     Clipboard := ""
  343.     Clipboard := toSend
  344.     ClipWait, 1
  345.     Send, {ctrl down}v{ctrl up}
  346.     SetTimer, RevertClipboard, -100
  347.     Return
  348.     RevertClipboard:
  349.        Clipboard := prevClip
  350.         prevClip := ""
  351.     Return
  352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement