1
votes

I'm using Firefox and I was looking for an autohotkey script which would enable me to skip the whole series of clicks when I bookmark a page in a specific folder and replace it with a single keyboard shortcut.

Although I've read forum threads on Autohotkey forum and here I still don't know how to make a working script that would reduce bookmarking a page to hitting a keyboard shortcut and the initial letter of the folder where I want to store that page. Using KeyWait command I've made it work for a single folder and don't know how to make it work for any letter or a number that I could possibly use as a name for a bookmark folder. Say I have a folder named XXXX, this script does send the webpage to the XXXX folder after hitting the assigned shortcut and the letter x (MouseClick command is needed to focus the window with folder in the Bookmark Dialog pane):

!+^w::
Send,^d
Sleep,400
MouseClick,Left,864,304
Sleep,400
KeyWait, x ,D    
Sleep, 400
Send,^{Enter}
return

I don't know how to make this script work for any letter or number, not only for a single one. Also a big problem with this script is that it blocks the keyboard until I hit X key. If I have that page bookmarked already, hitting escape to remove the bookmark pane will block the keyboard and I can unblock it only if I rerun the autohotkey script.

I've also tried using Input command as the contributors the Autohotkey forum pages suggested, but it didn't work either, because I don't understand how the Input command works. I did make it work for a single letter as the above script with KeyWait, but that's the best I could do. This script also blocks the keyboard until the letter is hit:

!+^w::
Send,^d
MouseClick,Left,864,304
Sleep,400
Input, Character, L1
If Character = t
Send, t
Sleep,400
Send,^{Enter}
return

Hope someone can help me with this, it would be convenient simplifying the bookmarking process in Firefox this way.

2
your second approach looks good to me ...? try to replace if character = t / send, t with a simple send %character%. If you want Input not to block the sent keys, use the V option (see ahkscript documentation -> input)phil294
Hi Blauhirn, thank you for the answer. Does the Input command work like KeyWait? I want the script to carry out the rest of the code after waiting for the input of a character. Confirming a bookmark in the Bookmark Dialog window is done by Ctrl+Enter, and I want to avoid that shortcut by having a script that will automate it for me.user5280114
yes, input "pauses" the script like keyWait. You stated L1, so after the first key press, it will continue instantly. The typed letter will be saved into Character.phil294

2 Answers

0
votes

I have a nice idea. This will open the add bookmark dialog and navigate you into the folder selection part and expand all folders. All you need to do is enter the folders name (or a part of it) and it will get selected automatically. When you're done, just hit enter.

!+^w::                      ;Hotkey: Ctrl+Alt+Shift+w
    Send, ^d                ;send Ctrl+d to open the add-bookmark dialog
    Sleep, 500              ;wait for the dialog to open
    Send, {Tab}{Tab}{Enter} ;navigate into the folder selection
    Sleep, 300              ;wait to make sure we are there
    Send,{Home}             ;select the first item in the list
                            ;The following line should expand all the folders so that you can just type the folders name to search for it
    Loop, 100 {             ;Increase the number if it doesn't expand all folders
        SendInput, {Right}{Down} ;expand folders
    }
    Send, {Home}            ;navigate to the first item in the list again
    Input, L, V L1 T2       ;wait until you start typing a folder name (if you just wait 2 seconds, the bookmark won't be created)
    If (ErrorLevel =  "Timeout") {
        Send, {Tab 5}       ;press tab 5 times to navigate to the cancel button
        Send, {Enter}       ;cancel the bookmark
        Return              ;end of the hotkey
    }
    Loop {                  ;wait until you haven't typed a new letter for 0.4 seconds
        Input, L, V L1 T0.4
        If (ErrorLevel =  "Timeout")
            Break
    }
    Send, {Tab 4}           ;press tab 4 times to navigate to the enter button
    Send, {Enter}           ;save the bookmark
Return
0
votes

My variant. Press f1 to create bookmark in folder test1. Press f2 to create bookmark in folder test2.

SetBatchLines, -1
Folders := {F1: "test1", F2: "test2"}
#IfWinActive, ahk_class MozillaWindowClass
F1::
F2::
Folder := Folders[A_ThisHotkey]
Send, ^d
AccFirefox := Acc_ObjectFromWindow(WinExist("ahk_class MozillaWindowClass"))
AccElem := SearchElement(AccFirefox, ROLE_SYSTEM_LISTITEM := 0x22, Folder, "")
AccElem.accDoDefaultAction(0)
sleep 100
Send {Enter}
msgbox done
return
#IfWinActive

SearchElement(ParentElement, params*)
{
   found := 1
   for k, v in params  {
      (k = 1 && ParentElement.accRole(0) != v && found := "")
      (k = 2 && ParentElement.accName(0) != v && found := "")
      (k = 3 && ParentElement.accValue(0) != v && found := "")
   }
   if found
      Return ParentElement

   for k, v in Acc_Children(ParentElement)
      if obj := SearchElement(v, params*)
         Return obj
}

Acc_Init()
{
    Static  h
    If Not  h
        h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}

Acc_ObjectFromWindow(hWnd, idObject = 0)
{
    Acc_Init()
    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
    Return  ComObjEnwrap(9,pacc,1)
}

Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
    try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}

Acc_Error(p="") {
    static setting:=0
    return p=""?setting:setting:=p
}

Acc_Children(Acc) {
    if ComObjType(Acc,"Name") != "IAccessible"
        ErrorLevel := "Invalid IAccessible Object"
    else {
        Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
        if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
            Loop %cChildren%
                i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
            return Children.MaxIndex()?Children:
        } else
            ErrorLevel := "AccessibleChildren DllCall Failed"
    }
    if Acc_Error()
        throw Exception(ErrorLevel,-1)
}