WINAPI Odrysowywanie własnego rysunku/wymiana kontekstu między komunikatami

0

Witam, mam problem z odrysowywaniem własnych bazgrołów w WINAPI.
Mam zamiar napisać program w stylu paint, który by rusował jakieś kreski i linie (poprzez komunikaty WM_LBUTTONDOWN, WM_LBUTTONUP i WM_MOUSEMOVE) i całość chciałem zrobić poprzez podwójne buforowanie bitmapy - rysuję po kompatybilnej bitmapie a potem przerzucam to na hdc głównego okna (mam nadzieję, że nie wyszedłem na głupka i dobrze zrozumiałem ideę podwójnego buforowania).
Jak do tej pory wszystko ok, kopiowanie bitmapek nie sprawia problemów, tylko gorzej z odrysowywaniem. Chciałem zrobić tak, żeby przy otrzymaniu komunikatu WM_PAINT program za każdym razem kopiował zawartość tej kompatybilnej bitmapy na hdc okna.

Dla treningu zrobiłem prosty kodzik, w którym po wciśnięciu LMB rysuje się krecha (LineTo) na kompatibilnej bitmapie a potem bitbltuje na hdc okna. Jeżeli cały kod umieszczam w komunikacie WM_PAINT to nie ma problemu - wszystko działa cacy. Kłopoty zacznają się, jeśli chcę całość obsłużyć różnymi komunikatami - linia rysuję się w WM_LBUTTONDOWN, tam też pierwsze, wstępne kopiowanie bitmap, następnie w WM_PAINT odrysowywanie bitmapy za każdym razem. No i właśnie - odrysowuje się pusta bitmapa, zupełnie tak, jakby kontekst pamięciowy użyty w WM_LBUTTONDOWN nie współgrał z tym samym kontekstem pamięciowym, ale w WM_PAINT.

Dużo różnych słów a moje pytanie proste - czy, i jeśli tak to jak, da się wymieniać kontekstymiędzy komunikatami, z zachowaniem ich wartości? Ewentualnie czy ktoś dostrzega inną, lepszą możliwość odrysowywania mojego rysuneczku?


[...]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    HDC hdc = GetDC( hwnd );
    HDC memDC = CreateCompatibleDC( hdc );
    HBITMAP memBM = CreateCompatibleBitmap( hdc, 800, 600 );
    HBITMAP stara =( HBITMAP ) SelectObject( memDC, memBM );
    POINT stary;
    HBRUSH wypelniak = CreateSolidBrush( RGB( 0, 0, 0 ) );
    Rectangle( memDC, - 1, - 1, 800, 600 ); // tutaj wypełniam kompatybilną bitmapę białym prostokątem, 
    // bo domyślnie jest całą czarna
    
    
    switch( msg )
    {
    case WM_PAINT:
        PAINTSTRUCT ps;
        BeginPaint( hwnd, & ps );
        BitBlt( hdc, 0, 0, 800, 600, memDC, 0, 0, SRCCOPY );
        EndPaint( hwnd, & ps );
        break;
        
    case WM_LBUTTONDOWN:
        MoveToEx( memDC, 10, 10, & stary );
        LineTo( memDC, 150, 150 );
        BitBlt( hdc, 0, 0, 800, 600, memDC, 0, 0, SRCCOPY );
        break;
        
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
        
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
        
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
    }
    
    return 0;
}

0

Spróbuj w WM_PAINT użyć kontekstu z PAINTSTRUCT: ps.hdc

0

Nie pomogło, tylko tyle, że teraz przy np. przesunięciu kawałku okienka za krawędź ekranu nie czyści mi sięcała bitmapa na biało tylko ten kawałk, który zniknął.

0

Ostatnio w WinAPI pisałem wieki temu. Może kontekst urządzenia nie jest w stanie przetrwać kolejki komunikatów. Na początku obsługi WM_LBUTTONDOWN daj hdc = GetDC(hwnd); lub zamiast tego BitBlt InvalidateRect

0

(...) czy, i jeśli tak to jak, da się wymieniać konteksty między komunikatami, z zachowaniem ich wartości?

Da się. Przenieś definicję memBM poza funkcję. Teraz za każdym wywołaniem WndProc operujesz na innej bitmapie. Dodatkowo nie zwalniasz kontekstów i nie usuwasz bitmapy, a to musi się skończyć katastrofą.

Podkreślę to, co napisał już byku_guzio: w WM_PAINT używaj kontekstu zwróconego przez BeginPaint

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