I am trying to move the mouse (on Windows 10) using SendInput when I perform a physical mouse click. It works fine if I click once or twice, but if clicking for examples 6 times in quick succession the mouse lags for a few seconds then the program stops responding.
Is there any obvious reason why this is happening?
(Edited)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
LRESULT CALLBACK MouseHook(int, WPARAM, LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
{
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseHook, NULL, 0);
MessageBox(NULL, L"Hello", L"Hello", MB_OK);
UnhookWindowsHookEx(hook);
return 0;
}
LRESULT CALLBACK MouseHook(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
switch (wParam) {
case WM_RBUTTONUP:
INPUT buffer;
ZeroMemory(&buffer, sizeof(buffer));
buffer.type = INPUT_MOUSE;
buffer.mi.dx = 0;
buffer.mi.dy = 10;
buffer.mi.mouseData = 0;
buffer.mi.dwFlags = MOUSEEVENTF_MOVE;
buffer.mi.time = 0;
buffer.mi.dwExtraInfo = 0;
SendInput(1, &buffer, sizeof(INPUT));
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
Using Raw Input sample:
#include <windows.h>
#include <iostream>
using namespace std;
BOOL registerTouchpadForInput(HWND hWnd)
{
RAWINPUTDEVICE rid;
rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
rid.usUsagePage = 1;
rid.usUsage = 2;
rid.hwndTarget = hWnd;
return RegisterRawInputDevices(&rid, 1, sizeof(rid));
}
void getinputdata(LPARAM lparam)
{
HRAWINPUT hInput = (HRAWINPUT)lparam;
RAWINPUT input = { 0 };
UINT size = sizeof(RAWINPUT);
GetRawInputData(hInput, RID_INPUT,&input, &size,sizeof(RAWINPUTHEADER));
if (RIM_TYPEMOUSE == input.header.dwType)
{
if (input.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
{
INPUT buffer;
ZeroMemory(&buffer, sizeof(buffer));
buffer.type = INPUT_MOUSE;
buffer.mi.dx = 0;
buffer.mi.dy = 10;
buffer.mi.mouseData = 0;
buffer.mi.dwFlags = MOUSEEVENTF_MOVE;
buffer.mi.time = 0;
buffer.mi.dwExtraInfo = 0;
SendInput(1, &buffer, sizeof(INPUT));
}
}
return;
}
static LRESULT CALLBACK NVTouch_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL registrationStatus = false;
switch (message)
{
case WM_CREATE:
registrationStatus = registerTouchpadForInput(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_INPUT:
getinputdata(lParam);
return DefWindowProc(hwnd, message, wParam, lParam);
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
int main()
{
WNDCLASSEX wndclass = {
sizeof(WNDCLASSEX),
CS_DBLCLKS,
NVTouch_WindowProc,
0,
0,
GetModuleHandle(0),
LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW),
HBRUSH(COLOR_WINDOW + 1),
0,
L"myclass",
LoadIcon(0,IDI_APPLICATION)
};
bool isClassRegistered = false;
isClassRegistered = RegisterClassEx(&wndclass);
if (isClassRegistered)
{
HWND window = CreateWindow(wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
Related
I have been trying to create a Window whose title bar could be in any language. But I am getting something like ▯*. I writing as escape characters as of now. I am attesting the entirity of the code.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
switch(Message) {
case WM_KEYDOWN: {
switch(WParam) {
case 'O': {
DestroyWindow(Window);
} break;
}
} break;
case WM_DESTROY: {
PostQuitMessage(0);
} break;
default: {
return DefWindowProc(Window, Message, WParam, LParam);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE Instance, HINSTANCE PrevInstance, PSTR CmdLine, int CmdShow) {
WNDCLASSW WindowClass = {0};
const wchar_t* ClassName = L"MyWindowClass";
WindowClass.lpfnWndProc = WindowProc;
WindowClass.hInstance = Instance;
WindowClass.lpszClassName = ClassName;
WindowClass.hCursor = LoadCursor(NULL, IDC_CROSS);
MessageBoxW(0, L"\u0906\u092a", L"\u0906\u092a", 0);
if(!RegisterClassW(&WindowClass)) {
MessageBoxW(0, L"RegisterClass failed", 0, 0);
return GetLastError();
}
HWND Window = CreateWindowExW(0, ClassName, L"\u0906\u092a",
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, Instance, 0);
if(!Window) {
MessageBoxW(0, L"CreateWindowEx failed", 0, 0);
return GetLastError();
}
int Running = 1;
while(Running) {
MSG Message;
while(GetMessageW(&Message, NULL, 0, 0)) {
if(Message.message == WM_QUIT) Running = 0;
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
return 0;
}
I was expecting the title bar to be something like 'आप'
When I first run the program, the window's theme is Windows 11 (as intended):
However, after a few frame updates, the theme changes to a previous version of Windows, and the title text also disappears:
This is my Framework class:
#include "Framework.h"
LRESULT CALLBACK Framework::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Framework* pThis = nullptr;
if (msg == WM_CREATE)
{
CREATESTRUCT* pcs = reinterpret_cast<CREATESTRUCT*>(lParam);
pThis = reinterpret_cast<Framework*>(pcs->lpCreateParams);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
}
else
{
pThis = reinterpret_cast<Framework*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
if (pThis)
return pThis->OnProcessMessage(hwnd, msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
LRESULT Framework::OnProcessMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(mRenderer)
return mRenderer->OnProcessMessage(hwnd, msg, wParam, lParam);
return NULL;
}
void Framework::Run()
{
RECT r;
GetClientRect(mWinHandle, &r);
mWidth = r.right - r.left;
mHeight = r.bottom - r.top;
std::atexit(ReportLiveObjects);
ShowWindow(mWinHandle, SW_SHOWNORMAL);
mRenderer = make_shared<DX12Renderer>();
mRenderer->Init(mWinHandle, mWidth, mHeight);
mRenderer->BuildObjects();
MsgLoop();
DestroyWindow(mWinHandle);
}
void Framework::Init(const string& winTitle, uint32_t width, uint32_t height)
{
const WCHAR* className = L"Main Window";
// Register the window class
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = className;
wc.hIconSm = LoadIcon(wc.hInstance, IDI_APPLICATION);
if (RegisterClassEx(&wc) == 0)
{
return;
}
// Window size we have is for client area, calculate actual window size
RECT r{ 0, 0, (LONG)width, (LONG)height };
int windowWidth = r.right - r.left;
int windowHeight = r.bottom - r.top;
// create the window
wstring wTitle = stringTowstring(winTitle);
mWinHandle = CreateWindow(className, wTitle.c_str(),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
windowWidth, windowHeight, NULL, NULL,
GetModuleHandle(NULL), this);
if (mWinHandle == nullptr)
{
return;
}
}
void Framework::MsgLoop()
{
MSG msg{};
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
mRenderer->Update();
mRenderer->Draw();
}
}
}
And this is my WinMain() function:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int mCmdShow)
{
#if defined(DEBUG) || defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
try
{
Framework app;
app.Init("Chulsu Renderer");
app.Run();
}
catch (std::exception& ex)
{
MessageBoxA(nullptr, ex.what(), "ERROR", MB_OK);
return -1;
}
return 0;
}
Lastly, message input processing functions:
LRESULT DX12Renderer::OnProcessMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_ACTIVATE:
break;
case WM_SIZE:
mSwapChainSize.x = LOWORD(lParam);
mSwapChainSize.y = HIWORD(lParam);
if (wParam == SIZE_MAXIMIZED)
{
OnResize();
}
else if (wParam == SIZE_RESTORED)
{
if (mDevice) {
OnResize();
}
}
break;
case WM_ENTERSIZEMOVE:
break;
case WM_EXITSIZEMOVE:
OnResize();
break;
case WM_GETMINMAXINFO:
reinterpret_cast<MINMAXINFO*>(lParam)->ptMinTrackSize = { 200, 200 };
break;
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
OnProcessMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
OnProcessMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MOUSEMOVE:
OnProcessMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_KEYDOWN:
case WM_KEYUP:
if (wParam == VK_ESCAPE)
{
PostQuitMessage(0);
return 0;
}
OnProcessKeyInput(msg, wParam, lParam);
break;
case WM_MENUCHAR:
return MAKELRESULT(0, MNC_CLOSE);
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
void DX12Renderer::OnResize()
{
}
void DX12Renderer::OnProcessMouseDown(WPARAM buttonState, int x, int y)
{
}
void DX12Renderer::OnProcessMouseUp(WPARAM buttonState, int x, int y)
{
}
void DX12Renderer::OnProcessMouseMove(WPARAM buttonState, int x, int y)
{
}
void DX12Renderer::OnProcessKeyInput(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
}
void DX12Renderer::Update()
{
}
If you need full codes, here's a GitHub page:
https://github.com/kcjsend2/Chulsu
It's a DirectX12 + Win32 application, but I think the DirectX12 layer probably has nothing to do with this problem.
UPDATE:
Seriously, this problem is really odd.
When I replace Framework::OnProcessMessage() like this:
LRESULT Framework::OnProcessMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_KEYDOWN:
case WM_KEYUP:
if (wParam == VK_ESCAPE) {
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Then it works well.
But no matter what's in the function, if I return mRenderer->OnProcessMessage(), it just makes the bug above.
LRESULT Framework::OnProcessMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (mRenderer)
return mRenderer->OnProcessMessage(hwnd, msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
problem was because of OnProcessMessage returns few NULLs when Renderer is not initialized.
change it to return DefWindowProc, it fixed problem.
I've successfully set up a mouse hook for a window, and I'd like to detect a drag operation when the left mouse button is clicked. I've tried using DragDetect, as shown below, but it never returns TRUE, and it never suppresses the subsequent mouse-up event (in this code, hwnd is the target window):
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
switch (wParam)
{
case WM_LBUTTONDOWN:
{
// Get the click point
LPMOUSEHOOKSTRUCT pMouseHookStruct = reinterpret_cast<LPMOUSEHOOKSTRUCT>(lParam);
CPoint ptClick = pMouseHookStruct->pt;
// Drag detect
BOOL fDrag = DragDetect(hwnd, ptClick);
if (fDrag)
{
MessageBox(NULL, L"Drag", NULL, MB_OK);
}
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
Does DragDetect not work within hook procedures, or am I just doing something wrong?
As comments pointed, DragDetect does not predict the future. But you can compare the POINT of WM_LBUTTONDOWN and WM_MOUSEMOVE in a click-time.
Sample:
#include <windows.h>
#include <iostream>
using namespace std;
typedef BOOL(*SETHOOK)(HWND hWnd);
typedef BOOL(*UNHOOK)();
LRESULT CALLBACK WndProcFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int main(int argc, char* argv[])
{
WNDCLASS wc{};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProcFunc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"Class_Name";
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
RegisterClass(&wc);
HWND hWnd = CreateWindow(L"Class_Name", L"Test", WS_OVERLAPPEDWINDOW, 0, 0, 1000, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
SETHOOK SetHook;
UNHOOK UnHook;
HMODULE h = LoadLibraryA("PATH\\DLL4.dll");
SetHook = (SETHOOK)GetProcAddress(h, "SetHook");
UnHook = (UNHOOK)GetProcAddress(h, "UnHook");
BOOL i = SetHook(hWnd);
ShowWindow(hWnd, 1);
UpdateWindow(hWnd);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
UnHook();
return 0;
}
DLL:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define PRESS TRUE
#define RELEASE FALSE
HHOOK tHook;
HMODULE hinstDLL;
BOOL button = RELEASE;
BOOL Drag = FALSE;
HWND hWnd;
POINT pt = { 0 };
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode < 0)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
LPMOUSEHOOKSTRUCT pMouseHookStruct = reinterpret_cast<LPMOUSEHOOKSTRUCT>(lParam);
if (pMouseHookStruct->hwnd != hWnd)
{
button = RELEASE;
Drag = FALSE;
}
else {
switch (wParam)
{
case WM_LBUTTONDOWN:
{
button = PRESS;
Drag = FALSE;
printf("WM_LBUTTONDOWN\n");
printf("%d , %d\n", pMouseHookStruct->pt.x, pMouseHookStruct->pt.y);
pt.x = pMouseHookStruct->pt.x;
pt.y = pMouseHookStruct->pt.y;
break;
}
case WM_LBUTTONUP:
{
button = RELEASE;
Drag = FALSE;
printf("WM_LBUTTONUP\n");
break;
}
case WM_MOUSEMOVE:
{
if (button == PRESS)
{
printf("%d , %d\n", pMouseHookStruct->pt.x, pMouseHookStruct->pt.y);
if (Drag == FALSE && (abs(pt.x - pMouseHookStruct->pt.x) >= GetSystemMetrics(SM_CXDRAG) || abs(pt.y - pMouseHookStruct->pt.y) >= GetSystemMetrics(SM_CYDRAG)))
{
printf("Drag\n");
Drag = TRUE;
}
}
break;
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) BOOL SetHook(HWND hwnd)
{
hWnd = hwnd;
tHook = SetWindowsHookEx(WH_MOUSE, MouseProc, hinstDLL, 0);
if (tHook == NULL)
return FALSE;
else
return TRUE;
}
extern "C" __declspec(dllexport) BOOL UnHook()
{
return UnhookWindowsHookEx(tHook);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hinstDLL = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
i hope to make a console when i click right button,
mouse move down little bit
i tried this code,
bool MouseMove(int x, int y)
{
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.time = 0;
input.mi.dx = x;
input.mi.dy = y;
input.mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(1, &input, sizeof(input));
return true;
}
HWND hWnd;
HHOOK hMSHook;
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= HC_ACTION)
{
if (wParam == WM_RBUTTONUP)
{
MouseMove(0, 10);
return 1;
}
}
return CallNextHookEx(hKBHook, nCode, wParam, lParam);
}
int _tmain() {
hWnd = ::GetConsoleWindow();
ShowWindow(hWnd, 0);
HMODULE hInstance = GetModuleHandle(NULL);
hMSHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, hInstance, NULL);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0)) { DispatchMessage(&Msg); }
return 0;
}
It works fine, but if i try it few times,
it causing lag (struggle, slow, laggy)
someone know how to fix it?
So is there a way to make my Win32 application "think" that the mouse is moving over its window and making some clicks when the actual window is hidden (i mean ShowWindow(hWnd, SW_HIDE);)?
I tried to simulate mouse moving with PostMessage and SendMessage but no luck so far.
int x = 0;
int y = 0;
while (true)
{
SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
x += 10;
y += 10;
Sleep(100);
}
Is this even possible?
Yes it's possible. This is a test hidden window:
#define UNICODE
#include <Windows.h>
#include <Strsafe.h>
#include <Windowsx.h>
LRESULT CALLBACK WndProc(HWND Hwnd, UINT Msg, WPARAM WParam, LPARAM LParam);
INT CALLBACK
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow)
{
WNDCLASSEX WndClass;
ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.lpfnWndProc = WndProc;
WndClass.hInstance = hInstance;
WndClass.lpszClassName = L"HiddenWinClass";
if(RegisterClassEx(&WndClass))
{
HWND Hwnd;
MSG Msg;
Hwnd = CreateWindowEx(0, L"HiddenWinClass", L"Nan",
0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
if(Hwnd)
{
UpdateWindow(Hwnd);
ShowWindow(Hwnd, SW_HIDE);
while(GetMessage(&Msg, 0, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
return 0;
}
LRESULT CALLBACK
WndProc(HWND Hwnd,
UINT Msg,
WPARAM WParam,
LPARAM LParam)
{
TCHAR Message[255];
switch(Msg)
{
case WM_MOUSEMOVE:
StringCbPrintf(Message, sizeof(Message), L"(%d, %d)",
GET_X_LPARAM(LParam), GET_Y_LPARAM(LParam));
MessageBox(NULL, Message, L"WM_MOUSEMOVE", MB_OK);
break;
default:
return DefWindowProc(Hwnd, Msg, WParam, LParam);
}
return 0;
}
and this is your code:
#define UNICODE
#include <Windows.h>
int
main(int argc, char **argv)
{
HWND Hwnd;
if((Hwnd = FindWindow(L"HiddenWinClass", L"Nan")))
{
int x, y;
for(x = y = 0 ; ; x += 10, y += 10)
{
SendMessage(Hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
Sleep(100);
}
}
return 0;
}
It works nicely.