Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JNA:将指向结构的指针作为LPRAM传递给User32.dll的SendMessage函数_Java_Winapi_Jna - Fatal编程技术网

Java JNA:将指向结构的指针作为LPRAM传递给User32.dll的SendMessage函数

Java JNA:将指向结构的指针作为LPRAM传递给User32.dll的SendMessage函数,java,winapi,jna,Java,Winapi,Jna,我需要执行一项简单的任务:在资源管理器窗口中打印列表视图项的名称。假设我在桌面上打开“C:\Documents and Settings”,那么我要做的是使用JNA编写一个java程序,在打开的资源管理器窗口中打印出所有文件夹/文件的名称 我所能做的是:获取打开的资源管理器窗口的句柄以及其中listview的句柄 我发现:我需要调用User32.dll的SendMessage函数,并将句柄传递给上面找到的listview,以及消息代码(对于LVM_GETITEMTEXTA是(0x1000+45)

我需要执行一项简单的任务:在资源管理器窗口中打印列表视图项的名称。假设我在桌面上打开“C:\Documents and Settings”,那么我要做的是使用JNA编写一个java程序,在打开的资源管理器窗口中打印出所有文件夹/文件的名称

我所能做的是:获取打开的资源管理器窗口的句柄以及其中listview的句柄

我发现:我需要调用User32.dll的SendMessage函数,并将句柄传递给上面找到的listview,以及消息代码(对于LVM_GETITEMTEXTA是(0x1000+45)),以及我需要获取名称的列表视图项的基于0的索引号,以及LPRAM(一个长值)。 此LPRAM将接受指向LVITEM类型结构的指针。 您可以在此处参阅该消息的文档:

我在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(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)));
}
我的结构初始化如下:

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(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)));
}
我在for循环中调用SendMessage函数以打印所有列表视图项的名称,如下所示:

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(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)));
}

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

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

我还建议您在初始化
User32
库时使用
w32api选项。默认\u选项
;它们会自动处理
字符串
发送消息
到适当的本机API映射(windows ANSI或UNICODE,默认为UNICODE)因此,您可以使用
String
代替
WString
SendMessage
代替
SendMessage w

编辑

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

public static class LVITEM extends Structure
{
    ...
    private static final int MEMSIZE = 260;
    public Pointer pszText = new Memory(MEMSIZE);
    public int cchTextMax = MEMSIZE;

上述结构(LVITEM)的大小应返回60(如果您使用64位,则会返回更多)。

Hi-technomage,谢谢您的回答。但我有一个问题。如果第四个参数的类型为LVITEM,我将如何为SendMessage定义我自己的方法签名?当我输入:LRESULT SendMessageA(HWND HWND,int Msg,WPARAM WPARAM WPARAM,LVITEM LVITEM);在User32和的接口中,LRESULT lrs=User32.INSTANCE.SendMessageA(handleToListView,(0x1000+45),新WPARAM(j),lvItem);我的程序只是在运行时崩溃。另外,我是否需要通过显式发出一些allocateMemory类型命令来将内存分配给结构?您的程序崩溃是因为
LVITEM
字段的大小不正确。UINT将是4字节,而不是2字节,并且pszText必须是指针类型。结构自动分配自己的内存,除非s您显式地将一个
指针
传递给ctor。我已经尝试按照您的建议做了,下面就是我所做的!我在结构LVItem中将pszText声明为指针-公共指针pszText;LVItem的构造函数现在看起来如下所示:public LVItem(){Memory m=new Memory(260);pszText=m.getPointer(0);cchTextMax=260;}对sendmessage的调用现在是这样的:LRESULT lrs=User32.INSTANCE.SendMessageA(handleToListView,(0x1000+45),new WPARAM(1),lvItem);我让他们这样做:lvItem.read();