Windows C++ - Need Ideas - Combining Mouse Input and Raw Input in the same app/window - c++

I'll try to keep this as short as possible.
I have an app that has worked for years with a single mouse input. I am looking to incorporate the ability for my users to use other forms of input, such as interactive projectors, touch devices, or pretty much anything that provides WM_INPUT messages when you register for them.
The general idea I had was I would have a list of Vendor IDs and/or Product IDs that I would handle with Raw Input (which provides VID/PID, device handle and other information) for each message (WM_INPUT) received. Any devices that are not handled in the Raw Input code would be handled in the Mouse Input code (WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_RBUTTONDOWN, etc).
Ideally, I would be able to leave all of my Mouse Input code as is, or close to it. This way, if a user plugs in two mice, or a mouse and an unsupported pointing device (meaning my Raw Input code doesn't handle it based on VID/PID) the devices would both use the same system cursor. Any device that is known by my Raw Input code would be given separate cursors that exist only within my app.
The problem is simple: Mouse Input does not provide any information about the source of the message (such as WM_MOUSEMOVE, etc). Knowing that the message originated from touch helps (I have this implemented) but is definitely not enough. I need some kind of unique identifier. If I could know the source of the Mouse Input, I could only handle Mouse Input from devices that aren't on my list of known devices, and I could only handle Raw Input that are on my list of known devices.
Unfortunately, I cannot seem to find a way to achieve this.
Any ideas?
Thanks for your time sorry for the lengthy post.
TL;DR - Can you identify the source of Mouse Input (not Raw Input) in Windows? Determining whether or not the source is touch is not enough information, I need some kind of unique identifier.
Mouse Input - http://msdn.microsoft.com/en-us/library/windows/desktop/ff468877(v=vs.85).aspx
Raw Input - http://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx

I don't know of any API for getting some sort of device id after the fact.
You could use the fact that WM_INPUT messages come before all other input messages, and when you handle WM_INPUT you could use GetRawInputDeviceInfo and a hash of the name returned by RIDI_DEVICENAME to use as a unique id. Or, you might be able to use the hDevice member of the RAWINPUTHEADER structure.

edit2: The answer to this question is "Not possible", you can't do it. Don't bother trying, but if you do and I'm wrong please explain. The fact of the matter is you can't rely on Windows to provide messages in any particular order consistently, which is what I was attempting to do. This bit me big time. Either use raw input (WM_INPUT) or use mouse messages (wm_mouse) don't try to combine the two somehow.
I never really got the answer I wanted, but I got something that works so I thought it was worth sharing.
I am working on a huge assumption, as I can't find any documentation from Windows to support this assumption (and probably wouldn't really even trust it if I found documentation from windows). To my understanding, when a mouse event is generated at the lowest level it comes through the system as a raw input message first (WM_INPUT). After the WM_INPUT message is posted, the OS gets the message and applies the ballistics and whatever else it does before a WM_*MOUSE* message is posted. The huge assumption is that this process is serial in that it is always 1 WM_INPUT message followed by 1 WM_*MOUSE* message in the queue.
With this assumption I am working with the following:
When an input message is received, store all relevant information about the source device as the "current input information"
When a mouse message is received, process it using the "current input information" as the source of the mouse message
This allows me to use n inputs in my application independently.
I'd also like to add that per Brandon's suggestion I am using the hDevice member of the RAWINPUTHEADER structure to uniquely identify each input. Since a unique device can have multiple inputs, I have yet to come up with a good way of uniquely identifying each device. VID/PID doesn't work because you can have 2 of the exact same device with multiple inputs each plugged in. I'm still working on this, see Windows HID Device Name Format
Please let me know if anyone would like me to elaborate!
edit: not marking this as the answer since I believe the correct answer is "Not possible"

Related

DirectInput console application

I'm working in C++ in Windows and I need to deal with an input device with force feedback. I found out that one solution could be to use DirectInput and so I start looking at that.
FIRST QUESTION: any suggestions on other ways for dealing with force feedback devices? (Win32 app, not UWP)
Coming back to DirectInput
The reference starting point I have got in my mind is the DirectInput Samples, in particular the FFconst example where a constant feedback force is applied to the first device axis according to a value grabbed from a simple GUI. In my case what I want to achieve is having a simple console application where I set a constant force according to a value grabbed from the standard input.
The basic steps for using the DirectInput API, according to the samples and the documentation, are:
create direct input device calling DirectInput8Create;
look for devices calling EnumDevices filtering devices and limiting scope to the enumeration according to what you are looking for (in my case I'm filtering for looking only in DI8DEVCLASS_GAMECTRL devices and limiting the scope to DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK);
set data format for the selected device(s) calling SetDataFormat in order to be able to acquire the device;
set the cooperative level for the device(s) calling SetCooperativeLevel once again in order to acquire the device;
use the device...
Now, all goes well until we encounter the SetCooperativeLevel mehtod since it needs as input a HWND window handle "to be associate to the device" and which "must be a valid top-level window handle that belongs to the process". Since I'm writing a console application I need to find a valid HWND pointer: I sorted the problem out following this suggestion. Anyway, the HWND pointer I get in that way seems not to be a valid window handle since I get a E_HANDLE error, as I would specify nullptr as argument. I found out that specifying the argument through the call of GetTopWindow allows not to get the invalid handle error. However I'm not able to acquire the device and I get the DIERR_OTHERAPPHASPRIO error, which is nothing more than E_ACCESSDENIED. I found that it seems someone use to treat that error in the same way the DIERR_INPUTLOST error is treated, i.e. re-acquiring the device in a while loop as shown in the Joystick direct input sample in the UpdateInputState function. Anyway trying this I'm not able to exit that loop, i.e. the device device keep being denied.
That said I end up with the
SECOND QUESTION: how to use the DirectInput API in a console application or inside a DLL? (Win32) In case of a console application I'd like to understand why the steps I've done don't work, and in case of a DLL I'd like to know if anyone has an idea on which HWND pointer could be used.
Microsoft provides a function to get a console application's window for uses like this.
HWND WINAPI GetConsoleWindow(void);

Find original name of a message obtained by RegisterWindowMessage Windows API

While debugging the application in an attempt to improve performance, I found that it loses time in processing a message that is greater then 0xC000. This is obviously a message created by the RegisterWindowMessage API. However, the application uses more than two hundreds such messages; is there a way to find the original name of the message by its numerical value?
The GetAtomName and GlobalGetAtomName fail with
ERROR_INVALID_HANDLE
error.
There is no official API to get the name of a registered window message.
That being said, RegisterWindowMessage() and RegisterClipboardFormat() happen to currently share a single atom table (along with a few other API functions), so in current version of Windows, you can use GetClipboardFormatName() to get the name of a registered window message.
This is described on Raymond Chen's blog on MSDN:
How can I investigate the possibility of a lot of leaked window classes (RegisterClass)?
It so happens that in current versions of Windows, registered class names, registered clipboard format names, and registered window message names all come from the same atom table. I wish to reiterate that this is an implementation detail which can change at any time, so don't take any dependencies on this. I provide this information for diagnostic purposes, which is what we have here.
The customer can do this once they encounter the problem:
Foreach atom in (0xC000 .. 0xFFFF)
If (GetClipboardFormatName(atom, buffer, bufferSize))
Print buffer
This will print out the names of all the classes, clipboard formats, and registered window messages. There is room in the atom table for 16,384 atoms, and in practice there aren't more than a hundred or so, so if you see more than 15,000 entries, that's a really good sign that you're leaking classes.
Some other places atoms (and the magical 0xC000) arise
I'll start with registered window messages, created by the RegisterWindowMessage function. These are not officially atoms; they are just integers that happen to lie in the range 0xC000 to 0xFFFF, just like atoms. But yeah, internally, they're atoms. Of course, you shouldn't rely on it since it's not contractual. Think of it as a fantastic coincidence.
Registered clipboard formats created by the RegisterClipboardFormat message are also not officially atoms; they're just UINTs. The numeric range for registered clipboard formats isn't even specified; that they hang out in the 0xC000 range is just an implementation detail. Someday, registered clipboard formats may have values like 0x1234, who knows.
So, as I said, there is currently NO OFFICIAL API to get the name of a registered window message, but you can currently get around that by treating a registered window message the same as a registered clipboard format. But using GetClipboardFormatName() in this manner MAY break in the future if the implementation of RegisterWindowMessage() ever changes.

Associate HID Touch Device with Pnp Monitor

I am developing a tool that displays a status about various hardware components on a system we use at work. Currently, we have 16 touch screen monitors (all by 3M) plugged in to a Windows 10 box. I need to verify that any given monitor has an associated touch screen recognized by windows. This is to assess the system for any hardware malfunctions i.e. bad cable, bad USB port, bad Monitor, etc. We see this more than we would like to admit, usually where a monitor's display will be working fine but the USB controller on either end drops out and needs to be reset by unplugging/plugging back in
Unfortunately my code posting will be limited due to work constraints.
I can enumerate all of the monitors plugged in to the system via winapi's EnumDisplayDevices and EnumerateDisplayMonitors. I am able to build a list of all the HID touch screen devices using HIDApi.
From here I have no direction on where to go to link these two things together, if it is even possible. My first thought was the HID device information should have some sort of identifier shared by the results of calling the EnumDisplayDevices and EnumerateDisplayMonitors, but I have not found this to be the case. Another possibility would be to compare the coordinates/size of a monitor to a region that one of the touch controllers is responsible for. Again, not sure if that is possible.
In short, is there a way to associate a Touch device with it's corresponding monitor via c++?
I think you were just lucky that this driver suffix matched your monitor configuration. In my Windows 10 multi-monitor setup I get wrong displays when I look them up with this number in the driver entry as you described.
A reliable way for associating a HID device with a display seems to be:
Call GetRawInputDeviceList() to obtain the HID devices
Call GetRawInputDeviceInfo() with RIDI_DEVICEINFO to determine Usage and UsagePage
Call GetRawInputDeviceInfo() with RIDI_DEVICENAME to get a device string in the form \\\\?\\HID#VID_0EEF&PID_7200&Col01#6&152cc7f9&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
Query the registry for the mapping table at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wisp\Pen\Digimon and look up the display device name. In my case the HID names are all prefixed with 20- there but the remaining part seems to match the name queried by GetRawInputDeviceInfo() exactly. As a fallback method in case there is no match, I also parse the middle part as Clay Brooks described in his answer.
Call EnumDisplayDevices() with a null pointer for lpDevice and 0 for dwFlags in a loop until the function returns zero.
Within each loop iteration, call EnumDisplayDevices() again with the current device as lpDevice and EDD_GET_DEVICE_INTERFACE_NAME for dwFlags and observe that it returns a DeviceID in the form \\\\?\\DISPLAY#ELO2243#5&607b301&0&UID24833#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
Loop until a HID <-> display match is found and take the DeviceName returned by the "outer" EnumDisplayDevices() call which should be something like \\.\DISPLAY3
After the suggestions in the comments and looking deeper into the registry, I've found a way to link Touch controllers to a monitor.
Using HIDApi, you can poll the system and find a list of all the Touch Controllers you need to monitor. I filtered by the VID of the monitors we are using. A sample return value for the path looks something like this:
"\\?\hid#vid_0596&pid_0520&col02#8&33d9e616&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}"
The bold part can be used to link to the entries in HKLM/Software/Microsoft/Wisp/Pen/Digimon. An example entry is this:
"\\?\HID#VID_0596&PID_0520&Col03#8&33d9e616&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" "\\?\DISPLAY#MSY1C2B#7&1083071f&0&UID524#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"
The first bold matches the data found through HIDApi and the second set of bolding, the monitor name and a UID, is listed in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY. Under here you can use the combination of monitor name and UID to find the Driver entry. Below is a sample driver entry:
{4d36e96e-e325-11ce-bfc1-08002be10318}\0010
The last bold number can then be used to match up with a DeviceID returned from EnumDisplayDevices(). Below is a sample DeviceID:
"MONITOR\MSY1C2B\{4d36e96e-e325-11ce-bfc1-08002be10318}\0010".
Then you can use this bolded section to match up to names of monitors returned from EnumDisplayMonitors().

SDL2 events on mobile

I've fought for a couple of hours with a bug due to a behavior of SDL2 of which I didn't know anything.
In particular, I didn't know that, on mobile, whenever the user touches the screen, two events are sent:
The first one was quite obvious to me: a finger down event.
The second one was indeed less obvious: a mouse button down event.
The same applies for the finger up/mouse button up events.
Because of them, an internal command was thrown twice giving me an headache.
The target is to support both mobile and desktop environments for reasons that are beyond the purpose of the question.
Also, I can guess SDL2 works like that in order to support smooth migration of already existent codebase.
Anyway, is there a (let me say) SDL2-way to inhibit the mouse related events on mobile?
Honestly, they don't make much sense from my point of view and I would like to get rid of them, unless the software is executed on a desktop environment.
Also, I don't want neither to use compile time parameters nor to have dedicated parts of code the aim of which is to suppress those events on mobile.
The code is quite simple. Below a (maybe) meaningful, reduced example:
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
switch(event.type) {
case SDL_FINGERDOWN:
// read it and throw an internal event E
break;
case SDL_MOUSEBUTTONDOWN:
// read it and throw an internal event E
break;
}
}
Unfortunately, both the events above are read when the user touches the screen, as explained.
* EDIT *
I didn't mention that I was testing my application on an Android device and I'm far to be sure that the same problem arises on iOS.
See the response below. It seems indeed that the issue (that so far I've understood it is not exactly an issue) is mainly due to the way SDL2 treats by default finger events on Android.
Even though I really like the idea of Christophe to add an event filter, I've found that SDL2 already gives support for this problem in terms of an hint on Android.
In particular, there exists the hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH.
One can set it by means of the function SDL_SetHint. See here for further details.
It's as simple as:
SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
As from the documentation of the hint, by default it is set to 0 and that means that:
mouse events will be handled as touch events and touch will raise fake mouse events
That's true, it was my problem, but by setting it to 1 we can get what follows:
mouse events will be handled separately from pure touch events
So, no longer fake mouse events on Android devices.
The reason behind the default value is not so clear to me, but this one sounds really like the right way to achieve it.
EDIT (more details)
This change seems to be recent.
Here is a link to the libsdl forum where they were discussing the issues that arose as a consequence of the patch that introduced this behavior.
Someone had the same problem I had and some others were trying also to explain why the patch had been accepted.
EDIT: alternative solution
The hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH is available since SDL v2.0.4, so it seems that the only viable solution for lower versions of SDL2 is to use an event filter.
Anyway, I discourage to query the platform by using SDL_GetPlatform in order to decide if to set or not to set an event filter.
Instead, as from the documentation of both SDL_MouseMotionEvent and SDL_MouseButtonEvent, there exists the which parameter that:
[...] may be SDL_TOUCH_MOUSEID, for events that were generated by a touch input device, and not a real mouse. You might want to ignore such events, if your application already handles SDL_TouchFingerEvent.
Because of that, I suggest to set an event filter no matter of what's the underlying platform, thus to queue the events or to filter them if needed.
Unfortunately, there is no such platform specific deactivation parameter.
The cleanest way to do it would hence be in the initialisation code to query for the platform with SDL_GetPlatform() and, if mobile, set an eventfilter with SDL_SetEventFilter() which prevents the mouse events from being queued.
It's not exactly the answer you expect, but I see no other sdl alternative.
A simpler approach, if you control the code of your event loop, would be to set a flag instead of an event filter, and if the flag is set do nothing on the mouse event. This second approach is however not so clean, as you have to take care of platform specific behaviour in all your code, whereas it's much more isolated in the first alternative.

How to make windows media player go to previous song in playlist?

I am writing a simple Windows app in c++, that will be able to send commands to windows media player. My problem is that I want my app to move to the previous song in the playlist.
IWMPControls::previous() seems to do the job, but its behavior differs from what is written in msdn. In fact this function rewinds current media to the beginning and then (if current position is less than 2-3 seconds) it switches to the previous song.
I would like to implement two different buttons (please, don't ask me why :)) - one for rewinding to the beginning, and one - to moving to previous song. Is there any easy way to do this through IWMPControls (or any other WMP-related COM interface)?
p.s. I could handle this if I could get the position (index) of the current song in the list. But as far as I read MSDN, it seems to me that there is no easy way to get the current item index from playlist...
I think, the easiest way to control a WMP application from outside is by sending messages. So, you stick to basic WinAPI and you have to get your WMP window handle.
After you've retrieved it's handle, it's easy to transfer certain commands to it using plain Windows messages.
Basically, you just invoke SendMessage to retrieved earlier HWND wmp_windows_handle. The control messages are generally a WM_COMMAND messages where a wParam specifies what you want your player to do.
For example, Stop command can be transfered if you specify 0x00004979 as your wParam.
Stick to Google or Windows Media Player SDK for more specific information on these command codes and you'll definitely find what you are looking for.
Also to mention, I'm not proficient with that IWMPStuff you described above, so if I were you and I wanted a concrete answer about it, I would probably refer to it's SDK.
Well, I think I figured it out. You can force the previous song by 1) first calling IWMPControls::put_currentPosition(0.0), 2) then calling IWMPControls::previous().
There can be some problems, as it seems that some time must pass between 1) and 2). The obvious solution is to use ::PostMessage() inside your program (NOT ::PostMessage to WMP), so you make step 1), then PostMessage and, while processing your message, make step 2).