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.
Related
I'm not sure where problem is.
Though, I have two modes in my application. By pressing "R" - key the modes are switching. The application-class is responsible for the entire app's demeanor. It contains the private member, the mode-flag (rotation_mode). In the key handling method I set this flag to the opposite value if the R-key has been pressed.
void Application::keyCallBack()
{
if (glfwGetKey(this->window, GLFW_KEY_ESCAPE) == GLFW_PRESS) this->setWindowShouldClose();
if (glfwGetKey(this->window, GLFW_KEY_R) == GLFW_PRESS) this->rotation_mode = !this->rotation_mode;
...
}
After, this flag uses as mode-definition. If a rotation mode is off, then we we should rotate a camera via mouse, otherwise we should rotate a model via mouse (when the left mouse button pressed), whereas the camera's direction is freezed.
...
if (this->rotation_mode)
{
std::cout << "rotation mode\n";
if (glfwGetMouseButton(this->window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS)
{
if (glfwGetKey(this->window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS)
{
std::cout << "rotate" << std::endl;
this->model.rotation_angle_x += this->y_offset * 6.0f * this->delta_time;
}
else
this->model.rotation_angle_z += this->x_offset * 6.0f * this->delta_time;
this->model.rotation_angle_y += this->y_offset * 6.0f * this->delta_time;
}
}
else
this->camera.camera_obj.ProcessMouseMovement(this->x_offset, this->y_offset);
...
Do not blame me for the implementation:)) It's not done, yet. The problem is that, when I press "R", occasionally the mode is not turning and the output "rotation mode" is still going on.
Note: I'm not using glfwSetKeyCallback, due to some implementation's troubles. I update it in the infinite while-loop.
According to the reference: "This function returns the last state reported for the...".
Possible that the states gets somehow overwritten or there is a race condition? Best would be to retrieve the input from the callback mechanism.
According to Thread Safety:
"This function must only be called from the main thread."
That's the thread where you initialized glfW and created your window. Where do you run your implementation?
Besides:
glfwGetMouseButton(this->window, GLFW_KEY_LEFT_ALT)
Can you do that? The reference lists only the 'GLFW_MOUSE_BUTTON_X'. Shouldn't that be glfWGetKey?
Edit:
I looked into the source code of glfW. The event processing function calls in case of KeyPress and KeyRelease the same function which sets the states of the window and calls the callback. Remember, after a Press there is a Release, which is handled by glfW but not by you.
The glfwGetKey function only reads the states of the specific window, which are set by the event processing function.
p.s. im under linux and i know X, so this was the place where i have done my research, how it is implemented for the other platforms, i don't know, but i think similar.
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.
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;}
I am having a hard time trying to get wgetch to read data from a window after moving and resizing it.
Upon input, I move the window up and increase it's height by 1 too. I then clear the window and write data back to it. The problem is when I do wgetch (or mvwgetch) it positions the input cursor at the previous position before I moved the window up.
Here's my code:
#include <ncurses.h>
int main() {
WINDOW *win=initscr();
int y,x,i=1;
getmaxyx(win, y, x);
//creates a sub windows 1 col high
WINDOW *child=derwin(win, i, x, y-i, 0);
//doc says to touch before refresh
touchwin(win);
//print to child
waddstr(child, "hello");
wrefresh(child);
wrefresh(win);
noecho();
while(wgetch(child)!='q') {
++i;
mvderwin(child, y-i, 0);
wresize(child, i, x);
touchwin(win);
wclear(child);
waddstr(child,"hello");
wrefresh(child);
wrefresh(win);
}
delwin(child);
delwin(win);
endwin();
}
Here the word "hello" does move up as expected, however, the input cursor is in the wrong place. Using mvwgetch still causes the same problem. cbreak(), noecho() and scrollok(child) also don't seem to be helping.
Thanks
EDIT: updated version better displaying the problem http://liveworkspace.org/code/31DruQ$0
You have to catch SIGWINCH, that signal is sent when you resize the terminal. Do an endwin(), a refresh(), and then repaint your windows. Cursor position is relative to the windows, not the actual terminal size. The windows are not resized automatically.
Edit: Right, you're actually resizing the windows, not the terminal. In that case, first of all, do a wrefresh on the child LAST, the cursor shown on the screen is the one of the refresh that happened last.
Put a box around your subwindows and check that they're actually getting resized / moved properly.
I am working on writing a program that will do a few mouse clicks for me in a loop. I created a struct and set it to type INPUT_MOUSE to replicate the clicks and used SendInput() to send the info. everything compiles right and could be called a "working" program but I ran into a rather funny glitch. I wrote the program on my laptop (windows vista) tried it and it worked fine. When I rewrote the same exact code and used it on my desktop (Windows 7) when I run the program my screen will go to black as soon as I start the automation part of the program just like it does when it goes into sleep mode. The program will run in the background just fine, but its kind of a pain that the automater blacks my screen out. What is going on here?
I am adding my code:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
void clicky(int x, int y)
{
// 5 sec wait
clock_t run;
run = clock()+5*CLOCKS_PER_SEC;
while (clock() < run) {}
//plug in cursor coords and click down and up
SetCursorPos(x,y);
INPUT mouse;
mouse.type = INPUT_MOUSE;
mouse.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1,&mouse,sizeof(INPUT));
mouse.type = INPUT_MOUSE;
mouse.mi.dwFlags= MOUSEEVENTF_LEFTUP;
SendInput(1,&mouse,sizeof(INPUT));
}
void main()
{
int coords=0;
string h;
//find out how many clicks are needed
cout << "How many clicks will you need?";
cin >> coords;
//extra getline here without it when return is hit
//from entering the click amount it would also enter
//a cursor coordinate
getline(cin,h);
POINT p[21];
for (int count = 1;count<=coords;count++)
{
cout << "Place mouse cursor where you want a click and press return"<<endl;
//each time return is hit the cursor coordinates
//will be stored in the corresponding spot in
// the p array
string key = "r";
getline(cin,key);
GetCursorPos(&p[count]);
break;
}
string go;
cout << "Hit Return to initialize your click loop";
getline(cin,go);
while (true)
//infinite loop cycling through the users
//cursor coordinates and clicking
{
for(int click=1;click<=coords;click++)
{
int x = p[click].x;
int y = p[click].y;
clicky(x,y);
}
}
}
Try initializing the INPUT structure to all zeroes before calling SendInput(), like
INPUT i;
ZeroMemory(&i, sizeof(i));
In addition to that, make sure that the coordinates you specify are not too large.
I had the screen go blank (in fact, the screensaver kicked in) when doing either of these two wrong.