The other day I wanted to pull some data out of a standalone application.
The application is like a database. Records are presented one at a time on a single screen.
Navigation buttons allowed First, Previous, Next, Last.
So, you can input OK, print OK, but when it comes to a data dump – no way – no how. No Export menu.
The data file didn’t look nice – binary. The strings were only partly visible – I didn’t fancy that track.
I might have tried setting up a Text File Printer (a fake printer which prints to a text file), but I thought I’d try something new.
Using Spy++, I discovered all of the data on screen were contained in separate textboxes.
(no Spy++ ??, Try Winspector)
Not all of the textboxes were useful, but I could massage the data later.
So here’s what the code does:
1. Get the Application Window Handle – hWnd
2. Walk the hierarchy and GetText each window.
3. Once walking done, Click the Next button
Repeat at 2
Declare Function GetWindow Lib “user32” (ByVal hWnd As Long, ByVal wCmd As Long) As Long
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
Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function PostMessage Lib “user32” Alias “PostMessageA” (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Dim rng As Range
Sub Extract()
Dim hWnd As Long, i As Long
Set rng = Selection
hWnd = GetDesktopWindow()
hWnd = FindWindowLike(hWnd, “My Application *”)
For i = 1 To 100
WalkWindowsText hWnd
Set rng = Cells(rng.Row + 1, 1)
ClickButton hWnd, “Next”
Next
rng.Select
End Sub
Sub WalkWindowsText(hWndParent As Long)
Dim hWnd As Long, lng As Long, str As String
Do
hWnd = FindWindowEx(hWndParent, hWnd, vbNullString, vbNullString)
If hWnd <> 0 Then
rng.Value = WindowText(hWnd)
Set rng = rng.Offset(, 1)
WalkWindowsText hWnd
End If
Loop Until hWnd = 0
End Sub
Function ClickButton(hWndParent As Long, ButtonText As String)
Const WM_COMMAND = &H111, GWL_ID = (-12)
Dim hWnd As Long, lngID As Long
hWnd = FindWindowEx(hWndParent, 0, “Button”, ButtonText)
lngID = GetWindowLong(hWnd, GWL_ID)
PostMessage hWndParent, WM_COMMAND, lngID And &HFFFF&, hWnd
End Function
Function FindWindowLike(hWndParent As Long, Caption As String) As Long
Const GW_HWNDNEXT = 2, GW_CHILD = 5
Dim hWnd As Long, str As String, lng As Long
hWnd = GetWindow(hWndParent, GW_CHILD)
Do Until hWnd = 0
If WindowText(hWnd) Like Caption Then
FindWindowLike = hWnd
Exit Do
End If
hWnd = GetWindow(hWnd, GW_HWNDNEXT)
Loop
End Function
Function WindowText(hWnd As Long) As String
Const WM_GETTEXT = &HD, WM_GETTEXTLENGTH = &HE
Dim lng As Long, str As String
If hWnd <> 0 Then
lng = SendMessage(hWnd, WM_GETTEXTLENGTH, 0&, 0&) + 1
If lng > 0 Then
str = String$(lng, vbNullChar)
lng = SendMessage(hWnd, WM_GETTEXT, lng, ByVal str)
If lng > 0 Then WindowText = Left$(str, lng)
End If
End If
End Function
I’ll have to pull this down a take a poper look, but the “Walk the hierarchy and GetText each window” bit sounds useful.
Too a look at that spy++ replacement, is it any good? – i’ve never had any issu ewith spymyself, but i might give it a whrill.
cheers Rob
[…] Export Data from Applications using API, hwnds, etc […]
[…] Export Data from Applications using API, hwnds, etc […]