Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
151 views
in Technique[技术] by (71.8m points)

c - Win32 program double buffering doesn't work

I think this is a basic double buffering win32 program. At the start of launching, it works well, but about 1 minute later (on my computer), it gets stuck. The time it takes to get stuck increases as you set the third parameter of SetTimer(hwnd, 1, 2, NULL) to a bigger value.

I have googled and checked for an answer for almost two hours, but I can't find where the bug is.

Here is the code:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("HelloWin");
    HWND         hwnd;
    MSG          msg;
    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("Something Wrong!"),
            szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,      // window class name
        TEXT("DoubleBuffer"), // window caption
        WS_OVERLAPPEDWINDOW,        // window style
        GetSystemMetrics(SM_CXSCREEN) / 2,
        GetSystemMetrics(SM_CXSCREEN) / 4,
        GetSystemMetrics(SM_CXSCREEN) / 3,
        GetSystemMetrics(SM_CXSCREEN) / 3,
        NULL,                       // parent window handle
        NULL,                       // window menu handle
        hInstance,                  // program instance handle
        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HBITMAP hBitmap, moldbmp;
    static HDC     hdcMem;
    static int     cxClient, cyClient;
    HDC            hdc;
    HMENU          hMenu;
    int            x, y;
    PAINTSTRUCT    ps;
    SIZE           size;

    static int  i = 50, j = 70;
    static BOOL bFlipUD = TRUE, bFlipLR = TRUE;
    static BOOL bTimerRunning = TRUE;

    switch (message)
    {
    case WM_CREATE:
        hdc = GetDC(hwnd);
        hdcMem = CreateCompatibleDC(hdc);

        hBitmap = CreateCompatibleBitmap(hdc, 750, 824);

        ReleaseDC(hwnd, hdc);

        moldbmp = SelectObject(hdcMem, hBitmap);
        SetTimer(hwnd, 1, 2, NULL);

        return 0;

    case WM_TIMER:

        if (bFlipUD)
        {
            i += 20;
            if (i >= 200)
            {
                bFlipUD ^= TRUE;
            }
        }
        else
        {
            i -= 20;
            if (i <= 0)
            {
                bFlipUD ^= TRUE;
            }
        }
        //
        if (bFlipLR)
        {
            j += 20;
            if (j >= 200)
            {
                bFlipLR ^= TRUE;
            }
        }
        else
        {
            j -= 20;
            if (j <= 0)
            {
                bFlipLR ^= TRUE;
            }
        }

        //background
        RECT rtClient;
        GetClientRect(hwnd, &rtClient);
        SetBkMode(hdcMem, TRANSPARENT);
        HBRUSH hBrush = CreateSolidBrush(RGB(155, 155, 155));
        FillRect(hdcMem, &rtClient, hBrush);
        DeleteObject(hBrush);
        //background

        //  1
        HPEN hPen = CreatePen(PS_SOLID, 7, RGB(255, 0, 0));
        HPEN hOldPen = (HPEN)SelectObject(hdcMem, hPen);

        MoveToEx(hdcMem, 0, i, NULL);
        LineTo(hdcMem, cxClient, i);
        TextOut(hdcMem, 30, i + 20, TEXT("88"), 2);
        //  2
        hPen = CreatePen(PS_SOLID, 7, RGB(55, 250, 0));
        hOldPen = (HPEN)SelectObject(hdcMem, hPen);

        MoveToEx(hdcMem, 0, i + 20, NULL);
        LineTo(hdcMem, cxClient, i + 20);
        TextOut(hdcMem, 70, i + 40, TEXT("1439"), 4);
        //  3
        hPen = CreatePen(PS_SOLID, 7, RGB(225, 150, 5));
        hOldPen = (HPEN)SelectObject(hdcMem, hPen);

        MoveToEx(hdcMem, j, 0, NULL);
        LineTo(hdcMem, j, cyClient);
        TextOut(hdcMem, 70, i + 40, TEXT("1439"), 4);

        //InvalidateRect(hwnd, NULL, FALSE);
        InvalidateRgn(hwnd, NULL, FALSE);

        return 0;

    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        BitBlt(hdc, 10, 10, 750, 824,
            hdcMem, 0, 0, SRCCOPY);

        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        KillTimer(hwnd, 1);

        SelectObject(hdcMem, moldbmp);
        DeleteObject(hBitmap);
        DeleteDC(hdcMem);

        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
question from:https://stackoverflow.com/questions/65866683/win32-program-double-buffering-doesnt-work

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A classic resource leak. Each run through your WM_TIMER handler creates 3 Pens that it never releases. As pointed out in the documentation for CreatePen:

When you no longer need the pen, call the DeleteObject function to delete it.

You aren't doing that and eventually run out of available GDI resources. You can use Task Manager to verify the increase in GDI object count over time by going to the Details tab, right-clicking on the header, picking the Select columns option and enabling GDI objects.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...