WinAPI计时器不发送WM_TIMER事件

时间:2015-11-15 20:30:16

标签: winapi timer

我在非常简单的程序中工作,动画形状运动。可以使用鼠标右键将动画切换到开/关模式。我正在窗口过程中创建计时器并等待WM_TIMER事件。但是在创建计时器(SetTimer的返回值为1)后,WM_TIMER情况永远不会到达(我在下一行设置断点来检测它)。 我的窗口程序:

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;

}

1 个答案:

答案 0 :(得分:4)

WM_PAINT处理程序中,您没有致电BeginPaint / EndPaint,这意味着您的窗口将始终标记为无效。这将生成连续的WM_PAINT消息流,这将阻止您的计时器工作,因为WM_TIMER消息仅在消息队列为空时生成。

有关控制何时生成WM_TIMER消息的基本算法,请参阅If my WM_TIMER handler takes longer than the timer period, will my queue fill up with WM_TIMER messages?