Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinAPI] Nakładanie bitmapy na wczesniejszą

Ostatnio zmodyfikowano 2013-10-13 21:14
Autor Wiadomość
Buby
Temat założony przez niniejszego użytkownika
[WinAPI] Nakładanie bitmapy na wczesniejszą
» 2013-10-13 15:08:42
Witam!
Napisałem kod, którego działanie ma być następujące:
1. Stworzy okno wypełnione bitmapą "xa.bmp".
2. Stworzy przycisk o nazwie "Zmień tło".
3. Po wciśnięciu przycisku program zmieni bitmapę na "xb.bmp" i usunie przycisk.

Problem polega na tym, że po skompilowaniu kodu bitmapa się nie zmienia.
Prosiłbym o poprawienie go i opisanie, dlaczego mój program nie ładuje drugiej bitmapy.
Z góry dziękuje.

C/C++
#include <windows.h>

HWND hwnd;
HDC hdc;
HDC hdcNowy;
HWND g_hPrzycisk1;


HFONT hNormalFont;
HBITMAP hbmObraz;
LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;

#define ID_PRZYCISK1 501

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    // WYPE£NIANIE STRUKTURY
    WNDCLASSEX wc;
   
    wc.cbSize = sizeof( WNDCLASSEX );
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground =( HBRUSH )( COLOR_WINDOW + 1 );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = NazwaKlasy;
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   
    // REJESTROWANIE KLASY OKNA
    if( !RegisterClassEx( & wc ) )
    {
        MessageBox( NULL, "Wysoka Komisja odmawia rejestracji tego okna!", "Niestety...",
        MB_ICONEXCLAMATION | MB_OK );
        return 1;
    }
    hbmObraz =( HBITMAP ) LoadImage( NULL, "xa.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
    hNormalFont =( HFONT ) GetStockObject( DEFAULT_GUI_FONT );
   
    // TWORZENIE OKNA
   
   
    hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, NazwaKlasy, "Nauka Geografii", WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
    CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL );
    g_hPrzycisk1 = CreateWindowEx( 0, "BUTTON", "Zmien tlo", WS_CHILD | WS_VISIBLE,
    250, 120, 150, 35, hwnd,( HMENU ) ID_PRZYCISK1, hInstance, NULL );
    SendMessage( g_hPrzycisk1, WM_SETFONT,( WPARAM ) hNormalFont, 0 );
   
   
    if( hwnd == NULL )
    {
        MessageBox( NULL, "Okno odmówilo przyjscia na swiat!", "Ale kicha...", MB_ICONEXCLAMATION );
        return 1;
    }
   
   
    hdc = GetDC( hwnd );
   
    ShowWindow( hwnd, nCmdShow ); // Pokaz okienko...
    UpdateWindow( hwnd );
   
    hdcNowy = CreateCompatibleDC( hdc );
    SelectObject( hdcNowy, hbmObraz );
    BITMAP bmInfo;
    GetObject( hbmObraz, sizeof( bmInfo ), & bmInfo );
    BitBlt( hdc, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, hdcNowy, 0, 0, SRCCOPY );
    ReleaseDC( hwnd, hdc );
   
    // Petla komunikatow
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
       
    }
    return Komunikat.wParam;
}

// OBSlUGA ZDARZEN
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
       
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
       
    case WM_PAINT:
        {
            PAINTSTRUCT ps; // deklaracja struktury
            HDC hdc = BeginPaint( hwnd, & ps );
            // ...
           
            HDC hdcNowy = CreateCompatibleDC( hdc );
            SelectObject( hdcNowy, hbmObraz );
            BITMAP bmInfo;
            GetObject( hbmObraz, sizeof( bmInfo ), & bmInfo );
            BitBlt( hdc, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, hdcNowy, 0, 0, SRCCOPY );
            ReleaseDC( hwnd, hdc );
            DeleteObject( hbmObraz );
            // ...
            EndPaint( hwnd, & ps ); // zwalniamy hdc
        }
        break;
       
    case WM_COMMAND:
        switch( wParam )
        {
        case ID_PRZYCISK1:
            DestroyWindow( g_hPrzycisk1 );
            hbmObraz =( HBITMAP ) LoadImage( NULL, "xb.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
            break;
        }
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
        return 0;
    }
}

Owe zmienianie bitmap, jest mi potrzebne, do zrealizowania celu, który założyłem sobie przed rozpoczęciem kursu.
Jeśli to opanuję, to program ukaże się w najbliższym czasie w dziale "Nasze Prace".
Pozdrawiam.
P-93617
Monika90
» 2013-10-13 17:10:30
Skąd wiesz że nie ładuje bitmapy? Jak to sprawdziłeś? Może po prostu jej nie wyświetla, bo nie odświeżasz okna po jej załadowaniu.

Na dodatek, w obsłudze WM_PAINT niszczysz tę bitmapę więc wyświetli się ona co najwyżej raz.

Poza tym, procedura WndProc powinna zawsze zwracać jakąś wartość za pomocą return, czego u ciebie nie robi.
P-93618
Buby
Temat założony przez niniejszego użytkownika
Re
» 2013-10-13 20:08:25
Posłuchałem twoich wskazówek, poszukałem w google odświeżanie okna.
Wstawienie tej komendy pomogło:  
InvalidateRect(hwnd,0,TRUE);
 
Bitmapę widać, ale nie działa WM_PAINT - po zminimalizowaniu i powiększeniu mam biały ekran z kontrolką.
Sam popróbuję coś z tym zrobić, jednak jeśli ktoś ma jakieś wskazówki to będą mile widziane.

P.S dziękuje Moniko, niby rzecz banalna, a jednak newbie taki jak ja, nawet o tym nie pomyślał.
P-93628
Monika90
» 2013-10-13 21:02:50
Posłuchałem twoich wskazówek
Słusznie.

po zminimalizowaniu i powiększeniu mam biały ekran z kontrolką.
To dlatego, że niszczysz bitmapę (DeleteObject) po narysowaniu.
ReleaseDC(hwnd, hdc) w obsłudze WM_PAINT też jest źle, ReleaseDC nie służy do zwalniania DC uzyskanego za pomocą BeginPaint(). Powinieneś za to niszczyć hdcNowy za pomocą DeleteDC.

Możesz też pozbyć się kodu rysującego bitmapę z WinMain, bo i tak będzie narysowna w WM_PAINT.
P-93637
Buby
Temat założony przez niniejszego użytkownika
Dziękuje
» 2013-10-13 21:14:56
Pozmieniałem wg. twojego wzoru i śmiga.
Dziękuje za wytłumaczenie, bo dzięki temu nie popełnię tego błędu w przyszłości.
;)
P-93639
« 1 »
  Strona 1 z 1