I'm using WinAPI, with C++, I want to make a right click simulation with SendInput, but I'm not sure of what's going wrong.
My test program should work like that: when i press middle button of mouse, it perform a right click.
#include <iostream>
#include <windows.h>
#include <stdio.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Fetch tab key state.
while (1)
{
SHORT tabKeyState = GetAsyncKeyState(4); // Mouse mid button
// Test high bit - if set, button was down when GetAsyncKeyState was called.
if (tabKeyState < 0)
{
INPUT Input[2] = { 0 };
// left down
Input[0].type = INPUT_MOUSE;
Input[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
Input[0].mi.time = 500;
// left up
Input[1].type = INPUT_MOUSE;
Input[1].mi.dwFlags = MOUSEEVENTF_RIGHTUP;
Input[1].mi.time = 500;
::SendInput(2, Input, sizeof(INPUT));
}
}
return 0;
}
In the code to set the properties for the second event record you use index 0 instead of index 1.
Input[1].type = INPUT_MOUSE;
Input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;
Input[0].mi.time = 100;
Use index 1 rather than 0 in the final two lines.
By the by, it's easier to write the if statement like this
if (tabKeyState < 0)
I solve this question using Sleep to make what i wanted to do and I discovered that the sendinput was not working cause I was executing this inside the VS. This question can be closed now.
Related
I am using "XGrabPointer" to get the mouse click events when ever they occured in the active window.But my requirement is to detect the clicks globally i.e in any application on the X11 desktop.
XGrabPointer blocks the active window so i can not move to other applications and detect the mouse click events.
Here are the codes:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
int main(int argc, char **argv)
{
Display *display;
XEvent xevent;
Window window;
int grb;
int scr;
if( (display = XOpenDisplay(NULL)) == NULL )
return -1;
unsigned int t_new=0,t_prev=0,t_diff=0;
scr = DefaultScreen(display);
window = RootWindow(display, scr);
while(1) {
XGrabPointer(display,
window,
True,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
XAllowEvents(display,AsyncPointer, CurrentTime);
XNextEvent(display, &xevent);
switch (xevent.type) {
case MotionNotify:{
printf("motion event\n");
break;
}
case ButtonPress:{
switch (xevent.xbutton.button) {
case 1:
printf("Left Click\n");
t_prev=t_new;
printf("Click Occured : [%d, %d]\n",
xevent.xbutton.x_root,
xevent.xbutton.y_root);
break;
case 2:
printf("Grabed\n");
printf("Middle Click\n");
break;
case 3:
printf("Right Click\n");
break;
case 4:
printf("Grabed\n");
printf("Scroll UP\n");
break;
case 5:
printf("Scroll Down\n");
break;
}
break;
}
}
}
XUngrabPointer(display,CurrentTime);
return 0;
}
Couldn't find an answer on how to listen to mouse events in the background as well. It's impossible to do it with mouse grabbing and you won't be able to click anywhere outside of your program.
So the solution is to read linux's /dev/input/mice device for the raw mouse input (we want button clicks) and when a low-level event occur we query X server for mouse position (can't query mouse key presses from X this way).
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = DefaultRootWindow(display);
int fd, bytes;
unsigned char data[3];
const char *pDevice = "/dev/input/mice";
// Open Mouse
fd = open(pDevice, O_RDWR);
if (fd == -1) {
printf("ERROR Opening %s\n", pDevice);
return -1;
}
int left, middle, right;
while (1) {
// Read Mouse
bytes = read(fd, data, sizeof(data));
if (bytes > 0) {
left = data[0] & 0x1;
right = data[0] & 0x2;
middle = data[0] & 0x4;
XQueryPointer(
display,
root_window,
&event.xbutton.root,
&event.xbutton.subwindow,
&event.xbutton.x_root,
&event.xbutton.y_root,
&event.xbutton.x,
&event.xbutton.y,
&event.xbutton.state
);
printf("x=%d, y=%d, left=%d, middle=%d, right=%d\n", event.xmotion.x, event.xmotion.y, left, middle, right);
}
}
Sample output
x=470, y=969, left=1, middle=0, right=0
x=470, y=969, left=0, middle=0, right=0
x=467, y=969, left=0, middle=4, right=0
x=463, y=969, left=0, middle=0, right=0
x=444, y=971, left=0, middle=0, right=2
x=441, y=971, left=0, middle=0, right=0
I took this example of subclassing a Form's HWND as a starting point and then added in jrohde's code from from here that is designed to let you drag a Form by clicking anywhere on it (not on the caption bar). This code fails on the ReleaseCapture()line with this message: E2283 Use . or -> to call '_fastcall TCommonCustomForm::ReleaseCapture()
If i comment that line out the code runs and i can move the form by left mouse don and drag, but i can't let go of it. The mouse gets stuck to the form like flypaper. If i replace the ReleaseCapture() with a ShowMessage i can break out but that is obviously not the way to go...
What do i need to do allow that RestoreCapture() to run? This is Win32 app.
BELOW IS THE CODE i added to the original switch(uMsg) block:
// two int's defined above the switch statement
static int xClick;
static int yClick;
// new case added to the switch
case WM_LBUTTONDOWN:
SetCapture(hWnd);
xClick = LOWORD(lParam);
yClick = HIWORD(lParam);
break;
case WM_LBUTTONUP:
//ReleaseCapture(); // This is the problem spot <------------------------
ShowMessage("Up");
break;
case WM_MOUSEMOVE:
{
if (GetCapture() == hWnd) //Check if this window has mouse input
{
RECT rcWindow;
GetWindowRect(hWnd,&rcWindow);
int xMouse = LOWORD(lParam);
int yMouse = HIWORD(lParam);
int xWindow = rcWindow.left + xMouse - xClick;
int yWindow = rcWindow.top + yMouse - yClick;
SetWindowPos(hWnd,NULL,xWindow,yWindow,0,0,SWP_NOSIZE|SWP_NOZORDER);
}
break;
thanks, russ
From the error message you can derive that the compiler resolves the function ReleaseCapture() to TCommonCustomForm::ReleaseCapture(). But you want to call the Win32 API function ReleaseCapture(). Use ::ReleaseCapture(); instead of ReleaseCapture(); to enforce this.
If we take a very simple counter using ncurses:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
int main(void) {
struct timespec start;
clock_gettime(CLOCK_REALTIME, &start);
initscr();
cbreak();
nodelay(stdscr, TRUE);
{
int key = -1;
struct timespec delay, now;
do {
clock_gettime(CLOCK_REALTIME, &delay);
delay.tv_sec = 0;
delay.tv_nsec = 1000L * 1000L * 1000L - delay.tv_nsec;
nanosleep(&delay, NULL);
clock_gettime(CLOCK_REALTIME, &now);
mvprintw(1, 1, "%ld\n", (long)(now.tv_sec - start.tv_sec));
refresh();
key = getch();
if (key >= 0)
break;
} while (now.tv_sec - start.tv_sec < 60);
}
endwin();
return 0;
}
it aborts after pressing any key (OK, because of cbreak() using ctrl-C would always work without any extra effort...).
But we can make this more complicated, like adding a function to pause the counter or resetting it on the fly (+/- 1 second).
We definitely need a non-blocking keyboard input for this.
I wonder if it possible to do this in Gforth? OK, I know how to catch interrupts like SIGINT there, but something like above, working for any key or a any predetermined key?
Use key?, it returns a flag which is true if new input is available.
You can augment the following code as you see fit, but I think it explains the basic idea of running in a loop until a key is pressed.
: run-until-key ( -- )
0
begin
\ place your terminal code here
." Num:" dup . cr
1+
key? until drop ;
If you want to wait for a specific key, just add an if before the until:
...
key? if key 13 = else false then until
...
You can also add your timer there.
I am experiencing odd behavior when using GetKeyState (or GetAsyncKeyState, for that matter) in a console app. One aspect of the app is to ask the user for a file to open using GetFileOpen. At the end of the program, GetKeyState monitors the state of the spacebar. The GetKeyState (or GetAsyncKeyState) function never sets the high order bit whenever the spacebar is pressed. If I do not call GetOpenFile and then monitor GetKeyState, all works as expected.
Here are the two basic scenarios.
Scenario 1:
#include <windows.h>
int main(int argc, char *argv[])
{
char filename[ 512 ] = {0};
OPENFILENAME ofn = {0};
int filenameSize = 512;
char title[1000] = {0};
strcpy(title, "Open File");
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = null;
ofn.lpstrFile = filename;
ofn.nMaxFile = filenameSize;
ofn.lpstrFilter = "All files (*.*)\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpfnHook = NULL;
ofn.lpstrTitle = title;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
GetOpenFileName(&ofn); // filename obtained
WaitForSpaceBar(); // return value's upper bit is never set for
// GetKeyState(VK_SPACE);
return 0;
}
Scenario 2:
int main(int argc, char *argv[])
{
WaitForSpaceBar(); // returns immediately after spacebar is pressed
return 0;
}
WaitForSpaceBar code
void WaitForSpaceBar()
{
#define KEY_PRESSED_FLAG 1
SHORT spacePressed = GetKeyState(VK_SPACE);
printf("\nPress spacebar to continue...\n");
while (!(spacePressed & KEY_PRESSED_FLAG))
{
Sleep(1);
spacePressed = GetKeyState(VK_SPACE);
// for debugging purposes only
printf("spacePressed = 0x%04x\n", spacePressed);
}
}
The first scenario outputs "spacePressed = 0x0000" indefinitely regardless of how many times I press the spacebar.
The second scenario outputs "spacePressed = 0x0000" until the spacebar is actually pressed. Once pressed, the output is "spacePressed = 0xffffff81", and the program terminates.
Any ideas as to what is happening?
The GetKeyState function is useless if your are not pumping message.
From the documentation:
Remarks
The key status returned from this function changes as a thread reads
key messages from its message queue. The status does not reflect the
interrupt-level state associated with the hardware. Use the
GetAsyncKeyState function to retrieve that information.
Use the following code for your WaitForSpaceBar function (note the new value for KEY_PRESSED_FLAG):
void WaitForSpaceBar()
{
SHORT spacePressed = GetAsyncKeyState(VK_SPACE);
#define KEY_PRESSED_FLAG 0x8000
printf("\nPress spacebar to continue...\n");
while (!(spacePressed & KEY_PRESSED_FLAG))
{
Sleep(1);
spacePressed = GetAsyncKeyState(VK_SPACE);
// for debugging purposes only
printf("spacePressed = 0x%04x\n", spacePressed);
}
}
From the MSDN documentation, it looks like GetKeyState is only meaningful when your thread is pumping messages and calling it in response to a keyboard message.
The key status returned from this function changes as a thread reads key messages from its message queue.
I suspect that GetOpenFile spins up its own thread and that thread somehow becomes the main UI thread for your process (because it's the only one doing GUI work).
If you're using Windows API calls, you may as well use something console-specific like ReadConsole.
Update: I pasted the question code into VS 2010, and cannot reproduce the problem. The GetKeyState function is working as expected regardless of whether GetOpenFileName was called.
I would like to make a key press translator that would "convert" one key press to another, eg. Ctrl+T would be translated to Ctrl+X. I would like it to make "gobal"; to make it work in any application.
As a proof of concept I'm experimenting with the code below but it doesn't work. The problem is that when I capture a key press I send out another key press that is again captured by my code... I'm getting an infinite loop (the counter is there only to break out of the infinite loop).
How should I send out key press event from a key press event handler?
#include <stdio.h>
#include <X11/Xlib.h>
#include <xdo.h>
#include <X11/extensions/XTest.h>
int main(void)
{
Display *dpy = XOpenDisplay(0x0);
XEvent ev;
int counter;
xdo_t *xdo = xdo_new(NULL);
XGrabKeyboard(dpy, DefaultRootWindow(dpy), False,
GrabModeAsync, GrabModeAsync,CurrentTime);
for(counter = 0; counter < 10; counter++)
{
XNextEvent(dpy, &ev);
if(ev.type == KeyPress) {
XUngrabKeyboard(dpy, CurrentTime);
printf("%d %d\n", ev.xkey.keycode, ev.xany.send_event);
xdo_keysequence(xdo, CURRENTWINDOW, "A", 0);
}
}
return 0;
}