Results 1 to 2 of 2

Thread: FindWindow API helper

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2006
    Location
    Melbourne, Australia
    Posts
    415

    FindWindow API helper

    This code will Debug.Print the required steps to take to find a window handle using FindWindow(Ex) calls. It will print out the steps for the handle of the window your cursor is over when you press the left-control button

    Based on the code from
    http://www.vbforums.com/attachment....achmentid=48851
    You need a timer called timer1 on the form

    VB Code:
    1. Private Type POINTAPI
    2.     x As Long
    3.     y As Long
    4. End Type
    5. Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    6. Private Declare Function WindowFromPointXY Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
    7. Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
    8. Private Declare Function GetWindowWord Lib "user32" (ByVal hwnd As Long, ByVal nIndex As Long) As Integer
    9. Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    10. Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    11. Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    12. Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    13. Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    14. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    15. Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    16.  
    17. Private Sub Form_Load()
    18. Timer1.Interval = 1
    19. End Sub
    20.  
    21. Sub Timer1_Timer()
    22. Dim pt32 As POINTAPI
    23. Dim sWindowText As String * 100, sWindowLen As Integer
    24. Dim sClassName As String * 100, sClassLen As Integer
    25. Dim hWndOver As Long
    26. Dim hWndParent As Long
    27. Dim sParentClassName As String * 100, sParentWindowLen As Integer
    28. Dim sParentWindowText As String * 100, sParentClassLen As Integer
    29. Static hWndLast As Long
    30.  
    31. If GetAsyncKeyState(17) Then
    32.     Call GetCursorPos(pt32)
    33.     hWndOver = WindowFromPointXY(pt32.x, pt32.y)
    34.     If hWndOver <> hWndLast Then
    35.         hWndLast = hWndOver
    36.         Debug.Print "-------------------------" & vbCrLf & "Window Info:"
    37.         Debug.Print "Window Handle: &H"; Hex(hWndOver)
    38.         sWindowLen = GetWindowText(hWndOver, sWindowText, 100)
    39.         Debug.Print "Window Text: " & Left(sWindowText, sWindowLen)
    40.         sClassLen = GetClassName(hWndOver, sClassName, 100)
    41.         Debug.Print "Window Class Name: "; Left(sClassName, sClassLen)
    42.         hWndParent = GetParent(hWndOver)
    43.        
    44.         Dim parentHandles() As Long, parentCount As Integer
    45.         Debug.Print vbCrLf & "#################################################" & vbCrLf & "Dim hWnd as Long"
    46.         While hWndParent <> 0
    47.             ReDim Preserve parentHandles(parentCount)
    48.             parentHandles(parentCount) = hWndParent
    49.             hWndParent = GetParent(hWndParent)
    50.             parentCount = parentCount + 1
    51.         Wend
    52.        
    53.         Dim printStr As String
    54.         For i = parentCount - 1 To 0 Step -1
    55.             sParentWindowLen = GetWindowText(parentHandles(i), sParentWindowText, 100)
    56.             sParentClassLen = GetClassName(parentHandles(i), sParentClassName, 100)
    57.            
    58.             If i = parentCount - 1 Then
    59.                 printStr = "hWnd = FindWindow(" & Chr(34) & Left(sParentClassName, sParentClassLen) & Chr(34) & ", " & Chr(34) & Left(sParentWindowText, sParentWindowLen) & Chr(34) & ")"
    60.             Else
    61.                 printStr = "hWnd = FindWindowEx(hWnd, 0&, " & Chr(34) & Left(sParentClassName, sParentClassLen) & Chr(34) & ", " & Chr(34) & Left(sParentWindowText, sParentWindowLen) & Chr(34) & ")"
    62.             End If
    63.             Debug.Print Replace(Replace(printStr, Chr(34) & Chr(34) & ",", "0&,"), Chr(34) & Chr(34), "vbNullString")
    64.        
    65.         Next
    66.         If parentCount = 0 Then
    67.             printStr = "hWnd = FindWindow(" & Chr(34) & Left(sClassName, sClassLen) & Chr(34) & ", " & Chr(34) & Left(sWindowText, sWindowLen) & Chr(34) & ")"
    68.         Else
    69.             printStr = "hWnd = FindWindowEx(hWnd, 0&, " & Chr(34) & Left(sClassName, sClassLen) & Chr(34) & ", " & Chr(34) & Left(sWindowText, sWindowLen) & Chr(34) & ")"
    70.         End If
    71.         Debug.Print Replace(Replace(printStr, Chr(34) & Chr(34) & ",", "0&,"), Chr(34) & Chr(34), "vbNullString")
    72.         Debug.Print "#################################################" & vbCrLf & "-------------------------" & vbCrLf
    73.        
    74.     End If
    75. End If
    76.  
    77. End Sub

    Note, this will always take the first window, if it finds two windows with the same class+caption with the same parents.
    If needed, you could add a loop to keep checking the windows until the right hWnd was reached, and I might do this some time in the future
    Last edited by Rob123; Dec 14th, 2006 at 10:42 PM.

  2. #2
    Oi, fat-rag! bushmobile's Avatar
    Join Date
    Mar 2004
    Location
    on the poop deck
    Posts
    5,592

    Re: FindWindow API helper

    I came up with something similar to this for a scripting language I was messing around with. It outputted the code on a single line in manner that my parser would understand, so I've modified it to output VB code instead - it can handle windows with the same classname & caption:
    VB Code:
    1. Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
    2.     ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    3.  
    4. Private Declare Function GetAncestor Lib "user32.dll" ( _
    5.     ByVal hwnd As Long, ByVal gaFlags As Long) As Long
    6.  
    7. Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
    8.     ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    9.  
    10. Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
    11.     ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    12.  
    13. Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" ( _
    14.     ByVal hwnd As Long) As Long
    15.    
    16. Private Declare Function GetDesktopWindow Lib "user32" () As Long
    17.  
    18. Private Const GA_PARENT As Long = 1
    19.  
    20. Private Function WindowCode(ByVal lhWnd As Long) As String
    21.     Dim lParent As Long, lChild As Long, lLen As Long, lCount As Long
    22.     Dim sClass As String, sCaption As String
    23.  
    24.     Do
    25.         ' ClassName
    26.         sClass = Space$(256)
    27.         lLen = GetClassName(lhWnd, sClass, 256)
    28.         sClass = Left$(sClass, lLen)
    29.  
    30.         ' Caption
    31.         sCaption = String$(GetWindowTextLength(lhWnd), vbNullChar)
    32.         GetWindowText lhWnd, sCaption, Len(sCaption) + 1
    33.  
    34.         ' Find Window
    35.         lParent = GetAncestor(lhWnd, GA_PARENT)
    36.        
    37.         lCount = 1: lChild = 0
    38.         WindowCode = "lhWnd = lChild: lChild = 0" & vbCrLf & WindowCode
    39.         Do
    40.             lChild = FindWindowEx(lParent, lChild, sClass, sCaption)
    41.             WindowCode = "lChild = FindWindowEx(lhWnd, lChild, """ & sClass & """, """ & sCaption & """)" & vbCrLf & WindowCode
    42.             If lChild = lhWnd Then Exit Do
    43.             lCount = lCount + 1
    44.         Loop Until lChild = lhWnd
    45.         lhWnd = lParent
    46.     Loop Until lhWnd = GetDesktopWindow
    47.    
    48.     WindowCode = "Dim lChild As Long, lhWnd As Long" & vbCrLf & vbCrLf & WindowCode & vbCrLf & "Debug.Print Hex(lhWnd)"
    49. End Function
    example output (the "=" button on the calculator):
    Code:
    Dim lChild As Long, lhWnd As Long
    
    lChild = FindWindowEx(lhWnd, lChild, "SciCalc", "Calculator")
    lhWnd = lChild: lChild = 0
    lChild = FindWindowEx(lhWnd, lChild, "Button", "=")
    lhWnd = lChild: lChild = 0
    
    Debug.Print Hex(lhWnd)
    you could use GetAsyncKeyState to get the hWnd to pass to the function as Rob showed above, or you could also use the MouseDown / MouseUp events of a picturebox, e.g.:
    VB Code:
    1. Private Type POINTAPI
    2.     X As Long
    3.     Y As Long
    4. End Type
    5.  
    6. Private Declare Function ClientToScreen Lib "user32" ( _
    7.     ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    8.  
    9. Private Declare Function WindowFromPoint Lib "user32" ( _
    10.     ByVal xPoint As Long, ByVal yPoint As Long) As Long
    11.  
    12. Private bFinding As Boolean
    13.  
    14. Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    15.     If Button = vbLeftButton Then
    16.         Me.MousePointer = vbSizePointer
    17.         bFinding = True
    18.     End If
    19. End Sub
    20.  
    21. Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    22.     Dim pt As POINTAPI
    23.     If bFinding Then
    24.         pt.X = X \ Screen.TwipsPerPixelX
    25.         pt.Y = Y \ Screen.TwipsPerPixelY
    26.         ClientToScreen Picture1.hwnd, pt
    27.         Debug.Print WindowCode(WindowFromPoint(pt.X, pt.Y))
    28.     End If
    29.     Me.MousePointer = vbNormal
    30.     bFinding = False
    31. End Sub
    Left-Click on the picturebox, hold it down and then move the mouse over the window of interest, release the left button and it'll find the window's hWnd (just like Spy++)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width