Make tab active Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
hannahelappin
Posts: 53
Joined: 01 Jun 2019, 09:02

Make tab active

14 Jul 2019, 14:38

Hi,

I know how to make program window active and if not active run. But how do I do the same with a Mozilla tab, bring that website to the front/active. If not active run?

Many thanks
GEV
Posts: 1002
Joined: 25 Feb 2014, 00:50

Re: Make tab active

14 Jul 2019, 16:57

If you have the option
Show tab previews in the Windows taskbar
enabled
you can use e.g.

Code: Select all

F1::
	DetectHiddenWindows, On
	If WinExist("Ask For Help - AutoHotkey Community - Mozilla Firefox ahk_class MozillaTaskbarPreviewClass")
		WinActivate
	else
		Run https://www.autohotkey.com/boards/viewforum.php?f=76
return
hannahelappin
Posts: 53
Joined: 01 Jun 2019, 09:02

Re: Make tab active  Topic is solved

15 Jul 2019, 11:56

Thanks very much I’ll have a look tomorrow at work using your script.

Regards
hannahelappin
Posts: 53
Joined: 01 Jun 2019, 09:02

Re: Make tab active

15 Jul 2019, 12:23

Is it not possible without selecting that Firefox option? Not that it matters, just out of interest really.
GEV
Posts: 1002
Joined: 25 Feb 2014, 00:50

Re: Make tab active

15 Jul 2019, 16:30

Not that I know of.
The hidden windows of class MozillaTaskbarPreviewClass are only present if this option is enabled.
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Make tab active

15 Jul 2019, 18:53

You could also try this:

Code: Select all

SetBatchLines, -1
if !hWndFF := WinExist("ahk_class MozillaWindowClass ahk_exe firefox.exe")
   throw Exception("Firefox window not found")
accFF := AccObjectFromWindow(hWndFF, OBJID_CLIENT := 0xFFFFFFFC)
if !IsObject(accFF)
   throw Exception("Failed to get the accessible object")

tabText := "Make tab active - AutoHotkey Community"

accTabList := SearchElement(accFF, ROLE_SYSTEM_PAGETABLIST := 0x3C)
accTab := SearchElement(accTabList, ROLE_SYSTEM_PAGETAB := 0x25, tabText)
if !IsObject(accTab)
   Run, https://www.autohotkey.com/boards/viewtopic.php?f=76&t=66263
else {
   accTab.accDoDefaultAction(0)
   WinActivate
}
Return

SearchElement(ParentElement, params*)
{ ; Object Roles: https://goo.gl/ybRZT7
   found := 1
   for k, v in params  {
      try  {
         (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 AccChildren(ParentElement)
      if obj := SearchElement(v, params*)
         Return obj
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   static IID_IDispatch   := "{00020400-0000-0000-C000-000000000046}"
        , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
        , OBJID_NATIVEOM  := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
        , h := DllCall("LoadLibrary", Str, "oleacc", Ptr)
        
   VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
   DllCall("ole32\CLSIDFromString", Str, idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, Ptr, &IID)
   if DllCall("oleacc\AccessibleObjectFromWindow", Ptr, hWnd, UInt, idObject, Ptr, &IID, PtrP, pAcc) = 0
      Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}

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

AccQuery(Acc)  {
   static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
   try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
For me this works well.
hannahelappin
Posts: 53
Joined: 01 Jun 2019, 09:02

Re: Make tab active

16 Jul 2019, 02:33

Cool guys both work. Many thanks for that huge help for so many things :dance:
ufunk
Posts: 54
Joined: 17 Jan 2020, 13:45

Re: Make tab active

01 Feb 2020, 15:44

Hello,
the script above by teadrinker is very practical.
I tried to modify the teadrinker's code slightly to include wildcard characters so the full name of the tab title need not be matched exactly. This is the original 8th line in the code:

Code: Select all

tabText := "Make tab active - AutoHotkey Community"
I tried to use asterisks:

Code: Select all

tabText := "*AutoHotkey*"
I did this in order to find tabText where "AutoHotkey" is somewhere written in the tab title, but it doesn’t work like it should. I’ve searched in the forum but couldn’t find a solution.
Does anyone has an idea how to include wildcard characters in the search for the tab title (tabText).

Thank you
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Make tab active

01 Feb 2020, 18:25

Hi
This variant of SearchElement() allows using RegEx patterns for accName() and accValue():

Code: Select all

...
tabTextRegEx := ".*AutoHotkey.*"

accTabList := SearchElement(accFF, {Role: ROLE_SYSTEM_PAGETABLIST := 0x3C})
accTab := SearchElement(accTabList, {Role: ROLE_SYSTEM_PAGETAB := 0x25, Name: tabTextRegEx})
...
SearchElement(parentElement, params)
{
   found := true
   for k, v in params {
      try {
         if (k = "State")
            (!(parentElement.accState(0)    & v) && found := false)
         else if (k ~= "^(Name|Value)$")
            (!(parentElement["acc" . k](0) ~= v) && found := false)
         else if (k = "ChildCount")
            (parentElement["acc" . k]      != v  && found := false)
         else
            (parentElement["acc" . k](0)   != v  && found := false)
      }
      catch 
         found := false
   } until !found
   if found
      Return parentElement
   
   for k, v in AccChildren(parentElement)
      if obj := SearchElement(v, params)
         Return obj
}
...
ufunk
Posts: 54
Joined: 17 Jan 2020, 13:45

Re: Make tab active

02 Feb 2020, 14:28

Thank you very much, very well written. It's great having a place where people write such awesome scripts. It's a great help in my workflow.

If it is of use to other people, in the following is a working example of teadrinker's code with the webiste "Linguee" (because at this website sometimes "Linguee" is written in the beginning or in the middle of the tab name, depending on the page content):

Code: Select all

F3::
SetBatchLines, -1
if !hWndFF := WinExist("ahk_class MozillaWindowClass ahk_exe firefox.exe")
   throw Exception("Firefox window not found")
accFF := AccObjectFromWindow(hWndFF, OBJID_CLIENT := 0xFFFFFFFC)
if !IsObject(accFF)
   throw Exception("Failed to get the accessible object")

tabTextRegEx := ".*Linguee.*"  ;This is the tab title that is searched for.

accTabList := SearchElement(accFF, {Role: ROLE_SYSTEM_PAGETABLIST := 0x3C})
accTab := SearchElement(accTabList, {Role: ROLE_SYSTEM_PAGETAB := 0x25, Name: tabTextRegEx})
if !IsObject(accTab)
   Run, www.linguee.de  ;This is the website that is opend if it doesn't exist already
else {
   accTab.accDoDefaultAction(0)
   WinActivate
}
Return

SearchElement(parentElement, params)
{
   found := true
   for k, v in params {
      try {
         if (k = "State")
            (!(parentElement.accState(0)    & v) && found := false)
         else if (k ~= "^(Name|Value)$")
            (!(parentElement["acc" . k](0) ~= v) && found := false)
         else if (k = "ChildCount")
            (parentElement["acc" . k]      != v  && found := false)
         else
            (parentElement["acc" . k](0)   != v  && found := false)
      }
      catch 
         found := false
   } until !found
   if found
      Return parentElement
   
   for k, v in AccChildren(parentElement)
      if obj := SearchElement(v, params)
         Return obj
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   static IID_IDispatch   := "{00020400-0000-0000-C000-000000000046}"
        , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
        , OBJID_NATIVEOM  := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
        , h := DllCall("LoadLibrary", Str, "oleacc", Ptr)
        
   VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
   DllCall("ole32\CLSIDFromString", Str, idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, Ptr, &IID)
   if DllCall("oleacc\AccessibleObjectFromWindow", Ptr, hWnd, UInt, idObject, Ptr, &IID, PtrP, pAcc) = 0
      Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}

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

AccQuery(Acc)  {
   static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
   try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
TriXxieDK
Posts: 3
Joined: 23 Apr 2022, 04:51

Re: Make tab active

23 Apr 2022, 04:58

Thanks a lot guys, I've been using this script for a few days, but I've found that sometimes it'll open a new tab even though there is an existing, and I think it might be due to popup windows, meaning there will be more than one result to WinExists. Now I'm a total n00b with AutoHotKey, so any hints as to what the easiest way to iterate through all window matching results would be would be greatly appreciated, and confirmation if it is likely to be the issue with open popup windows?
Kind regards,
Martin
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Make tab active

23 Apr 2022, 09:51

Hey, @TriXxieDK, welcome to the forum!
Try this:

Code: Select all

tabTextRegEx := ".*Linguee.*"  ; This is the tab title that is searched for.
url := "www.linguee.de"        ; This is the website that is opend if it doesn't exist already

F3::
SetBatchLines, -1
WinGet, list, List, ahk_class MozillaWindowClass ahk_exe firefox.exe
if !list
   throw "Firefox window not found"

accTab := ""
Loop % list {
   if !accFF := AccObjectFromWindow(hFF := list%A_Index%, OBJID_CLIENT := 0xFFFFFFFC)
      continue
   accTabList := SearchElement(accFF, {Role: ROLE_SYSTEM_PAGETABLIST := 0x3C})
   if accTab := SearchElement(accTabList, {Role: ROLE_SYSTEM_PAGETAB := 0x25, Name: tabTextRegEx})
      break
}
if !accTab
   Run, www.linguee.de  
else {
   accTab.accDoDefaultAction(0)
   WinActivate, ahk_id %hFF%
}
Return

SearchElement(parentElement, params)
{
   found := true
   for k, v in params {
      try {
         if (k = "State")
            (!(parentElement.accState(0)    & v) && found := false)
         else if (k ~= "^(Name|Value)$")
            (!(parentElement["acc" . k](0) ~= v) && found := false)
         else if (k = "ChildCount")
            (parentElement["acc" . k]      != v  && found := false)
         else
            (parentElement["acc" . k](0)   != v  && found := false)
      }
      catch 
         found := false
   } until !found
   if found
      Return parentElement
   
   for k, v in AccChildren(parentElement)
      if obj := SearchElement(v, params)
         Return obj
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   static IID_IDispatch   := "{00020400-0000-0000-C000-000000000046}"
        , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
        , OBJID_NATIVEOM  := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
        , h := DllCall("LoadLibrary", Str, "oleacc", Ptr)
        
   VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
   DllCall("ole32\CLSIDFromString", Str, idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, Ptr, &IID)
   if DllCall("oleacc\AccessibleObjectFromWindow", Ptr, hWnd, UInt, idObject, Ptr, &IID, PtrP, pAcc) = 0
      Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}

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

AccQuery(Acc)  {
   static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
   try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
TriXxieDK
Posts: 3
Joined: 23 Apr 2022, 04:51

Re: Make tab active

24 Apr 2022, 14:26

Thank you very much @teadrinker! I'll give it a whirl the next few days and report back if it works as expected :D
TriXxieDK
Posts: 3
Joined: 23 Apr 2022, 04:51

Re: Make tab active

03 May 2022, 17:13

Works perfectly, thank you so much @teadrinker ❤️

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: alawsareps, Google [Bot], mebelantikjaya, mikeyww, RussF and 311 guests