Reputation: 351
I'm workin at very simple program that animate shape movement. Animation can be switched to on/off mode using right mouse button. I'm creating timer in window procedure and waiting for WM_TIMER event. But after creating timer (return value of SetTimer is 1) WM_TIMER case never reaching (i'm set break point at next line to detect it). My window procedure:
fn CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT {
PAINTSTRUCT ps;
RECT win;
GetClientRect(hWnd, &win);
int w = win.right - win.left;
int h = win.bottom - win.top;
static COLORREF shape_color = RGB(0, 255, 255);
static int x = 50, y = 50;
static int r = 40;
int step = 50;
static bool animation = false;
switch (message) {
case WM_LBUTTONDOWN:
GetColorDlg(hWnd, shape_color);
break;
case WM_RBUTTONDOWN:
animation = !animation;
if (animation) {
timer_id = SetTimer(hWnd, 1, 500, NULL);
}
else {
KillTimer(hWnd, timer_id);
}
break;
case WM_TIMER:
++x_offset;
y_offset = sin(x_offset) * 20;
case WM_KEYDOWN: {
if (!animation) {
switch (wParam) {
case VK_UP:
y -= step;
break;
case VK_DOWN:
y += step;
break;
case VK_LEFT:
x -= step;
break;
case VK_RIGHT:
x += step;
break;
}
}
y += y_offset;
x += x_offset;
x = x + r > w ? w - r : x - r < 0 ? r : x;
y = y + r > h ? h - r : y - r < 0 ? r : y;
RECT invalid_area;
invalid_area.top = y + r;
invalid_area.left = x - r;
invalid_area.bottom = y - r;
invalid_area.right = x + r;
InvalidateRect(hWnd, &invalid_area, true);
break;
}
case WM_SIZE: {
if (x + r > w)
x = w - r;
if (y + r > h)
y = h - r;
break;
}
case WM_PAINT: {
//HDC hdc = BeginPaint(hWnd, &ps);
HDC hdc = GetDC(hWnd);
HBRUSH shape_brush = CreateSolidBrush(shape_color);
HPEN shape_pen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
SelectObject(hdc, shape_pen);
SelectObject(hdc, shape_brush);
Circle(hdc, x, y, r);
DeleteObject(shape_pen);
DeleteObject(shape_brush);
DeleteObject(hdc);
ReleaseDC(hWnd, hdc);
//EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Upvotes: 0
Views: 405
Reputation: 37122
In your WM_PAINT
handler you're not calling BeginPaint
/ EndPaint
, which means your window will always remain marked as invalid. This will generate a continuous stream of WM_PAINT
messages, and this stops your timer from working because WM_TIMER
messages are only generated when the message queue is empty.
See If my WM_TIMER handler takes longer than the timer period, will my queue fill up with WM_TIMER messages? for the basic algorithm that controls when WM_TIMER
messages are generated.
Upvotes: 4