基本思路
创建隐藏window
实现 winproc函数
注册设备通知,调用winproc处理
引入依赖
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.6.0</version>
</dependency>
代码实现
package com.cares.vip.front.service;
import com.sun.jna.platform.win32.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import static com.sun.jna.platform.win32.WinUser.WM_DEVICECHANGE;
/**
* 监听串口设备拔出、插入
*/
@Slf4j
public class SpDeviceChangeService implements WinUser.WindowProc, InitializingBean {
private SerialportService serialportService;
public void setup() {
serialportService.openSerialPort();
// define new window class
String windowClass = "MyWindowClass";
WinDef.HMODULE hInst = Kernel32.INSTANCE.GetModuleHandle("");
WinUser.WNDCLASSEX wClass = new WinUser.WNDCLASSEX();
wClass.hInstance = hInst;
wClass.lpfnWndProc = this;
wClass.lpszClassName = windowClass;
// register window class
User32.INSTANCE.RegisterClassEx(wClass);
getLastError();
// create new window
WinDef.HWND hWnd = User32.INSTANCE
.CreateWindowEx(
User32.WS_EX_TOPMOST,
windowClass,
"hidden window to catch the windows events",
0, 0, 0, 0, 0,
null, // WM_DEVICECHANGE contradicts parent=HWND_MESSAGE
null, hInst, null);
getLastError();
log.info("window sucessfully created! window hwnd: " + hWnd.getPointer().toString());
Wtsapi32.INSTANCE.WTSRegisterSessionNotification(hWnd,
Wtsapi32.NOTIFY_FOR_THIS_SESSION);
/* this filters for all usb device classes */
DBT.DEV_BROADCAST_DEVICEINTERFACE notificationFilter = new DBT.DEV_BROADCAST_DEVICEINTERFACE();
notificationFilter.dbcc_size = notificationFilter.size();
notificationFilter.dbcc_devicetype = DBT.DBT_DEVTYP_PORT;
notificationFilter.dbcc_classguid = DBT.GUID_DEVINTERFACE_HID;
WinUser.HDEVNOTIFY hDevNotify = User32.INSTANCE.RegisterDeviceNotification(
hWnd, notificationFilter, User32.DEVICE_NOTIFY_WINDOW_HANDLE);
getLastError();
if (hDevNotify != null)
log.info("RegisterDeviceNotification was sucessfully!");
WinUser.MSG msg = new WinUser.MSG();
while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) != 0) {
User32.INSTANCE.TranslateMessage(msg);
User32.INSTANCE.DispatchMessage(msg);
}
User32.INSTANCE.UnregisterDeviceNotification(hDevNotify);
Wtsapi32.INSTANCE.WTSUnRegisterSessionNotification(hWnd);
User32.INSTANCE.UnregisterClass(windowClass, hInst);
User32.INSTANCE.DestroyWindow(hWnd);
log.info("program exit!");
}
/**
* 实现 WinUser.WindowProc 的callback 接口
*/
public WinDef.LRESULT callback(WinDef.HWND hwnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
switch (uMsg) {
case WM_DEVICECHANGE: {
WinDef.LRESULT lResult = this.onDeviceChange(wParam, lParam);
return lResult != null ? lResult :
User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
}
default:
return User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
public int getLastError() {
int rc = Kernel32.INSTANCE.GetLastError();
if (rc != 0)
log.error("error: " + rc);
return rc;
}
protected WinDef.LRESULT onDeviceChange(WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
switch (wParam.intValue()) {
case DBT.DBT_DEVICEARRIVAL: {
return onDeviceChangeArrival(lParam);
}
case DBT.DBT_DEVICEREMOVECOMPLETE: {
return onDeviceChangeRemoveComplete(lParam);
}
case DBT.DBT_DEVNODES_CHANGED: {
return onDeviceChangeNodesChanged();
}
default:
log.info("Message WM_DEVICECHANGE message received, value unhandled.");
}
return null;
}
protected WinDef.LRESULT onDeviceChangeArrivalOrRemoveComplete(WinDef.LPARAM lParam, String action) {
DBT.DEV_BROADCAST_HDR bhdr = new DBT.DEV_BROADCAST_HDR(lParam.longValue());
switch (bhdr.dbch_devicetype) {
case DBT.DBT_DEVTYP_DEVICEINTERFACE: {
DBT.DEV_BROADCAST_DEVICEINTERFACE bdif = new DBT.DEV_BROADCAST_DEVICEINTERFACE(bhdr.getPointer());
log.info("BROADCAST_DEVICEINTERFACE: " + action);
log.info("dbcc_devicetype: " + bdif.dbcc_devicetype);
log.info("dbcc_name: " + bdif.getDbcc_name());
log.info("dbcc_classguid: "
+ bdif.dbcc_classguid.toGuidString());
if ("insert".equals(action)) {
serialportService.openSerialPort();
}
break;
}
case DBT.DBT_DEVTYP_PORT: {
if ("insert".equals(action)) {
serialportService.openSerialPort();
}
log.info("BROADCAST_PORT: " + action);
break;
}
default:
return null;
}
return new WinDef.LRESULT(1);
}
protected WinDef.LRESULT onDeviceChangeArrival(WinDef.LPARAM lParam) {
return onDeviceChangeArrivalOrRemoveComplete(lParam, "insert");
}
protected WinDef.LRESULT onDeviceChangeRemoveComplete(WinDef.LPARAM lParam) {
return onDeviceChangeArrivalOrRemoveComplete(lParam, "remove");
}
protected WinDef.LRESULT onDeviceChangeNodesChanged() {
log.info("Message DBT_DEVNODES_CHANGED");
return new WinDef.LRESULT(1);
}
public void setSerialportService(SerialportService serialportService) {
this.serialportService = serialportService;
}
@Override
public void afterPropertiesSet() throws Exception {
setup();
}
}
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!