1

Тема: AHK: ControlGetText и .NET Framework WinForms

Не могу нигде найти как считать текст из контрола.
Дело в том, что и "HWND" и "ClassNN" в окне клиента переодически меняется и

ControlGetText, str,, ahk_id %HWND%

не подходит.

Сейчас читаю текст из контролов по координатам


CtrlID(ParentHWND, x, y){
    WinGetPos, PX, PY,,, ahk_id %ParentHWND%
    if PX
        return DllCall("WindowFromPoint", "int", x + PX, "int", y + PY)
}

Но это вариант не нравится, так как работает только в активном окне


в AutoIt v3 например мой вопрос решается просто:

ControlGetText($hWnd, "", "[NAME:lblTime]")
Документация к AutoIt пишет:

NAME - The internal .NET Framework WinForms name (if available)
http://www.autoitscript.com/autoit3/doc … ntrols.htm


Вот картинка окна "AutiIt Window Info" и того что мне надо

Подскажите как решить? ткните носом, поделитесь ссылочкой.
Спасибо

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

2

Re: AHK: ControlGetText и .NET Framework WinForms

Так что за окно, картинка не открывается.

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

3

Re: AHK: ControlGetText и .NET Framework WinForms

вот изображение http://yadi.sk/d/d0bnLek4NvRKc
Мне нужно в ahk скрипте читать строки из контролов по их названию, по аналогии как AutoIt.

как уже писал в AutoIt можно прочитать так

ControlGetText($hWnd, "", "[NAME:lblTime]")

как это сделать в AhtoHotkey я не знаю. :(

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

4

Re: AHK: ControlGetText и .NET Framework WinForms

Интересно, не сталкивался с таким. Можете привести ссылку на програмку небольшого размера с подобными контролами?

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

5

Re: AHK: ControlGetText и .NET Framework WinForms

Может задаваться как *** как имя/текст контрола. *** При использовании имени/текста параметры их поиска можно задавать командой SetTitleMatchMode.

Судя по справке, должно работать:

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

6

Re: AHK: ControlGetText и .NET Framework WinForms

На самом деле это клиент игры, вести примерно ~300мб. Там есть чат. и мне нужно его мониторить на предмет появления некоторых людей в чате (достаю RegEx-ми).  Клиент игры должен работать в фоне и если кто-то, что-то написал, происходят некоторые действия уведомляющие меня.
Сейчас дело обстоит так. Поскольку и ClassNN и HWND котрола меняются приходится активировать окно
получать его ID через

DllCall("WindowFromPoint", "int", x , "int", y)

скрывать окно и продолжать заниматься своими делами...

писал прослойку на AutoIt, которая переодически запускается и сохраняет hwnd-шники в ini файл, но это как-то дико

вот не знаю, может Dllcall какой нужен?

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

7

Re: AHK: ControlGetText и .NET Framework WinForms

ControlGetText, str,  lblTime, A

пробовал, не катит.

Это какие-то ".NET Framework WinForms name"? с которыми мне тоже не приходилось встречаться.

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

8

Re: AHK: ControlGetText и .NET Framework WinForms

вот тут народ тоже сталкивался

http://www.autohotkey.com/board/topic/6 … -net-name/

http://www.autohotkey.com/board/topic/9 … to-change/

но решения я пока не вижу.

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

9

Re: AHK: ControlGetText и .NET Framework WinForms

polyethene пишет:

.NET windows forms, like Java Swing or AWT, do not respond by default to standard windows messages so Control commands will not work.

http://www.autohotkey.com/board/topic/3 … dowsforms/

но это сообщение от 2008 года, надо копать дальше. Есть предложения?

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

10

Re: AHK: ControlGetText и .NET Framework WinForms

Отсюда


1::
HWND := ControlIdFromPoint(12, 77, WinExist("ahk_class Notepad"))
ControlGetText, str, , ahk_id %HWND%
MsgBox % str
return

ControlIdFromPoint(X, Y, HW) 
{ 
    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 
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11

Re: AHK: ControlGetText и .NET Framework WinForms

Так по короче: отсюда.



1::   
    ControlGetText, str, , % "ahk_id" CtrlID(12, 77, WinExist("ahk_class Notepad"))   
    ToolTip % str
    Return 
    
CtrlID(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) 
            id := A_LoopField
    }  
    Return id
} 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

12

Re: AHK: ControlGetText и .NET Framework WinForms

OOO, просто отлично, в коде не разбирался, но работает (хотя не для всех контролов) 20% не считываются.
Меня пока это устраивает. Дома буду разбираться.

С вами приятно общаться. Все остаюсь...

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

13

Re: AHK: ControlGetText и .NET Framework WinForms

20% не считываются.

Может IsWindowVisible мешается:


1::   
    ControlGetText, str, , % "ahk_id" CtrlID(12, 77, WinExist("ahk_class Notepad"))   
    ToolTip % str
    Return 
    
CtrlID(X, Y, Wnd)   { 
    WinGet, List, ControlListHwnd, ahk_id %Wnd%    
    Loop, parse, List, `n
    {  
        ControlGetPos, cX, cY, cW, cH, , ahk_id %A_LoopField% 
        If (cX <= X && cY <= Y && cX+cW >= X && cY+cH >= Y) 
            id := A_LoopField
    }  
    Return id
} 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14

Re: AHK: ControlGetText и .NET Framework WinForms

У меня работает первый вариант
буду тестить...

WinXPx32, AutoHotkey v1.1.14.04 (Unicode 32-bit)

15

Re: AHK: ControlGetText и .NET Framework WinForms

[NAME:] это  accName

16

Re: AHK: ControlGetText и .NET Framework WinForms

bWRmeA
Так что Вы именно предлагаете? Перебирать все контролы окна на соответствие accName? Так может быть много совпадений.

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

17

Re: AHK: ControlGetText и .NET Framework WinForms

Но ведь

cmdz пишет:

в AutoIt v3 например мой вопрос решается просто:

ControlGetText($hWnd, "", "[NAME:lblTime]")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: ControlGetText и .NET Framework WinForms

Имеешь ввиду, что совпадений быть не может?

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

19

Re: AHK: ControlGetText и .NET Framework WinForms

Я-то откуда знаю? Но если вопрос решается подобным образом, значит решение устраивает.

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

20

Re: AHK: ControlGetText и .NET Framework WinForms

Наверное, с .NET Framework WinForms не сталкивался. Может быть там accName как уникальные идентификаторы.

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

21

Re: AHK: ControlGetText и .NET Framework WinForms

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

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

22 (изменено: serzh82saratov, 2014-05-06 15:15:06)

Re: AHK: ControlGetText и .NET Framework WinForms

А какой в итоге код должен быть? Что то Я не пойму как hwnd контрола вернуть, возвращает нечто не то:

+ открыть спойлер

#SingleInstance Force
#Persistent    
#NoEnv
ListLines Off 
DetectHiddenWindows, on
SetBatchLines -1 
SetFormat, IntegerFast, h

winid := WinExist("ahk_class IEFrame ahk_exe iexplore.exe")
name = Избранное 

hwnd := HwndFromAccName(winid, name)
ControlGet, thwnd, Hwnd,, ToolbarWindow324, ahk_id %winid%
MsgBox, % hwnd "   " thwnd
return 

ExistAccName(AccObj, name, byref hwnd="")
{  
    if (AccObj.accName(0) = name) 
        Return AccObj, hwnd := AccWindowFromObject(AccObj) 
    for k, v in AccChildren(AccObj)
        if IsObject(obj := ExistAccName(v, name, hwnd)) 
        Return obj 
}  

HwndFromAccName(winid, name)
{
    if !winid
        MsgBox, % "Окно не найдено"  
    else if !IsObject(AccObj := AccObjectFromWindow(winid))
        MsgBox, % "Не удалось получить IAccessible" 
    else if !IsObject(oExist := ExistAccName(AccObj, name, hwnd)) || !hwnd
        MsgBox, % "Элемент с таким именем не найден" 
    else 
        Return hwnd
}     

AccWindowFromObject(pacc)
{
    If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd) = 0
    Return    hWnd
} 
AccInit()
{
   Static   h
   If Not   h
      h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   AccInit()
   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)
}        
AccError(p="") {
   static setting:=0
   return p=""?setting:setting:=p
}
AccQuery(Acc) {
    try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
AccChildren(Acc) {
   if ComObjType(Acc,"Name") != "IAccessible"
      ErrorLevel := "Invalid IAccessible Object"
   else {
      AccInit(), 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?AccQuery(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
         return Children.MaxIndex()?Children:
      } else
         ErrorLevel := "AccessibleChildren DllCall Failed"
   }
   if AccError()
      throw Exception(ErrorLevel,-1)
}
  
Esc::   
    ExitApp 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

23 (изменено: serzh82saratov, 2014-05-06 20:28:11)

Re: AHK: ControlGetText и .NET Framework WinForms

достаточно быть первым найденным.

А  да, нужны уточнения role и ChildId в AccObj.accName(2). Как переделать чтобы ChildId знать не нужно было.

+ открыть спойлер

#SingleInstance Force
#Persistent    
#NoEnv
ListLines Off 
DetectHiddenWindows, on
SetBatchLines -1 
SetFormat, IntegerFast, h
 
winid := WinExist("ahk_class IEFrame ahk_exe iexplore.exe")
name = Избранное 
role = панель инструментов

hwnd := HwndFromAccName(winid, name, role)
ControlGet, thwnd, Hwnd,, ToolbarWindow324, ahk_id %winid%
MsgBox, % hwnd "   " thwnd
ControlGetText, str,, ahk_id %hwnd%
MsgBox, % str
return 

HwndFromAccName(winid, name, role)
{
    if !winid
        MsgBox, % "Окно не найдено"  
    else if !IsObject(AccObj := AccObjectFromWindow(winid))
        MsgBox, % "Не удалось получить IAccessible" 
    else if !IsObject(oExist := ExistAccName(AccObj, name, role, hwnd)) || !hwnd
        MsgBox, % "Элемент не найден" 
    else 
        Return hwnd
}     

ExistAccName(AccObj, name, role, byref hwnd="")
{   
    try if (AccRole(AccObj) = role && AccObj.accName(2) = name)
        Return AccObj, hwnd := AccWindowFromObject(AccObj) 
    for k, v in AccChildren(AccObj)
        if IsObject(obj := ExistAccName(v, name, role, hwnd)) 
        Return obj 
}  

AccWindowFromObject(pacc)
{
    If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd) = 0
    Return    hWnd
} 
AccInit()
{
   Static   h
   If Not   h
      h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   AccInit()
   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)
}        
AccRole(Acc, ChildId=0) {
    try Return ComObjType(Acc,"Name")="IAccessible"?AccGetRoleText(Acc.accRole(ChildId)):""
}
AccGetRoleText(nRole)  {
    nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
    VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
    DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
    Return    sRole
}
AccError(p="") {
   static setting:=0
   return p=""?setting:setting:=p
}
AccQuery(Acc) {
    try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
AccChildren(Acc) {
   if ComObjType(Acc,"Name") != "IAccessible"
      ErrorLevel := "Invalid IAccessible Object"
   else {
      AccInit(), 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?AccQuery(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
         return Children.MaxIndex()?Children:
      } else
         ErrorLevel := "AccessibleChildren DllCall Failed"
   }
   if AccError()
      throw Exception(ErrorLevel,-1)
}
  
Esc::   
    ExitApp 

UPD: Дошло.


#SingleInstance Force  
#NoEnv
ListLines Off  
SetBatchLines -1  

WinTitle = ahk_class IEFrame ahk_exe iexplore.exe
name = Избранное 
role = панель инструментов

winid := WinExist(WinTitle)
hwnd := HwndFromAccName(winid, role, name)
ControlGet, thwnd, Hwnd,, ToolbarWindow324, ahk_id %winid%
MsgBox, % hwnd "   " thwnd+0
ControlGetText, str,, ahk_id %hwnd%
MsgBox, % str
return 

HwndFromAccName(winid, role, name)
{
    if !winid
        MsgBox, % "Окно не найдено"  
    else if !IsObject(AccObj := AccObjectFromWindow(winid))
        MsgBox, % "Не удалось получить IAccessible" 
    else if !IsObject(AccObj := ExistAccName(AccObj, role, name))
        MsgBox, % "Элемент не найден" 
    else
        Return AccWindowFromObject(AccObj) 
}     

ExistAccName(AccObj, role, name)
{   
    if (AccRole(AccObj) = role) 
        loop % AccObj.accChildCount
            if AccObj.accName(A_Index-1) = name 
                Return AccObj
    for k, v in AccChildren(AccObj)
        if IsObject(obj := ExistAccName(v, role, name)) 
            Return obj 
}  

AccWindowFromObject(pacc)
{
    If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd) = 0
    Return    hWnd
} 
AccInit()
{
   Static   h
   If Not   h
      h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}

AccObjectFromWindow(hWnd, idObject = 0)
{
   AccInit()
   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)
}        
AccRole(Acc, ChildId=0) {
    try Return ComObjType(Acc,"Name")="IAccessible"?AccGetRoleText(Acc.accRole(ChildId)):""
}
AccGetRoleText(nRole)  {
    nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
    VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
    DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
    Return    sRole
}
AccError(p="") {
   static setting:=0
   return p=""?setting:setting:=p
}
AccQuery(Acc) {
    try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
AccChildren(Acc) {
   if ComObjType(Acc,"Name") != "IAccessible"
      ErrorLevel := "Invalid IAccessible Object"
   else {
      AccInit(), 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?AccQuery(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
         return Children.MaxIndex()?Children:
      } else
         ErrorLevel := "AccessibleChildren DllCall Failed"
   }
   if AccError()
      throw Exception(ErrorLevel,-1)
}
  
Esc::   
    ExitApp 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui