MFC C++ differentiate between two devices from WM_DEVICECHANGE notifications - c++

I am coding a function to detect addition/removal of USB devices using C++ VS2019 in windows. WM_DEVICECHANGE gives notification when a device is removed or connected to PC, but it gives multiple notifications for a single device. The parameters that are returned through are also same for all notifications.
The problem is When 2 devices are connected or removed just one after another, the number of notifications increases but the parameters remains the same. How can i differentiate that the notifications are from different devices.
BEGIN_MESSAGE_MAP(CCheckDlg, CDialogEx)
ON_MESSAGE(WM_DEVICECHANGE, &CCheckDlg::OnMyDeviceChange)
END_MESSAGE_MAP()
The function:
LRESULT CCheckDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
//When USB device connected or removed,
//The wParam is always equal to 7 and lParam is equal to 0.
}
Or, if there is any other way to detect device addition/removal using C++, you can suggest.
Thank you.

The wParam of the WM_DEVICECHANGE message contains the particular event that triggered this message. A value of 7 refers to the DBT_DEVNODES_CHANGED event.
The documentation for DBT_DEVNODES_CHANGED explains:
There is no additional information about which device has been added to or removed from the system. Applications that require more information should register for device notification using the RegisterDeviceNotification function.

Related

Can I distinguish touchpad and mouse messages within a low level hook proc? (Win32)

I am working on adding touchpad-specific functionality to a windows desktop application (written in C/C++). Here are my requirements:
The user shall be able to use both a standard windows mouse and touchpad simultaneously.
All touchpad HID events shall be custom-handled by the application as long as it is running. It shall not be able to control the mouse or interact with other windows.
Normal mouse operation shall not be affected when a touchpad is in use.
Through researching the Win32 API, I learned that a low level mouse hook could be used to block touchpad/mouse input from the rest of the system. I got a message queue and simple hook proc working.
static LRESULT CALLBACK lowLevelHIDHookProc
(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
HHOOK ignored( NULL );
// have to pass message along to next hook
if( nCode < 0 )
{
return( CallNextHookEx( ignored, nCode, wParam, lParam ) );
}
// THIS IS WHAT I CAN'T FIGURE OUT
else if( eventComingFromNormalMouse ) // allow normal mouse events
{
return( CallNextHookEx( ignored, nCode, wParam, lParam ) );
}
// block touchpad stuff here
else
{
printf( "********\nTOUCH INTERCEPTED!!!\n********\n" );
return( -1 );
}
What I'm stuck on right now is distinguishing mouse messages coming from touchpads and normal mice. I found a couple open source projects and examples that use HID Raw Input in order to detect and read generic touchpad data, but they are fine with the mouse cursor being disabled while the touchpad is in use. Instead, I need to figure out in this hook proc whether the message is being generated by a touchpad device, and only block in that case, so the mouse can work normally.
I'm looking through the lParam/MSLLHOOKSTRUCT documentation, but am not seeing anything that looks helpful for making this distinction. I'm open to any ideas, including not using low-level hooks at all since they have a performance impact. Maybe there's a way to open a serial connection to a USB touchpad without windows detecting it as an HID device at all?
SetWindowsHookEx() hooks, like WH_MOUSE_LL, do not provide any identifying information about the devices that are generating input events. Raw Input hooks can identify devices, but they can't block input events.
So, you will have to use both kinds of hooks and coordinate them - use a Raw Input hook to identify the touchpad events, and use a WH_MOUSE (not WH_MOUSE_LL) hook to block the events.
However, this is not easy to do reliably. See Combining Raw Input and keyboard Hook to selectively block input from multiple keyboards 1 for more info, and gotchas.
1: that article was written for keyboard input, but should be applicable to mouse/touchpad input, too.

In MFC, in wizard-generated WindowProc, how do I determine message sender window handle?

I have a legacy MFC application originally written in Visual C++ 6. I need to do some minor changes to it but MFC is a black box to me.
There is this apparently wizard-generated function that processes messages
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch (message)
{
case WM_CLOSE:
...;
...
etc.
}
For some messages I need to get the sender window handle (which is from a different process). In Windows API a standard WindowProc has this handle as the first argument, but where is it in MFC?
Edit: Thank you Raymond and Mark. I see that I misunderstood how it works.
This information isn't available. The first parameter in a standard window procedure is the receiver, not the sender. This makes sense, too, since SendMessage and PostMessage identify the receiver by window handle. The sender, on the other hand, can be any thread, including a thread that doesn't own any windows.
If you need to identify the sender of a message in the code receiving a message you will have to explicitly pass an ID along. When crossing process boundaries you're going to have to marshal any referenced memory. The system won't do that for custom messages.

WM_DEVICECHANGE comes twice when disconnecting/connecting device

I'm listening in my message loop for WM_DEVICECHANGE, and when I remove or thrust my webcam, WM_DEVICECHANGE comes twice, with identical MSG (with same HWND, UINT, WPARAM and LPARAM). How to fix it?
This is to be expected. Although the wParam and lParam should be different to indicate a different stage of the device state change, it would not surprise me to know there are duplicate messages.
If I recall correctly, what we did in our code is that when we received a WM_DEVICECHANGE event is to do any of the following:
Once the first one came in, ignore all subsequent notifications for the next couple of seconds.
Or just use the WM_DEVICECHANGE as a hint and not the truth. When we received such a message, we would re-enumerate the device list with the appropriate API and see if anything changed since the last time we enumerated. If the new list was the same as the original list, then there was nothing to do.

How Can I pass message from DLL to Application

I have a ATLCOM Shell Extension which adds Right Click Extension to Windows Explorer. How Can I pass a message from my DLL to another MFC application.
To Sumarize, I want to pass a Message from DLL to MFC application.
You can use Windows API SendMessage or PostMessage.
Have you tried using Windows messages?
You can define you own custom messages like this:
const UINT WM_YOUR_CUSTOM_MESSAGE = ::RegisterWindowMessage(_T("Your_custom_message"));
You receive the message in a standard WindowProc() function:
WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
You can add one by overriding the CWnd::WindowProc() function in your receiving application (use classwizard in either the dialog in an MFC dialog app, or the MainFrm in a Single / Multiple Document MFC app)
You send the message to all windows like this:
ULONG ulRC = BSM_APPLICATIONS;
BroadcastSystemMessage(BSF_IGNORECURRENTTASK | BSF_FORCEIFHUNG, // do not send message to this process and don't hang
&ulRC, // broadcast only to applications
WM_YOUR_CUSTOM_MESSAGE, // message registered in previous step
0, // wParam message-specific value
0); // lParam message-specific value
If you need to pass some information with the message, you can also make use of the wParam and lParam values in the message.
There is one big assumption in the current answers. You normally send messages to processes, not applications. This is a huge difference. There could be zero, one or more instances of the MFC application running.
In the case of zero applications, the DLL will have to call CreateProcess. CreateProcess allows the DLL to pass command-line arguments to your MFC app.
In the case of one MFC application, the message-based solutions offered above will work.
In the case of more than one running MFC application, they'll have different HWNDs. THe DLL picks the application(s) by picking which HWND to send the message to. The logic by which an HWND is picked is outside the scope of this question. One common solution is to just send the message to the HWND's of all running instances.
Finding out how many instances of your application are running is achieved by Process Enumeration

What HID device information is returned in LParam when a device is reported by the system?

I have been searching for information on this for about 30mins now and got nothing so far. Does anyone know what HID information is buried within LParam that's returned when the system (in this case windows) reports a system device change? (either removal or arrival)
Starting from the accepted answer to your previous question, I went to the very first link which says:
Any application with a top-level window can receive basic notifications by processing the WM_DEVICECHANGE message.
Then I clicked on WM_DEVICECHANGE which brought me to another page that says:
lParam
A pointer to a structure that contains event-specific data. Its format depends on the value of the wParam parameter. For more information, refer to the documentation for each event.
Each of the events is linked in the wParam description on this same page.
I hope that describing these steps will help you in future searches.