automated mouse clicks make screen go blank - c++

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.

Related

Implementing WM_QUERYENDSESSION

I've just started programming in C++ and I have a lot of fun fiddeling around. But right now I have hit a brick wall for me: the WM_QUERYENDSESSION. I have no idea how to implement it. Let me explain how my code should work.
I have a txt document where I write down the time in days, hours, minutes and seconds. My program reads this txt and converts them into seconds. If the seconds are negative, a message box will appear. If they are positive, my program will get the current system time. When the user decides to shut down the PC, my program should get the current system time again and calculate the elapsed-seconds from start to end. The program now calculates the difference between the seconds from my txt document and the elapsed-seconds, converting this back to my days, hours, minutes, seconds format and re-write them back into my txt document.
I tested my code with a manual stop, just worked fine. I just have to implement the WM_QUERYENDSESSION. I thought about a while-loop with a variable that's true in the beginning and in this loop my program should check if the lParam (I think) is 0. If it is, set the loop variable to false, run the rest of the program and close it.
I hope, some of you can help me and explain how it works and what something does.
Note: Some codelines are going to be deleted. They were just to see if he read the text file the way i wanted it to for example.
I already searched for examples for that but i never understood exactly how to do it. The Microsoft website didn't help me aswell
#include <iostream>
#include <ctime>
#include <string>
#include <cmath>
#include <fstream>
#include <chrono>
#include <windows.h>
using namespace std;
double k; //Get leftover time from txt doc//
int s; //Seconds//
int m; //Minutes//
int h; //Hours//
int d; //Days//
int t; //Var containing new leftover time//
bool z = true; //Loop variable//
int main()
{
ifstream Check ("Test.txt");
Check >> d; //Writing days from txt doc to d//
Check >> h; //Writing hours from txt doc to h//
Check >> m; //Writing minutes from txt doc to m//
Check >> s; //Writing seconds from txt doc to s//
cout << d << "\n" << h << "\n" << m << "\n" << s << "\n";
//Display leftover time; will be deleted//
k = (s + 60*m + 3600*h + 24*3600*d);
//Converting days, hours, minutes and seconds into seconds//
cout << k << "\n";
//Displaying k; will be deleted//
if (k <= 0) //Show messagebox when k <= 0//
{
MessageBox(0,
"Textmessage",
"Texttitle",
MB_OK | MB_ICONEXCLAMATION); //Support MessageBox//
}
auto start = std::chrono::system_clock::now();
//Get current time starting the program//
while (z = true)
{
if () {
}
};
auto end = std::chrono::system_clock::now();
//Get current time ending the program//
std::chrono::duration<double> elapsed_seconds = end-start;
//Calculate difference between start and end//
t = (k-round(elapsed_seconds.count()));
//Calculate time difference in seconds//
//Converting seconds into days, hours, minutes, seconds//
d = t / (24*3600);
h = (t / 3600) % 24;
m = (t / 60) % 60;
s = t % 60;
//End of converting//
ofstream Write ("Test.txt");
Write << d << "\n" << h << "\n" << m << "\n" << s;
//Write all values back to txt doc//
}
Since you don't have a window, or a window handle, or a message pump for that window, you should use the console functions. In particular, you should register a handler with SetConsoleCtrlHandler to receive CTRL_CLOSE_EVENT.
WM_QUERYENDSESSION is a "Windows Message", part of Win32 API.
To receive and process such messages you need to put a message loop in your program.
This loop should be put after all your initialization code, because it will not end until the user exits your program.
Usually, the loop just dispatches the message to GUI windows, and each window has a function attached that handles relevant messages.
This is what is shown in the example in the link.
Your program is different, because you do not have any windows, and only run in background.
So your loop should look something like this:
// Start the message loop.
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, WM_QUERYENDSESSION, WM_QUERYENDSESSION )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
DispatchMessage(&msg); //just in case
//if you want to check that user is logging off:
if (msg.lParam & ENDSESSION_LOGOFF > 0) {
//do the time thing you want, then exit the program
}
}
}
Your program will only look for one message and handle it directly in the loop.
I left the dispatch function in because I could not find any documentation about what would happen if a message is retrieved and not dispatched.
You can try removing it, but it may cause issues when the user tries to shutdown the computer, because the OS needs all apps to return non-zero value (TRUE) for this message to close cleanly.
EDIT: The lParam of the message is a bit mask, so should not be compared to possible values directly (it is in the doc, but easy to miss).
Also, since your application does not have a permanent window on screen, it may be a better choice to use a different method to detect shutdown, such as this:
BOOL WINAPI ShutdownHandler(DWORD dwCtrlType) {
//you can delete the second condition if you only care about shutdown
if (dwCtrlType == CTRL_SHUTDOWN_EVENT || dwCtrlType == CTRL_LOGOFF_EVENT) {
//do the date and time stuff
return TRUE;
}
return FALSE;
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd) {
//you code to read the file
BOOL res = SetConsoleCtrlHandler(ShutdownHandler, TRUE);
if (res) {
while (true) { Sleep(10000); } //note your app will never exit like this
//maybe add some more logic to allow user to shut it down
} else {
//handle the error, you will not get shutdown notifications in this case!
}
}
Another option is to turn your app in to a service and then use RegisterServiceCtrlHandlerEx to get shutdown notifications.

How can I watch multiple variables while debugging without stopping at breakpoints?

Suppose I have a complex C++ application that I need to debug with a lot of variables. I wanna avoid using std::cout and printf approaches (below there's an explaination why).
In order to explain my issue, I wrote a minimal example using chrono (This program calculates fps of its while cycle over time and increment i_times counter until it reaches 10k):
#include <chrono>
using chrono_hclock = std::chrono::high_resolution_clock;
int main(int argc, char** argv){
bool is_running = true;
float fps;
int i_times=0;
chrono_hclock::time_point start;
chrono_hclock::time_point end;
while(is_running){
start = chrono_hclock::now();
// Some code execution
end = chrono_hclock::now();
fps=(float)1e9/(float)std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count());
if(++i_times==10000) is_running=false;
}
return 0;
}
I would like to debug this program and watch for fps and i_times variables continuosly over time, without stopping execution.
Of course I can simply use std::cout, printf or other means to output variables values redirecting them to stdout or a file while debugging and those are OK for simple types, but I have multiple variables which data type are struct-based and it would be creepy, time expensive and code bloating to write instructions to print each one of them. Also my application is a realtime video/audio H.264 encoder streaming with RTSP protocol and stopping at breakpoints means visualizing artifacts in my other decoder application because the encoder can't keep up with the decoder (because the encoder hit a breakpoint).
How can I solve this issue?
Thanks and regards!
The IDE I'm currently using for developing is Visual Studio 2019 Community.
I'm using the Local Windows Debugger.
I'm open to using alternative open source IDEs like VSCode or alternative debugging methods to solve this problem and/or to not be confinated into using a specific IDE.
To watch for specific multiple variables in VS I use the built-in Watch Window. While debugging with LWD, I add manually variables by right-clicking them in my source code and click Add Watch. Then those are showed in the Watch Window (Debug-Windows-Watch-Watch 1):
However I can only watch this window contents once I hit a breakpoint I set inside the while cycle, thus blocking execution, so that doesn't solve my issue.
You can use nonblocking breakpoint. First add the breakpoint. Then click on breakpoint settings or right click and select action.
Now you add a message like any string that is suggestive for you. And in brackets include the values to show, for instance
value of y is {y} and value of x is {x}
In the image is shown the value of i when it hits the breakpoint. Check the "Continue code execution" so breakpoint will not block execution. The shape of your breakpoint will change to red diagonal square. You can add also specific conditions if you click the Conditions checkbox.
Now while debugging all these debug messages will be shown in the output window:
In the above image it is showing the following message:
the value of i is {i}
By checking the "Conditions" you can add specific conditions, for instance i%100==0 and it will show the message only if i is divisible by 100.
This time your breakpoint will be marked with a + sign, meaning it has condition. Now while debugging there will be shown the i only when divisible by 100, so you can restrict the output to some more meaningful cases
The strict answer is "no" but...
I think I understand what you're trying to accomplish. This could be done by dumping the watched variables into to shared memory which is read by 2nd process. A watch and a break point in the 2nd would allow you to see the values in Visual Studio without interrupting the original application.
A few caveats:
UAC must be admin on both sides to open the memory handle
This wouldn't work with pointers as the 2nd program only has access to the shared memory
Windows anti-virus went nuts for the first few times I
ran this but eventually calmed down
Worker application:
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <windows.h>
#include <chrono>
#include <thread>
PCWSTR SHARED_MEMORY_NAME = L"Global\\WatchMemory";
struct watch_collection // Container for everything we want to watch
{
int i;
int j;
int k;
};
using chrono_hclock = std::chrono::high_resolution_clock;
int main(int argc, char** argv)
{
bool is_running = true;
float fps;
int i_times = 0;
chrono_hclock::time_point start;
chrono_hclock::time_point end;
HANDLE map_file;
void* shared_buffer;
// Set up the shared memory space
map_file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(watch_collection), SHARED_MEMORY_NAME);
if (map_file == NULL)
{
return 1; // Didn't work, bail. Check UAC level!
}
shared_buffer = MapViewOfFile(map_file, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(watch_collection));
if (shared_buffer == NULL)
{
CloseHandle(map_file); // Didn't work, clean up the file handle and bail.
return 1;
}
// Do some stuff
while (is_running) {
start = chrono_hclock::now();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
for (int k = 0; k < 10000; k++) {
watch_collection watches { i = i, j = j, k = k };
CopyMemory(shared_buffer, (void*)&watches, (sizeof(watch_collection))); // Copy the watches to the shared memory space
// Do more things...
}
}
}
end = chrono_hclock::now();
fps = (float)1e9 / (float)std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
if (++i_times == 1000000) is_running = false;
}
// Clean up the shared memory buffer and handle
UnmapViewOfFile(shared_buffer);
CloseHandle(map_file);
return 0;
}
Watcher application:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
PCWSTR SHARED_MEMORY_NAME = L"Global\\WatchMemory";
struct watch_collection // Container for everything we want to watch
{
int i;
int j;
int k;
};
int main()
{
HANDLE map_file;
void* shared_buffer;
bool is_running = true;
watch_collection watches; // Put a watch on watches
// Connect to the shared memory
map_file = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, SHARED_MEMORY_NAME);
if (map_file == NULL)
{
return 1; // Couldn't open the handle, bail. Check UAC level!
}
shared_buffer = MapViewOfFile(map_file, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(watch_collection));
if (shared_buffer == NULL)
{
CloseHandle(map_file);
return 1;
}
// Loop forever
while (is_running)
{
CopyMemory((void*)&watches, shared_buffer, (sizeof(watch_collection)));
} // Breakpoint here
UnmapViewOfFile(shared_buffer);
CloseHandle(map_file);
return 0;
}

Window Hangs And Freezes [SDL 2]

I have a text file full of information on where to place tiles in a game i'm making, the fastest way to access this information is with a for loop. But whenever i use the for loop to get through all the information it freezes the program for about 12 seconds, in those 12 i cant move the window, nothing on the renderer updates/is drawn, and then when i click on the window it breaks and says "window name (Not Responding)". I tried using a while loop but it still does the same thing.
How can i loop through bigger numbers (there are about 4,000 tiles in the level) without the program freezing/hanging on me? I'm just using SDL 2, no OpenGL involved.
int tiles = 4000;
int x[4000];
int y[4000];
tile obj[4000];
for(int i = 0; i < tiles; i++)
{
x[i] = txt.x;
y[i] = txt.y;
obj[i].Load(x[i], y[i]);
obj[i].Add();
SDL_RenderClear(ren);
LoadScreen();
SDL_RenderPresent(ren);
}
Thanks.
You need to create another thread.
It's good idea to wait for all data to load before starting game, so during load, you don't need to render anything. Even with this approach, it is better to use another thread and don't keep "UI Thread" busy. During load time your UI would be mostly disabled except a cancel button that will stop loading thread.
#include <process.h>
bool bReady;
void LoadTiles(void* pArg)
{
// Load Data here
*((int*)pArg) = 0;
///////////////////
bReady = true;
}
void main()
{
btnStart.SetEnabled(false);
bReady = false;
int iTarget;
uintptr_t hLoadingThread = _beginthread(LoadTiles, 0, &iTarget);
while (true) // usually you pick a message here
{
if (bReady)
btnStart.SetEnabled(true);
}
}
This is just a very simple example, multi-threading needs a lot of work and study!

My program checking for mouse click can be run just once

I have made this program in Turbo C++ wherein when the user clicks inside the square that comes on screen, the program should exit. The program works fine if I run it once. But when I run it again, it exits as soon as mouse is inside the square. It does not wait for the click. I think it is something to do with resetting the mouse.
#include<process.h>
#include<conio.h>
#include<graphics.h>
#include<dos.h>
union REGS in,out;
void main()
{
int gdriver = DETECT,gmode;
int xp,yp,cl=0;
int x,y;
initgraph(&gdriver,&gmode,"C:\\Turboc3\\BGI");
x=getmaxx()/2;
y=getmaxy()/2;
in.x.ax=4;
in.x.cx=10;
in.x.dx=10;
int86(51,&in,&out);
in.x.ax=1;
int86(51,&in,&out);
setcolor(RED);
rectangle((x-100),(y-100),x,y);
in.x.ax=3;
while(1)
{
int86(51,&in,&out);
cl=out.x.bx;
xp=out.x.cx;
yp=out.x.dx;
if(((xp>=x-100)&&(xp<=x))&&((yp>=y-100)&&(yp<=y)))
if(cl==1)
{
cl=0;
exit(1);
}
}
}
OUTPUT
P.S. I already know that Turbo C++ is an "ancient compiler" and I am well aware of the existence of other modern compilers, but I am forced to use this compiler.
Ok I have figured out the problem. When I start the program again, instead of dragging the mouse inside the square button straight away, if I click outside the square button first and then move towards the square button, the problem doesn't happen.
Basically, when the program starts for the 2nd time, the mouse starts with click=1 instead of click=0. I can't find out how to fix this though..
I've found this, dunno if that would help any. Depending what your OS you're running... or is that DosBox? It uses BGI to set graphic mode which may not work if you run it from x64 windows, should work from DosBox(at least, Turbo Pascal's version does). It is curious, that program does one dummy reading of mouse status after making cursor visible, to flush the registers. Is that the gotcha you're hit by?
#include<graphics.h>
#include<conio.h>
#include<dos.h>
union REGS i, o;
int initmouse()
{
i.x.ax = 0;
int86(0X33,&i,&o);
return ( o.x.ax );
}
void showmouseptr()
{
i.x.ax = 1;
int86(0X33,&i,&o);
}
void getmousepos(int *button, int *x, int *y)
{
i.x.ax = 3;
int86(0X33,&i,&o);
*button = o.x.bx;
*x = o.x.cx;
*y = o.x.dx;
}
main()
{
int gd = DETECT, gm, status, button, x, y;
char array[50];
initgraph(&gd,&gm,"C:\\TC\\BGI");
settextstyle(DEFAULT_FONT,0,2);
status = initmouse();
if ( status == 0 )
printf("Mouse support not available.\n");
else
{
showmouseptr();
getmousepos(&button,&x,&y);
while(!kbhit())
{
getmousepos(&button,&x,&y);
if( button == 1 )
{
button = -1;
cleardevice();
sprintf(array,"Left Button clicked x = %d y = %d",x,y);
outtext(array);
}
else if( button == 2 )
{
button = -1;
cleardevice();
sprintf(array,"Right Button clicked x = %d y = %d",x,y);
outtext(array);
}
}
}
getch();
return 0;
}
You're doing what my boss called jokingly "Computer necrophilia". Those old systems had all kind of quirks. There were reasons why programmers of old where maniacal about initializing variables. You could run into issue that if you declare a long int variable, then assigning to it a long value, then a short value, then only lower word will be set in second case - all because compiler wasn't "casting" short to long implicitly, it was just copying binary image to the same address.
I have faced the same problem recently and the cause is DOSBox, more precisely Turbo C++ IDE running in DOSBox. Try exiting the IDE and runnning your compiled program from the command line, it will work fine. Or try a virtualbox MS-DOS machine, it will work fine even from the IDE.

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.