1 (изменено: serzh82saratov, 2014-01-17 00:28:09)

Тема: AHK: ClassNN контрола по координатам

Вопрос заключается в том, как получить ClassNN и порядковый номер контрола в GUI стороннего приложения, также как это делает MouseGetPos, но не перемещая курсор, а указав просто координаты в окне.

Вариант с получением списка всех контролов, извлечением их координат и определением что они находятся в нужной точке, по многим причинам не подходит.

---

--Решено--

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2

Re: AHK: ClassNN контрола по координатам

Как же вы узнаете порядковый номер без пересчёта контролов? Этот номер не является частью имени класса, а обозначает позицию в наборе.

3

Re: AHK: ClassNN контрола по координатам

Как же вы узнаете порядковый номер без пересчёта контролов?

Я и не говорил, что список всех контролов не надо получать в принципе.
Я сказал, что вариант по определению координат контролов из списка подходящих под заданную точку в окне, не подходит.
Когда курсор мыши находится над контролом, MouseGetPos точно определяет именно тот контрол с которым мы сейчас будем взаимодействовать при следующем клике.
Речь про то, что в этих-же координатах могут находится ещё несколько нескрытых контролов, но именно тот, что определяет MouseGetPos всегда поверх остальных.
Возможно есть вариант покопаться в исходниках АНК, и понять метод такого определения.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

Re: AHK: ClassNN контрола по координатам

Определить контрол — это что вы имеете в виду? Если его хэндл, то вам нужна WindowFromPoint или ChildWindowFromPoint.

5

Re: AHK: ClassNN контрола по координатам

Противоречие.

Вариант с получением списка всех контролов, извлечением их координат и определением что они находятся в нужной точке, по многим причинам не подходит.

Я и не говорил, что список всех контролов не надо получать в принципе.
Я сказал, что вариант по определению координат контролов из списка подходящих под заданную точку в окне, не подходит.

ControlGetPos определяет координаты и размеры элемента управления, при этом не обязательно, чтобы курсор нахдился над ним. Но получить список всех э. у. всё-таки придётся.

6

Re: AHK: ClassNN контрола по координатам

Если его хэндл, то вам нужна WindowFromPoint или ChildWindowFromPoint.

Хорошо, скажите пожалуйста как получить хэндл? И зная хэндл, получить ClassNN и порядковый номер?

Противоречие.

Да нет тут ни какого противоречия.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7

Re: AHK: ClassNN контрола по координатам

WinGet выдаёт список э. у. в виде HWND/handle или ClassNN.  ControlGetPos определяет расположение и размеры э. у. в окне. Остаётся только проверить , пересекаются ли они с Вашей точкой или областью.

8

Re: AHK: ClassNN контрола по координатам

serzh82saratov пишет:

Если его хэндл, то вам нужна WindowFromPoint или ChildWindowFromPoint.

Хорошо, скажите пожалуйста как получить хэндл? И зная хэндл, получить ClassNN и порядковый номер?

Скопипастить сюда описание этих функций? Готового кода, делающего то, что вы описали, у меня нет. Я бы мог его написать, но для этого мне самому надо почитать описания и т.д. Почему бы вам этого не сделать?

9

Re: AHK: ClassNN контрола по координатам

WinGet выдаёт список э. у. в виде HWND/handle или ClassNN.  ControlGetPos определяет расположение и размеры э. у. в окне. Остаётся только проверить , пересекаются ли они с Вашей точкой или областью.

Ммм...

Вариант с получением списка всех контролов, извлечением их координат и определением что они находятся в нужной точке, по многим причинам не подходит.

Я даже не знаю как ещё довести мысль...

Gui, Add, Text, w111 h44, Text 
Gui, Add, Text, wp hp xp yp, Text 
Gui, Add, Text, wp hp xp yp, Text 
Gui, Add, Text, wp hp xp yp, Text 
Gui, Add, Text, wp hp xp yp, Text  
Gui, Show 
return

Тут MouseGetPos выводит: Static5.
В вашем варианте вообще все 5 контролов подходят.

В моём случае с сторонним приложением никогда неизвестно какой контрол будет "сверху", но MouseGetPos это определяет.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10 (изменено: serzh82saratov, 2014-01-01 17:18:49)

Re: AHK: ClassNN контрола по координатам

YMP
WindowFromPoint - не плохо. А возможно задавать координаты относительно окна?
Я конечно понимаю что можно в начале определить координаты самого окна, и.т.д.

Я бы мог его написать, но для этого мне самому надо почитать описания и т.д. Почему бы вам этого не сделать?

Если бы я сам мог, я бы не стал засорять эфир настолько простыми и глупыми вопросами.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11

Re: AHK: ClassNN контрола по координатам

Очевидное:
Через WinGet получить List и ControlList.
Зная хэндл от WindowFromPoint, получить ClassNN по номеру строки в списке ControlList, который соответствует номеру строки в List совпадающим с хэндл WindowFromPoint.
Возможно как-то проще?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

12

Re: AHK: ClassNN контрола по координатам

serzh82saratov пишет:

Вопрос заключается в том, как получить ClassNN и порядковый номер контрола в GUI стороннего приложения, также как это делает MouseGetPos, но не перемещая курсор, а указав просто координаты в окне.

Вариант с получением списка всех контролов, извлечением их координат и определением что они находятся в нужной точке, по многим причинам не подходит.

Как понять "также как это делает MouseGetPos"? Имеется в виду, что интересует только верхний э. у. (контрол)?

13

Re: AHK: ClassNN контрола по координатам

Как понять "также как это делает MouseGetPos"? Имеется в виду, что интересует только верхний э. у. (контрол)?

Скорее всего, да.
Возможно я и сам не до конца понимаю что имеется в виду под "верхний". Но на примерах кода всё станет ясно. Не могли бы вы что-то предложить, в виде варианта:

1::
    MouseGetPos, X, Y
    ToolTip % GetControlUnderCoord( X, Y) 
    return
   
GetControlUnderCoord( X, Y)   {
     ...
    return Control 
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14

Re: AHK: ClassNN контрола по координатам

serzh82saratov пишет:

YMP
WindowFromPoint - не плохо. А возможно задавать координаты относительно окна?
Я конечно понимаю что можно в начале определить координаты самого окна, и.т.д.

В каком смысле возможно? Физически возможно задать что угодно, только поймёт ли это функция, которая на оное не рассчитана? Может, вы как-то сможете её уговорить, включив обаяние, я не знаю.

15

Re: AHK: ClassNN контрола по координатам

WindowFromPoint.
Я имел ввиду что может есть некий её аналог...
Ну да ладно, и этого достаточно. Спасибо за подсказку!
По упрощению дальнейшего алгоритма из поста 11 есть идеи?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

16

Re: AHK: ClassNN контрола по координатам

Нет, пока нету. А для чего вам ClassNN? Для операций с окном достаточно хэндла.

17 (изменено: serzh82saratov, 2014-01-01 22:27:09)

Re: AHK: ClassNN контрола по координатам

А для чего вам ClassNN? Для операций с окном достаточно хэндла.

Увы, но требуется именно ClassNN и порядковый номер для идентификации того с чем имеем дело, по другому никак, в частном случае.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

18

Re: AHK: ClassNN контрола по координатам

Нашёл такой вариант:


2::
    CoordMode, Mouse
    MouseGetPos, X, Y 
    ToolTip % GetClassNN( X, Y)   
    Return
    
GetClassNN(X, Y)   {   
    HC := DllCall( "WindowFromPoint", Int, X, Int,Y )
    HW := DllCall( "GetAncestor", UInt, HC, UInt, 1)
    WinGetClass, CL, ahk_id %HC%
  
    While HA := DllCall("FindWindowEx", UInt,HW, UInt,HA, UInt,&CL, UInt,0) 
        If (HA = HC)
            Return CL . A_Index 
    Return False
}

Не знаю как сделать чтобы возвращало False, если в координатах нет контрола. В таком виде возвращает класс окна с единицей.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

19

Re: AHK: ClassNN контрола по координатам

Не знаю как сделать чтобы возвращало False, если в координатах нет контрола. В таком виде возвращает класс окна с единицей.


2::
    CoordMode, Mouse
    MouseGetPos, X, Y 
    ToolTip % GetClassNN( X, Y)   
    Return
    
GetClassNN(X, Y)   {   
    HC := DllCall( "WindowFromPoint", Int, X, Int,Y )
    HW := DllCall( "GetAncestor", UInt, HC, UInt, 1)   
    If !DllCall( "IsChild", uint, HW, Int,HC )
        Return False
    WinGetClass, CL, ahk_id %HC%
  
    While HA := DllCall("FindWindowEx", UInt,HW, UInt,HA, UInt,&CL, UInt,0) 
        If (HA = HC)
            Return CL . A_Index 
    Return False
}

Но теперь выяснил что не выполняется условие из 9 поста, возвращается нижний контрол а не верхний.
Видимо требуется какая-то другая функция, возможно ChildWindowFromPoint или подобная.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

20

Re: AHK: ClassNN контрола по координатам

Или, может, EnumChildWindows спасёт отца русской демократии.

21

Re: AHK: ClassNN контрола по координатам

Наверняка спасёт, раз Вы так думаете. Но, чем мне поможет:

Enumerates the child windows that belong to the specified parent window by passing the handle to each child window, in turn, to an application-defined callback function. EnumChildWindows continues until the last child window is enumerated or the callback function returns FALSE.Enumerates the child windows that belong to the specified parent window by passing the handle to each child window, in turn, to an application-defined callback function. EnumChildWindows continues until the last child window is enumerated or the callback function returns FALSE.

не ясно.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

22

Re: AHK: ClassNN контрола по координатам

Нет, я подумал, что может быть спасёт. Возможно, не до конца понял проблему.

23

Re: AHK: ClassNN контрола по координатам

Нет, я подумал, что может быть спасёт.

Тут FindWindowEx справляется "как бы проще" чем EnumChildWindows.

Возможно, не до конца понял проблему.

Ну если в данной стадии, то проблема в получении хэндла верхнего контрола в заданных координатах.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

24

Re: AHK: ClassNN контрола по координатам

Есть подозрения на помощь AccessibleObjectFromPoint.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

25

Re: AHK: ClassNN контрола по координатам

Видимо требуется какая-то другая функция, возможно ChildWindowFromPoint или подобная.

Ну дык в чём проблема попробовать?

26 (изменено: serzh82saratov, 2014-01-15 20:19:05)

Re: AHK: ClassNN контрола по координатам

Проблема в том что не могу найти таковые методы.
AccessibleObjectFromPoint извлекает текст именно верхнего контрола:


Gui, Add, Text, w111 h111, Text 1
Gui, Add, Text, wp hp xp yp, Text 2
Gui, Add, Text, wp hp xp yp, Text 3
Gui, Add, Text, wp hp xp yp, Text 4
Gui, Add, Text, wp hp xp yp, Text 5
Gui, Show 
return
  
1:: ToolTip % GetTextUnderMouse()
 
GetTextUnderMouse( x="", y="")  {
    Static h
    If Not h
        h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
    If DllCall("oleacc\AccessibleObjectFromPoint"
                , "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32
                , "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
    Acc:=ComObjEnwrap(9,pacc,1), child:=NumGet(varChild,8,"UInt")
    try value := Acc.accValue(child)
    if Not value
        try value := Acc.accName(child)
    return value
}

но как попросить вернуть его хэндл этого контрола, не могу понять.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

27

Re: AHK: ClassNN контрола по координатам

Никак, наверно. Это же доступ через COM, зачем тут хэндлы?

28

Re: AHK: ClassNN контрола по координатам

serzh82saratov пишет:

Ну если в данной стадии, то проблема в получении хэндла верхнего контрола в заданных координатах.

А WindowFromPoint разве не этот хэндл возвращает?

29 (изменено: YMP, 2014-01-16 18:31:23)

Re: AHK: ClassNN контрола по координатам

Вот так у меня показывает ClassNN по координатам.


pEnumChildProc := RegisterCallback("EnumChildProc", "Fast")

F11::
    CoordMode, Mouse, Screen
    MouseGetPos, mX, mY
    mX &= 0x00000000FFFFFFFF
    Point := mX | mY<<32
    hWnd := DllCall("WindowFromPoint", "int64", Point, "ptr")
    WinGetClass, Class, ahk_id %hWnd%
    ClassNN := "", NN := 0
    hwndRoot := DllCall("GetAncestor", "ptr", hWnd, "uint", 2, "ptr") ; GA_ROOT
    DllCall("EnumChildWindows", "ptr", hwndRoot, "ptr", pEnumChildProc, "ptr", 0)
    MsgBox, %ClassNN%
Return

EnumChildProc(hwndChild)
{
    global hWnd, Class, ClassNN, NN
    WinGetClass, Class1, ahk_id %hwndChild%
    If (Class1 = Class) {
        ++NN
        If (hwndChild = hWnd) {
            ClassNN := Class . NN
            Return False
        }
    }
    Return True
}

30 (изменено: serzh82saratov, 2014-01-16 18:18:29)

Re: AHK: ClassNN контрола по координатам

Уже было, и "проще".
WindowFromPoint возвращает нижний контрол.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

31

Re: AHK: ClassNN контрола по координатам

У меня возвращает верхний.

32 (изменено: serzh82saratov, 2014-01-16 18:40:51)

Re: AHK: ClassNN контрола по координатам

Запустите это:


Gui, Add, Text, w111 h111, Static 1
Gui, Add, Text, wp hp xp yp, Static 2
Gui, Add, Text, wp hp xp yp, Static 3
Gui, Add, Text, wp hp xp yp, Static 4
Gui, Add, Text, wp hp xp yp, Static 5
Gui, Show 
return

Потом свой код, что возвращает?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

33

Re: AHK: ClassNN контрола по координатам

Насчёт статиков в описании есть оговорка.

If the point is over a static text control, the return value is a handle to the window under the static text control.

Так что странно, что вообще что-то возвращает.

34

Re: AHK: ClassNN контрола по координатам

С порядком контролов вообще не всё понятно. Вот пример ниже. Когда окно создаётся, сверху вроде бы Edit5. Но если щёлкнуть в нём мышью, там оказывается Edit1. Или просто вывести поверх другое окно — тот же эффект.


Gui, Add, Edit, w111 h111, Edit 1
Gui, Add, Edit, wp hp xp yp, Edit 2
Gui, Add, Edit, wp hp xp yp, Edit 3
Gui, Add, Edit, wp hp xp yp, Edit 4
Gui, Add, Edit, wp hp xp yp, Edit 5
Gui, Show 
return

GuiClose:
    ExitApp

35

Re: AHK: ClassNN контрола по координатам

Со всеми остальными контролами также:


Gui, Add, Progress, w111 h111 
Gui, Add, Progress, wp hp xp yp 
Gui, Show 
return

Очевидно что WindowFromPoint совсем не то. Но как то MouseGetPos всегда определяет верхний...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

36 (изменено: serzh82saratov, 2014-01-16 19:58:52)

Re: AHK: ClassNN контрола по координатам

В случае с Tab ом вообще не видит контролы:


Gui, Add, Tab, , 1|2
Gui, Tab, 1
Gui, Add, Edit, w111 h111, Edit 1

Gui, Tab, 2
Gui, Add, Edit, w111 h111, Edit 2
Gui, Show 
return
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

37

Re: AHK: ClassNN контрола по координатам

Что касается определения хэндла верхнего контрола, то я нашёл у себя функцию, написанную когда-то Lexikos'ом. Судя по примечанию, алгоритм взят из исходников AutoHotkey, по кр. мере callback-функция. Попробуйте разобраться, а я спать пошёл, уже голова не работает.


; Retrieves the control at the specified point. 
; X         [in]    X-coordinate relative to the top-left of the window. 
; Y         [in]    Y-coordinate relative to the top-left of the window. 
; WinTitle  [in]    Title of the window whose controls will be searched. 
; WinText   [in] 
; cX        [out]   X-coordinate relative to the top-left of the control. 
; cY        [out]   Y-coordinate relative to the top-left of the control. 
; ExcludeTitle [in] 
; ExcludeText  [in] 
; Return Value:     The hwnd of the control if found, otherwise the hwnd of the window.
 
ControlFromPoint(X, Y, WinTitle="", WinText="", ByRef cX="", ByRef cY="", ExcludeTitle="", ExcludeText="") 
{ 
    static EnumChildFindPointProc=0 
    if !EnumChildFindPointProc 
        EnumChildFindPointProc := RegisterCallback("EnumChildFindPoint","Fast") 
    
    if !(target_window := WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText)) 
        return false 
    
    VarSetCapacity(rect, 16) 
    DllCall("GetWindowRect","uint",target_window,"uint",&rect) 
    VarSetCapacity(pah, 36, 0) 
    NumPut(X + NumGet(rect,0,"int"), pah,0,"int") 
    NumPut(Y + NumGet(rect,4,"int"), pah,4,"int") 
    DllCall("EnumChildWindows","uint",target_window,"uint",EnumChildFindPointProc,"uint",&pah) 
    control_window := NumGet(pah,24) ? NumGet(pah,24) : target_window 
    DllCall("ScreenToClient","uint",control_window,"uint",&pah) 
    cX:=NumGet(pah,0,"int"), cY:=NumGet(pah,4,"int") 
    return control_window 
} 

; Ported from AutoHotkey::script2.cpp::EnumChildFindPoint() 
EnumChildFindPoint(aWnd, lParam) 
{ 
    if !DllCall("IsWindowVisible","uint",aWnd) 
        return true 
    VarSetCapacity(rect, 16) 
    if !DllCall("GetWindowRect","uint",aWnd,"uint",&rect) 
        return true 
    pt_x:=NumGet(lParam+0,0,"int"), pt_y:=NumGet(lParam+0,4,"int") 
    rect_left:=NumGet(rect,0,"int"), rect_right:=NumGet(rect,8,"int") 
    rect_top:=NumGet(rect,4,"int"), rect_bottom:=NumGet(rect,12,"int") 
    if (pt_x >= rect_left && pt_x <= rect_right && pt_y >= rect_top && pt_y <= rect_bottom) 
    { 
        center_x := rect_left + (rect_right - rect_left) / 2 
        center_y := rect_top + (rect_bottom - rect_top) / 2 
        distance := Sqrt((pt_x-center_x)**2 + (pt_y-center_y)**2) 
        update_it := !NumGet(lParam+24) 
        if (!update_it) 
        { 
            rect_found_left:=NumGet(lParam+8,0,"int"), rect_found_right:=NumGet(lParam+8,8,"int") 
            rect_found_top:=NumGet(lParam+8,4,"int"), rect_found_bottom:=NumGet(lParam+8,12,"int") 
            if (rect_left >= rect_found_left && rect_right <= rect_found_right 
                && rect_top >= rect_found_top && rect_bottom <= rect_found_bottom) 
                update_it := true 
            else if (distance < NumGet(lParam+28,0,"double") 
                && (rect_found_left < rect_left || rect_found_right > rect_right 
                 || rect_found_top < rect_top || rect_found_bottom > rect_bottom)) 
                 update_it := true 
        } 
        if (update_it) 
        { 
            NumPut(aWnd, lParam+24) 
            DllCall("RtlMoveMemory","uint",lParam+8,"uint",&rect,"uint",16) 
            NumPut(distance, lParam+28, 0, "double") 
        } 
    } 
    return true 
}

38 (изменено: serzh82saratov, 2014-01-18 07:43:37)

Re: AHK: ClassNN контрола по координатам

Огромное спасибо! Оставил пока в таком виде:


1::   
    MouseGetPos, X, Y
    Global HW := WinExist("A") 
    HC := ControlIdFromPoint( X, Y)  
    ToolTip % GetClassNN(HC) 
    Return 
 
 
ControlIdFromPoint(X, Y) 
{ 
    static EnumChildFindPointProc=0 
    if !EnumChildFindPointProc 
        EnumChildFindPointProc := RegisterCallback("EnumChildFindPoint","Fast")   
    VarSetCapacity(rect, 16) 
    DllCall("GetWindowRect","uint",HW,"uint",&rect) 
    VarSetCapacity(pah, 36, 0) 
    NumPut(X + NumGet(rect,0,"int"), pah,0,"int") 
    NumPut(Y + NumGet(rect,4,"int"), pah,4,"int") 
    DllCall("EnumChildWindows","uint",HW,"uint",EnumChildFindPointProc,"uint",&pah)  
    return NumGet(pah,24) 
} 
 
EnumChildFindPoint(aWnd, lParam) 
{ 
    if !DllCall("IsWindowVisible","uint",aWnd) 
        return true  
    VarSetCapacity(rect, 16) 
    if !DllCall("GetWindowRect","uint",aWnd,"uint",&rect) 
        return true 
    pt_x:=NumGet(lParam+0,0,"int"), pt_y:=NumGet(lParam+0,4,"int") 
    rect_left:=NumGet(rect,0,"int"), rect_right:=NumGet(rect,8,"int") 
    rect_top:=NumGet(rect,4,"int"), rect_bottom:=NumGet(rect,12,"int") 
    if (pt_x >= rect_left && pt_x <= rect_right && pt_y >= rect_top && pt_y <= rect_bottom) 
    { 
        center_x := rect_left + (rect_right - rect_left) / 2 
        center_y := rect_top + (rect_bottom - rect_top) / 2 
        distance := Sqrt((pt_x-center_x)**2 + (pt_y-center_y)**2) 
        update_it := !NumGet(lParam+24) 
        if (!update_it) 
        { 
            rect_found_left:=NumGet(lParam+8,0,"int"), rect_found_right:=NumGet(lParam+8,8,"int") 
            rect_found_top:=NumGet(lParam+8,4,"int"), rect_found_bottom:=NumGet(lParam+8,12,"int") 
            if (rect_left >= rect_found_left && rect_right <= rect_found_right 
                && rect_top >= rect_found_top && rect_bottom <= rect_found_bottom) 
                update_it := true 
            else if (distance < NumGet(lParam+28,0,"double") 
                && (rect_found_left < rect_left || rect_found_right > rect_right 
                 || rect_found_top < rect_top || rect_found_bottom > rect_bottom)) 
                 update_it := true 
        } 
        if (update_it) 
        { 
            NumPut(aWnd, lParam+24) 
            DllCall("RtlMoveMemory","uint",lParam+8,"uint",&rect,"uint",16) 
            NumPut(distance, lParam+28, 0, "double") 
        } 
    } 
    return true 
}

    
GetClassNN(HC)   {      
    WinGetClass, CL, ahk_id %HC%   
    WinGet, List, ControlList, ahk_id %HW%
    Loop, parse, List, `n
    {
        If InStr(A_LoopField, CL)
        {
            ControlGet, id, Hwnd, , %A_LoopField%, ahk_id %HW% 
            If (id = HC)
                Return A_LoopField
        }
    } 
    Return False
} 

Что интересно, оказалось что FindWindowEx  "не знает" про многие контролы, например ListView:


GetClassNN(HC)   {      
    WinGetClass, CL, ahk_id %HC%    
    While HA := DllCall("FindWindowEx", UInt,HW, UInt,HA, UInt,&CL, UInt,0) 
        If (HA = HC)
            Return CL . A_Index 
    Return False
}

Заменил на WinGet, List, ControlList

Совсем немного сократил ControlNNFromPoint, но не смог EnumChildFindPoint, если вы знаете что ненужного можно вычеркнуть, подскажите.
---

Что ж, всё пока супер, координаты задаются относительно окна и контрол определяется даже в свёрнутом окне!

---

С порядком контролов вообще не всё понятно. Вот пример ниже. Когда окно создаётся, сверху вроде бы Edit5. Но если щёлкнуть в нём мышью, там оказывается Edit1. Или просто вывести поверх другое окно — тот же эффект.

Угу, но продолжает определяться MouseGetPos и этой функцией как Edit5. Но при запуске скрипта ControlFocus сразу определяет Edit1.
Если сделать так:


Gui, Add, Edit, x5 y5 w111 h111, Edit 1
Gui, Add, Edit, wp hp xp yp, Edit 2
Gui, Add, Edit, wp hp xp yp, Edit 3
Gui, Add, Edit, wp hp xp yp, Edit 4
Gui, Add, Edit, wp vEdit hp xp yp, Edit 5
GuiControl, Focus, Edit 
Gui, Show   

ControlFocus определяет Edit5, но при клике всё тоже самое.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

39 (изменено: serzh82saratov, 2014-06-25 11:44:24)

Re: AHK: ClassNN контрола по координатам

ТС пишет:

Вариант с получением списка всех контролов, извлечением их координат и определением что они находятся в нужной точке, по многим причинам не подходит.

Немного подумав, мне показалось что принцип эдинтичен, тому что мне пришло в голову перед созданием темы:


Gui, Add, Edit, x5 y5 w110 h111, Edit 1
Gui, Add, Edit, wp hp xp yp, Edit 2
Gui, Add, Edit, wp hp xp+55 yp, Edit 3
Gui, Add, Edit, wp hp xp yp, Edit 4 
Gui, Show 

2::   
    MouseGetPos, X, Y
    ToolTip % GetClassNN2( X, Y, WinExist("A"))   
    Return 
    
GetClassNN2(X, Y, Wnd)   { 
    WinGet, List, ControlListHwnd, ahk_id %Wnd%    
    Loop, parse, List, `n
    { 
        If !DllCall("IsWindowVisible", "uint", A_LoopField) 
            Continue
        ControlGetPos, cX, cY, cW, cH, , ahk_id %A_LoopField% 
        If (cX <= X && cY <= Y && cX+cW >= X && cY+cH >= Y) 
            i := A_Index
    } 
    If !i 
        Return 0 
    WinGet, List, ControlList, ahk_id %Wnd%
    Return StrSplit(List,"`n")[i]
} 

Но только до этого я не знал про IsWindowVisible и отбрасывал только hidden контролы, а также выходил из цикла при первом "попадании" в координаты.

На первый взгляд коды работают одинаково, но если контролы накладываются друг на друга то в этом месте 1 код (Lexikos'а) показывает нижний в Z порядке Edit2, мой код - Edit4 (ну это понятно). Также заметил в Notepad++ - 1 код правильно определяет Scintilla1, мой код в этом месте выдаёт SysTabControl325.

По какому признаку 1 код отбрасывает SysTabControl325 который идёт дальше в Z порядке и подходит по координатам?попадании

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

40

Re: AHK: ClassNN контрола по координатам

serzh82saratov пишет:

По какому признаку 1 код отбрасывает SysTabControl325 который идёт дальше в Z порядке и подходит по координатам?

Не знаю. Тогда, помнится, я разобрался, как этот код работает, но теперь всё уже забыл.

41 (изменено: serzh82saratov, 2014-01-18 21:30:53)

Re: AHK: ClassNN контрола по координатам

Например, если текущий контрол находится полностью в рамках (размерах) или внутри предыдущего подходящего,
или если вектор (от левого верхнего угла окна до центра контрола) короче предыдущего, и один из краёв входит в рамки предыдущего:


        if (!update_it) 
        { 
            rect_found_left:=NumGet(lParam+8,0,"int"), rect_found_right:=NumGet(lParam+8,8,"int") 
            rect_found_top:=NumGet(lParam+8,4,"int"), rect_found_bottom:=NumGet(lParam+8,12,"int") 
            if (rect_left >= rect_found_left && rect_right <= rect_found_right 
                && rect_top >= rect_found_top && rect_bottom <= rect_found_bottom) 
                update_it := true 
            else if (distance < NumGet(lParam+28,0,"double") 
                && (rect_found_left < rect_left || rect_found_right > rect_right 
                 || rect_found_top < rect_top || rect_found_bottom > rect_bottom)) 
                 update_it := true 
        } 

то он считается подходящим. Такая вот логика, но не на все случаи .

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui