Home |
Search |
Today's Posts |
#1
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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
Posted to microsoft.public.excel.programming
|
|||
|
|||
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 |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Forum | |||
close workbook without closing excel and stop recursive function | Excel Discussion (Misc queries) | |||
Recursive Functio help | Excel Worksheet Functions | |||
Recursive Function + File searching to return path | Excel Programming | |||
recursive sums | Excel Worksheet Functions | |||
Recursive Subs? | Excel Programming |