我想在winapi的其他应用程序中将鼠标双击的信息发送到树视图中的选定项目。
P.S。在spy ++中,我只处理树视图。
谢谢!
答案 0 :(得分:0)
最好使用UI Automation来处理,它使用COM接口公开对{@ 3}}和TreeView controls等UI元素的访问:
通过CUIAutomation
创建CoCreateInstance()
COM对象的实例并获取其IUIAutomation
界面。
调用其ElementFromHandle()
方法为TreeView窗口检索IUIAutomationElement
接口。
调用其FindFirst()
方法查找第一个选定项并获取其IUIAutomationElement
界面。
调用其GetCurrentPattern()
方法获取IUnknown
控制模式的Invoke
界面。
查询IUIAutomationInvokePattern
接口,然后调用其Invoke()
方法
但是,如果您只想坚持使用窗口消息,可以执行以下操作:
使用TreeView items消息获取所选项目,为TVGN_CARET
指定wParam
。
使用TVM_GETNEXTITEM
消息在TreeView的客户区域中获取项目文本的矩形,为其wParam
指定TRUE。
但是,这需要跨进程边界手动封送RECT
,因为RECT
必须存在于拥有TreeView的同一进程中。
使用GetWindowThreadProcessId()
获取拥有TreeView的进程的ID
使用OpenProcess()
获取流程ID的HANDLE
,请求PROCESS_VM_OPERATION
和PROCESS_VM_READ
访问
使用VirtualAllocEx()
在流程中分配RECT
在lParam
TVM_GETITEMRECT
中传递分配的指针
使用ReadProcessMemory()
阅读RECT
数据
使用VirtualFreeEx()
使用CloseHandle()
关闭流程句柄。
向TreeView窗口发送TVM_GETITEMRECT
消息,指定项目文本矩形内的X,Y坐标。
答案 1 :(得分:0)
我知道这是旧的,但我尝试了很多方法让它在 VB.net 中工作。我需要为 RECT 创建 2 个不同的结构,因为它为带有 Long 参数的 RECT 位置返回了错误的值。 这是示例,您可以轻松转换为 C#
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim SelNodeRectangle As RECT = GetTreeViewSelectedNodeRECT(TreeViewPtr)
End Sub
Private Const TV_FIRST As Integer = &H1100
Private Const TVGN_CARET As Integer = &H9
Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
Private Const PROCESS_VM_OPERATION As Integer = &H8
Private Const PROCESS_VM_READ As Integer = &H10
Private Const PROCESS_VM_WRITE = (&H20)
Private Const PAGE_READWRITE As Long = &H4
Private Const MEM_COMMIT As Long = &H1000&
Private Const MEM_RELEASE As Long = &H8000&
Private Structure RECTPointer
Public Left As IntPtr
End Structure
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
<Flags>
Public Enum AllocationType
Commit = &H1000
Reserve = &H2000
Decommit = &H4000
Release = &H8000
Reset = &H80000
Physical = &H400000
TopDown = &H100000
WriteWatch = &H200000
LargePages = &H20000000
End Enum
Private Declare Function SendMessageA Lib "user32" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Long) As IntPtr
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef buffer As RECTPointer, ByVal dwSize As Integer, ByVal lpNumberOfBytesWritten As IntPtr) As Boolean
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Boolean, ByVal dwProcessId As UInteger) As IntPtr
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As IntPtr,
ByVal lpAddress As IntPtr,
ByVal dwSize As Integer,
ByVal dwFreeType As AllocationType) As Boolean
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.Bool)> Boolean
Private Function GetTreeViewSelectedNodeRECT(TreeViewPTR As IntPtr) As RECT
Const dwBufferSize As Integer = 1024
Dim dwProcessID As Integer
Dim processHandle As IntPtr = IntPtr.Zero
Dim remotePointerBuffer As IntPtr = IntPtr.Zero
Dim localPointerBuffer As IntPtr = IntPtr.Zero
Dim threadId As IntPtr = IntPtr.Zero
localPointerBuffer = Runtime.InteropServices.Marshal.AllocHGlobal(dwBufferSize)
threadId = GetWindowThreadProcessId(TreeViewPTR, dwProcessID)
processHandle = OpenProcess(PROCESS_VM_OPERATION + PROCESS_VM_WRITE + PROCESS_VM_READ, False, dwProcessID)
remotePointerBuffer = VirtualAllocEx(processHandle, IntPtr.Zero, dwBufferSize, MEM_COMMIT, PAGE_READWRITE)
Dim bSuccess As Boolean
Dim tvItem As New RECTPointer()
Dim SelectedNodePTR As IntPtr = SendMessageA(TreeViewPTR, TVM_GETNEXTITEM, TVGN_CARET, 0)
tvItem.Left = SelectedNodePTR
bSuccess = WriteProcessMemory(processHandle, remotePointerBuffer, tvItem, Runtime.InteropServices.Marshal.SizeOf(GetType(RECTPointer)), IntPtr.Zero)
If Not bSuccess Then
Throw New SystemException("Fail writing to process memory!")
End If
SendMessageA(TreeViewPTR, TVM_GETITEMRECT, 0, remotePointerBuffer)
bSuccess = ReadProcessMemory(processHandle, remotePointerBuffer, localPointerBuffer, dwBufferSize, IntPtr.Zero)
If Not bSuccess Then
Throw New SystemException("Fail reading from process memory!")
End If
Dim returnRECT As RECT = Runtime.InteropServices.Marshal.PtrToStructure(localPointerBuffer, GetType(RECT))
If localPointerBuffer <> IntPtr.Zero Then
Runtime.InteropServices.Marshal.FreeHGlobal(localPointerBuffer)
End If
If remotePointerBuffer <> IntPtr.Zero Then
VirtualFreeEx(processHandle, remotePointerBuffer, 0, MEM_RELEASE)
End If
If processHandle <> IntPtr.Zero Then
CloseHandle(processHandle)
End If
Return returnRECT
End Function