Count number of mouse clicks C - c++

I have a C code that checks if the left buttom of the mouse has been pressed. It works fine but I want to use it to count how many times the button has been clicked and call to a function when the button has been clicked a random number of times.
This is the code:
LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int count = 0;
MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
if (pMouseStruct != NULL){
if (wParam == WM_LBUTTONDOWN)
{
count++;
printf("%d",count);
if (count==finalNum){ // user clicked random times the mouse so we launch the final function
printf("\ndone!\n");
final();
}
printf("clicked");
}
printf("Mouse position X = %d Mouse Position Y = %d\n", pMouseStruct->pt.x, pMouseStruct->pt.y);
}
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
DWORD WINAPI MyMouseLogger(LPVOID lpParm)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
// here I put WH_MOUSE instead of WH_MOUSE_LL
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, hInstance, NULL);
MSG message;
while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
UnhookWindowsHookEx(hMouseHook);
return 0;
}
void custom_delay(){
}
int main(int argc, char *argv[])
{
int count = 0;
HANDLE hThread;
DWORD dwThread;
//////Generate random number to call a function after rand() number of clicks
srand(time(NULL)); // Seed the time
int finalNum = rand() % (150 - 50) + 50; // Generate the number, assign to variable.
////////////////////////////////////////////////////////////////////////////
printf("%d", finalNum);
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MyMouseLogger, (LPVOID)argv[0], NULL, &dwThread);
if (hThread)
return WaitForSingleObject(hThread, INFINITE);
else
return 1;
}
}
The problem is that the count variable resets to 0 each time that a mouse event take place so I can't get a track of the times that the user clicks with the mouse.
The other problem is that I would like to generate a random number of times between 50 and 150 to call the final() function. How can I send that random number as an argument?
thank you for your help!

Since you declare count in a function it is allocated when the function is called and automatically deallocated as soon as the function returns, if you want count to last longer you could make it global (declare it outside the function).
Or you use the static key word in the delcaration of count, i.e. static int count = 0. When a variable is declared with static it's allocated for the length of the whole program. This way when the function returns count won't be unallocated.
Here's some more info about static -
What does static mean in ANSI-C
http://en.wikipedia.org/wiki/Static_variable
Now for the next part of your question, you can generate a pseudo random number in C by using the rand function. The function rand returns an integer from 0 to RAND_MAX which is a constant defined by the standard library. you can read more about rand here -
http://www.cplusplus.com/reference/cstdlib/rand/
Also if you want to store some random number and be able to access it from mouseProc you could give it global scope however be aware that it isn't always a good practice to make all your variables global.
http://en.wikipedia.org/wiki/Scope_(computer_science)

Related

WinAPI: repeatable check in a separate thread that notifies UI thread when check fails

My application has a separate thread that repeatably performs some check. If the check fails, the UI thread is notified (a MessageBox is displayed that requires user action what to do next).
Unfortunately, I have to use C++03 compiler (Visual Studio 2010 SP1) and boost library usage is prohibited. Therefore, I cannot use <thread>, <atomic>, <chrono>, etc. Thats why I have to use CreateThread, PostMessage and other WinAPI functions.
Here is my UI thread code (simplified). My main window is CMDIFrameWnd (from MFC):
//a struct with all parameters that is needed for a repeatable check
struct RepeatFunctionParameters
{
unsigned int repeatDelayInMilliseconds;
HWND checkIsFailedPostMessageWindowHandler;
UINT checkIsFailedPostMessageMessageId;
HANDLE checkIsPausedMutexHandle;
RepeatFunctionParameters(unsigned int _repeatDelayInMilliseconds, HWND _checkIsFailedPostMessageWindowHandler,
UINT _checkIsFailedPostMessageMessageId, HANDLE _haspSerialCheckIsPausedMutexHandle)
: repeatDelayInMilliseconds(_repeatDelayInMilliseconds), checkIsFailedPostMessageWindowHandler(_checkIsFailedPostMessageWindowHandler),
checkIsFailedPostMessageMessageId(_checkIsFailedPostMessageMessageId), haspSerialCheckIsPausedMutexHandle(_haspSerialCheckIsPausedMutexHandle)
{}
};
----------------------------
//creating a mutex to pause repeatable checks (whe Messagebox is displayed in UI thread)
HANDLE haspSerialCheckIsPausedMutexHandle = CreateMutex(NULL, FALSE, NULL);
//starting a separate thread with a check that repeats every 5000 milliseconds
auto params = new RepeatFunctionParameters(5000, myApp_hWnd, WM_USER_HASP_CHECK_FAILED, haspSerialCheckIsPausedMutexHandle);
CreateThread(NULL, 0, RepeatFunction, params, 0, NULL);
----------------------------
//special message that is sended when check is failed
#define WM_USER_HASP_CHECK_FAILED (WM_USER+0x150)
//mapping message handling function to that message
ON_MESSAGE( WM_USER_HASP_CHECK_FAILED, OnUserHaspCheckFailed)
//message handling function definition
afx_msg LRESULT OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam);
//message handling function body
LRESULT CMainWnd::OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam)
{
//capturing a mutex that signals to pause repeatable checks
WaitForSingleObject(haspSerialCheckIsPausedMutexHandle, INFINITE);
//show a messagebox that requires user action what to do next
if (::MessageBox(myApp_hWnd, ("Check is failed! Retry or cancel?").c_str(),
myApp_name, MB_RETRYCANCEL | MB_ICONERROR | MB_SYSTEMMODAL) == IDCANCEL)
//closing main windows if user clicks Cancel
pWnd->SendMessage(WM_CLOSE, 0x00010000, 0);
//releasing a mutex that signals to pause repeatable checks
ReleaseMutex(haspSerialCheckIsPausedMutexHandle);
return 0;
}
//WM_CLOSE handling function body
LRESULT CMainWnd::OnClose( WPARAM wParam, LPARAM lParam)
{
----------------------------
if( haspSerialCheckIsPausedMutexHandle != NULL)
CloseHandle( haspSerialCheckIsPausedMutexHandle);
----------------------------
CMDIFrameWnd::OnClose();
return NULL;
}
Here is my separate thread with repeatable check code (simplified):
DWORD WINAPI RepeatFunction(LPVOID parameters)
{
//getting parameters struct from a pointer
auto temp = static_cast<RepeatFunctionParameters*>(parameters);
//make a struct local copy (Further, all work goes only with it, regardless of the
state of the object, the pointer to which came as a function parameter)
auto params = *temp;
//deleting the structure, the pointer to which came as a function parameter
delete temp;
//repeatable check
while (true)
{
//checking a mutex that signals to pause repeatable checks. if it is free
//then there is no messagebox in UI thread and we can perform a check.
//if it is captured - wait until user clicks some button in that messagebox
WaitForSingleObject(params.haspSerialCheckIsPausedMutexHandle, INFINITE);
//and releasing it immediately
ReleaseMutex(params.haspSerialCheckIsPausedMutexHandle);
auto startMilliseconds = GetTickCount();
//performing a check
BOOL success = PerformACheck();
unsigned long defaultSleepDelay = 1000;
//if PerformACheck() will last longer than params.repeatDelayInMilliseconds,
//then check will be repeated after 1000 milliseconds, otherwise -
//after params.repeatDelayInMilliseconds minus PerformACheck() call time
auto endMilliseconds = GetTickCount();
if ((endMilliseconds - startMilliseconds) < params.repeatDelayInMilliseconds)
sleepDelay = params.repeatDelayInMilliseconds - (endMilliseconds - startMilliseconds);
//if check is failed
if (!success)
{
//sending a message with an identifier params.checkIsFailedPostMessageMessageId
//to a HWND params.checkIsFailedPostMessageWindowHandler so in it's
//handling function a messagebox with will be displayed and a mutex
//params.haspSerialCheckCanRunMutexHandle will be captured until
//user click some button in that messagebox
PostMessage(params.checkIsFailedPostMessageWindowHandler, params.checkIsFailedPostMessageMessageId, 0, 0);
//if check is failed then next check always repeats after 1000 milliseconds
sleepDelay = 1000;
}
Sleep(sleepDelay);
}
}
The result is that the main window becomes unresponsive after some time. It looks like my code has some logical mistake, or a memory leak.
I'm a newbie to C++ (and especially to outdated standards).

How do you write an IsPressed (a function that should only return true on first press)?

I need a function in a game loop that should only return true on first press.
I don't know which game I can give an example from which game is currently on the market, but I will explain this request in detail (I haven't played/can't play any of the modern games because I'm blind).
For example, there is an event you are listening to in the loop. When the user presses the S key, a text showing the last status of the character appears on the screen: Stamina, energy etc.
This loop can run thousands of times per second, as the loops depend on the speed of the hardware and the code you write.
We only need to detect the first press of the user. It should return false when the key is hold pressed. Otherwise, the last status of the user is shown thousands of times on the screen.
I am trying to provide this functionality using win32api. GetAsyncKeyState seems like the right option for this scenario but I don't understand how this can be done.
bool IsPressed(int key) {
return GetAsyncKeyState(key) & 1 != 0;
}
The function I wrote acts like a char event.
How can I write this?
I tried using other answers on StackOwerflow. However, I could not find an answer to the question I asked. Still, these answers helped me with some issues:
What is the fastest way to determine a key press and key holding in Win32?
While the GetAsyncKeyState can indicate via least significant bit whether the key has been pressed since the last call to this function, this behavior cannot be relied on.
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...
Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the preemptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application.
Therefore, you can't rely on the Windows API to do the bookkeeping for you. I suggest wrapping any key queries in a class that you'll use for any button presses.
class KeyInput {
public:
using key_type = int;
enum class Transition {
none,
pressed,
released,
};
struct PressResult {
bool pressed;
Transition transition;
};
PressResult state(key_type key) {
PressResult result;
result.pressed = (GetAsyncKeyState(key) < 0);
if (auto it = last_states_.find(key); it != last_states_.end()) {
if (last_states_[key] == result.pressed) {
result.transition = Transition::none;
}
else if (result.pressed) {
result.transition = Transition::pressed;
}
else {
result.transition = Transition::released;
}
}
else {
result.transition = Transition::none;
}
last_states_[key] = result.pressed;
return result;
};
private:
std::unordered_map<key_type, bool> last_states_{};
};
See it in action
Note
This will not capture transitions since the last iteration of your program. In order to handle that, you'll need your class to check every button press (that you care about) on every iteration.
After working on it a more, I realized that I cannot do this with GetAsyncKeyState or a similar function. I wrote something simple using Windows' callback and event system.
I didn't care about data race and other issues. You probably need to use a mutex but that depends on your code.
The code below keeps the state of the keys in an array. Changes are sent to the array with a function by the callback.
If you compile the program in console mode, you will see that it is printed to the console only once when you press A. It was exactly what I was looking for.
To compile you can use:
g++ minimal.cpp
You can press a to test it on a standard querty keyboard.
#include <iostream>
#include <windows.h>
#include <vector>
// We define a struct that holds the key state.
// firstPress will be updated by IsPressed.
struct keyState {
bool firstPress;
bool down;
};
// We have an Array-based collection of keys. Changes will be made by callback.
std::vector<keyState> allKeyStates(256);
void keyProcess(unsigned short key, bool down)
{
if(down) {
if(!allKeyStates[key].down) {
allKeyStates[key].down = true;
allKeyStates[key].firstPress = true;
}
return;
}
allKeyStates[key].down = false;
allKeyStates[key].firstPress = false;
}
bool IsPressed(unsigned short key)
{
if(allKeyStates[key].firstPress) {
allKeyStates[key].firstPress = false;
return true;
}
return false;
}
// forward decleration
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int main()
{
MSG msg = {0};
HWND handle;
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = "mini_windows_test";
if( !RegisterClass(&wc) )
return -1;
handle = CreateWindow(wc.lpszClassName, "Minimal Key handling application", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0, 640, 480, 0, 0, GetModuleHandle(NULL), NULL);
if(handle == NULL)
return -1;
while(GetMessage(&msg, NULL, 0, 0 ) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if(IsPressed(0x41)) {
std::cout << "Key A: it will only be print on the first press. Holding the key will not run repeatedly.\n";
}
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case WM_KEYDOWN:
keyProcess((unsigned short)wParam, true);
break;
case WM_KEYUP:
keyProcess((unsigned short)wParam, false);
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Apologize for the bady English and typos. You can edit my question and my answer if it works for you.
I do not know about C ++, but it certainly follows the same process in all languages, so you can set that pressure method to "if" and define a number that, by pressing its value, becomes one, And write. In "If" if the value of the number is equal to 1, do not do this again
In java, for example, it says:
int x = 0;
Button back = findViewById(R.id.button);
if(x == 0){
back.setOnClickListener(v -> {
//your code to do;
x = 1;
});
}else{}
that work in C++ too,

Weird array behavior in classes along with Windows DCs (C++)?

I'm working on creating a text based Windows game, and I am having a problem (I guess) with arrays not working the same within a class scope as within the main function. As far as I can tell it is some kind of interaction between a larger array class member (or large total amount of variables) and Windows creating a DC or other Windows API calls and/or variables.
What I want to do is a have a class called Map that contains a two dimensional array of Tiles. Tile is just a simple struct with basic tile information. I would like to make the array 256 x 256. This shouldn't be a problem as far as I can figure. Each Tile should be 32 bytes. That's 2 MB total for the array.
However, the game crashes when I declare a variable of the Map class in the main function, and then do things with Windows DCs. The return value seems to vary, In the current form, it usually returns 255, but I have also gotten "process terminated with status -1073741571". A 128 x 128 array does work in the class though. It also works fine if I remove either the array or the code in DisplayScreen. And as I implied, it also works if I just move the array of Tiles to the main function.
I'm honestly baffled. I have no idea what the difference would be. Nothing is going out of scope. Doesn't matter if it is a public or private member. Non dynamic class members should all get declared on the stack and it shouldn't work any differently in a class versus otherwise, right?
For other information, I am using Code::Blocks with the Min GW compiler. Everything is up to date. I am running Windows 10. My computer specs shouldn't be an issue either, but if it matters, I have 16 GB memory and a 4Ghz Athlon FX 8 core processor.
Edit: Here is the full code, so nothing is left out
Game.h:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
struct Tile
{
char chr[2];
int r[2], b[2], g[2];
bool solid;
bool translucent;
int opacity;
};
class Map
{
Tile tileMap[256][256];
public:
Map();
};
Map::Map()
{
int i, j;
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
main.cpp:
#include <windows.h>
#include "Game.h"
#define FRAMERATE 60
//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);
//Make the class name into a global variable
char strClassName[ ] = "GameApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd; //This is the handle for our window
MSG messages; //Here messages to the application are saved
WNDCLASSEX wndClassEx; //Data structure for the windowclass
Map test;
DWORD sysTimer;
DWORD sysPrevTime = 0;
DWORD timerDelta = 1000 / FRAMERATE;
//Get a handle for the whole screen
HDC hDC = GetDC(NULL);
//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL; //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));
//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;
//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName, //Class name
"Game Test", //Title Text
WS_OVERLAPPEDWINDOW, //default window type
0, //X pos of window at top left
0, //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP, //Child-window to desktop
NULL, //No menu
hThisInstance, //Program Instance handler
NULL); //No Window Creation data
//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);
//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}
TranslateMessage(&messages);
DispatchMessage(&messages);
}
sysTimer = timeGetTime();
if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}
}
}
//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}
void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);
HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);
SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));
//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World #", 15);
//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);
//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);
DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}
It crashes with even one instance of something creating a DC. It works fine otherwise creating and destroying the DCs and displaying the bitmap over and over again even if I leave it for an hour. Once I create that class with the large array in it though, it just dies.
I actually used to have the Display function as a class function and I moved it out because I thought that was the problem, but it wasn't.
Interestingly, if I change the declaration from 'Map test;' to 'Map* test = new Map;' and change the rest of the program appropriately, it works. Honestly though, doing that just seems kind of dumb, and I think that would slow everything down if I don't have a good reason to put everything on the heap. Plus, I don't like bandages. If there is a problem I'd rather fix it.
Any ideas?
You have a stack overflow (the condition, not the website).
The problem can be reproduced in this program:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}
It fails because it reaches stack limit.
Also tileMap[i][j].chr[2] is out of bound. It is declared as char chr[2]; valid index is 0 and 1. It can only go up to tileMap[i][j].chr[1]
Ditto b[], r[], and g[]
Change the Map class so that it allocates memory on heap and fix chr:
class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};
Map::Map()
{
int i, j;
tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];
for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X'; //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}

C++ Animating a button with MoveWindow()

I am new to C++ and seem to be stuck. I basically have a Window and a Button inside it(also created with CreateWindow()). I want to have the button moving on the X axis, I tried doing with MoveWindow() but I cant seem to do the animation effect. I tried writing it in a for loop but I have not found what to use to delay the animation. I would appreciate any help.
for (int i = 0; i < 50; i++) {
MoveWindow(g_MovingDot, i, ButtonTop, ButtonWidth, ButtonHeight, true);
//Delay it somehow
}
Would this be the right way to do it? I just want the button to move slowly to the right.
Use the SetTimer function to be notified when the time-out value is elapse.
Implement a function with the signature
VOID (CALLBACK* TIMERPROC)(HWND, UINT, UINT_PTR, DWORD);
and pass a function pointer to SetTimer, to register a callback procedure .
Use a global control variable, which controls the animation of the window. In the following code snippet the control variable is named i_g.
When the timer is elapsed, then the callback procedure is called. Increment the control variable, slightly move the dialog element and restart the timer, until the final position is reached.
The animation time is controlled by the number of animation steps and the time interval of a single step.
int g_i=0;
void CALLBACK BtnTimer( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
{
KillTimer( hwnd, idEvent );
if ( g_i < 50 )
{
MoveWindow(g_MovingDot, i, ButtonTop, ButtonWidth, ButtonHeight, true);
g_i ++;
SetTimer( hwnd, idEvent, 100 /* time milliseconds */, &BtnTimer );
}
}
void AnimateButton( HWND hDialogWnd //* HWND from Dialog */)
{
g_i = 0;
SetTimer( hDialogWnd, 0 /* idEvent */, 100 /* time milliseconds */, &BtnTimer );
}

Finish a thread when condition is produced. C/C++

I have a C code that checks if the left buttom of the mouse has been pressed. It works fine but I don't know how to unhook and exit the current thread after calling the final() function.
This is the code:
LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static int count = 0;
static int finalNum;
if (count==0){
//////Generate random number
srand(time(NULL)); // Seed the time
finalNum = rand() % (150 - 50) + 50; // Generate the number, assign to variable.
////////////////////////////////////////////////////////////////////////////
}
//int count = 0;
MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
if (pMouseStruct != NULL){
if (wParam == WM_LBUTTONDOWN)
{
count++;
printf("%d",count);
if (count==finalNum){ // user clicked random times the mouse so we launch the final function
printf("\ndone!\n");
final();
}
printf("clicked");
}
printf("Mouse position X = %d Mouse Position Y = %d\n", pMouseStruct->pt.x, pMouseStruct->pt.y);
}
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
DWORD WINAPI MyMouseLogger(LPVOID lpParm)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
// here I put WH_MOUSE instead of WH_MOUSE_LL
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, hInstance, NULL);
MSG message;
while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
UnhookWindowsHookEx(hMouseHook);
return 0;
}
void custom_delay(){
}
int main(int argc, char *argv[])
{
int count = 0;
HANDLE hThread;
DWORD dwThread;
//////Generate random number to call a function after rand() number of clicks
srand(time(NULL)); // Seed the time
int finalNum = rand() % (150 - 50) + 50; // Generate the number, assign to variable.
////////////////////////////////////////////////////////////////////////////
printf("%d", finalNum);
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MyMouseLogger, (LPVOID)argv[0], NULL, &dwThread);
if (hThread)
return WaitForSingleObject(hThread, INFINITE);
else
return 1;
}
printf("Keep going");
}
I've tried with ExitThread(0); but it closes all the threads and not only the MyMouseLogger process to print "Keep going".
How should I do it?
thank you for your help!
You can use PostThreadMessage to send a WM_QUIT to the thread, which will cause its message loop to exit.
This isn't really related to hooks as such; you are rather just asking how to safely stop a thread from running.
ExitThread() is never a good choice. So implement your own way to safely stop the thread. In this case, it can be done by for example creating an event through CreateEvent() before creating the thread. Then have your thread check for this event each time in the loop:
while (WaitForSingleObject(hevent_stopthread, 0) != WAIT_OBJECT_0 &&)
GetMessage(&message, NULL, 0, 0))
where hevent_stopthread it the HANDLE to your custom event.
Then simply set this event from the final() function. Your main() function will wait until the thread has finished by its own, by returning 0. Once that happens, you can clean up the event with a call to CloseHandle().