 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
ahklerner
Joined: 26 Jun 2006 Posts: 1381 Location: USA
|
Posted: Thu Oct 01, 2009 1:36 am Post subject: Function - Control_GetClassNN() - Get a control ClassNN |
|
|
I searched in vain for something to do this...
So here it is.
Gets the ClassNN for a given hWnd
Some commands allow usage of ClassNN for a control, however there is not a function to get the ClassNN of a control. all base functions return ClassName only.
i borrowed part of this function from SKAN....
| Code: | ;Control_GetClassNN()
;by ahklerner
;
Control_GetClassNN(hWndWindow,hWndControl){
DetectHiddenWindows, On
WinGet, ClassNNList, ControlList, ahk_id %hWndWindow%
Loop, PARSE, ClassNNList, `n
{
ControlGet, hwnd, hwnd,,%A_LoopField%,ahk_id %hWndWindow%
if (hWnd = hWndControl)
return A_LoopField
}
}
;return
;Test script
Gui, +LastFound
hWindow := WinExist()
Gui, Add, Text, hwndhWnd, some text
Gui, Show
WinGetClass, ClassNN, ahk_id %hWnd%
MsgBox % Control_GetClassNN(hWindow,hWnd)
ExitApp
|
_________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
[VxE]
Joined: 07 Oct 2006 Posts: 3254 Location: Simi Valley, CA
|
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1381 Location: USA
|
Posted: Tue Oct 06, 2009 4:48 am Post subject: |
|
|
i was interested in the dllcall version, but it just gets classname and not classNN  _________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 8688
|
Posted: Tue Oct 06, 2009 6:45 am Post subject: |
|
|
Avoiding LOOP...
| Code: | Control_GetClassNN( hWnd,hCtrl ) { ; SKAN: www.autohotkey.com/forum/viewtopic.php?t=49471
WinGet, CH, ControlListHwnd, ahk_id %hWnd%
WinGet, CN, ControlList, ahk_id %hWnd%
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CH, 1, InStr( CH, LF hCtrl LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CN, `n, L%ErrorLevel%
Return SubStr( CN, P+2, InStr( CN, LF, 0, P+2 ) -P-2 )
} |
|
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1381 Location: USA
|
Posted: Sun Oct 11, 2009 4:16 am Post subject: |
|
|
Very Nice! mine takes fewer query performance counter increments. at least here
| Code: | freq := 0
Gui, +LastFound
hWindow := WinExist()
Gui, Add, Text, hwndhWnd, some text
Gui, Show
WinGetClass, ClassNN, ahk_id %hWnd%
;MsgBox % Control_GetClassNN(hWindow,hWnd)
;ExitApp
Loop 1000
{
freq += 100
DllCall("QueryPerformanceCounter", "Int64 *", CounterBefore1)
Loop %freq%
hWnd := Control_GetClassNN(hWindow,hWnd)
DllCall("QueryPerformanceCounter", "Int64 *", CounterAfter1)
DllCall("QueryPerformanceCounter", "Int64 *", CounterBefore2)
Loop %freq%
hWnd2 := sControl_GetClassNN(hWindow,hWnd)
DllCall("QueryPerformanceCounter", "Int64 *", CounterAfter2)
DllCall("QueryPerformanceFrequency","int64*",f)
avg1 := (CounterAfter1 - CounterBefore1) / f
avg2 := (CounterAfter2 - CounterBefore2) / f
MsgBox % "queryperformancecounterfrequency: " . f. "`nloops: " . freq . "`navg QPC time is ahklerner:" . avg1 . "`navg QPC time is skan:" . avg2
}
Control_GetClassNN(hWndWindow,hWndControl){
DetectHiddenWindows, On
WinGet, ClassNNList, ControlList, ahk_id %hWndWindow%
Loop, PARSE, ClassNNList, `n
{
ControlGet, hwnd, hwnd,,%A_LoopField%,ahk_id %hWndWindow%
if (hWnd = hWndControl)
return A_LoopField
}
}
sControl_GetClassNN( hWnd,hCtrl ) { ; SKAN: www.autohotkey.com/forum/viewtopic.php?t=49471
WinGet, CH, ControlListHwnd, ahk_id %hWnd%
WinGet, CN, ControlList, ahk_id %hWnd%
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CH, 1, InStr( CH, LF hCtrl LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CN, `n, L%ErrorLevel%
Return SubStr( CN, P+2, InStr( CN, LF, 0, P+2 ) -P-2 )
} |
_________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 8688
|
Posted: Tue Oct 13, 2009 10:13 am Post subject: |
|
|
| ahklerner wrote: | mine takes fewer query performance counter increments. at least here
| Code: | ; ...
hWindow := WinExist()
Gui, Add, Text, hwndhWnd, some text
Gui, Show
; ...
|
|
You are creating only a single control.
In real world, the control list could be long where the Loop command can never match the speeds of String manipulation commands.
| Code: | SetBatchLines -1
Run Calc
WinWait, Calculator ahk_class SciCalc
hWnd := WinExist( "Calculator ahk_class SciCalc" )
SendMessage, 0x111, 304,,, ahk_id %hWnd% ; MenuSelect : View > Scientific
ControlGet, hCtrl, Hwnd,, Button72, ahk_id %hWnd%
TC := A_TickCount
Loop 1000
sControl_GetClassNN( hWnd,hCtrl )
TC1 := ( A_TickCount - TC ) / 1000
TC := A_TickCount
Loop 1000
Control_GetClassNN( hWnd,hCtrl )
TC2 := ( A_TickCount - TC ) / 1000
MsgBox, 0, in Milliseconds, % "skan:`t"TC1 "`nahkl:`t" TC2
sControl_GetClassNN( hWnd,hCtrl ) { ; SKAN: www.autohotkey.com/forum/viewtopic.php?t=49471
WinGet, CH, ControlListHwnd, ahk_id %hWnd%
WinGet, CN, ControlList, ahk_id %hWnd%
Clipboard := CN
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CH, 1, InStr( CH, LF hCtrl LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CN, `n, L%ErrorLevel%
Return SubStr( CN, P+2, InStr( CN, LF, 0, P+2 ) -P-2 )
}
Control_GetClassNN(hWndWindow,hWndControl){
DetectHiddenWindows, On
WinGet, ClassNNList, ControlList, ahk_id %hWndWindow%
Loop, PARSE, ClassNNList, `n
{
ControlGet, hwnd, hwnd,,%A_LoopField%,ahk_id %hWndWindow%
if (hWnd = hWndControl)
return A_LoopField
}
}
|
|
|
| Back to top |
|
 |
ghee22
Joined: 04 Jul 2009 Posts: 36
|
Posted: Sat Nov 07, 2009 2:26 pm Post subject: |
|
|
| Micahs's script may be useful. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7295 Location: Australia
|
Posted: Sat Nov 07, 2009 7:19 pm Post subject: |
|
|
I was interested to try a couple different approaches, and I found that the poor performance of ahklerner's function with greater number of controls was not due to the use of Loop. Maybe no method using a scripted Loop will be as efficient as SKAN's method, but in ahklerner's case something else makes a much bigger difference: the conversion of each ClassNN back into a HWND, I believe.
Anyway, my first idea was to use EnumChildWindows. This is used internally by AutoHotkey to list controls and convert between HWND and ClassNN. The order in which EnumChildWindows enumerates controls determines the NN value and the order of controls in the list. The basic premise is to copy this in script, counting how many controls are encountered with the same class before the target control is found.
I think the main problem with that idea was the overhead of the callback required to enumerate controls. My second idea replaces the oft called script callback with a parsing loop, letting AutoHotkey do the control enumeration - i.e. WinGet,v,ControlListHwnd.
Each run of the benchmark begins with 16 controls. Each iteration calls each method 1000 times to retrieve the ClassNN of the last control, then shows the results. The average time in ms of each method and the factor by which the time increased are shown. Before continuing to the next iteration, the number of controls is doubled.
| Code: | #NoEnv
DetectHiddenWindows, On
SetBatchLines, -1
SetFormat, FloatFast, 0.3
Gui, +LastFound
hWnd := WinExist()
i = 1000 ; iterations
n = 16 ; initial number of controls
Loop %n%
Gui, Add, Text, hwndhCtrl
Loop
{
TC := A_TickCount
Loop %i%
eControl_GetClassNN( hWnd,hCtrl )
TC1 := ( A_TickCount - TC ) / i
TC := A_TickCount
Loop %i%
lControl_GetClassNN( hWnd,hCtrl )
TC2 := ( A_TickCount - TC ) / i
TC := A_TickCount
Loop %i%
sControl_GetClassNN( hWnd,hCtrl )
TC3 := ( A_TickCount - TC ) / i
TC := A_TickCount
Loop %i%
aControl_GetClassNN( hWnd,hCtrl )
TC4 := ( A_TickCount - TC ) / i
; OutputDebug % n "`tE " TC1 " (" TC1/pTC1 ")`tL " TC2 " (" TC2/pTC2 ")`tS " TC3 " (" TC3/pTC3 ")`tA " TC4 " (" TC4/pTC4 ")"
MsgBox % "Controls: " n "`n`n"
. "E`t" TC1 "`t=prev*" TC1/pTC1 "`n"
. "L`t" TC2 "`t=prev*" TC2/pTC2 "`n"
. "S`t" TC3 "`t=prev*" TC3/pTC3 "`n"
. "A`t" TC4 "`t=prev*" TC4/pTC4 "`n"
Loop %n%
Gui, Add, Text, hwndhCtrl
n *= 2
pTC1 := TC1, pTC2 := TC2, pTC3 := TC3, pTC4 := TC4
}
; Lexikos: Find ClassNN by enumerating child controls and counting
; the number of controls of the target class.
eControl_GetClassNN(hWnd, hCtl)
{
static sCtl, sCls, sProc, sNN, sRet
if (A_EventInfo = sProc)
{
WinGetClass, cls, ahk_id %hWnd%
if (cls == sCls)
{
sNN += 1
if (hWnd = sCtl)
{
sRet := sCls sNN
return false ; stop
}
}
return true ; continue
}
if !sProc
sProc := RegisterCallback(A_ThisFunc,"F")
sCtl := hCtl
WinGetClass, sCls, ahk_id %sCtl%
sNN := 0
sRet := ""
DllCall("EnumChildWindows", "uint", hWnd, "uint", sProc, "uint", 0)
return sRet
}
; Lexikos: Find ClassNN by retrieving list of HWNDs and counting
; the number of controls of the target class.
lControl_GetClassNN(hwnd, hctl)
{
WinGet, hlist, ControlListHwnd, ahk_id %hwnd%
WinGetClass, tclass, ahk_id %hctl%
Loop, Parse, hlist, `n
{
WinGetClass, lclass, ahk_id %A_LoopField%
if (lclass == tclass)
{
nn += 1
if A_LoopField = %hctl%
return tclass nn
}
}
}
; SKAN
sControl_GetClassNN( hWnd,hCtrl ) { ; SKAN: www.autohotkey.com/forum/viewtopic.php?t=49471
WinGet, CH, ControlListHwnd, ahk_id %hWnd%
WinGet, CN, ControlList, ahk_id %hWnd%
LF:= "`n", CH:= LF CH LF, CN:= LF CN LF, S:= SubStr( CH, 1, InStr( CH, LF hCtrl LF ) )
StringReplace, S, S,`n,`n, UseErrorLevel
StringGetPos, P, CN, `n, L%ErrorLevel%
Return SubStr( CN, P+2, InStr( CN, LF, 0, P+2 ) -P-2 )
}
; ahklerner
aControl_GetClassNN(hWndWindow,hWndControl){
WinGet, ClassNNList, ControlList, ahk_id %hWndWindow%
Loop, PARSE, ClassNNList, `n
{
ControlGet, hwnd, hwnd,,%A_LoopField%,ahk_id %hWndWindow%
if (hWnd = hWndControl)
return A_LoopField
}
}
|
SKAN's method still wins, but my enumeration and looping methods come close with a reasonable number of controls.
Also note that SKAN's benchmark script fails completely on Windows 7.
SciCalc -> CalcFrame |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 8688
|
Posted: Sun Nov 08, 2009 7:50 am Post subject: |
|
|
@Lexikos: Thanks for the info and the interesting benchmark. 
Last edited by SKAN on Wed Nov 18, 2009 8:57 pm; edited 1 time in total |
|
| Back to top |
|
 |
nick
Joined: 24 Aug 2005 Posts: 549 Location: Berlin / Germany
|
Posted: Sun Nov 08, 2009 10:35 am Post subject: |
|
|
FYI:
| Code: | GetClassNN(HW, HC) { ; HW : Window's HWND, HC : Control's HWND
VarSetCapacity(CL,256,0), HA := 0
, DllCall("GetClassName", UInt,HC, Str,CL, Int,255)
While HA := DllCall("FindWindowEx", UInt,HW, UInt,HA, UInt,&CL, UInt,0)
If (HA = HC)
Return CL . A_Index
Return False
} |
_________________ nick  |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7295 Location: Australia
|
Posted: Sun Nov 08, 2009 10:44 am Post subject: |
|
|
| Unless I'm mistaken, that method will iterate through the controls in z-order, which can vary at run-time and is quite possibly the wrong order. As I mentioned earlier, EnumChildWindows defines the order in which AutoHotkey assigns NN values to controls. |
|
| Back to top |
|
 |
nick
Joined: 24 Aug 2005 Posts: 549 Location: Berlin / Germany
|
Posted: Sun Nov 08, 2009 11:18 am Post subject: |
|
|
| Quote: | | z-order, which can vary at run-time and is quite possibly the wrong order |
What a pity!  _________________ nick  |
|
| Back to top |
|
 |
Scoox
Joined: 28 Nov 2010 Posts: 35 Location: Wuxi, China
|
Posted: Sun Jan 16, 2011 5:10 pm Post subject: |
|
|
Not really what the original poster was asking but I stumbled upon this thread while looking for a way to determine the ClassNN of a control so I thought others would find it useful.
The following function returns the ClassNN of the currently focused control:
| Code: | ControlFocusedClassNN()
{
ControlGetFocus, ControlClassNN, A
Return ControlClassNN
} |
The following function returns the ClassNN of the control currently under the mouse:
| Code: | ControlUnderMouseClassNN()
{
MouseGetPos,,,, ControlClassNN, 1
Return ControlClassNN
} |
|
|
| Back to top |
|
 |
mcouthon Guest
|
Posted: Tue Jan 25, 2011 11:22 am Post subject: Thank you very much!! |
|
|
Scoox,
your post really saved my day. I always knew there had to be a way to do this without loops and all kinds of crazy stuff. Thank you so much! |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|