Miganie grafiki w oknie (winapi)

0

Witam,

Mój problem jest następujący: Gdy poruszam oknem po krawędzi ekranu, cała grafika miga. Jaki jest na to sposób? Używam GDI+. Moja obsługa WM_PAINT wygląda tak:

case WM_PAINT:
{
	PAINTSTRUCT ps; 
    HDC hdc = BeginPaint( hwnd, & ps );
	displayImage(loadedScreen, hwnd);
    EndPaint( hwnd, & ps );
    break;
}

Funkcja displayImage (wyświetlająca):

void displayImage(HBITMAP mBmp, HWND mHwnd)
{
    RECT myRect;
    BITMAP bm;
    HDC screenDC, memDC;
    HBITMAP oldBmp;
    BLENDFUNCTION bf;

    GetObject(mBmp, sizeof(bm), &bm);

    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 0xff;

    bf.AlphaFormat = AC_SRC_ALPHA;

    screenDC = GetDC(mHwnd);
    GetClientRect(mHwnd, &myRect);

    if (mBmp == NULL)
        FillRect(screenDC, &myRect, WHITE_BRUSH);
	
    else
    {
        memDC = CreateCompatibleDC(screenDC);
        oldBmp = (HBITMAP)SelectObject(memDC, mBmp);
        AlphaBlend (screenDC, 0, 0, myRect.right,myRect.bottom, memDC, 0, 0, bm.bmWidth,bm.bmHeight, bf);
        SelectObject(memDC, oldBmp);
        DeleteDC(memDC);
        ReleaseDC(mHwnd, screenDC);
    }
}

Zmienna loadedScreen to zmienna typu HBITMAP - uchwyt do załadowanej grafiki. Czyli po prostu:

HBITMAP mLoadImg(WCHAR *szFilename)
{
   HBITMAP result=NULL;

   Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(szFilename,false);
   bitmap->GetHBITMAP(NULL, &result);
   delete bitmap;
   return result;
}


loadedScreen = mLoadImg(L"data\\img\\screen.png");
1

Wywołanie BeginPaint powoduje wysłanie komunikatu WM_ERASEBKGND, który to z kolei powoduje odmalowanie tła. I to odmalowanie przed właściwym malowaniem okna powoduje efekt błyskania. Zrób własną obsługę tego komunikatu...

Dlaczego nie użyjesz funkcji LoadBitmap zamiast tych zabaw z Gdiplus::Bitmap i GetHBITMAP?

0
0x666 napisał(a):

Wywołanie BeginPaint powoduje wysłanie komunikatu WM_ERASEBKGND, który to z kolei powoduje odmalowanie tła. I to odmalowanie przed właściwym malowaniem okna powoduje efekt błyskania. Zrób własną obsługę tego komunikatu...

Rozumiem, a jak powinna wyglądać obsługa WM_ERASEBKGND? Próbowałem w ten sposób, ale nic z tego:

case WM_ERASEBKGND:
{
	return 0;
	break;
} 
0x666 napisał(a):

Dlaczego nie użyjesz funkcji LoadBitmap zamiast tych zabaw z Gdiplus::Bitmap i GetHBITMAP?

Mogę prosić o jakiś przykład? Próbowałem już ładować grafikę domyślnymi funkcjami winAPI, ale stawało na tym, że ładowało pliki *.bmp, a potrzebne u mnie *.png już nie.

1

Obsługa WM_ERASEBKGND powinna chyba zwrócić wartość niezerową. Ten break jest zbędny.

Mogę prosić o jakiś przykład?

Myślałem, że chodzi o zwykłe bitmapy. Z ładowaniem plików .png faktycznie może być problem, jeśli mowa o LoadBitmap.

0

Gdy zwracam wartość niezerową, faktycznie, grafika nie miga już sama w sobie na biało, ale pojawił się inny problem:
Mianowicie w moim programie rysuję dwa pliki *.png, jeden na drugim. I teraz przy WM_PAINT (gdy poruszam oknem po granicy ekranu) miga ten plik graficzny, który powinien być "na wierzchu". Podejrzewam, że po prostu przez ułamek sekundy przy przerysowaniu grafika "na spodzie" przykrywa tę "na wierzchu", która zaraz potem się także rysuje ponownie. Jak mogę to rozwiązać?

1

Składaj obraz na tymczasowej bitmapie (off-screen drawing), którą to później "blitujesz" na okno.

1
    HDC hdc = BeginPaint( hwnd, & ps );

    ...

    screenDC = GetDC(mHwnd);

Masz HDC które zwraca ci BeginPaint, i jego używaj. Wywal to GetDC/ReleaseDC.

Używam GDI+

Właśnie jakoś nie bardzo. Ładujesz bimapę przez GDI+, a potem rysujesz wszystko przez GDI.
Wywal całe displayImage i użyj klasy Graphics do rysowania.

0
  1. ładowanie bitmapy.
Gdiplus::Bitmap* bitmap;

...

// Gdzieś po zainicjowaniu GDI+, np w WM_CREATE
bitmap = new Gdiplus::Bitmap(szFilename, false);
  1. rysowanie
case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    {
        Graphics g(hdc);
        g.DrawImage(bitmap, 0, 0);
    }
    EndPaint(hwnd, &ps);
    break;
}

I tyle.
Robiłeś na około.

1 użytkowników online, w tym zalogowanych: 0, gości: 1