gpt4 book ai didi

java - 使用 JNA 检测 HICON 的尺寸

转载 作者:行者123 更新时间:2023-12-01 11:59:46 25 4
gpt4 key购买 nike

我的最终目标是在JNA库的帮助下获得Java中HWND的图标。一切工作正常,除了一件重要的事情:我需要图标的大小以便在 Java 中进行进一步的处理步骤。

看来我无法要求尺寸。我总是得到大小 0x0。我究竟做错了什么?基本代码示例如下所示。大多数 API 函数模板不是 JNA 的一部分。因此,我必须自己定义它们。

    final long hicon = ExtUser32.INSTANCE.SendMessageA(hwnd, ExtUser32.WM_GETICON, ExtUser32.ICON_BIG, 0);
final Pointer hIcon = new Pointer(hicon);
final ICONINFO info = new ICONINFO();
final BITMAP bmp = new BITMAP();
final SIZE size = new SIZE();

System.out.println(ExtUser32.INSTANCE.GetIconInfo(hIcon, info));
System.out.println(info);
System.out.println(ExtGdi32.INSTANCE.GetBitmapDimensionEx(info.hbmColor, size));
System.out.println(size);

if (info.hbmColor != null)
{
final int nWrittenBytes = ExtGdi32.INSTANCE.GetObjectA(info.hbmColor, bmp.size(), bmp.getPointer());
System.out.println(nWrittenBytes);
System.out.println(bmp);
}

系统输出打印以下内容:

true
ICONINFO(auto-allocated@0x5b72b4f0 (32 bytes)) {
WinDef$BOOL fIcon@0=1
WinDef$DWORD xHotspot@4=16
WinDef$DWORD yHotspot@8=16
WinDef$HBITMAP hbmMask@10=native@0xffffffffb00515e8 (com.sun.jna.platform.win32.WinDef$HBITMAP@b00515e7)
WinDef$HBITMAP hbmColor@18=native@0xffffffffa50515c8 (com.sun.jna.platform.win32.WinDef$HBITMAP@a50515c7)
}
true
WinUser$SIZE(auto-allocated@0x652a3000 (8 bytes)) {
int cx@0=0
int cy@4=0
}
32
BITMAP(auto-allocated@0x5b72b5b0 (32 bytes)) {
WinDef$LONG bmType@0=0
WinDef$LONG bmWidth@4=0
WinDef$LONG bmHeight@8=0
WinDef$LONG bmWidthBytes@c=0
WinDef$WORD bmPlanes@10=0
WinDef$WORD bmBitsPixel@12=0
WinDef$LPVOID bmBits@18=0
}

ICONINFO结构的请求似乎是正确的。但是,如果我尝试通过 Gdi32.GetBitmapDimensionEx() 请求设置的 hbmColor 结构组件的尺寸,则该结构将保持初始化为零。这种通过 hbmColorhbmMask 的方法是由以下人建议的:

How to determine the size of an icon from a HICON?

更新1

添加了错误跟踪!

正如系统输出所示 (true),相关函数调用并未失败。

更新2

进一步观察:在Java中,这些重新创建的结构类型在实例化后用零进行初始化。我将 SIZE 和 BITMAP 中的结构组件的初始值设置为偏离零的值。 GetBitmapDimensionEx 将其设置回零。但是 GetObjectA 不会修改结构!该函数的返回结果表明字节已写入,但事实并非如此!

        ...
size.cx = 1;
size.cy = 2;

bmp.bmType.setValue(1);
bmp.bmWidth.setValue(2);
bmp.bmHeight.setValue(3);
bmp.bmWidthBytes.setValue(4);
bmp.bmPlanes.setValue(5);
bmp.bmBitsPixel.setValue(6);
bmp.bmBits.setValue(7);

System.out.println(ExtGdi32.INSTANCE.GetBitmapDimensionEx(info.hbmColor, size));
System.out.println(size);

if (info.hbmColor != null)
{
final int nWrittenBytes = ExtGdi32.INSTANCE.GetObjectA(info.hbmColor, bmp.size(), bmp.getPointer());
System.out.println(nWrittenBytes);
System.out.println(bmp);
}

结果:

true
WinUser$SIZE(auto-allocated@0x64fbcb20 (8 bytes)) {
int cx@0=0
int cy@4=0
}
32
BITMAP(auto-allocated@0x64fb91f0 (32 bytes)) {
WinDef$LONG bmType@0=1
WinDef$LONG bmWidth@4=2
WinDef$LONG bmHeight@8=3
WinDef$LONG bmWidthBytes@c=4
WinDef$WORD bmPlanes@10=5
WinDef$WORD bmBitsPixel@12=6
WinDef$LPVOID bmBits@18=7
}

最佳答案

我本想将此添加为评论,但我的声誉太低:

您没有显示您的 BITMAP 或 GetObjectA 定义,所以我猜测但是在你的行中:

        final int nWrittenBytes = ExtGdi32.INSTANCE.GetObjectA(info.hbmColor, bmp.size(), bmp.getPointer());

之后您无法调用“bmp.read()”。

如果您查看 Struture.getPointer() 的 javadoc

https://jna.java.net/javadoc/com/sun/jna/Structure.html

您会发现,您负责在调用使用 getPointer() 获得的指针的 native 方法之前和之后调用 Structure.write() 和 Structure.read()。在您的情况下,写入是多余的,但这是一个很好的做法。

要理解为什么这是必要的,请考虑您的 BITMAP/bmp 对象是一个位于 Java 堆中的 Java 对象,它可以在垃圾收集期间四处移动。因此 getPointer() 无法返回“真实”对象的真实地址。相反,它返回一个指向 native 堆中单独的固定(不可移动)内存块的指针(JNA 分配该 block 并与您的 Java 对象关联)。现在您的 getObjectA() 例程会将其内容写入 内存,但 JNA 或 java 端的任何人都不知道发生了什么。因此您需要调用 read() 来告诉 JNA 将 native 端的内容复制到 Java 对象。

关于java - 使用 JNA 检测 HICON 的尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28065952/

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