我需要执行一个简单的任务:在资源管理器窗口中打印出列表视图项的名称。假设,我打开" C:\ Documents and Settings"在我的桌面上,然后我想要做的是使用JNA编写一个java程序,打印出打开的资源管理器窗口中所有文件夹/文件的名称。
我能做的事情:获取打开的资源管理器窗口的句柄以及其中listview的句柄。
我发现:我需要调用User32.dll的SendMessage函数并将其传递给上面找到的listview,以及消息代码(LVM_GETITEMTEXTA为(0x1000 + 45)),以及我需要获取其名称的列表视图项的基于0的索引号,以及LPARAM(长值)。 此LPARAM将接受指向LVITEM类型结构的指针。 您可以在此处参考消息的文档:http://msdn.microsoft.com/en-us/library/windows/desktop/bb761055(v=vs.85).aspx
我在User32的界面中创建了结构LVITEM,如下所示:
public static class LVITEM extends Structure
{
public short mask;
public int iItem;
public int iSubItem;
public short state;
public short stateMask;
public char[] pszText;
public int cchTextMax;
public int iImage;
public LPARAM lParam;
public int iIndent;
protected List getFieldOrder()
{
return Arrays.asList(new String[] { "mask", "iItem", "iSubItem", "state", "stateMask", "pszText", "cchTextMax", "iImage", "lParam", "iIndent" });
}
}
我的结构初始化如下:
User32.LVITEM lvItem = new User32.LVITEM(); //User32 is the name of the interface containing the LVITEM structure
lvItem.mask = 0x00000001; //code for LVIF_TEXT
lvItem.pszText= new char[260];
lvItem.iSubItem = 0;
lvItem.cchTextMax = 260;
我在for循环中调用SendMessage函数来打印所有列表视图项的名称,如下所示:
for(int j=0;j<nItems;j++)
{
lvItem.iItem= j;
LRESULT lrs = User32.INSTANCE.SendMessageA(handleToListView, (0x1000 + 45) , new WPARAM(j), new LPARAM(lvItem.getPointer().getLong(0)));
}
如果我打印lvItem.getPointer()。getLong(0) - 我得到0,而不是表示指针的长值。
如果我打印lrs或lvItem.pszText - 我没有得到该文件夹的名称。我得到一个空白值/ 0。
我知道JNA文档说明结构的指针被视为JNA中的结构。但是,如果我不执行lvItem.getPointer,那么我将如何将结构转换为一个long值,该值是LPARAM构造函数的参数所必需的?
我做错了什么?请帮忙。我已经花了很多时间研究,因为我是JNA的新手,还没能理解出了什么问题。
环境:Win XP Pro, JNA版本:3.4
答案 0 :(得分:1)
如果在Structure
中使用基本数组,JNA会将其解释为嵌套在本机struct
中的基本数组。 LVITEM
字段pszText
具有指针类型,更具体地表示可写字节缓冲区,因此必须使用Memory
(或NIO缓冲区)。使用String
仅适用于本地const char *
(即缓冲区是只读的)。调用之后,您可以使用Pointer.getString(0)
从内存缓冲区中提取本机NUL终止的字符串。
至于将结构“转换”为LPARAM
值,则没有必要。您可以自由为SendMessage
定义自己的方法签名,其中第四个参数的类型为LVITEM
(即本机struct *
)。
我还建议在初始化W32APIOptions.DEFAULT_OPTIONS
库时使用User32
;它们会自动将映射String
和SendMessage
映射到相应的本机API映射(Windows ANSI或UNICODE,默认为UNICODE),因此您可以使用String
代替WString
和{{ 1}}而不是SendMessage
。
修改强>
用于分配被调用函数将写入的缓冲区:
SendMessageW
上述结构(LVITEM)的大小应该返回60(如果你是64位,则更多)。