JNA:将指针传递给User32.dll的SendMessage函数作为LPARAM

时间:2013-02-20 08:32:43

标签: java winapi jna

我需要执行一个简单的任务:在资源管理器窗口中打印出列表视图项的名称。假设,我打开" 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

1 个答案:

答案 0 :(得分:1)

如果在Structure中使用基本数组,JNA会将其解释为嵌套在本机struct中的基本数组。 LVITEM字段pszText具有指针类型,更具体地表示可写字节缓冲区,因此必须使用Memory(或NIO缓冲区)。使用String仅适用于本地const char *(即缓冲区是只读的)。调用之后,您可以使用Pointer.getString(0)从内存缓冲区中提取本机NUL终止的字符串。

至于将结构“转换”为LPARAM值,则没有必要。您可以自由为SendMessage定义自己的方法签名,其中第四个参数的类型为LVITEM(即本机struct *)。

我还建议在初始化W32APIOptions.DEFAULT_OPTIONS库时使用User32;它们会自动将映射StringSendMessage映射到相应的本机API映射(Windows ANSI或UNICODE,默认为UNICODE),因此您可以使用String代替WString和{{ 1}}而不是SendMessage

修改

用于分配被调用函数将写入的缓冲区:

SendMessageW

上述结构(LVITEM)的大小应该返回60(如果你是64位,则更多)。