WM_DEVICECHANGE comes twice when disconnecting/connecting device - c++

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.

Related

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.

MFC C++ differentiate between two devices from WM_DEVICECHANGE notifications

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.

Using WM_KEYDOWN and wParam

Noob question here, but I can't find any other threads that answer it. All I want to know is how to use the WM_KEYDOWN message, and then proceed to use its wParam parameter to check which key has been pressed. Like a lot of people, I'm using this to try and get windows to stop with the key-repeat delay.
I can get my program to respond to WM_KEYDOWN with
if (WM_KEYDOWN)
//do something
But I can't work out how to access the wParam parameter. The code
if (WM_KEYDOWN)
if (wParam == 'A')
//do something
doesn't seem to work.
This kind of code is way out of my depth, but people are saying it's the easiest way to get around the key-repeat delay. I don't really understand what a message is or how it can have a parameter.
As was pointed out in the comments you probably meant to write
if( message == WM_KEYDOWN )
since
if( WM_KEYDOWN )
will always be true since it's a constant.
As for the wparam check if I recall correctly you need to compare it to a lowercase character not an uppercase one.
This is a very old question as there were some changes to MSDN, however I will try to cover the multiple scenarios.
Scenario A
You're capturing a Message Callback through a Windows Procedure without using SetwindowsHookEx. Example: You're capturing messages inside WNDPROC.
First you need to detect the message type as in (msg == WM_KEYDOWN). msg contains the event that triggered the call. This way you can utilize wParam where it will be the Virtual Key code.
Scenario B
You're capturing a Message Callback through Low Level Keyboard Procedure (WH_KEYBOARD_LL). In this scenario wParam acts as msg from Scenario A, and lParam contains additional info. You'll need to map lParam into a KBDLLHOOKSTRUCT and extract the Virtual Key code from it.
KBDLLHOOKSTRUCT kbStruct = *((KBDLLHOOKSTRUCT*)lParam);
You can now access the Virtual Key code by using kbStruct.vkCode.
Scenario C
You're capturing a Message Callback through Keyboard Procedure (WH_KEYBOARD). In this scenario wParam contains your Virtual Key code, and lParam contains the flags. Refer to MSDN for more info the flags. In order to detect Key Down/Up and/or Holding the button, you'll have to rely on the flags on bits 31 and 30 (lParam>>31 and lParam&0x40000000).

Intercept mouse input

I was wondering if there is a way to intercept and modify mouse input before it gets to windows?
What I'm wanting to do is intercept mouse motion events, apply some custom scaling and acceleration to the values, and then continue passing them along. I'd need something that can do this before the inputs get to the raw input API or DirectInput.
In order to affect all mouse input, including DirectInput, during logon and the SAS screen, etc., you'll need to load a filter driver into the mouse driver stack.
Other people have done it, for example http://www.maf-soft.de/mafmouse/
There should be a moufiltr sample in the Windows DDK which you can use as a starting point. You will most likely want to use a virtual machine for development since errors in a driver on your development machine could be difficult to recover from.
Have you seen this method of intercepting mouse and keyboard input without having to make a filter driver or hook?
http://oblita.com/Interception.html
There is a LowLevelMouseProc hook procedure that you can use to get information on any mouse input entering the system, although I doubt if you can actually change this information (and the docs are silent on this).
If this fails, GetMsgProc is an alternative that lets you intercept all messages posted to any window. Though this hook does let you modify the message, it's probably too late to have any effect on APIs such as DirectInput.
You could try a windows hook - which are functions you set to receive windows messages before they get passed through to the rest of the system - a CBT hook (for computer based training) is what might get you best results.
I don't know Whether this will work with DirectInput or the other new stuff MS has added to break all the old internal consistency. Its easy to set up though, so try it and see.
As far as I know the best way is to hook to windows message loop, In your case you should pass HWND 0 (If I remember correctly this the HWND of the desktop) so all the messages will pass though your function first.
http://msdn.microsoft.com/en-us/library/ms633591%28VS.85%29.aspx
More on hooks : http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx
Use it as follows:
m_nOldWindowProc = ::SetWindowLong(0 /I think.../, GWL_WNDPROC, (LPARAM)(WNDPROC)WindowProcCallback);
and the callback:
LRESULT CALLBACK CStubWindow::WindowProcCallback(HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lParam)->cx = STATUS_BAR_WIDTH;
((WINDOWPOS*)lParam)->flags = SWP_NOOWNERZORDER | SWP_NOMOVE;
break;
default:
break;
}
return ::CallWindowProc(m_nOldWindowProc, hwnd, message, wParam, lParam);
}

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.