我正在尝试从Win32 ListView控件(SysListView32)检索项目信息(文本就足够了)。我正在使用JNA的sendMessage()发送LVM_GETITEMTEXT。SendMessage()使用指向如下所示的LVITEM结构的指针(http://msdn.microsoft.com/zh-cn/library/windows/desktop/bb774760(v=vs.85).aspx):
typedef struct {
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPTSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
int iIndent;
#endif
#if (_WIN32_WINNT >= 0x0501)
int iGroupId;
UINT cColumns;
UINT puColumns;
#endif
#if (_WIN32_WINNT >= 0x0600)
int piColFmt;
int iGroup;
#endif
} LVITEM, *LPLVITEM;
以下是我对LVITEM结构的Java实现:
public static class LVITEM extends Structure {
public WinDef.UINT mask;
public int iItem;
public int iSubItem;
public WinDef.UINT state;
public WinDef.UINT stateMask;
public Pointer pszText;
public int cchTextMax;
public int iImage;
public WinDef.LPARAM lParam;
public int iIndent;
public int iGoupId;
public WinDef.UINT cColumns;
public WinDef.UINT puColumns;
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[] {
"mask", "iItem", "iSubItem", "state", "stateMask", "pszText", "cchTextMax", "iImage", "lParam", "iIndent", "iGoupId", "cColumns", "puColumns" });
}
//Constructor
public LVITEM() {
Memory m = new Memory(260);
mask = new WinDef.UINT((long)1); //code for LVIF_TEXT
iItem = 0;
iSubItem = 0; //no subitem
pszText = m.getPointer(0);
cchTextMax = 260;
iImage = 0;
lParam = new WinDef.LPARAM(0);
iIndent = 0;
}
}
Java结构的大小为52个字节,应与C ++结构的大小匹配。
这是我的User32
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
...
int SendMessage (WinDef.HWND hWnd, int msg, WinDef.WPARAM wparam, LVITEM lvItem);
//Several alternative definitions
//int SendMessage (WinDef.HWND hWnd, int msg, int wparam, Pointer lvItem);
...
}
我这样声明我的结构:
LVITEM lvi = new LVITEM();
lvi.iItem = itemIdx; // the zero-based index of the ListView item
基于其他两篇文章的建议(请参见下文),我尝试了具有不同结果的SendMessage()的不同实现。例如:
int ret = user32.SendMessage(hWnd, User32.LVM_GETITEMTEXT, 0,lvi);
该程序使ListView使第三方软件崩溃,并且不检索项目的文本。这是结构的转储(设置jna.dump_memory = true):
ListView$LVITEM([email protected] (52 bytes)) {
WinDef$UINT [email protected]=1
int [email protected]=0
int [email protected]=0
WinDef$UINT [email protected]=0
WinDef$UINT [email protected]=0
Pointer [email protected][email protected]
int [email protected]=104
int [email protected]=0
WinDef$LPARAM lP[email protected]=0
int [email protected]=0
int [email protected]=0
WinDef$UINT [email protected]=0
WinDef$UINT [email protected]=0
}
memory dump
[01000000]
[00000000]
[00000000]
[00000000]
[00000000]
[38033800]
[04010000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
和
ret= 0
这意味着我什么也没拿回来
lvi.pszText.getString(0) = 8 8
(奇怪的符号链,此处无法很好地复制)。
例如,如果我这样做:
int ret = user32.SendMessage(hWnd, User32.LVM_GETITEMTEXT, new WPARAM(0),new LPARAM(lvi.getPointer().getLong(0)));
我得到:
ListView$LVITEM([email protected] (52 bytes)) {
WinDef$UINT [email protected]=1
int [email protected]=0
int [email protected]=0
WinDef$UINT [email protected]=0
WinDef$UINT [email protected]=0
Pointer [email protected][email protected]
int [email protected]=104
int [email protected]=0
WinDef$LPARAM [email protected]=0
int [email protected]=0
int [email protected]=0
WinDef$UINT [email protected]=0
WinDef$UINT [email protected]=0
}
memory dump
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
(所以结构是空的?)和
ret= 0
和
lvi.pszText.getString(0) = 05 05 � 8
在这种情况下,具有ListView的第三方软件不会崩溃。
我已经成功地从ListView控件中检索了其他项目信息,例如count(使用LVM_GETITEMCOUNT)或选定的项目(使用LVM_GETSELECTEDCOUNT)。
我已经回顾了几个类似的线程,例如:使用JNA和SendMessage()和JNA检索项目文本:将指针作为结构传递给User32.dll的SendMessage函数的LPARAM和网络上的许多其他帖子,并实现了许多建议,但问题仍然存在。
任何帮助我解决此问题的建议将不胜感激。
谢谢
如果有人对此感兴趣,我可以使用它(草稿版):
PointerByReference lngProcID;
int lngProcHandle;
LVITEM lvi;
int strSize = 255;
int result = 0;
IntByReference byteIO = new IntByReference();
Pointer lngVarPtr1 = null;Pointer lngMemVar1 = null;
Pointer lngVarPtr2 = null;Pointer lngMemVar2 = null;
Pointer lviVarPtr = null;Pointer lviVar = null;
int lngMemLen1; int lngMemLen2;
lngProcID = new PointerByReference();
int ThreadId = user32.GetWindowThreadProcessId(hWnd, lngProcID);
lngProcHandle = Kernel32.OpenProcess(Kernel32.PROCESS_VM_OPERATION | Kernel32.PROCESS_VM_WRITE | Kernel32.PROCESS_VM_READ, false, lngProcID.getValue());
lvi = new LVITEM();
lngMemLen1 = strSize;
lngMemLen2 = lvi.size();
lngMemVar2 = Kernel32.VirtualAllocEx(lngProcHandle, 0, lngMemLen2, Kernel32.MEM_RESERVE|Kernel32.MEM_COMMIT, Kernel32.PAGE_READWRITE);
lvi.cchTextMax = strSize;
lvi.iItem = itemIdx;
lvi.iSubItem = 0;
lvi.mask = User32.LVIF_TEXT;
lvi.pszText = lngMemVar1;
//result = Kernel32.WriteProcessMemory(lngProcHandle, lngMemVar1, lngVarPtr1, lngMemLen1, byteswritten1);
result = Kernel32.WriteProcessMemory(lngProcHandle, lngMemVar2, lvi, lngMemLen2, byteIO);
result = user32.SendMessage (hWnd, User32.LVM_GETITEM, 0, lngMemVar2);
lngVarPtr1 = new Memory(strSize + 1);
result = Kernel32.ReadProcessMemory(lngProcHandle, lngMemVar1, lngVarPtr1, lngMemLen1, byteIO);
result = Kernel32.VirtualFreeEx (lngProcHandle, lngMemVar1, 0, Kernel32.MEM_RELEASE);
result = Kernel32.VirtualFreeEx (lngProcHandle, lngMemVar2, 0, Kernel32.MEM_RELEASE);
result = Kernel32.CloseHandle(lngProcHandle);
return lngVarPtr1.getWideString(0);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句