Receiving Windows messages / detecting USB device unplug events

446 views
Skip to first unread message

Kustaa Nyholm

unread,
Mar 6, 2016, 2:11:45 PM3/6/16
to jna-...@googlegroups.com
Hi,

this is not directly a JNA question but since I'm using it and probably someone on this list
knows the answer I'm asking it here.

I'm writing a library to access USB HID devices:


In that library I need to detect when a USB device is unplugged.

To do that I need to (I think) receive messages using the WindowProc:


But as far as I understand the WindowProc is associated with a window
when the window is generated and my library (by nature) does not
create any windows so I'm stuck at how to proceed from here.

Any help/pointers greatly appreciated, 

br Kusti




This e-mail may contain confidential or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden. We will not be liable for direct, indirect, special or consequential damages arising from alteration of the contents of this message by a third party or as a result of any virus being passed on or as of transmission of this e-mail in general.

croudet

unread,
Mar 6, 2016, 2:19:02 PM3/6/16
to Java Native Access

Kustaa Nyholm

unread,
Mar 6, 2016, 3:13:31 PM3/6/16
to jna-...@googlegroups.com
Looks like this is right on the money. Thank you very much.

br Kusti



--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kustaa Nyholm

unread,
Mar 13, 2016, 1:58:19 PM3/13/16
to jna-...@googlegroups.com
In this example



https://github.com/java-native-access/jna/blob/master/contrib/native_window_msg/src/com/sun/jna/platform/win32/Win32WindowDemo.java


the hidden message handling window is created as

// create new window
HWND hWnd = User32.INSTANCE.CreateWindowEx(
User32.WS_EX_TOPMOST,
windowClass,
"My hidden helper window, used only to catch the windows events",
0, 0, 0, 0, 0, null,
// WM_DEVICECHANGE contradicts parent=WinUser.HWND_MESSAGE
null, hInst, null);

I'm curious why the last but fourth parameter (hWndParent) is null instead
of HWND_MESSAGE which seems to be the recommend way to create
a message only window:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx

The comment in the code (WM_DEVICECHANGE contradicts parent=WinUser.HWND_MESSAGE)
seems to indicate that there is a problem in using the recommended solution.

Can anyone shed some light on this?

br Kusti

Timothy Wall

unread,
Mar 13, 2016, 2:26:50 PM3/13/16
to jna-...@googlegroups.com
Could by typos or copy/paste errors. If there’s no comment, I would consider it unintentional. PRs welcome.

Kustaa Nyholm

unread,
Mar 13, 2016, 2:44:55 PM3/13/16
to jna-...@googlegroups.com
Hi,



don't think it is a typo as there is that comment there, that is why asked more info.

I will try and check if it works if I modify it to match the MSDN documentation.

br Kusti

L Will Ahonen

unread,
Mar 14, 2016, 3:22:35 AM3/14/16
to Java Native Access

Message-Only Windows

message-only window enables you to send and receive messages. It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages. The window simply dispatches messages.

L Will Ahonen

unread,
Mar 14, 2016, 3:34:15 AM3/14/16
to Java Native Access
Hi,

Sorry, didn't mean to post that unfinished.  WM_DEVICECHANGE is a broadcast message, so a message-only window will not catch it.

I'm lazy to set up my own window classes, so I just abuse the common controls static class.

WinStructs.INITCOMMONCONTRLSEX initcommoncontrlsex = new WinStructs.INITCOMMONCONTRLSEX();
initcommoncontrlsex.dwSize = initcommoncontrlsex.size();
initcommoncontrlsex.dwICC = Comctl32.ICC_STANDARD_CLASSES;
Comctl32.INSTANCE.InitCommonControlsEx(initcommoncontrlsex);
handle = User32.INSTANCE.CreateWindowEx(0, "STATIC", "", 0, 0, 0, 0, 0, null, 0, 0, null);

And you need

INITCOMMONCONTRLSEX extends Structure {
    public int dwSize;
public int dwICC;

protected List<String> getFieldOrder() {
return Arrays.asList(new String[]{"dwSize", "dwICC"});
}
}

Also, annoyingly you need to call a different function to register your windowproc on 32 and 64 bit JVMs.

if (Tools.is64Bit())
Pointer previousFunction = User32RW.INSTANCE.SetWindowLongPtr(handle, GWLP_WNDPROC, listener);
else
Pointer previousFunction = User32RW.INSTANCE.SetWindowLong(handle, GWLP_WNDPROC, listener);

There's a comment in our codebase saying "if you use the WindowProc callback type for previousFunction, things crash sporadically. Keep it Pointer.". You have been warned, although I have no idea if 1) that warning is still relevant 2) that warning ever was relevant :)

Cheers,
Will


Kustaa Nyholm

unread,
Mar 14, 2016, 4:20:17 AM3/14/16
to jna-...@googlegroups.com
Sorry, didn't mean to post that unfinished.  WM_DEVICECHANGE is a broadcast message, so a message-only window will not catch it.


Ah, now the penny dropped, I see, so the MSDN doc, while correct, is misleading for the uninitiated and the jnd demo code is correct.

thanks for the education.

wbr Kusti




Reply all
Reply to author
Forward
0 new messages