C++ Animating a button with MoveWindow() - c++

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 );
}

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).

Count number of mouse clicks 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)

How to check mouse is not moved from last 5 seconds?

I'm working on a task for my game program, in which I want to hide my mouse after 10 seconds from my screen. However I'm able to check the mouse move condition...
Here is my code..
using namespace std;
HHOOK g_hMouseHook;
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
PMSLLHOOKSTRUCT pmll = (PMSLLHOOKSTRUCT) lParam;
switch (wParam)
{
case WM_MOUSEMOVE:
printf("Mouse has been moved\n");
break;
}
}
return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
}
int _tmain(int argc, _TCHAR* argv[])
{
MSG msg;
g_hMouseHook = SetWindowsHookEx( WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(NULL), 0 );
if (!g_hMouseHook)
printf("err: %d\n", GetLastError());
while ( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(g_hMouseHook);
return (int) msg.wParam;
}
I'm doing it by using hook and it is displaying the mouse movement successfully.
Now I'm searching for an option with which I can also check that my mouse has not been moved.
*one thing I'm making it on console.
I've changed the mouse cursor or the hide by using LoadCursorfromFile and it's working properly.
Please share your opinions on to check when the mouse is not moving.
Call TrackMouseEvent to set up an idle time of 5000 milliseconds. You'll get a WM_HOVER message after 5 seconds. You could reset the timer on every keypress, but that's a bit inefficient. Instead, on every keypress you should update a lastKeyPressedTime variable. Now, if WM_HOVER arrives after 5 seconds, you check to see if the last keypress is 5 seconds ago. If it is, you have neither keyboard nor mouse input an can remove the mouse.
If you had keyboard input in the last 5 seconds while the mouse was idle, you should reset the TrackMouseEvent. If you're lazy, reset it to 5 seconds again. If you're being accurate, you have to get a bit more creative.
Perhaps GetLastInputInfo is what you need MSDN here.
For example, to get the elapsed milliseconds since the last mouse move or key press, you might have a function like this:
DWORD GetIdleTime()
{
LASTINPUTINFO pInput;
pInput.cbSize = sizeof(LASTINPUTINFO);
if (!GetLastInputInfo(&pInput))
{
// report error, etc.
}
// return idle time in millisecs
return pInput.dwTime;
}

SetTimer function in a dll file

I'm writing a plugin for the musicplayer named MusicBee.
The plugin is for the Logitech G keyboards LCD.
Now I will look at buttons activity every 30ms so everyting is fast when pressing on it.
I will use the setTimer function of windows.h but I can't get it to work in my dll file.
Can someone help me with this little problem??
The code I have is (TimerProc function is a static function):
Logitech * Logitech::LogitechObject;
Logitech::Logitech(): stopthread(false), firstTime(true), position(0), duration(0)
{
LogitechObject = this;
SetTimer(NULL, 1, 30, &Logitech::TimerProc);
}
Logitech::~Logitech()
{
stopthread = true;
this->state = StatePlay::Undefined;
timerThread.detach();
}
VOID CALLBACK Logitech::TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
LogitechObject->time = 0;
LogitechObject->m_lcd.SetProgressBarPosition(LogitechObject->progressbar, static_cast<FLOAT>(100));
LogitechObject->m_lcd.Update();
SetTimer(NULL, 1, 30, &Logitech::TimerProc);
}
In order SetTimer to work the application should run "message pump" loop ( GetMessage()/DispatchMessage() ). Without it WM_TIMER message will not be delivered and so your TimerProc will not be invoked.
Use CreateTimerQueueTimer() instead.

Win32 function for scheduled tasks in C++

I have a function in C++ that needs to be called after a period of time and this task is repeated. Do you know any built-in function or sample code in Win32 or pthread?
Thanks,
Julian
How about SetTimer.
Create a wrapper function to use as the callback for set timer.
Wrapper function calls your function.
After your function finishes, wrapper function calls SetTimer again to re-set the timer.
Just as a side note, I hope that you aren't doing something in code which could be done via the OS. (I don't know enough about your requirements to say, but I thought I'd point it out).
Things such as task-scheduler (windows) are made for scheduling recurring tasks, and they often do a better job than hand-rolled solutions.
SetTimer!
An example:
#include <windows.h>
#include <stdio.h>
void CALLBACK scheduled_task_1 (HWND hwnd, UINT msg, UINT id, DWORD time)
{
puts("Executing scheduled_task_1 every half-second event");
}
void CALLBACK scheduled_task_2 (HWND hwnd, UINT msg, UINT id, DWORD time)
{
puts("Executing scheduled_task_2 every two seconds event");
}
void CALLBACK scheduled_task_3 (HWND hwnd, UINT msg, UINT id, DWORD time)
{
puts("Executing scheduled_task_3 24 hours event");
}
void messageLoop(void) {
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
DispatchMessage( &msg );
}
int main(void)
{
while(true)
{
SetTimer (NULL, 0, 500, scheduled_task_1); /* every half-second */
SetTimer (NULL, 0, 2000, scheduled_task_2); /* every two seconds */
SetTimer (NULL, 0, 60*60*24*1000, scheduled_task_3); /* after 24 hours or 86400000 milliseconds */
messageLoop();
}
return 0;
}