问题描述
我正在尝试访问与JNA的接口,但我碰壁了。
I'm trying to access the IDesktopWallpaper interface with JNA, but I've hit a wall.
我经历了 ShOljIdl_core.idl
(来自Windows 10 SDK),并发现了界面的GUID,如下所示
I went through ShOljIdl_core.idl
(from Windows 10 SDK) and discovered the GUID of the interface as follows
// IDesktopWallpaper
[
uuid(B92B56A9-8B55-4E14-9A89-0199BBB6F93B),
object
]
以及实现该接口的具体类的GUID
and the GUID of the concrete class that implements the interface
// CLSID_DesktopWallpaper
[uuid(C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD)] coclass DesktopWallpaper { interface IDesktopWallpaper; }
因此,我遵循了JDA github中的官方示例并编写了以下内容
So I followed the official example in the JDA github and wrote the following
@ComObject(clsId="{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}")
public interface DesktopWallpaper extends IUnknown{
}
和 Main code>
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
try {
Factory factory = new Factory();
try {
DesktopWallpaper dw = factory.createObject(DesktopWallpaper.class);
} finally {
factory.disposeAll();
factory.getComThread().terminate(1 * 1000);
}
} finally {
Ole32.INSTANCE.CoUninitialize();
}
但是 factory.createObject(DesktopWallpaper.class)
抛出不支持这样的接口(HRESULT:80004002)(puArgErr =)
我不知道如何解决这个问题或它为什么会发生。
But the factory.createObject(DesktopWallpaper.class)
throws No such interface supported(HRESULT: 80004002) (puArgErr=)
and I don't know how to get around this or why it is happening.
任何专家都可以启发我发生了什么事吗? (我是一个完全菜鸟),我将提供所有必要的进一步信息。 JNA可以实现我想要的功能还是必须使用Com4j等其他功能?
Can any experts enlighten me on what's happening? (I am a complete noob) I will provide any further info that's necessary. Can JNA achieve what I want or do I have to use something else like Com4j?
推荐答案
经过大量的搜索后,我终于可以使用它了。问题(至少就我目前的理解而言)是,当前的JNA帮助器只能与从 IDispatch
继承的接口一起使用。因此,如果所讨论的接口(例如 IDesktopWallpaper
)没有继承自 IDispatch
,则应该使用vtable进行函数调用。我从 此 很棒的Google论坛帖子,其中的张贴者还提供了使我入门的代码示例。
After a lot of googling, I finally got it to work. The problem (at least to my current understanding) is that the current JNA helpers only work with interfaces that inherit from IDispatch
. So if the interface in question such as IDesktopWallpaper
does not inherit from IDispatch
, then one should use vtable for function calls. I got this information from this amazing Google forum post in which the poster also provided a code sample that got me started.
以下是 SetWallpaper()
函数的一些工作代码:
Here is some working code for the SetWallpaper()
function:
public class DesktopWallpaperHandler extends Unknown{
private static final GUID CLSID_DesktopWallpaper = new GUID("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}");
private static final GUID IID_IDesktopWallpaper = new GUID("{B92B56A9-8B55-4E14-9A89-0199BBB6F93B}");
private DesktopWallpaperHandler(Pointer pvInstance) {
super(pvInstance);
}
public static DesktopWallpaperHandler create(){
PointerByReference p = new PointerByReference();
WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(CLSID_DesktopWallpaper, null, WTypes.CLSCTX_SERVER, IID_IDesktopWallpaper, p);
COMUtils.checkRC(hr);
DesktopWallpaperHandler handler = new DesktopWallpaperHandler(p.getValue());
return handler;
}
public void SetWallpaper(WTypes.LPWSTR monitor, WTypes.LPWSTR wallpaper){
int result = this._invokeNativeInt(3, new Object[]{this.getPointer(), monitor, wallpaper});
COMUtils.checkRC(new HRESULT(result));
}
}
然后在 Main
:
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
try {
WTypes.LPWSTR path = new LPWSTR("C:\\Users\\Harry\\Desktop\\1.jpg");
DesktopWallpaperHandler handler = DesktopWallpaperHandler.create();
handler.SetWallpaper(null, path);
} finally {
Ole32.INSTANCE.CoUninitialize();
}
使用 IDesktopWallpaper $ c的原始动机$ c>可以访问渐变效果,现在可以通过添加以下内容来实现:
The original motive to use IDesktopWallpaper
was to access the fade in transition effect, and now that can be done by adding the following:
User32.INSTANCE.SendMessageTimeout(User32.INSTANCE.FindWindow("Progman", null), 0x52c, 0, 0, 0, 500, null);
这篇关于使用JNA访问COM接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!