JAVA JNA WindowProc实现

我正在尝试用Java编写一个简单的应用程序,它将与USB设备通信。 USB设备由我使用Microchip微控制器制造。 通信相当简单,因为USB设备来自HID类,所以在计算机和设备之间交换64字节的数组。 我的程序根据产品ID和供应商ID查找设备,可以写入和读取64个字节,但现在我想检测设备何时连接或与计算机断开连接。

正如我在Microchip提供的C#程序中看到的那样,WndProc方法被覆盖并处理WM_DEVICECHANGE消息。 我的问题是如何使用JNA在Java中完成,我如何覆盖WindowProc方法并处理消息,如果可能的话:),但我希望它是:D

提前谢谢你的答案。

的Gabor。

我终于设法解决了问题:)我找到了以下解决方案:

首先以下列方式扩展User32接口

public interface MyUser32 extends User32 { public static final MyUser32 MYINSTANCE = (MyUser32) Native.loadLibrary("user32", MyUser32.class, W32APIOptions.UNICODE_OPTIONS); /** * Sets a new address for the window procedure (value to be set). */ public static final int GWLP_WNDPROC = -4; /** * Changes an attribute of the specified window * @param hWnd A handle to the window * @param nIndex The zero-based offset to the value to be set. * @param callback The callback function for the value to be set. */ public int SetWindowLong(WinDef.HWND hWnd, int nIndex, Callback callback); } 

然后使用您需要的Windows消息代码扩展WinUser接口,在我的情况下,这是WM_DEVICECHANGE,因为我想检查USB设备是否已连接或与计算机分离。

 public interface MyWinUser extends WinUser { /** * Notifies an application of a change to the hardware configuration of a device or the computer. */ public static final int WM_DEVICECHANGE = 0x0219; } 

然后用回调函数创建一个接口,它实际上是我的WndProc函数。

 //Create the callback interface public interface MyListener extends StdCallCallback { public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); } public MyListener listener = new MyListener() { public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam) { if (uMsg == MyWinUser.WM_DEVICECHANGE) { // TODO Check If my device was attached or detached return new LRESULT(1); } return new LRESULT(0); } }; 

然后在初始化事物的JFrame代码中的某处使用SetWindowLong函数为窗口过程添加新地址:

  // Get Handle to current window HWND hWnd = new HWND(); hWnd.setPointer(Native.getWindowPointer(this)); MyUser32.MYINSTANCE.SetWindowLong(hWnd, MyUser32.GWLP_WNDPROC, listener); 

这段代码很好用,但我对一件事情有些怀疑。 我不确定回调函数的返回值是否正确。 我在MSDN中读到,在处理WM_DEVICECHANGE消息后,回调函数应该返回true,我不确定我当前返回的值是系统预期的值,所以欢迎任何建议。

如果有人对我为HID通信编写的整个代码感兴趣,请问,我会非常乐意帮助:)

干杯,Gabor。

如果您没有现有的窗口句柄,则必须先创建自己的窗口。 当您创建新窗口时,您还必须管理其消息泵。 这是一个如何做到这一点的例子。 JNA自己的示例代码也非常有用。

 Thread thread; HWND hWnd; static final int WM_NCCREATE = 0x0081; void start() { thread = new Thread(this::myThread); thread.start(); } void stop() { User32.INSTANCE.PostMessage(hWnd, User32.WM_QUIT, null, null); } WindowProc callback = new WindowProc() { @Override public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_NCCREATE: return new LRESULT(1); case User32.WM_DEVICECHANGE: return new LRESULT(1); default: return new LRESULT(0); } } }; void myThread() { WString className = new WString("myclass"); WNDCLASSEX wx = new WNDCLASSEX(); wx.clear(); wx.lpszClassName = className; wx.lpfnWndProc = callback; if (User32.INSTANCE.RegisterClassEx(wx).intValue() != 0) { hWnd = User32.INSTANCE.CreateWindowEx(0, className, null, 0, 0, 0, 0, 0, null, null, null, null); WinUser.MSG msg = new WinUser.MSG(); msg.clear(); while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) > 0) { User32.INSTANCE.TranslateMessage(msg); User32.INSTANCE.DispatchMessage(msg); } } } 

您可以创建C#程序的COM DLL或OCX,并在java代码中使用它。 如果您创建应用程序。

使用JACOB或JCOM

它将成为Java和COM对象之间的桥梁。 其他选项是您可以使用JNI与DLL和OCX进行通信。

我之前发布的解决方案有一些问题,不幸的是:(

由于它覆盖了窗口的WndProc,我添加到我的Frame的控件无法正常工作(不足为奇,因为没有处理任何绘制,重绘等消息)。 然后我意识到,不应该返回LRESULT(1)我应该调用默认窗口proc(因为它在Win32 C ++程序中使用),但这仍然没有解决问题,框架被绘制但按钮不起作用虽然我能够更新标签……所以我不得不放弃这个解决方案。

在互联网上搜索了一些之后我在这里发现了一篇很棒的文章(编辑:链接已经死了, 原文可以在这里找到 ) ,其中创建了一个静态隐藏窗口来处理Windows消息。 我设法为我的应用程序编写代码,它工作得很好。 (我不得不从JNA进一步扩展类,因为没有包含几个函数。如果有人感兴趣,我可以发布我的代码。)

希望这可以帮助。