Hi all,
I need to get handle of .NET controls. Here is my code.
Sub Main()
Dim hwndParent As Long
hwndParent = Win32.user32.GetDesktopWindow
Dim controlHandle As Long
controlHandle = FindWindowsFormsControlRecursive(hwndParent, "listview_Report")
End Sub
Function FindWindowsFormsControlRecursive(startWnd As Long, controlName As String) As Long
Dim childWnd As Long
Dim tmpWnd As Long
Dim retVal As Long
' Start with the first child.
childWnd = GetWindow(startWnd, GW_CHILD)
Do While childWnd <> 0 And retVal = 0
' Compare the WindowsFormsID and see if this is the control.
If GetWindowsFormsID(childWnd) <> controlName Then
tmpWnd = childWnd
' Do depth-first recursion on the children.
retVal = FindWindowsFormsControlRecursive(tmpWnd, controlName)
childWnd = GetWindow(childWnd, GW_HWNDNEXT)
Else
' Found it.
retVal = childWnd
Exit Do
End If
Loop
FindWindowsFormsControlRecursive = retVal
End Function
Function GetWindowsFormsID(ByVal wnd As Long) As String
Dim PID As Long 'pid of the process that contains the control
Dim msg As Long
' Define the buffer that will eventually contain the desired
' component's name.
Dim bytearray As String * 65526
' Allocate space in the target process for the buffer as shared
' memory.
Dim bufferMem As Long
' Base address of the allocated region for the buffer.
Dim size As Long
' The amount of memory to be allocated.
Dim written As Long
' Number of bytes written to memory.
Dim retLength As Long
Dim retVal As Long
Dim errNum As Integer
Dim errDescription As String
Dim lp As Long
size = 65527 '65536 'Len(bytearray)
' Creating and reading from a shared memory region is done
' differently in Win9x than in newer Oss.
Dim processHandle As Long
Dim fileHandle As Long
msg = RegisterWindowMessage("WM_GETCONTROLNAME")
If Not IsWin9x() Then
On Local Error GoTo Error_Handler_NT
'Dim dwResult As Long
'dwResult = GetWindowThreadProcessId(wnd, VarPtr(PID))
Call GetWindowThreadProcessId(wnd, PID)
processHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, PID)
If processHandle = 0 Then
Error Err 'OpenProcess API Failed
End If
bufferMem = VirtualAllocEx(processHandle, 0, size, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
If bufferMem = 0 Then
Error Err 'VirtualAllocEx API Failed
End If
' Send message to the control's HWND for getting the
' Specified control name.
retLength = SendMessage(wnd, msg, size, ByVal bufferMem)
If retLength <> 0 Then
' Now read the component's name from the shared memory location.
Call WriteProcessMemory(processHandle, bufferMem, bytearray, size, lp)
retVal = ReadProcessMemory(processHandle, bufferMem, bytearray, size, lp)
If retVal = 0 Then
Error Err 'ReadProcessMemory API Failed
End If
End If
Error_Handler_NT:
errNum = Err
errDescription = Error$
' Free the memory that was allocated.
retVal = VirtualFreeEx(processHandle, bufferMem, 0, MEM_RELEASE)
If retVal = 0 Then
Error Err 'VirtualFreeEx API Failed
End If
CloseHandle (processHandle)
If errNum <> 0 Then
On Local Error GoTo 0
Error errNum ', errDescription
End If
On Local Error GoTo 0
Else
On Local Error GoTo Error_Handler_9x
Dim SA As SECURITY_ATTRIBUTES
fileHandle = CreateFileMapping(INVALID_HANDLE_VALUE, SA, PAGE_READWRITE, 0, size, Null)
If fileHandle = 0 Then
Error Err 'CreateFileMapping API Failed
End If
bufferMem = MapViewOfFile(fileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
If bufferMem = 0 Then
Error Err 'MapViewOfFile API Failed
End If
Call CopyMemory(bufferMem, bytearray, size)
' Send message to the treeview control's HWND for
' getting the specified control's name.
retLength = SendMessage(wnd, msg, size, bufferMem)
' Read the control's name from the specific shared memory
' for the buffer.
Call CopyMemoryA(bytearray, bufferMem, 1024)
Error_Handler_9x:
errNum = Err
errDescription = Error$
' Unmap and close the file.
UnmapViewOfFile (bufferMem)
CloseHandle (fileHandle)
If errNum <> 0 Then
On Local Error GoTo 0
Error errNum 'errDescription
End If
On Local Error GoTo 0
End If
If retLength <> 0 Then
' Get the string value for the Control name.
GetWindowsFormsID = ByteArrayToString(bytearray, retLength)
End If
End Function
Function IsWin9x() As Boolean
Dim osVerInfo As OSVERSIONINFO
osVerInfo.dwOSVersionInfoSize = 128 + 4 * 5
Dim l As Long
l = GetVersionEx(osVerInfo)
IsWin9x = osVerInfo.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS
End Function
Function ByteArrayToString(bytes As String, length As Long) As String
Dim retValStr As String
Dim l As Long
If IsWin9x() Then
retValStr = Left(bytes, InStr(1, bytes, Chr(0)) - 1)
Else
retValStr = String$(length + 1, Chr(0))
l = WideCharToMultiByte(CP_ACP, 0, bytes, -1, retValStr, length + 1, Null, Null)
End If
ByteArrayToString = retValStr
End Function
And some declarations:
Public Const MEM_COMMIT As Long = &H1000
Public Const MEM_RESERVE As Long = &H2000
Public Const MEM_RELEASE = &H8000&
Public Const PAGE_READWRITE = &H4
Public Const PROCESS_VM_OPERATION = &H8
Public Const PROCESS_VM_READ = &H10
Public Const PROCESS_VM_WRITE = &H20
Declare Function VirtualAllocEx Lib "kernel32" _
(ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As Long
Declare Function ReadProcessMemory Lib "kernel32" _
(ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
lpBuffer As Any, _
ByVal nSize As Long, _
lpNumberOfBytesRead As Long) As Long
Declare Function VirtualFreeEx Lib "kernel32" _
(ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal dwFreeType As Long) As Long
Declare Function WriteProcessMemory Lib "kernel32" _
(ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
lpBuffer As Any, _
ByVal nSize As Long, _
lpNumberOfBytesWritten As Long) As Long
I got error in WideCharToMultiByte:
Run-time error '94':
Invalid use of Null
It seems like bytes in ByteArrayToString is empty. What am I doing wrong?
No one has replied yet! Why not be the first?
Sign in or Join us (it's free).