gpt4 book ai didi

java - JNA:将结构体指针作为 LPARAM 传递给 User32.dll 的 SendMessage 函数

转载 作者:行者123 更新时间:2023-12-01 14:50:07 32 4
gpt4 key购买 nike

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

我能够做的:获取打开的资源管理器窗口的句柄以及其中的 ListView 的句柄。

我发现:我需要调用 User32.dll 的 SendMessage 函数,并将其传递给上面找到的 ListView 的句柄,以及消息代码(LVM_GETITEMTEXTA 为 (0x1000 + 45)),以及我需要获取其名称的 ListView 项的从 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 函数来打印所有 ListView 项的名称,如下所示:

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

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

我知道 JNA 文档说指向结构的指针在 JNA 中被视为结构。但是如果我不执行 lvItem.getPointer,那么我如何能够将结构转换为作为 LPARAM 构造函数的参数所需的长值?

我做错了什么?请帮忙。我已经花了很多时间研究,而且由于我是 JNA 的新手,无法理解出了什么问题。

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

最佳答案

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

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

我还建议在初始化 User32 库时使用 W32APIOptions.DEFAULT_OPTIONS ;它们自动处理将 StringSendMessage 映射到适当的 native API 映射(Windows ANSI 或 UNICODE,默认为 UNICODE),因此您可以使用 String 代替WStringSendMessage 而不是 SendMessageW

编辑

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

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 位,则返回值会更多)。

关于java - JNA:将结构体指针作为 LPARAM 传递给 User32.dll 的 SendMessage 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14975347/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com