[WinApi] Miganie obrazu

0

Witam.
Jak zrobic, zeby przy zmianie rozmiaru okna rysunek w nim nie migal? Slyszalem cos o podwojnym buforowaniu, ale probowalem korzystac z roznych przykladow i niestety nic z tego nie dzialalo w moim przypadku.
Czy ktos moglby mi wytlumaczyc w ktorym miejscu programu co powinienem napisac aby obraz nie migal podczas zmiany rozmiaru okna?

Oto fragment mojego kodu:

Sekcja WM_PAINT w WindowProcedure

case WM_PAINT:
          {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint (hwnd, &ps);
            GPS.SetDC(hdc);

            GPS.DrawMap();

            EndPaint(hwnd, &ps);
            break;
          }

Funkcja DrawMap

void GPSApi::DrawMap()
{

    HPEN COLOR_P = CreatePen(PS_TYPE_, PS_SIZE_, 0x000000);
    HPEN OLD_COLOR_P = (HPEN)SelectObject(hdcOkno_, COLOR_P);
    HBRUSH COLOR_B = CreateSolidBrush(0xFFFFFF);
    HBRUSH OLD_COLOR_B = (HBRUSH)SelectObject(hdcOkno_, COLOR_B);

    Ellipse(hdcOkno_, x-radius, y-radius, x+radius, y+radius);

    SelectObject(hdcOkno_, OLD_COLOR_P);
    DeleteObject(COLOR_P);
    SelectObject(hdcOkno_, OLD_COLOR_B);
    DeleteObject(COLOR_B);

}

W funkcji SetDC(hdc) po prostu przypisuje hdcOkno_ = hdc;

I teraz pytanie gdzie i jak zrobic to buforowanie zeby zniwelowac miganie?
Z gory dziekuje za pomoc :)

0

Malować na bitmapie (o rozmiarze okna) w pamięci (CreateCompatibleBitmap, CreateCompatibleDC, SelectObject, i zwalnianie na końcu)
A następnie malować całą bitmapę na oknie

0

Napisalem cos takiego:

case WM_PAINT:
          {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint (hwnd, &ps);
            HDC NewDC = CreateCompatibleDC(hdc);
            HBITMAP bitmap = CreateCompatibleBitmap(hdc, GPS.GetSize().x, GPS.GetSize().y);
            HBITMAP oldBitmap = (HBITMAP) SelectObject(NewDC, bitmap);
            GPS.SetDC(NewDC);
            HBRUSH COLOR_B = CreateSolidBrush(0xFFFFFF);
            HBRUSH OLD_COLOR_B = (HBRUSH)SelectObject(NewDC, COLOR_B);
            Rectangle(NewDC, 0, 0, GPS.GetSize().x, GPS.GetSize().y);

            GPS.DrawMap();

            BitBlt(hdc, 0, 0, GPS.GetSize().x, GPS.GetSize().y, NewDC, 0, 0, SRCCOPY);
            DeleteDC (NewDC);
            DeleteObject (bitmap);
            EndPaint(hwnd, &ps);
            break;
          }

Nic sie nie zmienilo, dalej miga obraz przy zmianie rozmiaru. Dodatkowo jeszcze musialem dodac malowanie calego okna na bialo (tak jak mam domyslnie ustawione) bo to nowe DC tworzy sie z czarnym tlem niewiedziec czemu :P

Nie wiem gdzie moze byc blad.

0

A GPS.DrawMap(); dalej maluje po oknie czy po tej bitmapie ? Bo jak po oknie to bez sensu jest ...

0

Caly czas maluje po oknie korzystajac z hdc. Do malowania po bitmapie jeszcze nie doszedlem i szczerze mowiac nie wiem jak to sie robi, ale sprobuje poczytac z czym to sie je :P

1

Gdy zwiększasz rozmiar okna, powstaje jeden lub dwa puste prostokąty. System wtedy wysyła WM_ERASEBKGND by program wypełnił je tłem. Jeżeli nie obsługujesz tego komunikatu, to pewnie przekazujesz go do funkcji DefWindowProc, która wypełnia tłem całe okno, i tu jest pies pogrzebany.
W obsłudze WM_ERASEBKGND wymazujesz tło lub tego nie robisz. Zwracasz BOOL mówiący czy wymazałeś tło, a ta (zwrócona) wartość po zanegowaniu pojawia się w PAINTSTRUCT.fErase podczas obsługi WM_PAINT.
Poniższy kod przesuwa konieczność wymazania tła z WM_ERASEBKGND do WM_PAINT:

case WM_ERASEBKGND:
   return 0; // nie wymazano tła
   break;

case WM_PAINT:
   BeginPaint(, &ps);
   // jeśli koniecznie trzeba, to wymaż tło
   if (ps.fErase) FillRect(ps.hdc, ps.rcPaint, hBrush);
   // rysuj coś
   BitBlt() EndPaint()

Musisz wiedzieć że WM_PAINT może zostać odpalone dwa razy dla jednej zmiany wielkości okna. Gdy powiększysz okno ukośnie, to odsłonisz dwa prostokąty (wycinek kwadratu w kształcie litery L) które kolejno pojawią się w WM_PAINT.

0

Czasy się zmieniają, a tu dalej pojawiają się tacy, co nie potrafią rysować po bitmapie.
U mnie problem ten sam, tylko, że jak mam o tyle łatwiej, że nie zmieniam rozmiaru okna, tylko rysuje jego wartość od nowa po wciśnięciu klawiszy, albo przy przesuwaniu myszy z wciśniętym klawiszem.
Czy jest może jeszcze jakaś ina prosta sztuczka oprócz tej bitmapy aby obraz nie migał. Jakiś parametr okna, albo jakaś prosta procedura?
Np coś na wzór "Form1.DoubleBuffered:=true;" w środowiskach Borland'a.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.