Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Have a recursive function that returns the window handle of a particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't return the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as well. It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS


  #2   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 5,600
Default Why doesn't this recursive function return the right value?

Hi Bart,

My take is the function return value persists only in the calling stack.

So two solutions, the first as you've described and include an additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions, just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't return

the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as well.

It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS




  #3   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling stack.

So two solutions, the first as you've described and include an additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't return

the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as well.

It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS





  #4   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Oops, overlooked one important thing:
Doing dim bFound in the recursive routine will make the variable False every
time it passes this line of code. Declaring it Static shows there is lots of
code running after a find.
Maybe I am on the right track here.

RBS


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the
right window was found, but nil of these show, so no code runs after the
window was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in
any case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about
more than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling stack.

So two solutions, the first as you've described and include an additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't return

the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as
well.

It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS






  #5   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 5,600
Default Why doesn't this recursive function return the right value?

How and where are nTmp and nResult declared?

Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the stack

requires the same API's & Const's per your OP, maybe also Compare Text (just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in

any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't return

the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS









  #6   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Hi Peter,

Thanks, the second method works indeed, so I now got this:

Sub tester()
MsgBox FindWindowHwndLike_B(0, "Static", "DOB", 0, 0)
End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold)
If nTmp Then nResult = nTmp

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

FindWindowHwndLike_B = nResult

End Function


Still, I am wondering now if I really need the 3 extra variables you have
introduced.
I agree though that it is better now, because it is nice to make the
function self-contained and not needing
a private or public variable.
Will see if I can simplify it a bit.


RBS



"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?


Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in

any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS








  #7   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

It looks you can indeed simplify by getting rid of 2 variables and just keep
the extra
one nHolder (which I renamed to lHolder):

Sub tester()
MsgBox FindWindowHwndLike_B(0, "Static", "DOB", 0, 0)
End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef lHolder As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

lHolder = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, lHolder)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
lHolder = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

FindWindowHwndLike_B = lHolder

End Function


RBS


"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?


Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in

any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS








  #8   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

This will make it slightly quicker:

If InStr(1, sWindowTitle, WindowTitle, vbBinaryCompare) 0 And _
sClassName Like ClassName & "*" Then
FindWindowHwndLike_B = hwnd
lHolder = hwnd
Exit Function
End If

I want it case-sensitive, so that is OK.
Couldn't find anything for the ClassName comparison.

RBS


"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?


Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in

any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS








  #9   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Actually it can be speeded up further by declaring everything ByRef:

Function FindWindowHwndLike(hWndStart As Long, _
ClassName As String, _
WindowTitle As String, _
level As Long, _
lHolder As Long) As Long

RBS

"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?


Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling in

any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS








  #10   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 5,600
Default Why doesn't this recursive function return the right value?

Re your last 4 posts:

2/4
It looks you can indeed simplify by getting rid of 2 variables and just

keep
the extra
one nHolder (which I renamed to lHolder):


Exactly. But I'm surprised your tester() msgbox in this post (as quoted
below) shows a value, I would have expected you would need to do -

Dim n as long
call FindWindowHwndLike_B(0, "Static", "DOB", 0, n)
Msgbox n

To clarify what I should have done previously, in my demo altogether I
introduced 4 var's vs your original.

Passed to the function
bUsetmpVar : purely for testing two methods whereby the function returns a
value, or does not (like your original).
nHold : the ByRef arg

Declared in the function
nTmp & nResult

Simply the ByRef nHold arg works fine, though of course the function may not
return a value (depends on levels of recursions). With this method get rid
of nTmp & nResult and don't rely on the function returning a value.

However, if you want the function to consistently return a value, then use
nTmp & nResult and can dispense with the ByRef nHold arg.

With your recursive routine both methods work, I suspect the byRef arg
faster. However some routines may dictate one or other, or even both
methods.

nHolder (which I renamed to lHolder):


Guess I ought to get out of my "n" convention for longs, and adapt to the
rest of the world and use an l !

============

3/4 Text Compare etc
I want it case-sensitive, so that is OK.
Couldn't find anything for the ClassName comparison.


I don't quite follow. If you want case-sensitive nothing is required and NOT
Option Text (Option Compare Binary ?)

============

4/4
Actually it can be speeded up further by declaring everything ByRef:


Yes ByRef is always faster, though depending on the routine ByVal might be
required for some var's.

============

FWIW, for enumerating all windows this is probably faster (XL2K or later)

Public Declare Function EnumWindows Lib "user32" _
(ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean

EnumWindows AddressOf MyFunc, ByVal 0&
then in MyFunc return value to a module/public variable

though probably not appropriate for your particular "get out when got
something" routine.

Regards,
Peter T

PS, not sure if you noticed but I posted a question minutes after your OP,
it's still looking very solitary !


"RB Smissaert" wrote in message
...
Actually it can be speeded up further by declaring everything ByRef:

Function FindWindowHwndLike(hWndStart As Long, _
ClassName As String, _
WindowTitle As String, _
level As Long, _
lHolder As Long) As Long

RBS

"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?


Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the

stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the

right
window was found, but nil of these show, so no code runs after the

window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling

in
any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry about

more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an

additional
ByRef arg to return the value all the way back to the original

calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window

captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a

particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when I
retrieve the value with a private variable I get the right value as

well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As

Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with

ClassName
'and where the Window title starts with WindowTitle, returns

Hwnd

'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS












  #11   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 2,452
Default Why doesn't this recursive function return the right value?

Will have a look at all this, but it seems to be working all fine now and
fully behaving like a function.
Also knocked about 5% of the time off.
Had a look at your new posting, but not sure I quite understand it.
Must be the late hour after a busy day.

RBS

"Peter T" <peter_t@discussions wrote in message
...
Re your last 4 posts:

2/4
It looks you can indeed simplify by getting rid of 2 variables and just

keep
the extra
one nHolder (which I renamed to lHolder):


Exactly. But I'm surprised your tester() msgbox in this post (as quoted
below) shows a value, I would have expected you would need to do -

Dim n as long
call FindWindowHwndLike_B(0, "Static", "DOB", 0, n)
Msgbox n

To clarify what I should have done previously, in my demo altogether I
introduced 4 var's vs your original.

Passed to the function
bUsetmpVar : purely for testing two methods whereby the function returns a
value, or does not (like your original).
nHold : the ByRef arg

Declared in the function
nTmp & nResult

Simply the ByRef nHold arg works fine, though of course the function may
not
return a value (depends on levels of recursions). With this method get rid
of nTmp & nResult and don't rely on the function returning a value.

However, if you want the function to consistently return a value, then use
nTmp & nResult and can dispense with the ByRef nHold arg.

With your recursive routine both methods work, I suspect the byRef arg
faster. However some routines may dictate one or other, or even both
methods.

nHolder (which I renamed to lHolder):


Guess I ought to get out of my "n" convention for longs, and adapt to the
rest of the world and use an l !

============

3/4 Text Compare etc
I want it case-sensitive, so that is OK.
Couldn't find anything for the ClassName comparison.


I don't quite follow. If you want case-sensitive nothing is required and
NOT
Option Text (Option Compare Binary ?)

============

4/4
Actually it can be speeded up further by declaring everything ByRef:


Yes ByRef is always faster, though depending on the routine ByVal might be
required for some var's.

============

FWIW, for enumerating all windows this is probably faster (XL2K or later)

Public Declare Function EnumWindows Lib "user32" _
(ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean

EnumWindows AddressOf MyFunc, ByVal 0&
then in MyFunc return value to a module/public variable

though probably not appropriate for your particular "get out when got
something" routine.

Regards,
Peter T

PS, not sure if you noticed but I posted a question minutes after your OP,
it's still looking very solitary !


"RB Smissaert" wrote in message
...
Actually it can be speeded up further by declaring everything ByRef:

Function FindWindowHwndLike(hWndStart As Long, _
ClassName As String, _
WindowTitle As String, _
level As Long, _
lHolder As Long) As Long

RBS

"Peter T" <peter_t@discussions wrote in message
...
How and where are nTmp and nResult declared?

Sorry, I should have stated within the FindWindowHwndLike function

Following attempts to demonstrate the two methods I mentioned earlier -
- an additional ByRef var to pass back to the calling routing
- re-assigning the value to the Function on each return back up the

stack

requires the same API's & Const's per your OP, maybe also Compare Text
(just
in case)

Option Compare Text

Sub tester2()
Dim s1 As String, s2 As String
Dim x As Long, y As Long

s1 = "EXCE": s2 = "Book" ' eg like EXCEL7 & Book1.xls

x = FindWindowHwndLike_B(0, s1, s2, 0, y, False)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

x = FindWindowHwndLike_B(0, s1, s2, 0, y, True)
MsgBox "Func-return " & x & vbCr & "ByRef Arg " & y

End Sub

Function FindWindowHwndLike_B(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long, _
ByRef nHold As Long, _
bUseTmpVar As Boolean) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim nTmp As Long
Dim nResult As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion

If bUseTmpVar Then
nTmp = FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
If nTmp Then nResult = nTmp
Else
Call FindWindowHwndLike_B(hwnd, ClassName, WindowTitle, _
level, nHold, bUseTmpVar)
End If

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike_B = hwnd
nHold = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop
If bUseTmpVar Then
FindWindowHwndLike_B = nResult
End If
End Function

Regards,
Peter T


"RB Smissaert" wrote in message
...
Hi Peter,


Sorry, but I don't understand this bit at all:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

How and where are nTmp and nResult declared?
Why would it make a difference?
I tried something like you suggested, but still get zero.

What I don't understand is this: It finds the right window, with the
right
hwnd, but it returns zero.
Where does the variable hwnd change from the right value to zero?
I put messageboxes in the recursive function that could show after the
right
window was found, but nil of these show, so no code runs after the

window
was found:


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with ClassName
'and where the Window title starts with WindowTitle, returns Hwnd
'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long
Dim bFound As Boolean

If bFound Then
MsgBox "test1"
End If

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

If bFound Then
MsgBox "test2"
End If

Do Until hwnd = 0

If bFound Then
MsgBox "test3"
End If

'Search children by recursion
FindWindowHwndLike hwnd, ClassName, WindowTitle, level

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then

If bFound Then
MsgBox "test4"
End If

bFound = True
MsgBox hwnd
FindWindowHwndLike = hwnd
Exit Function
If bFound Then
MsgBox "test5"
End If

End If

If bFound Then
MsgBox "test6"
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

If bFound Then
MsgBox "test7"
End If

Loop

If bFound Then
MsgBox "test8"
End If

End Function


The trouble probably is that recursive function are bit mind-boggling

in
any
case and I might be overlooking something simple here.
I just know that in my particular situation I don't have to worry
about
more
than one qualifying windows.
Thanks in any case for your suggestions.


RBS


"Peter T" <peter_t@discussions wrote in message
...
Hi Bart,

My take is the function return value persists only in the calling
stack.

So two solutions, the first as you've described and include an
additional
ByRef arg to return the value all the way back to the original

calling
routine. Or something like this:

'recursive
nTmp = FindWindowHwndLike(hwnd, ClassName, WindowTitle, level)
If nTmp Then nResult = nTmp

'then finally -
FindWindowHwndLike = nResult
Exit function

I think passing the additional ByRef arg would be faster.

Just a thought, maybe build an array of all the "like" window

captions,
just
in case more than one.

Regards,
Peter T



"RB Smissaert" wrote in message
...
Have a recursive function that returns the window handle of a
particular
window, based on the window type and text.
It works fine and it finds the right window, but it just doesn't
return
the
right value. It returns zero.
When I do a msgbox before the Exit function it shows fine, or when
I
retrieve the value with a private variable I get the right value as
well.
It
is not a problem, but just wondering why this happens.

Option Explicit
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String,
_
ByVal nMaxCount As Long) As

Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5

Sub tester()
MsgBox FindWindowHwndLike(0, "Static", "DOB", 0)
End Sub


Function FindWindowHwndLike(ByVal hWndStart As Long, _
ByVal ClassName As String, _
ByVal WindowTitle As String, _
ByVal level As Long) As Long

'finds the first window where the class name start with

ClassName
'and where the Window title starts with WindowTitle, returns

Hwnd

'-----------------------------------------------------------------
Dim hwnd As Long
Dim sWindowTitle As String
Dim sClassName As String
Dim r As Long

'Initialize if necessary. This is only executed
'when level = 0 and hWndStart = 0, normally
'only on the first call to the routine.
If level = 0 Then
If hWndStart = 0 Then
hWndStart = GetDesktopWindow()
End If
End If

'Increase recursion counter
level = level + 1

'Get first child window
hwnd = GetWindow(hWndStart, GW_CHILD)

Do Until hwnd = 0

'Search children by recursion
Call FindWindowHwndLike(hwnd, ClassName, WindowTitle,
level)

'Get the window text
sWindowTitle = Space$(255)
r = GetWindowText(hwnd, sWindowTitle, 255)
sWindowTitle = Left$(sWindowTitle, r)

'get the class name
sClassName = Space$(255)
r = GetClassName(hwnd, sClassName, 255)
sClassName = Left$(sClassName, r)

'Check if the window matches the search parameters
If (sWindowTitle Like "*" & WindowTitle & "*") And _
(sClassName Like ClassName & "*") Then
FindWindowHwndLike = hwnd
Exit Function
End If

'Get next child window
hwnd = GetWindow(hwnd, GW_HWNDNEXT)

Loop

End Function


Thanks for any advice.


RBS











Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
close workbook without closing excel and stop recursive function chris Excel Discussion (Misc queries) 3 July 10th 06 08:23 PM
Recursive Functio help BigBobbo Excel Worksheet Functions 1 May 10th 06 07:23 PM
Recursive Function + File searching to return path ph8[_6_] Excel Programming 24 October 14th 05 08:45 AM
recursive sums Joe Excel Worksheet Functions 6 July 17th 05 09:45 AM
Recursive Subs? ExcelMonkey[_74_] Excel Programming 5 February 5th 04 02:54 AM


All times are GMT +1. The time now is 11:16 PM.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2004-2024 ExcelBanter.
The comments are property of their posters.
 

About Us

"It's about Microsoft Excel"