|
-
Dec 14th, 2006, 04:20 AM
#1
Thread Starter
Hyperactive Member
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:
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPointXY Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private Declare Function GetWindowWord Lib "user32" (ByVal hwnd As Long, ByVal nIndex As Long) As Integer
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd 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 Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
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
Private Sub Form_Load()
Timer1.Interval = 1
End Sub
Sub Timer1_Timer()
Dim pt32 As POINTAPI
Dim sWindowText As String * 100, sWindowLen As Integer
Dim sClassName As String * 100, sClassLen As Integer
Dim hWndOver As Long
Dim hWndParent As Long
Dim sParentClassName As String * 100, sParentWindowLen As Integer
Dim sParentWindowText As String * 100, sParentClassLen As Integer
Static hWndLast As Long
If GetAsyncKeyState(17) Then
Call GetCursorPos(pt32)
hWndOver = WindowFromPointXY(pt32.x, pt32.y)
If hWndOver <> hWndLast Then
hWndLast = hWndOver
Debug.Print "-------------------------" & vbCrLf & "Window Info:"
Debug.Print "Window Handle: &H"; Hex(hWndOver)
sWindowLen = GetWindowText(hWndOver, sWindowText, 100)
Debug.Print "Window Text: " & Left(sWindowText, sWindowLen)
sClassLen = GetClassName(hWndOver, sClassName, 100)
Debug.Print "Window Class Name: "; Left(sClassName, sClassLen)
hWndParent = GetParent(hWndOver)
Dim parentHandles() As Long, parentCount As Integer
Debug.Print vbCrLf & "#################################################" & vbCrLf & "Dim hWnd as Long"
While hWndParent <> 0
ReDim Preserve parentHandles(parentCount)
parentHandles(parentCount) = hWndParent
hWndParent = GetParent(hWndParent)
parentCount = parentCount + 1
Wend
Dim printStr As String
For i = parentCount - 1 To 0 Step -1
sParentWindowLen = GetWindowText(parentHandles(i), sParentWindowText, 100)
sParentClassLen = GetClassName(parentHandles(i), sParentClassName, 100)
If i = parentCount - 1 Then
printStr = "hWnd = FindWindow(" & Chr(34) & Left(sParentClassName, sParentClassLen) & Chr(34) & ", " & Chr(34) & Left(sParentWindowText, sParentWindowLen) & Chr(34) & ")"
Else
printStr = "hWnd = FindWindowEx(hWnd, 0&, " & Chr(34) & Left(sParentClassName, sParentClassLen) & Chr(34) & ", " & Chr(34) & Left(sParentWindowText, sParentWindowLen) & Chr(34) & ")"
End If
Debug.Print Replace(Replace(printStr, Chr(34) & Chr(34) & ",", "0&,"), Chr(34) & Chr(34), "vbNullString")
Next
If parentCount = 0 Then
printStr = "hWnd = FindWindow(" & Chr(34) & Left(sClassName, sClassLen) & Chr(34) & ", " & Chr(34) & Left(sWindowText, sWindowLen) & Chr(34) & ")"
Else
printStr = "hWnd = FindWindowEx(hWnd, 0&, " & Chr(34) & Left(sClassName, sClassLen) & Chr(34) & ", " & Chr(34) & Left(sWindowText, sWindowLen) & Chr(34) & ")"
End If
Debug.Print Replace(Replace(printStr, Chr(34) & Chr(34) & ",", "0&,"), Chr(34) & Chr(34), "vbNullString")
Debug.Print "#################################################" & vbCrLf & "-------------------------" & vbCrLf
End If
End If
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.
-
Dec 14th, 2006, 05:46 PM
#2
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:
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
Private Declare Function GetAncestor Lib "user32.dll" ( _
ByVal hwnd As Long, ByVal gaFlags 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 Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" ( _
ByVal hwnd As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Const GA_PARENT As Long = 1
Private Function WindowCode(ByVal lhWnd As Long) As String
Dim lParent As Long, lChild As Long, lLen As Long, lCount As Long
Dim sClass As String, sCaption As String
Do
' ClassName
sClass = Space$(256)
lLen = GetClassName(lhWnd, sClass, 256)
sClass = Left$(sClass, lLen)
' Caption
sCaption = String$(GetWindowTextLength(lhWnd), vbNullChar)
GetWindowText lhWnd, sCaption, Len(sCaption) + 1
' Find Window
lParent = GetAncestor(lhWnd, GA_PARENT)
lCount = 1: lChild = 0
WindowCode = "lhWnd = lChild: lChild = 0" & vbCrLf & WindowCode
Do
lChild = FindWindowEx(lParent, lChild, sClass, sCaption)
WindowCode = "lChild = FindWindowEx(lhWnd, lChild, """ & sClass & """, """ & sCaption & """)" & vbCrLf & WindowCode
If lChild = lhWnd Then Exit Do
lCount = lCount + 1
Loop Until lChild = lhWnd
lhWnd = lParent
Loop Until lhWnd = GetDesktopWindow
WindowCode = "Dim lChild As Long, lhWnd As Long" & vbCrLf & vbCrLf & WindowCode & vbCrLf & "Debug.Print Hex(lhWnd)"
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:
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function ClientToScreen Lib "user32" ( _
ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" ( _
ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private bFinding As Boolean
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbLeftButton Then
Me.MousePointer = vbSizePointer
bFinding = True
End If
End Sub
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim pt As POINTAPI
If bFinding Then
pt.X = X \ Screen.TwipsPerPixelX
pt.Y = Y \ Screen.TwipsPerPixelY
ClientToScreen Picture1.hwnd, pt
Debug.Print WindowCode(WindowFromPoint(pt.X, pt.Y))
End If
Me.MousePointer = vbNormal
bFinding = False
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++)
Last edited by bushmobile; Dec 18th, 2006 at 07:19 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|