1,601

Re: AHK: Замена "Window Spy"

Никак.

1,602

Re: AHK: Замена "Window Spy"

Malcev
А какой тогда смысл, если нет возможности использовать данные из этого Spy?

Если технология не освобождает людей от рутины, тогда весь технический прогресс бессмысленен.
© Жак Фреско

1,603

Re: AHK: Замена "Window Spy"

user7256, этот инструмент не для программного использования. С его помощью вы можете визуально ознакомиться со структурой окна, и скопировать какие-либо данные в буфер обмена.

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

1,604 (изменено: user7256, 2020-12-31 02:22:03)

Re: AHK: Замена "Window Spy"

Плохо. Большинство - хочет строить свою логику на основе выдаваемых данных, а не просто скопировать в буфер.

Если технология не освобождает людей от рутины, тогда весь технический прогресс бессмысленен.
© Жак Фреско

1,605

Re: AHK: Замена "Window Spy"

Почему плохо? Просто эта программа не для этого. Вы можете посмотреть в коде, какие методы используются, и применять их отдельно. Либо спросить здесь, если чего-то не понимаете.

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

1,606

Re: AHK: Замена "Window Spy"

user7256

Какой смысл использовать огромный кусок кода для своих мелких поделок? Не легче разобраться как оно устроено и сделать свою версию?

1,607

Re: AHK: Замена "Window Spy"

Библиотека Acc настолько сложна и забагованна, что без обертки пользоваться ей невозможно.
То тут, то там возникают ошибки.
Яркий тому пример - протухшая библиотека AccV2.ahk на гитхабе.

Хорошие программисты всегда стремились к понижению сложности.
Для уменьшения затрат на программирование практикуется code reuse, разбивка на модули и много других техник.
У вас ничего этого нет. Все в кучу на 8 тыс строк на 280 кб.

Вы предлагаете выдирать отдельные функции из вашего скрипта для использования в моих скриптах.
Но логичнее было бы один раз создать библиотеку Acc.ahk, и подключать к вашему AhkSpy.ahk где была бы только рисовалка формы с выводом данных в нее.
Это и было бы настоящим code reuse и разбивкой на модули на практике.
Так чтобы другие могли ей пользоваться, а не только трое программистов на свете, участвовавших в разработке.

Вы потратили столько времени на скрипт, это похвально.
Но ваш код очень быстро придет в негодность как только исчезнет желание его поддерживать.
И все сотни часов разработки окажутся потрачены зря, как у того самого юзера sancarn на гите.

Если технология не освобождает людей от рутины, тогда весь технический прогресс бессмысленен.
© Жак Фреско

1,608

Re: AHK: Замена "Window Spy"

Вот я выдрал все процедуры и хочу получить адрес бар из firefox с помощью GetBrowserURL()
Вот что получаю в результате:
https://i.imgur.com/C99WU58.png


ComObjError(false)

Global WS_EX_APPWINDOW := 0x40000, WS_CHILDWINDOW := 0x40000000, WS_EX_LAYERED := 0x80000
		, WS_EX_TRANSPARENT := 0x20, WS_POPUP := 0x80000000, WS_EX_NOACTIVATE := 0x8000000

#NoEnv
#UseHook
#KeyHistory 0

SetBatchLines, -1
ListLines, Off
DetectHiddenWindows, On
CoordMode, Pixel
CoordMode, Menu

oOther.anchor := {}, oOther.CurrentProcessId := DllCall("GetCurrentProcessId")

; If MemoryAnchor
; {
; 	If oOther.anchor["Win_text"] := IniRead("Win_Anchor")
; 		oOther.anchor["Win"] := 1
; 	If oOther.anchor["Control_text"] := IniRead("Control_Anchor")
; 		oOther.anchor["Control"] := 1
; } 

SeDebugPrivilege() 
oBody := oDoc.body 
oJScript := oDoc.Script
oJScript.WordWrap := WordWrap
oJScript.MoveTitles := MoveTitles
ComObjConnect(oDoc, Events)





url := GetBrowserURL()
OutputDebug, url: %url%

GetBrowserURL()
{
	WinGet, hw, ID, ahk_exe firefox.exe
	AccAccFocus(hw, name, value, role, irole)
	OutputDebug, value: %value%
	return value
}

SeDebugPrivilege() {
	Static PROCESS_QUERY_INFORMATION := 0x400, TOKEN_ADJUST_PRIVILEGES := 0x20, SE_PRIVILEGE_ENABLED := 0x2

	hProc := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION, Int, false, UInt, oOther.CurrentProcessId, Ptr)
	DllCall("Advapi32\OpenProcessToken", Ptr, hProc, UInt, TOKEN_ADJUST_PRIVILEGES, PtrP, token)
	DllCall("Advapi32\LookupPrivilegeValue", Ptr, 0, Str, "SeDebugPrivilege", Int64P, luid)
	VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
	NumPut(1, TOKEN_PRIVILEGES, "UInt")
	NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
	NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
	DllCall("Advapi32\AdjustTokenPrivileges", Ptr, token, Int, false, Ptr, &TOKEN_PRIVILEGES, UInt, 0, Ptr, 0, Ptr, 0)
	res := A_LastError
	DllCall("CloseHandle", Ptr, token)
	DllCall("CloseHandle", Ptr, hProc)
	Return res  ;; в случае удачи 0
}


AccWindowFromObject(pacc) {
	If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc) ? ComObjValue(pacc) : pacc, "Ptr*", hWnd) = 0
		Return hWnd
}
	;;	http://forum.script-coding.com/viewtopic.php?pid=130762#p130762

AccAccFocus(hWnd, byref name, byref value, byref role, byref irole) {
	Acc := Acc_ObjectFromWindow(hWnd)
	While IsObject(Acc.accFocus)
		Acc := Acc.accFocus
	try 
	{
		child := Acc.accFocus
		name := Acc.accName(child)
		value := Acc.accValue(child)
		role := AccRole(Acc, child) 
		irole := Acc.accRole(0) 
	}
}

AccRole(Acc, ChildId=0) {
	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
}

AccGetStateText(nState) {
	nSize := DllCall("oleacc\GetStateText", "UInt", nState, "Ptr", 0, "UInt", 0)
	VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetStateText", "UInt", nState, "str", sState, "UInt", nSize+1)
	Return sState
}

Acc_GetPath(byref arr) {
    Static DesktopHwnd := DllCall("User32.dll\GetDesktopWindow", "ptr") 
	If oPubObj.Acc.CLOAKED
		Return 0
	Acc := Object(oPubObj.Acc.AccObj) 
	arr := []
	
	While Hwnd := Acc_WindowFromObject(Parent := Acc_Parent(Acc)) { 
		If (DesktopHwnd != Hwnd)
			t1 := GetEnumIndex(Acc)
		If t1 = -1
			Return arr := ""
		If (PrHwnd != "" && Hwnd != PrHwnd)
		{
			PrHwnd := Format("0x{:06X}", PrHwnd)
			WinGetClass, WinClass, ahk_id %PrHwnd%
			WinGet, ProcessName, ProcessName, ahk_id %PrHwnd%
			arr.InsertAt(1, {Hwnd: PrHwnd, Path: SubStr(t2, 1, -1), WinClass: WinClass, ProcessName: ProcessName})
		}
		if (t1 = "" || Hwnd = DesktopHwnd)
		   break
		t2 := t1 "." t2
		PrHwnd := Hwnd
		Acc := Parent 
	}
	Return arr.Count()
}

GetEnumIndex(Acc) {	
	If oPubObj.Acc.CLOAKED
		Return -1
	For Each, child in Acc_Children(Acc_Parent(Acc))
	{ 
		if CompareAcc(child, Acc) 
			return A_Index
	}
}

CompareAcc(Acc1, Acc2) { 
	if IsObject(Acc1) && IsObject(Acc2)
	&& (Acc_Location(Acc1) = Acc_Location(Acc2))
	&& (Acc1.accDefaultAction(0) = Acc2.accDefaultAction(0)) 	
	&& (Acc1.accDescription(0) = Acc2.accDescription(0)) 	
	&& (Acc1.accHelp(0) = Acc2.accHelp(0)) 	
	&& (Acc1.accKeyboardShortcut(0) = Acc.accKeyboardShortcut(0)) 
	
	&& (Acc1.accChildCount = Acc2.accChildCount) 
	&& (Acc1.accName(0) = Acc2.accName(0)) 	
	&& (Acc1.accRole(0) = Acc2.accRole(0)) 	
	&& (Acc1.accState(0) = Acc2.accState(0)) 
	&& (Acc1.accValue(0) = Acc2.accValue(0))
		return 1
}

Acc_Children(Acc) {
	if ComObjType(Acc, "Name") != "IAccessible"
		return
	else
	{
		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 : ""
		}
	}
}
AccGetLocation(Acc, ChildId=0) {
	Static x := 0, y := 0, w := 0, h := 0
	try Acc.accLocation(ComObj(0x4003,&x), ComObj(0x4003,&y), ComObj(0x4003,&w), ComObj(0x4003,&h), ChildId)
	AccCoord[1]:=NumGet(x,0,"int"), AccCoord[2]:=NumGet(y,0,"int"), AccCoord[3]:=NumGet(w,0,"int"), AccCoord[4]:=NumGet(h,0,"int")
}
Acc_Location(Acc, ChildId=0) {
	Static x := 0, y := 0, w := 0, h := 0
	try Acc.accLocation(ComObj(0x4003,&x), ComObj(0x4003,&y), ComObj(0x4003,&w), ComObj(0x4003,&h), ChildId)
	return "x" NumGet(x, 0, "int") " y" NumGet(y, 0, "int") " w" NumGet(w, 0, "int") " h" NumGet(h, 0, "int")
}
Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "") {
	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
		Return ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}
Acc_ObjectFromWindow(hWnd, idObject = 0) {
	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_WindowFromObject(pacc) {
	If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc) ? ComObjValue(pacc) : pacc, "Ptr*", hWnd)=0
		Return	hWnd
} 
Acc_Parent(Acc) { 
	try parent := Acc.accParent 
	return parent ? Acc_Query(parent) : ""
}
Acc_Query(Acc) {
	try return ComObj(9, ComObjQuery(Acc, "{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
	static setting:=0
	return p=""?setting:setting:=p
}
Acc_Role(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_GetRoleText(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
}
Acc_ChildrenByRole(Acc, Role) {
	if ComObjType(Acc,"Name")!="IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		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)
				if NumGet(varChildren,i-8)=9
					AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
				else
					Acc_Role(Acc, child)=Role?Children.Insert(child):
			}
			return Children.MaxIndex()?Children:, ErrorLevel:=0
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
	static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
	AccObj :=   IsObject(WinTitle)? WinTitle
			:   Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
	if ComObjType(AccObj, "Name") != "IAccessible"
		ErrorLevel := "Could not access an IAccessible Object"
	else {
		StringReplace, ChildPath, ChildPath, _, %A_Space%, All
		AccError:=Acc_Error(), Acc_Error(true)
		Loop Parse, ChildPath, ., %A_Space%
			try {
				if A_LoopField is digit
					Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
				else
					RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
				if Not Children.HasKey(m2)
					throw
				AccObj := Children[m2]
			} catch {
				ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
				if Acc_Error()
					throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
				return   ; Acc_Error
			}
		Acc_Error(AccError)
		StringReplace, Cmd, Cmd, %A_Space%, , All
		properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
		try {
			if (Cmd = "Location")
				AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
			  , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
			else if (Cmd = "Object")
				ret_val := AccObj
			else if Cmd in Role,State
				ret_val := Acc_%Cmd%(AccObj, ChildID+0)
			else if Cmd in ChildCount,Selection,Focus
				ret_val := AccObj["acc" Cmd]
			else
				ret_val := AccObj["acc" Cmd](ChildID+0)
		} catch {
			ErrorLevel := """" Cmd """ Cmd Not Implemented"
			if Acc_Error()
				throw Exception("Cmd Not Implemented", -1, Cmd)
			return
		}
		return ret_val, ErrorLevel:=0
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}


AccUnderMouse(WinID, ByRef child) {
	Static h
	If Not h
		h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
	If DllCall("oleacc\AccessibleObjectFromPoint"
		, "Int64", 0 * DllCall("GetCursorPos", "Int64*", pt) + pt, "Ptr*", pacc
		, "Ptr", VarSetCapacity(varChild, 8 + 2 * A_PtrSize, 0) * 0 + &varChild) = 0
	Acc := ComObjEnwrap(9, pacc, 1)
	If IsObject(Acc)
		Return Acc, child := NumGet(varChild, 8, "UInt")
}
Если технология не освобождает людей от рутины, тогда весь технический прогресс бессмысленен.
© Жак Фреско

1,609

Re: AHK: Замена "Window Spy"

user7256 пишет:

Библиотека Acc настолько сложна и забагованна, что без обертки пользоваться ей невозможно.

Пока я багов не обнаружил и по сравнению с UIA ничуть не сложна.

1,610

Re: AHK: Замена "Window Spy"

user7256, думаю, не стоит в этой теме обсуждать неудачные попытки использования выдранного наугад кода. Эта тема предназначена для обсуждения AhkSpy. Создайте свою тему со внятным заголовком, напишите, что пытались сделать, задайте конкретный вопрос.

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

1,611

Re: AHK: Замена "Window Spy"

serzh82saratov, у меня последняя версия не подсвечивает acc-элементы на семёрке, на десятке работает.

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

1,612

Re: AHK: Замена "Window Spy"

У меня нет семёрки, а координаты и размер правильно определяет?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

1,613

Re: AHK: Замена "Window Spy"

Отбой, я просто не включил режим Control.

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