NO

Author Topic: Sleep ahead of time  (Read 4345 times)

czerny

  • Guest
Sleep ahead of time
« 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?

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Sleep ahead of time
« Reply #1 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)
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

czerny

  • Guest
Re: Sleep ahead of time
« Reply #2 on: February 04, 2015, 10:00:25 AM »
Always this damned message loop problem!  >:(

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Sleep ahead of time
« Reply #3 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.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

czerny

  • Guest
Re: Sleep ahead of time
« Reply #4 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.

Offline DMac

  • Member
  • *
  • Posts: 272
Re: Sleep ahead of time
« Reply #5 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.
No one cares how much you know,
until they know how much you care.