Raw Input Device RAWMOUSE Usage - c++

I'm using winapi's raw input devices for mouse input and it seems I'm not getting the correct values in my RAWMOUSE struct.
When I get the RAWMOUSE struct I get the values of lLastX and lLastY as I'd expect but for some reason the ulRawButtons is constantly 0. The msdn documentation says that ulRawButtons is "The raw state of the mouse buttons" so I take it this should change when I press a mouse button.
This is the code I create the raw input device with (I removed error checking for readability):
RAWINPUTDEVICE rid;
rid.usUsagePage = 0x01;
rid.usUsage = 0x02;
rid.dwFlags = RIDEV_INPUTSINK;
rid.hwndTarget = myWindowHandle;
RegisterRawInputDevices(&rid, 1, sizeof(rid));
After the WM_INPUT message I call:
void handleRawInput(HWND window, UINT, WPARAM wParam, LPARAM lParam)
{
RAWINPUT input;
UINT szData = sizeof(input), szHeader = sizeof(RAWINPUTHEADER);
HRAWINPUT handle = reinterpret_cast<HRAWINPUT>(lParam);
GetRawInputData(handle, RID_INPUT, &input, &szData, szHeader);
if (input.header.dwType == RIM_TYPEMOUSE)
{
// Here input.data.mouse.ulRawButtons is 0 at all times.
}
}
I'm using mingw32 (4.7) and I've defined WIN32_LEAN_AND_MEAN, WINVER=0x0501 and WIN32_WINNT=0x0501.
Any ideas why I'm not getting the correct values for ulRawButtons?

Windows populates the RAWMOUSE struct with what the mouse driver tells it via the MOUSE_INPUT_DATA struct.
You'll notice that the MSDN page for MOUSE_INPUT_DATA states the following:
RawButtons
Specifies the raw state of the mouse buttons. The Win32 subsystem does not use this member.
What the MSDN page doesn't say is that not only does Win32 not use RawButtons/ulRawButtons but the mouse drivers it ships do not populate them. So, unless you have a mouse driver from a 3rd party vendor, you are never going to get this field set.
I think what you are looking to use is: input.data.mouse.usButtonFlags for mouse clicks and input.data.mouse.usButtonData for scroll wheel delta.

Related

What information does dwExtraInfo hold for the PMOUSEHOOKSTRUCT?

LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
BOOL fpassmove = FALSE;
if (nCode == HC_ACTION)
{
switch (wParam)
{
case WM_MOUSEMOVE: // how do i catch a dx instead of a cursor points?
PMOUSEHOOKSTRUCT me = (PMOUSEHOOKSTRUCT)lParam;
printf("x:%d\ny:%d\nextrainfo:%04X\n", me->pt.x,me->pt.y, me->dwExtraInfo );
break;
}
}
return(fpassmove ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
int main()
{
// Install the low-level keyboard & mouse hooks
HHOOK hhkLowLevelMouse = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, 0, 0);
// Keep this app running until we're told to stop
MSG msg;
while (!GetMessage(&msg, NULL, NULL, NULL)) { //this while loop keeps the hook
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhkLowLevelMouse);
return(0);
}
I am looking at all mouse moment from a global hook, and I'm trying to find the dx and dy of the mouse event, And I was hoping to find it in "dwExtraInfo". However, I have no idea how to make sense of the data inside "dwExtraInfo".
the windows documentation is not helpful in telling me what the data in dwExtraInfo means
dwExtraInfo
Type: ULONG_PTR
Additional information associated with the message.
Could not find any documentation on dwExtraInfo directly, but found something related: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessageextrainfo:
Return value
Type: LPARAM
The return value specifies the extra information. The meaning of the
extra information is device specific.
One example of such device specific extra information is Pen gestures: https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
Distinguishing Pen Input from Mouse and Touch
When your application receives a mouse message (such as
WM_LBUTTONDOWN), it may call the GetMessageExtraInfo function to
evaluate whether the message originated from a pen or a mouse device.
The value returned from GetMessageExtraInfo needs to be mask-checked
against 0xFFFFFF00, and then compared with 0xFF515700. The following
definitions may make this clearer:
#define MI_WP_SIGNATURE 0xFF515700
#define SIGNATURE_MASK 0xFFFFFF00
#define IsPenEvent(dw) (((dw) & SIGNATURE_MASK) == MI_WP_SIGNATURE
If the comparison is true, then this mouse message was generated by a
Tablet PC pen or touch screen. In all other cases, you can assume that
this message was generated by a mouse device.
The lower 8 bits returned from GetMessageExtraInfo are variable. Of
those bits, 7 (the lower 7, masked by 0x7F) are used to represent the
cursor ID, zero for the mouse or a variable value for the pen ID.
Additionally, in Windows Vista, the eighth bit, masked by 0x80, is
used to differentiate touch input from pen input (0 = pen, 1 = touch).

How to make Windows Hot Keys work in Direct X environments?

I am programming a really simple MFC C++ Application which is working with HotKeys. To set a HotKey I use the following method from the WinAPI for my application:
BOOL RegisterHotKey(
HWND hWnd, // window to receive hot-key notification
int id, // identifier of hot key
UINT fsModifiers, // key-modifier flags
UINT vk // virtual-key code
);
To catch any HotKey Message I use: ON_MESSAGE(WM_HOTKEY,OnHotKey) in the message map and this Callback Method to test it's functionality:
LRESULT OnHotKey(WPARAM wParam, LPARAM lParam)
{
if (wParam == MY_HOTKEY_KEY_CODE)
{
MessageBox(L"HotKey was pressed!");
return TRUE;
}
return FALSE;
}
When a HotKey is pressed it enters the OnHotKey Method and does not process the key normally. For example if I write some text in Notepad and press "O" as HotKey, the "O" wont append to my text but the Message "HotKey was pressed!" appears, which is nice.
But when I am in any Direct X Game and press my HotKey, it is not sent to my application. Also when typing something in a Direct X environment the HotKey just works as normal key.
Is Direct X binding all key inputs somehow? Is there a way to make Windows HotKeys work with Direct X environments?

C++: Trying to hook a message box and change its position

I recently started coding in C++ and I am very new to it. (I code in Javascript, PHP, Java and Obj-C more often)
I'm practicing how to hook a message box and change its position. This is what I have in my .cpp file (after reading this SO post).
#include <iostream>
#pragma comment(lib,"User32.lib")
#include <windows.h>
HHOOK hhookCBTProc = 0;
LRESULT CALLBACK pfnCBTMsgBoxHook(int nCode, WPARAM wParam, LPARAM lParam){
if (nCode == HCBT_CREATEWND)
{
CREATESTRUCT *pcs = ((CBT_CREATEWND *)lParam)->lpcs;
if ((pcs->style & WS_DLGFRAME) || (pcs->style & WS_POPUP))
{
HWND hwnd = (HWND)wParam;
SetWindowPos(hwnd, HWND_TOP,130,122, 0, 0,SWP_NOSIZE);
}
}
return (CallNextHookEx(hhookCBTProc, nCode, wParam, lParam));
}
int main(void)
{
hhookCBTProc = SetWindowsHookEx(WH_CBT,pfnCBTMsgBoxHook,
0, GetCurrentThreadId());
int sResult = MessageBox ( NULL, "Hooked!", "oh my", MB_OK );
UnhookWindowsHookEx(hhookCBTProc);
return 0;
}
For some reason the position of the message box isn't changing. Where did it go wrong?
(I know I can create a customized window or dialog. But I am doing it this way because I want to learn how to hook a message box and where I did wrong.)
Firstly you should check in the debugger that your hook is actually being called, if you haven't already.
Secondly, at the time the HCBT_CREATEWND hook event is triggered, the window has only just been created - the system has yet to size and position it. It will do this with the values in the CREATESTRUCT after the hook returns - overriding your SetWindowPos call.
See the docs from MSDN on the lParam value for this particular hook event:
Specifies a long pointer to a CBT_CREATEWND structure containing
initialization parameters for the window. The parameters include the
coordinates and dimensions of the window. By changing these
parameters, a CBTProc hook procedure can set the initial size and
position of the window.
Therefore, the correct way to use this hook to change a window's position is to modify the values in the CREATESTRUCT directly.
Also note that it's quite possible that the dialog manager sizes and positions the window after creation, so if you find that this still isn't working for you, you may need to try watching for the HCBT_MOVESIZE event instead.
From the docs
At the time of the HCBT_CREATEWND notification, the window has been
created, but its final size and position may not have been determined
and its parent window may not have been established.
Maybe try hooking into CBT_ACTIVATE instead.

Get all position values from CScrollBar

Trying to use a CScrollBar in my MFC C++ application for Windows7.
I receive all messages just fine and have a handler that looks something like this:
void Dialog::OnHScroll(UINT nSBCode, UINT apos, CScrollBar* pScrollBar)
{
SCROLLINFO si;
si.cbSize = sizeof( si );
si.fMask = SIF_TRACKPOS;
m_slider.GetScrollInfo(&si,SIF_TRACKPOS|SIF_POS|SIF_PAGE);
int nTrackPos = si.nTrackPos; //0 except on TB_THUMBTRACK
int nPos = si.nPos; //0 except on TB_THUMBTRACK
UINT nPage = si.nPage; //seems correct always but I dont need it
The reason I try to extract the position using GetScrollInfo is because they may be bigger than what fits inside a 16bit var, and therefore I cannot use the pos being passed as the argument.
My problem however is that I only get a valid position when dragging the bar and receiving the TB_THUMBTRACK as well as the ending TB_ENDTRACK for drag operations. If I click in the scrollbar or use the arrows at each end all positions (argument pos, and everything in the SCROLLINFO struct except page) will be 0.
Does anyone know how to get the correct positions for all messages? Ie TB_LINEUP, TB_LINEDOWN etc.
Take a look at the sample code for the WM_HSCROLL event handler that's shown in MSDN:
MSDN Documentation

How to get (true) mouse displacement with windows

I'm wondering how to get true mouse displacement with windows.
For example, I could save the position of a previous mouse position, and request the new position, and subtract the latter from the previous. But this would not give me true mouse displacement.
Imagine the previous cursor position would be the maximum x coordinate of your screen resolution, and the user is moving his mouse to the right. Is there still a way to capture the true mouse displacement then?
Thanks
Although it might be possible to actually read sensor data (after all the mouse itself only reports movement, not location), I'm not aware of how this could be done. I think at the very low levels of windows, that displacement information gets translated into cursor position on the screen and from then on, you will always be limited by your screen resolution.
In whatever you are trying to do, is the mouse cursor still visible?
A little while ago, I wrote a WPF numeric edit box control that mimicked the way those controls work in Expression Blend. The ones where you can drag the mouse from the edit box itself and it'll change the value. I ran into exactly same issue that you found and my solution was to hide the mouse cursor, detect displacement on every tick and reset the cursor to the center of the screen. Then when the user lets go of the button to stop dragging, I would put the cursor back to where I found it before the drag. This worked out really well and Expression Blend also behaves this way in hiding the cursor.
As far as I know DirectX has its own APIs to interact with peripherals, that is recommended for game developers. You should look into it - try for example DirectX 8 and the Mouse, more detailed documentation you can find on MSDN.
The most reliable way is to use window hooks. Here is a minimalist sample using C(++)
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){
MSLLHOOKSTRUCT* hookStruct = (MSLLHOOKSTRUCT*)lParam;
int ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int x = hookStruct->pt.x * ScreenWidth / 65536);
int y = hookStruct->pt.y * ScreenHeight / 65536);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
HHOOK LowLevelMouseProcHook = NULL;
void hook_window_procedure()
{
if (LowLevelMouseProcHook == NULL)
LowLevelMouseProcHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LowLevelMouseProc, (HINSTANCE)NULL, NULL);
}
void unhook_window_procedure()
{
if (LowLevelMouseProcHook != NULL)
UnhookWindowsHookEx(LowLevelMouseProcHook);
}
You can hook the mouse calling hook_window_procedure(); and unhook it by calling unhook_window_procedure();
You will receive calls to void LowLevelMouseProc(...) whenever the mouse moves. lParam contains a pointer to MSLLHOOKSTRUCT and you find all needed mouse information in its structs. Most interesting here is POINT pt; that is in relative screen coordinates assuming 1/65536th of the screen. Transform them to real pixels by multiplying with int ScreenWidth or int ScreenHeight and dividing by 65536
If you struggle being clamped by the screen borders, you can make a workaround setting the mouse back to the center of your window each call. This is often seen in older games. If you are not forced to use only the Windows API, I would try using Direct Input.
Another way would be to evaluate WM_INPUT directly in your WindowProc for example. This reads data directly from the Human Interface Device (HID) stack and should have raw Mouse-Data in it. Here is a link to the MS-Documentation
The method on windows is as such:
// you can #include <hidusage.h> for these defines
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
then in message loop:
case WM_INPUT:
{
UINT dwSize = sizeof(RAWINPUT);
static BYTE lpb[sizeof(RAWINPUT)];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
}
break;
}
Installing hooks will trigger sensitive antiviruses.
MSDN doc to refer
This sort of displacement ? : http://en.wikipedia.org/wiki/Differential_calculus
Try pitch/yaw : How could simply calling Pitch() and Yaw() cause the camera to eventually Roll()?
FPS style : http://cboard.cprogramming.com/game-programming/94944-mouse-input-aiming-fps-style-using-glut.html
and this : Jittering when moving mouse
pseudo code:
int mouseX, mouseY;
int oldMouseX, oldMouseY;
while(game_is_Running)
{
oldMouseX = mouseX;
oldMouseY = mouseY;
mouseX = get_new_mouse_from_windows_X();
mouseY = get_new_mouse_from_windows_Y();
if ((mouseX - oldMouseX) > 0)
{
// mouse moved to the right
}
else if ((mouseX - oldMouseX) < 0)
{
// mouse moved to the left
}
if ((mouseY - oldMouseY) < 0)
{
// mouse moved down
}
else if ((mouseY - oldMouseY) > 0)
{
// mouse moved up
}
}
A common method for this (in games):
Every frame of the game, get the position of the mouse and then recenter the mouse in the middle of the window using operating system functions. For every frame other than the first, this should give you an accurate displacement information. The key is to just be re-centering the mouse every frame so it never reaches the blocking outer bounds of the screen.
EDIT: Woops, didn't realize that DXM had already said this.
It is not possible to track physical mouse displacement with the Windows API. However, DirectInput provides features to keep track of it. You can also 'fake' it using only the Windows API, using the neat little trick in the answer of SO user DXM