This question was previously asked in stackoverflow where no one gives an answer. I also found a similiar question here, but in my situation, I hook and simulate mouse inputs and send them to the game window.
Here is the body of the original question:
After hooking windows mouse and keyboard APIs, I wanted to simulate the mouse input message for free look technique (Move the mouse to rotate the player character's view). Before coding, I used spy++ to monitor a fps game observing which mouse-related message was sent to the window of the game's program. I got these following lines when I moved the mouse:
P WM_INPUT nInputCode:RIM_INPUT hRawInput:065A04FD S WM_NCHITTEST xPos:2504 yPos:889 R WM_NCHITTEST nHittest:HTCLIENT S WM_SETCURSOR hwnd:0016089A nHittest:HCLIENT wMouseMsg:WM_MOUSEMOVE R WM_SETCURSOR fHaltProcessing:True P WM_MOUSEMOVE fwKeys:0000 xPos:419 yPos:183 ...
So I wrote these lines of codes (sent WM_INPUT message using codes in How to simulate raw input / Send a WM_INPUT message to an application the right way?, Simulating Raw Input on Windows, and codes in github):
// ... // mData->px and mData->py indicating the mouse position in client window are double type. WORD xCor = static_cast<WORD>(mData->px); WORD yCor = static_cast<WORD>(mData->py); LPARAM lParamMouseMove = (yCor << 16) | (xCor & 0xFFFFFFFF); // lParam for mouse movement message // prepare for sending WM_INPUT LONG _mouse_position.x = static_cast<long>(mData->px); LONG _mouse_position.y = static_cast<long>(mData->py); WPARAM wParamRawMouse = RIM_INPUT; HGLOBAL hRaw = ::GlobalAlloc(GHND, sizeof(RAWINPUT)); RAWINPUT* pRaw = reinterpret_cast<RAWINPUT*>(::GlobalLock(hRaw)); memset((void*)pRaw, 0, sizeof(RAWINPUT)); pRaw->header.dwType = RIM_TYPEMOUSE; pRaw->header.dwSize = sizeof(RAWINPUT); pRaw->header.hDevice = GetRawMouseDevice(); // can return the mouse HANDLE correctly pRaw->header.wParam = wParamRawMouse; RAWMOUSE rawMouseInfo; memset((void*)&rawMouseInfo, 0, sizeof(RAWMOUSE)); rawMouseInfo.usFlags = MOUSE_MOVE_RELATIVE; rawMouseInfo.lLastX = _mouse_position.x - _last_mouse_position.x; // get the mouse's location change rawMouseInfo.lLastY = _mouse_position.y - _last_mouse_position.y; rawMouseInput.data.mouse = rawMouseInfo; rawMouseInfo.ulExtraInformation = 0; rawMouseInfo.ulButtons = 0; rawMouseInfo.usButtonFlags = 0; rawMouseInfo.ulRawButtons = 0; pRaw = &rawMouseInput; ::GlobalUnlock(hRaw); // mainGameWnd is the main window handle PostMessageA(mainGameWnd, WM_INPUT, wParamRawMouse, (LPARAM)hRaw); SendMessageA(mainGameWnd, WM_NCHITTEST, 0, MAKELPARAM(_mouse_position.x, _mouse_position.y)); SendMessageA(mainGameWnd, WM_SETCURSOR, (WPARAM)mainGameWnd, MAKELPARAM(HTCLIENT,WM_MOUSEMOVE)); PostMessageA(mainGameWnd, WM_MOUSEMOVE, 0, lParamMouseMove); // ...
And I used spy++ to monitor my own program:
P WM_INPUT nInputCode:RIM_INPUT hRawInput:0000023822711808 S WM_NCHITTEST xPos:492 yPos:373 R WM_NCHITTEST nHittest:HTNOWHERE S WM_SETCURSOR hwnd:001B0794 nHittest:HCLIENT wMouseMsg:WM_MOUSEMOVE R WM_SETCURSOR fHaltProcessing:True P WM_MOUSEMOVE fwKeys:0000 xPos:492 yPos:373
It didn't work, when I moved the mouse, the character's view didn't change and the cursor just moved. So how to correctly send the four message? Do some magics beyond sending message for free look in games? By the way, this question mentions camera, I think in this hooking situation, the camera is still handled by the game and I just need to send mouse-related message to the game. No need to consider the camera. Am I right?