Как избежать чрезмерного мерцания экрана с помощью GDI - PullRequest
4 голосов
/ 03 октября 2011

Я новичок в рендеринге графики с помощью GDI ...

Я создал программу рисования, и она отлично работает, просто она вызывает много раздражающего мерцания экрана.Я признаю, что мой код рисования не очень оптимизирован (нехватка времени), но он также не должен быть супер неэффективным, поэтому я озадачен.

В основном я делаю создание совместимого DC наinit, затем создайте совместимое растровое изображение.Затем я выбираю его в совместимый DC и рисую в совместимый DC.Затем я использую BitBlit (), чтобы скопировать его в окно hDC ...

Может кто-нибудь сказать мне возможные причины этого разрыва экрана?РЕДАКТИРОВАТЬ: кстати, мерцание экрана происходит только во время рисования пути (перед тем, как путь обращается к hMemDC, он обращается к hDC окна)

Примеры кода: (РЕДАКТИРОВАТЬ: Если вам нужносм. любой другой код, который, по вашему мнению, является релевантным, прокомментируйте, и я отредактирую), WPARAM, LPARAM)

LRESULT MyApp::WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    if(iMsg == WM_CREATE)
    {
        CREATESTRUCT *pCS = (CREATESTRUCT*)lParam;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)pCS->lpCreateParams);

    }
    else
    {
        //retrieve the stored "this" pointer
        MyApp* pApp = (MyApp*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

        switch (iMsg)
        {
            case WM_PAINT:
                {
                pApp->Paint();
                return 0;
                }

            case WM_COMMAND:
            {
                int wmId    = LOWORD(wParam);
                int wmEvent = HIWORD(wParam);

                // Parse the menu selections:
                switch (wmId)
                {
                case IDM_NEW:
                    {
                        ////
                        return 0;
                    }
                    return 0;
                case IDM_LOAD:
                    {
                        //////
                        return 0;
                    }
                case IDM_SAVE:
                    {
                    //////
                    return 0;
                    }
                case IDM_SAVEAS:
                    {
                        //////
                        return 0;
                    }
                case IDM_COLOURMAIN:
                    {
                        COLORREF col;
                        if(MyWin32Funcs::OnColorPick(col)) {
                            pApp->m_pPath->SetColor1(col);
                        }
                    return 0;
                    }
                case IDM_COLOURSECONDARY:
                    {
                    COLORREF col;
                        if(MyWin32Funcs::OnColorPick(col)) {
                            pApp->m_pPath->SetColor2(col);
                        }
                    return 0;
                    }
                case IDM_PEN:
                    {
                        pApp->m_pPath->SetTool(Tool_Pen);
                        return 0;
                    }
                case IDM_LINE:
                    {
                        pApp->m_pPath->SetTool(Tool_Line);
                        return 0;
                    }
                case IDM_ELLIPSE:
                    {
                        pApp->m_pPath->SetTool(Tool_Ellipse);
                        return 0;
                    }
                case IDM_RECTANGLE:
                    {
                        pApp->m_pPath->SetTool(Tool_Rectangle);
                        return 0;
                    }
                case IDM_LINETRACK:
                    {
                        pApp->m_pPath->SetTool(Tool_LineTrack);
                        return 0;
                    }
                default:
                    {
                    //////
                    return 0;
                    }
                }
            }

            case WM_LBUTTONUP:
                {
                    //////
                    Point2D p;
                    p.x = LOWORD(lParam); 
                    p.y = HIWORD(lParam);

                    switch(pApp->m_pPath->GetTool()) {
                        case Tool_Pen:
                            {
                                pApp->m_bPaintToBitmap = true;
                                InvalidateRect(pApp->m_hWnd,NULL,true);
                                break;
                            }
                        case Tool_Ellipse:
                            {
                                pApp->m_bPaintToBitmap = true;
                                InvalidateRect(pApp->m_hWnd,NULL,true);
                                break;
                            }
                        case Tool_Rectangle:
                            {
                                pApp->m_bPaintToBitmap = true;
                                InvalidateRect(pApp->m_hWnd,NULL,true);
                                break;
                            }
                        case Tool_Line:
                            {
                                pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                                InvalidateRect(pApp->m_hWnd,NULL,false);
                                break;
                            }
                        case Tool_LineTrack:
                            {
                                pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                                InvalidateRect(pApp->m_hWnd,NULL,false);
                                break;
                            }
                    }

                    return 0;
                }

            case WM_RBUTTONUP:
                {
                    //////
                    int x = LOWORD(lParam);
                    int y = HIWORD(lParam);

                    switch(pApp->m_pPath->GetTool()) {
                        case Tool_Line:
                            {
                                pApp->m_bPaintToBitmap = true;
                                InvalidateRect(pApp->m_hWnd,NULL,true);
                                break;
                            }
                        case Tool_LineTrack:
                            {
                                pApp->m_bPaintToBitmap = true;
                                InvalidateRect(pApp->m_hWnd,NULL,true);
                                break;
                            }
                    }

                    return 0;
                }
            case WM_LBUTTONDOWN:
                {
                    Point2D p;
                    p.x = LOWORD(lParam);
                    p.y = HIWORD(lParam);
                    switch(pApp->m_pPath->GetTool()) {
                    case Tool_Pen:
                        pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                        InvalidateRect(pApp->m_hWnd,NULL,false);
                        break;
                    }
                }
            case WM_MOUSEMOVE:
                {
                    Point2D p;
                    p.x = LOWORD(lParam);
                    p.y = HIWORD(lParam);
                    if (wParam & MK_LBUTTON) {
                        switch(pApp->m_pPath->GetTool()) {
                        case Tool_Pen:
                            {
                            pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                            InvalidateRect(pApp->m_hWnd,NULL,false);
                            break;
                            }
                        case Tool_Ellipse:
                            {
                            if( pApp->m_pPath->GetLen() >= 1) {
                                pApp->m_pPath->SetPointAt(1,p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                            }
                            else {
                                pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                            }
                            InvalidateRect(pApp->m_hWnd,NULL,false);
                            break;
                            }
                        case Tool_Rectangle:
                            {
                            if( pApp->m_pPath->GetLen() >= 1) {
                                pApp->m_pPath->SetPointAt(1,p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                            }
                            else {
                                pApp->m_pPath->AddPoint(p,pApp->m_pBitmapPainter->GetBmpSize(),pApp->m_pBitmapPainter->GetBmpOffset());
                            }
                            InvalidateRect(pApp->m_hWnd,NULL,false);
                            break;
                            }
                        }
                    }

                    return 0;
                }

            case WM_CLOSE:
                {
                    //////
                                return 0;
                            }
                        }
                    PostQuitMessage(0);
                    return 0;
                }
        }
    }
    return DefWindowProc (hWnd, iMsg, wParam, lParam) ;
}

MyApp :: Paint ()

void MyApp::Paint()
{
    BeginPaint(m_hWnd,&m_PaintStruct);
    if (m_bPaintToBitmap) {
        Point2D p;
        p.x = BMPXOFFSET;
        p.y = BMPYOFFSET;
        m_pPath->Offset(p);
        m_pPath->DrawTo(m_pBitmapPainter->GetMemDC());
        m_pPath->ClrPath();
        m_pBitmapPainter->Paint(); //this is where BitBlt() occurs
        m_bPaintToBitmap = false;
        if(m_pBitmapPainter->IsAdjusted() == false) {
            m_pBitmapPainter->SetbAdjusted(true);
        }
    }
    else {
        m_pBitmapPainter->Paint(); //this is where BitBlt() occurs
        m_pPath->DrawTo(m_hDC);
    }
    EndPaint(m_hWnd,&m_PaintStruct);
}

Любая помощь будет высоко ценится.

Ответы [ 4 ]

7 голосов
/ 03 октября 2011

Я думаю, то, что вы видите, - это мерцание, а не слеза.Чтобы свести к минимуму мерцание, ваш WM_PAINT должен записать в окно DC ровно один раз.Как правило, это одна операция: BitBlt:

HDC hdc = BeginPaint(m_hwnd, &m_PaintStruct);
... paint to bitmap ...
BitBlt(hdc, ...); // blt from bitmap to screen
EndPaint(m_hwnd, &m_PaintStruct);

Если вы рисуете в окно DC в несколько шагов, то вы открываете окно для мерцания.

Ваше описание проблемыне соответствует коду.В своем описании вы говорите, что вы моргаете от совместимого DC к окну hDC.Но в вашем коде за вашим BitBlt следует m_pPath->DrawTo(m_hDC).Если обновление происходит во время DrawTo, экран обновляется с частично нарисованным видом, что приводит к мерцанию.

4 голосов
/ 03 октября 2011

Если вы рисуете всю клиентскую область, переопределите WM_ERASEBKGND и просто верните TRUE.Это уменьшит мерцание.

Как указали другие;используйте HDC, заданное WM_PAINT, поскольку оно может содержать области отсечения, и другие вещи, которые могут оптимизировать обновление экрана.

EDIT Если вы не рисуете всю клиентскую область, вы можете выполнять фоновое рисование в тех областях, которые вы знаете, где ваш обработчик WM_PAINT не будет рисовать.

0 голосов
/ 03 октября 2011

На какой ОС вы работаете?Если это Vista или Windows 7, вы работаете в каком-то «режиме совместимости», отключающем композитинг на рабочем столе?

Предположительно, одним из преимуществ диспетчера окон рабочего стола (DWM), представленного в Vista, является ( source)):

В Windows XP приложения обновляют свои окна непосредственно, когда ОС запрашивает их.Эти запросы могут выполняться асинхронно в отношении частоты обновления монитора или любых обновлений, которые могут быть запущены в данный момент.Эффект этих запросов заключается в том, что пользователь видит, что окна рвутся и перерисовываются неправильно или медленно.Стиль оконного представления в DWM устраняет разрывные артефакты, обеспечивая высокое качество рабочего стола.Преимущество для конечного пользователя заключается в том, что система выглядит более отзывчивой, а восприятие более чистым.

, т. Е. С DWM композитинг на рабочий стол будет синхронизирован с рисованием, чтобы избежать появления частично нарисованного«порванные» вещи.

Если это не так, вы уверены, что не путаете «разрыв» с мерцанием фонового стирания или что-то в этом роде?

0 голосов
/ 03 октября 2011

BeginPaint дает вам HDC, который вы должны рисовать. Вы игнорируете это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...