尝试使用jna 4.5.2并在SysTreeView中遇到问题。
我的考试班:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.DesktopWindow;
import com.sun.jna.platform.WindowUtils;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.W32APIOptions;
public class SysTreeViewExample {
static final int TV_FIRST = 0x1100;
static final int TVM_GETCOUNT = TV_FIRST + 5;
static final int TVM_GETNEXTITEM = TV_FIRST + 10;
static final int TVM_GETITEMW = TV_FIRST + 62;
static final int TVGN_ROOT = 0;
static final int TVIF_TEXT = 1;
static final int TVIF_CHILDREN = 64;
//https://docs.microsoft.com/en-us/windows/desktop/api/commctrl/ns-commctrl-tagtvitemw
public static class TVITEMW extends Structure {
private static final int MEMSIZE = 260;
public WinDef.UINT mask;
public WinNT.HANDLE hItem;
public WinDef.UINT state;
public WinDef.UINT stateMask;
public Pointer pszText = new Memory(MEMSIZE);
public int cchTextMax = MEMSIZE;
public int iImage;
public int iSelectedImage;
public int cChildren;
public WinDef.LPARAM lParam;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("mask", "hItem", "state", "stateMask", "pszText", "cchTextMax", "iImage", "iSelectedImage", "cChildren", "lParam");
}
}
public interface User32Ext extends User32 {
User32Ext INSTANCE = Native.loadLibrary("user32", User32Ext.class, W32APIOptions.DEFAULT_OPTIONS);
LRESULT SendMessageW(HWND hWnd, int msg, WPARAM wParam, TVITEMW tvitemw);
}
public static void main(String[] args) {
List<DesktopWindow> timeTrackerWindows = WindowUtils.getAllWindows(false).stream()//
.filter(desktopWindow -> desktopWindow.getFilePath().contains("TimeTracker.exe"))//
.collect(Collectors.toList());
List<WinDef.HWND> sysTreeViewHwnds = timeTrackerWindows.stream()//
.map(DesktopWindow::getHWND)//
.flatMap(windowHwnd -> {
List<WinDef.HWND> sysTreeViews = new ArrayList<>();
char[] buff = new char[8 * 1024];
User32.INSTANCE.EnumChildWindows(windowHwnd, (windowChildHwnd, data) -> {
User32.INSTANCE.GetClassName(windowChildHwnd, buff, buff.length);
String className = Native.toString(buff);
if (className.contains("SysTreeView"))
sysTreeViews.add(windowChildHwnd);
return true;
}, null);
return sysTreeViews.stream();
})//
.collect(Collectors.toList());
sysTreeViewHwnds.forEach(sysTreeViewHwnd -> {
//https://docs.microsoft.com/en-us/windows/desktop/controls/tvm-getcount
WinDef.LRESULT countItems = User32.INSTANCE.SendMessage(sysTreeViewHwnd, TVM_GETCOUNT, new WinDef.WPARAM(0), new WinDef.LPARAM(0));
System.out.println(countItems);//return correct value
//https://docs.microsoft.com/en-us/windows/desktop/controls/tvm-getnextitem
WinDef.LRESULT handleFirstItem = User32.INSTANCE.SendMessage(sysTreeViewHwnd, TVM_GETNEXTITEM, new WinDef.WPARAM(TVGN_ROOT), null);
TVITEMW tvitemw = new TVITEMW();
tvitemw.hItem = new WinNT.HANDLE(handleFirstItem.toPointer());
tvitemw.mask = new WinDef.UINT(TVIF_TEXT | TVIF_CHILDREN);
//https://docs.microsoft.com/en-us/windows/desktop/controls/tvm-getitem
WinDef.LRESULT isGetItem = User32Ext.INSTANCE.SendMessageW(sysTreeViewHwnd, TVM_GETITEMW, new WinDef.WPARAM(0), tvitemw);
System.out.println(isGetItem);// return 0
});
}
}
我不明白我在做什么错? 也许当尝试获取第一个SysTreeView项时
//https://docs.microsoft.com/en-us/windows/desktop/controls/tvm-
WinDef.LRESULT handleFirstItem = User32.INSTANCE.SendMessage(sysTreeViewHwnd, TVM_GETNEXTITEM, new WinDef.WPARAM(TVGN_ROOT), null);
或者在创建TVITEMW或发送消息TVM_GETITEMW时。
我使用了来自 JNA: Pass Pointer to Structure to SendMessage function of User32.dll as the LPARAM 但没有成功
在拥有SysTreeView的过程中,可能需要为TVITEMW分配内存,然后发送消息TVM_GETITEMW,然后选择TVITEMW。 但是怎么做,我没找到。
答案 0 :(得分:0)
我的解决方案: 1)SysTreeView过程中的VirtualAllocEx TVITEMW->获取指向分配内存的指针 2)在分配内存中写处理内存TVITEMW 3)SendMessage TVM_GETITEMW,指针从1开始 4)从1开始读取ProcessMemory指针 5)获取文字