JNA:将指针传递给User32.dll的SendMessage函数作为LPARAM [英] JNA: Pass Pointer to Structure to SendMessage function of User32.dll as the LPARAM

查看:662
本文介绍了JNA:将指针传递给User32.dll的SendMessage函数作为LPARAM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to perform a simple task : Print out the names of the list view items inside an explorer window. Suppose, I open "C:\Documents and Settings" on my desktop, then what I want to do is that write a java program using JNA to print out all the names of the folders / files within the opened explorer window.

我能做的事情:获取打开的资源管理器窗口的句柄和里面listview的句柄。

What I have been able to do: Get the handle of the opened explorer window and the handle to the listview inside it.

我发现:我需要调用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

What I have found out: I need to call the SendMessage function of User32.dll and pass it the handle to the listview found above, along with the message code (which is (0x1000 + 45) for LVM_GETITEMTEXTA), along with the 0 based index number of the list view item whose name I need to get, and, an LPARAM (which is a long value). This LPARAM will accept a pointer to a structure of type LVITEM. You can refer the documentation of the message here : http://msdn.microsoft.com/en-us/library/windows/desktop/bb761055(v=vs.85).aspx

我在User32的界面中创建了结构LVITEM,如下所示:

I have created the structure LVITEM in my interface for User32 as follows:

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

    }

我的结构初始化如下:

My structure initialization is as follows:

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函数来打印所有列表视图项的名称如下:

I am calling the SendMessage function inside a for loop to print the names of all the list view items as follows:

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,而不是表示指针的长值。

If I print lvItem.getPointer().getLong(0) - I get 0, instead of a long value which represents the pointer.

如果我打印lrs或lvItem.pszText - 我没有得到文件夹的名称。我得到一个空值/ 0。

If I print lrs or lvItem.pszText - I dont get the name of the folder. I get a blank value / 0.

我知道JNA文档说明结构的指针被视为JNA中的结构。但是,如果我不执行lvItem.getPointer,那么我将如何将结构转换为一个long值,该值是LPARAM构造函数的参数所必需的?

I know that the JNA documentation says that a pointer to a structure is treated as a structure in JNA. But if I dont do lvItem.getPointer, then how will I be able to convert the structure to a long value which is required as an argument to the LPARAM constructor?

什么我做错了吗?请帮忙。我已经花了很多时间研究,因为我是JNA的新手,还没能理解出了什么问题。

What am I doing wrong? Please help. I have already spent alot of time researching and since I am new to JNA, havent been able to understand what is going wrong.

环境:Win XP Pro,
JNA版本:3.4

Environment: Win XP Pro, JNA version : 3.4

推荐答案

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

If you use a primitive array within a Structure, JNA interprets it as a primitive array nested within the native struct. The LVITEM field pszText has pointer type, and more specifically represents a writable byte buffer, so you must use Memory (or an NIO buffer). Using String is only appropriate for native const char * (i.e. where the buffer is read-only). After the call, you can use Pointer.getString(0) to extract the native NUL-terminated string from the memory buffer.

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

As for "converting" a structure into an LPARAM value, there's no need. You are free to define your own method signature for SendMessage where the fourth parameter is of type LVITEM (i.e. a native struct *).

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

I'd also recommend using the W32APIOptions.DEFAULT_OPTIONS when initializing your User32 library; they automatically handle mapping String and SendMessage to the appropriate native API mappings (windows ANSI or UNICODE, defaulting to UNICODE) so you can use String instead of WString and SendMessage instead of SendMessageW.

编辑

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

For allocating the buffer to which the called function will write:

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-则更多)比特)。

The above structure (LVITEM) should return 60 for its size (more if you're on 64-bit).

这篇关于JNA:将指针传递给User32.dll的SendMessage函数作为LPARAM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆