Pelles C forum

C language => Windows questions => Topic started by: czerny on February 04, 2015, 09:13:16 AM

Title: Sleep ahead of time
Post by: czerny on February 04, 2015, 09:13:16 AM
I have the following function:
Code: [Select]
void DeflateRect(RECT* rect)
{
rect->left++;
rect->top++;
rect->bottom--;
rect->right--;
}

#define BTN_NORMAL 0
#define BTN_PRESSED 1
#define BTN_DEFAULT 2

void PushMyButton(HDC dc, RECT *rect, int state)
{
UINT uType = DFCS_BUTTONPUSH;

if (state == BTN_NORMAL) // disabled
uType |= DFCS_INACTIVE;
if (state) // default or pressed
{
FrameRect(dc, rect, GetSysColorBrush(COLOR_WINDOWFRAME));
DeflateRect(rect);
}
if (state & BTN_PRESSED)
{
FrameRect(dc, rect, GetSysColorBrush(COLOR_BTNSHADOW));
DeflateRect(rect);
FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
}
else
{
DrawFrameControl(dc, rect, DFC_BUTTON, uType);
}

}

static void Main_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
RECT rc, rcc;

BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);

rcc.top = rcc.left = 10;
rcc.bottom = rcc.right = 42;

PushMyButton(ps.hdc, &rcc, 0);
Sleep(3000);
PushMyButton(ps.hdc, &rcc, 1);
//MessageBeep(-1);
Sleep(3000);
PushMyButton(ps.hdc, &rcc, &rcc), 0);
EndPaint(hwnd, &ps);
}
If the example runs as is, the first 'Sleep' takes effective 6s and the second 'PushMyButton' is invisible.
If I include the 'MessageBeep'  all is as intended, both 'Sleep' functions take 3s and the 3 states of my Button can be seen clearly.
What exactly happens here?
Title: Re: Sleep ahead of time
Post by: frankie on February 04, 2015, 09:44:52 AM
Maybe during the execution of MyBeep the message loop runs and executes messages dispatching? (Sleep stops whole thread)
Title: Re: Sleep ahead of time
Post by: czerny on February 04, 2015, 10:00:25 AM
Always this damned message loop problem!  >:(
Title: Re: Sleep ahead of time
Post by: frankie on February 04, 2015, 10:41:37 AM
I don't want be boring, but the good practice for GUI programs development is to have a single thread managing the GUI and executing short time consuming tasks. Where timings, and heavy computation is involved should be preferred a separate thread.
Title: Re: Sleep ahead of time
Post by: czerny on February 04, 2015, 10:55:39 AM
I will do this in real applications. Thank you!
But this was only a short test. And it would be overkill to implement several tasks for this.
Title: Re: Sleep ahead of time
Post by: DMac on February 04, 2015, 05:17:05 PM
As a matter of course in my GUI stuff I use the following (borrowed from VB) in the place where you used MessageBeep().

Code: [Select]
/// @brief Yields execution of the current thread so that
///         the operating system can process other events.
///
/// @returns VOID.
static VOID DoEvents(VOID)
{
    MSG Msg;
    while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

So with the example lets suppose we put the DoEvents() in PushMyButton() like so:

Code: [Select]
void DeflateRect(RECT* rect)
{
rect->left++;
rect->top++;
rect->bottom--;
rect->right--;
}

#define BTN_NORMAL 0
#define BTN_PRESSED 1
#define BTN_DEFAULT 2

void PushMyButton(HDC dc, RECT *rect, int state)
{
UINT uType = DFCS_BUTTONPUSH;

if (state == BTN_NORMAL) // disabled
uType |= DFCS_INACTIVE;
if (state) // default or pressed
{
FrameRect(dc, rect, GetSysColorBrush(COLOR_WINDOWFRAME));
DeflateRect(rect);
}
if (state & BTN_PRESSED)
{
FrameRect(dc, rect, GetSysColorBrush(COLOR_BTNSHADOW));
DeflateRect(rect);
FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
}
else
{
DrawFrameControl(dc, rect, DFC_BUTTON, uType);
}
DoEvents(); //Update the view by emptying the message queue
}

static void Main_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
RECT rc, rcc;

BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);

rcc.top = rcc.left = 10;
rcc.bottom = rcc.right = 42;

PushMyButton(ps.hdc, &rcc, 0);
Sleep(3000);
PushMyButton(ps.hdc, &rcc, 1);
Sleep(3000);
PushMyButton(ps.hdc, &rcc, &rcc), 0);
EndPaint(hwnd, &ps);
}

That should achieve the desired result.