1 (изменено: Gh0sTG0, 2021-09-16 17:21:02)

Тема: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Всем привет.
Есть chrome. В нем есть много вкладок.
Возможно ли как то определить, что текущая открытая вкладка - самая правая? Т.е та вкладка, на которую как то наводится Ctrl+9? Возможно через chrome.ahk.

2

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Попробуйте так:

ROLE_SYSTEM_PAGETABLIST := 0x0000003c
STATE_SYSTEM_SELECTED   := 0x00000002

ChromeAccObj := GetAccObjFromChrome( WinExist("ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe") )
AccTabList := SearchElement(ChromeAccObj, {Role: ROLE_SYSTEM_PAGETABLIST})
AccTabs := AccTabList.accChild(1)
Loop % tabsCount := AccTabs.accChildCount()
   accState := AccTabs.accChild(A_Index).accState(0)
until (accState & STATE_SYSTEM_SELECTED) && activeTabNumber := A_Index

MsgBox, % "Всего вкладок: "    . tabsCount . "`n"
        . "Активная вкладка: " . activeTabNumber

GetAccObjFromChrome(hWnd) {
   static WM_GETOBJECT := 0x3D, AccArray := []
   if !AccArray[hWnd] {
      try SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, ahk_id %hWnd%
      if !AccChrome := AccObjectFromWindow(hWnd)
         throw "Failed to get accessible object from hWnd " . Format("{:#x}", hWnd)
      AccArray[hWnd] := AccChrome
   }
   Return AccArray[hWnd]
}

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, AccObject := 0
   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
      AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
   Return AccObject
}

SearchElement(parentElement, params)
{ ; params — object like {Role: ROLE_SYSTEM_PUSHBUTTON := 0x2B, Name: "5"}
   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
}

AccChildren(Acc) {
   if ComObjType(Acc, "Name") != "IAccessible" {
      ErrorLevel := "Invalid IAccessible Object"
      Return
   }
   try childCount := Acc.accChildCount
   if !childCount
      Return
   Children := []
   VarSetCapacity(varChildren, childCount*(8 + A_PtrSize*2), 0)
   res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0
                                             , "Int", childCount, "Ptr", &varChildren, "IntP", childCount)
   if (res != 0) {
      ErrorLevel := "winapi AccessibleChildren failed"
      Return
   }
   Loop % childCount  {
      offset := (A_Index - 1)*(A_PtrSize*2 + 8)
      _child := NumGet(varChildren, offset + 8)
      if NumGet(varChildren, offset) != (VT_DISPATCH := 9)
         child := _child
      else
         child := AccQuery(_child), ObjRelease(_child)
      Children.Push(child)
   }
   Return 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)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: Gh0sTG0, 2021-09-17 19:43:14)

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

teadrinker Вроде работает, спасибо.
Upd: Расширения топ... Часть из них обрабатывается как еще одна, n+1 вкладка примерно в 50% случаев.
Upd2: Или это не расширения о__0

4

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Замените код на такой.

ROLE_SYSTEM_PAGETABLIST := 0x0000003c
STATE_SYSTEM_SELECTED   := 0x00000002

ChromeAccObj := GetAccObjFromChrome( WinExist("ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe") )
AccTabList := SearchElement(ChromeAccObj, {Role: ROLE_SYSTEM_PAGETABLIST})
AccTabs := AccTabList.accChild(1)
tabsCount := activeTabNumber := 0
Loop % AccTabs.accChildCount()
{
   if (AccTabs.accChild(A_Index).accRole(0) = 37)   ; ROLE_SYSTEM_PAGETAB
   {
      if (activeTabNumber = 0) and (AccTabs.accChild(A_Index).accState(0) & STATE_SYSTEM_SELECTED)
         activeTabNumber := A_Index
      tabsCount++
   }
}
MsgBox, % "Всего вкладок: "    . tabsCount . "`n"
        . "Активная вкладка: " . activeTabNumber

5 (изменено: Gh0sTG0, 2021-09-19 01:04:11)

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Malcev Первый код продолжает работать, выдавая на 1 вкладку больше. Иногда не выдавая. Решил проблему тем, что мой код IFает на последней и, временами, предпоследней вкладке (2 из 50+ это :смайликпалецвверх:)

Post's attachments

2021-09-18_23-46-17.png
2021-09-18_23-46-17.png 10.98 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

6

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Не знаю, что у вас понаписано на 350 строк.
У меня мой вариант работает без ошибок.

7 (изменено: Gh0sTG0, 2021-09-19 01:14:23)

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Malcev
Запихнул в нулевый файл, действительно работает о__0
Пойду разбираться как же так, хн...

Ок... Почему то этой версии кода надо поспать не меньше 300 после ^w чтобы начать работать... Мб старой версии это тоже помогло бы и она просто цепляла недозакрывшуюся вкладку в число существующих, хз.

8 (изменено: Gh0sTG0, 2023-07-20 16:22:14)

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Malcev Добрый день.
Почему то оно не работает?
В хроме чего то изменилось?

Мой код (весь тестовый файл, у меня открыто одно окно хрома не от админа, в нем с десяток вкладок):


F2::
{
	ROLE_SYSTEM_PAGETABLIST := 0x0000003c
	STATE_SYSTEM_SELECTED   := 0x00000002

	ChromeAccObj := GetAccObjFromChrome( WinExist("ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe") )
	AccTabList := SearchElement(ChromeAccObj, {Role: ROLE_SYSTEM_PAGETABLIST})
	AccTabs := AccTabList.accChild(1)
	tabsCount := activeTabNumber := 0
	Loop % AccTabs.accChildCount()
	{
	   if (AccTabs.accChild(A_Index).accRole(0) = 37)   ; ROLE_SYSTEM_PAGETAB
	   {
	      if (activeTabNumber = 0) and (AccTabs.accChild(A_Index).accState(0) & STATE_SYSTEM_SELECTED)
	         activeTabNumber := A_Index
	      tabsCount++
	   }
	}
	MsgBox, % "Всего вкладок: "    . tabsCount . "`n"
	        . "Активная вкладка: " . activeTabNumber
	Return
}

GetAccObjFromChrome(hWnd) {
   static WM_GETOBJECT := 0x3D, AccArray := []
   if !AccArray[hWnd] {
      try SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, ahk_id %hWnd%
      if !AccChrome := AccObjectFromWindow(hWnd)
         throw "Failed to get accessible object from hWnd " . Format("{:#x}", hWnd)
      AccArray[hWnd] := AccChrome
   }
   Return AccArray[hWnd]
}

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, AccObject := 0
   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
      AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
   Return AccObject
}

SearchElement(parentElement, params)
{ ; params — object like {Role: ROLE_SYSTEM_PUSHBUTTON := 0x2B, Name: "5"}
   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
}

AccChildren(Acc) {
   if ComObjType(Acc, "Name") != "IAccessible" {
      ErrorLevel := "Invalid IAccessible Object"
      Return
   }
   try childCount := Acc.accChildCount
   if !childCount
      Return
   Children := []
   VarSetCapacity(varChildren, childCount*(8 + A_PtrSize*2), 0)
   res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0
                                             , "Int", childCount, "Ptr", &varChildren, "IntP", childCount)
   if (res != 0) {
      ErrorLevel := "winapi AccessibleChildren failed"
      Return
   }
   Loop % childCount  {
      offset := (A_Index - 1)*(A_PtrSize*2 + 8)
      _child := NumGet(varChildren, offset + 8)
      if NumGet(varChildren, offset) != (VT_DISPATCH := 9)
         child := _child
      else
         child := AccQuery(_child), ObjRelease(_child)
      Children.Push(child)
   }
   Return 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)
}

При нажатии F2 стабильно выдает "всего вкладок 0, активная вкладка 0", пробовал запускать скрипт и от админа, и без.

PS и можно ли отсюда как то вынуть id вкладок?

9

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Скачайте acceexplorer 2 и проанализируйте, что вы получаете этим кодом и что следует заменить.

Gh0sTG0 пишет:

можно ли отсюда как то вынуть id вкладок?

Нельзя.

10

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Malcev
Ага, спасибо.

11

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Ну и в коде 2 ошибки.
1) Это неправильно:

if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0

Надо так:

if DllCall("oleacc\AccessibleObjectFromWindow", "uptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0

2) Это неправильно:

ChromeAccObj := GetAccObjFromChrome( WinExist("ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe") )

Надо так:

ChromeAccObj := GetAccObjFromChrome( WinExist("ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe", "Chrome Legacy Window") )

12

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Malcev пишет:

1) Это неправильно:

Если имеешь в виду "Ptr" и "uptr", то вроде без разницы. В DllCall главное правильно указать размерность, а знаковое значение или беззнаковое по идее определит сама winapi-функция.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Будет разница:
https://www.autohotkey.com/boards/viewt … mp;t=89745

14

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

А разве может быть хэндл окна Хрома больше UInt ? Я так понял, это какая-то внутренняя проблема AHK, когда возвращаются такие хэндлы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

15

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Я обнаружил данный баг, когда автоматизировал программу, которая во время автоматизации постоянно создавала и уничтожала свои дочерние окна.
И в какой-то момент новые окна получали хэндл больше чем uint.

16

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Не совсем понятно, где баг, в программе, или в AHK при получении хэндла. Так-то они должны быть 32 битными.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17 (изменено: Malcev, 2023-07-20 19:30:00)

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Как я понимаю, для каждого 64 бит процесса Windows, после примерно 32000 окон созданных данным процессом, возвращает хендл окна в виде 0xffffffffhwnd, а автохотки преобразует хендл в строку и не обрезает биты.
При этом при использовании внутренних команд ахк с таким хендлом работает нормально (с обрезанным нет), а при вызове dllcall нужно либо отрезать либо передавать как uptr.

18

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Ясно, похоже, так и есть. Но на AHK v2 вроде проблема отсутствует:

#Requires AutoHotkey v2

Loop {
    ToolTip A_Index
    wnd := Gui()
    if InStr(Format('{:#x}', wnd.hwnd), '0xffffffff') {
        MsgBox Format('{:#x}', wnd.hwnd)
    }
    wnd.Destroy()
}

В случае с Хромом вряд ли это имеет значение, поскольку маловероятно, что у его процесса создано больше 32000 окон. Но в общем случае, конечно, не помешает знать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

Re: AHK: Возможно ли определить что текущая вкладка chrome - самая правая?

Да, на ahk v2 lexikos этот баг пофиксил.