SendInput does not send the exact amount of pixels I specify - c++

I prepare the input buffer like this
...
buffer->mi.dx = x;
buffer->mi.dy = y;
buffer->mi.mouseData = 0;
buffer->mi.time = 0;
buffer->mi.dwExtraInfo = 0;
buffer->mi.dwFlags = (MOUSEEVENTF_MOVE);
SendInput(1, buffer, sizeof(INPUT));
std::cout << "moving " << buffer->mi.dx << "," << buffer->mi.dy << " relative to current position" << std::endl;
...
Here's the output of this code:
Current Mouse position: 755,286
moving 0,10 relative to current position
Result: 755,294
I need to avoid MOUSEEVENTF_ABSOLUTE dwflag if possible.
Any ides on why this is happening and how can I fix it?

Any ides on why this is happening and how can I fix it?
I'm guessing it's mouse-acceleration. This is mentioned in the documentation:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mouse_event
Relative mouse motion is subject to the settings for mouse speed and acceleration level. An end user sets these values using the Mouse application in Control Panel. An application obtains and sets these values with the SystemParametersInfo function.
Obviously a workaround is to disable mouse-acceleration, but that's not something you should be doing (and if I ever catch any programs on my computer messing with my mouse settings, they find themselves uninstalled very quickly).
A better idea is to use MOUSEEVENTF_ABSOLUTE and apply the (0,+10) offset to the current position in your own code - I don't know why you're so opposed to using MOUSEEVENTF_ABSOLUTE, it just means you need to get the current coordinates first, which is hardly much work.

Related

How to easy check if joystick plugged (by c++)

I need to write an easy function that only return bool answer.
if there is joystick plugged in the computer - true,else - false.
how can i do this?
I have tried to write this code, but i only get the num of deviced that plug by usb to my computer, i need to know that this usb is joystick.
UINT pNum = 0;
RAWINPUTDEVICELIST* arr = new RAWINPUTDEVICELIST;
PRAWINPUTDEVICELIST pRawInputDeviceList = arr;
GetRawInputDeviceList(pRawInputDeviceList, &pNum, sizeof(RAWINPUTDEVICELIST));
std::cout << "Num entered: " << pNum << std::endl;
Use the joyGetPos function to determine whether a given joystick is physically attached to the system. If the specified joystick is not connected, joyGetPos returns a JOYERR_UNPLUGGED error value.
The joyGetNumDevs function returns the number of joysticks supported by the current driver or zero if no driver is installed.

C++, detecting if mouse is idle-ing (short-time, 20ms)

this is my first post!
I'm writing a C++ program to control main character in Touhou Games series; i'm making it for those who have hands disabilities and can't click arrow keys, but still can use mouse.
The player should trigger Arrow Keys with mouse movements (mouse goes left and left key is pressed, and so on..). I already did that part, but the character moves as if the arrow keys were pressed multiple times, so the character movements are a little clumsy and rough, not smooth and clean as if the key was HOLD.
My problem is that i have to know when mouse is idling/not moving (to understand how long the player wants to hold the arrow key -- the more the player slides the mouse in a direction, the more that arrow key is hold), but can't figure out how. Searching on Stackoverflow i've found GetLastInput function, but it triggers for EVERY input, and is not mouse-only related.
It should come out something like:
while( *mousenotidling* )
{
//holdbutton
}
What would you suggest? How can i know when mouse is idling (for short-times, like 20ms)? (or if you suggest other solutions, every opinion is welcomed)
I'm writing it in C++, with Codeblock and GCC compiler, my OS is Windows 7 x86 :)
You can call TrackMouseEvent and set the idling time to what is desire like 2000ms for 2sec idle time. Also you can use GetLastInputInfo to get the amount of milliseconds the last key or mouse movement was performed.
DWORD GetIdleTime()
{
LASTINPUTINFO pInput;
pInput.cbSize = sizeof(LASTINPUTINFO);
if (!GetLastInputInfo(&pInput))
{
// any errors will be reported
}
// return idle time in milliseconds
return pInput.dwTime;
}
Also you can try this one suggestion
int prev_x = 0, prev_y = 0; while (1)
{int x = ..., y = ...; if (x == prev_x && y == prev_y) {mouse was moved}
else {mouse wasn't moved} prev_x = x; prev_y = y;}

Moving mouse position then back to beginning position

I'm trying to make keys move the mouse to a different position on the screen and then instantly back, at a very fast rate (50+ times per second) This is my current Code.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
int main()
{
POINT p;
for( ; ; )
{
if (GetAsyncKeyState(0x57) < 0)
{
GetCursorPos(&p);
std::cout << "W key pressed";
SetCursorPos(0, 0);
SetCursorPos(p.x, p.y);
Sleep(100);
}
}
With this code it'll just change my mouse position then update as to where it was (I don't have free movement of my mouse and just keeps it at/around 0,0) If I put Sleep(100) at the end then it works pretty consistently but every ~10 seconds my mouse will get stuck at 0,0 again, the more I put up the sleep the less this happens, but why?
edit console app in Visual Studio
See documentation for GetAsyncKeyState
Return value
Type: SHORT
If the function succeeds, the return value specifies whether the key
was pressed since the last call to GetAsyncKeyState, and whether the
key is currently up or down. If the most significant bit is set, the
key is down, and if the least significant bit is set, the key was
pressed after the previous call to GetAsyncKeyState. However, you
should not rely on this last behavior; for more information, see the
Remarks.
Example
if (GetAsyncKeyState('W') & 0x8000)
{
std::cout << "W key pressed\n";
}
SetCursorPos(0,0) moves the cursor to top-left corner, while SetCursorPos(p.x, p.y) moves the cursor back to where it was when you called GetCursorPos. You won't see any changes to the mouse position.
It is not common to use these WinAPI functions in a console program.

C++: How Can I keep my program (output console) alive

I am writing a simple program (my 1st program) to display the laptop battery, however, I would like to keep it active to monitor the battery %.:
using namespace std;
int main(int argc, char *argv[]) {
id:
SYSTEM_POWER_STATUS spsPwr;
if (GetSystemPowerStatus(&spsPwr)) {
cout << "\nAC Status : " << static_cast<double>(spsPwr.ACLineStatus)
<< "\nBattery Status : " << static_cast<double>(spsPwr.BatteryFlag)
<< "\nBattery Life % : " << static_cast<double>(spsPwr.BatteryLifePercent)
<< endl;
system("CLS");
goto id;
return 0;
}
else return 1;
}
using goto seems to be a bad idea as the CPU utilization jump to 99% ! :(, I am sure this is not the right way to do it.
Any suggestion?
Thanks
while (true) {
// do the stuff
::Sleep(2000); // suspend thread to 2 sec
}
(you are on Windows according to the API function)
see: Sleep
First of all, the issue you are asking about: of course you get 100% CPU usage, since you're asking the computer to try and get and print the power status of the computer as fast it possibly can. And since computers will happily do what you tell them to, well... you know what happens next.
As others have said, the solution is to use an API that will instruct your application to go to sleep. In Windows, which appears to be your platform of choice, that API is Sleep:
// Sleep for around 1000 milliseconds - it may be slightly more since Windows
// is not a hard real-time operating system.
Sleep(1000);
Second, please do not use goto. There are looping constructs in C and you should use them. I'm not fundamentally opposed to goto (in fact, in my kernel-driver programming days I used it quite frequently) but I am opposed to seeing it used when better alternatives are available. In this case the better alternative is a while loop.
Before I show you that let me point out another issue: DO NOT USE THE system function.
Why? The system function executes the command passed to it; on Windows it happens to execute inside the context of the command interpreter (cmd.exe) which supports and internal command called cls which happens to clear the screen. At least on your system. But yours isn't the only system in the world. On some other system, there might be a program called cls.exe which would get executed instead, and who knows what that would do? It could clear the screen, or it could format the hard drive. So please, don't use the system function. It's almost always the wrong thing to do. If you find yourself looking for that command stop and think about what you're doing and whether you need to do it.
So, you may ask, how do I clear the screen if I can't use system("cls")? There's a way to do it which should be portable across various operating systems:
int main(int, char **)
{
SYSTEM_POWER_STATUS spsPwr;
while (GetSystemPowerStatus(&spsPwr))
{
std::string status = "unknown";
if (spsPwr.ACLineStatus == 0)
status = "offline";
else if (spsPwr.ACLineStatus == 1)
status = "online";
// The percent of battery life left is returned as a value
// between 0 and 255 so we normalize it by multiplying it
// by 100.0 and dividing by 255.0 which is ~0.39.
std::cout << "Current Status: " << status << " ("
<< static_cast<int>(spsPwr.BatteryFlag) << "): "
<< 0.39 * static_cast<int>(spsPwr.BatteryLifePercent)
<< "% of battery remaining.\r" << std::flush;
// Sleep for around 1000 milliseconds - it may be slightly more
// since Windows is not a hard real-time operating system.
Sleep(1000);
}
// Print a new line before exiting.
std::cout << std::endl;
return 0;
}
What this does is print the information in a single line, then move back to the beginning of that line, sleep for around one second and then write the next line, overwriting what was previously there.
If the new line you write is shorter than the previous line, you may see some visual artifacts. Removing them should not be difficult but I'll leave it for you as an exercise. Here's a hint: what happens if you output a space where a letter used to be?
In order to do this across lines, you will need to use more advanced techniques to manipulate the console, and this exercise becomes a lot trickier.
You are having 100% CPU usage because your program is always running.
I don't want to get into details, and given that this is your first program, I'll recommend to put a call to usleep before the goto.
And, of course, avoid goto, use a proper loop instead.
int milliseconds2wait = 3000;
while (!flag_exit) {
// code
usleep( 1000 * milliseconds2wait )
}
Update: This is windows, use Sleep instead of usleep:
Sleep( milliseconds2wait );

Sleep(x) causes computer to sleep instead

This is probably one of the strangest things I've encountered so far in C++:
while(counter != stop_value)
{
//Part A starting
ip.ki.wVk = VK_RETURN;
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.wVk = VK_RETURN;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
//Part A ending
if (s == 2) counter++;
else counter--;
cout << counter; //for debugging
Sleep(i);
}
Whenever I comment the "Part A"-part away, it works properly; the program sleeps for i seconds, depending on user input. However, as soon as I add the easy way of triggering the return-key again, it makes my whole computer sleep instead (AKA, the screen goes entirely black for i seconds). I've tried googling, but I can't find anything about this.
And, this is only a small part of the code. I have added the INPUT class and everything further up. s is also a user-defined variable, that (in this case) can vary between 2 and 3. If equal to two, the counter's value will be set to 0, and it will increase until it has reached its max value (which is user-defined, and set to stop-value). While using this method, the sleep function works properly, and only the program "pauses" for i seconds. HOWEVER, as soon as a user set s to 3, it will start decreasing from the max value (user-defined) until it has reached its stop-value, which always is equal to zero. When this happens, the screen gets a blackout instead.
I've tried debugging for ages now, and I just can't seem to find the solution... Since the code is way more complex than this, and I'd need to use way more space (which I don't want to), I'll give you some inputs for the variables you can use instead:
Working input: counter = 0; stop_value = 21; s = 2; i = 1000;
Input leading to screen blackout: counter = 20; stop_value = 0; s = 3; i = 1000;
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx
May as well stick it as an answer :)
Are you setting the type of ip to INPUT_KEYBOARD? and are you using ZeroMemory on the structure prior to use?