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

[WinAPI] Prostokąt nie aktualizuje swojej pozycji

Ostatnio zmodyfikowano 2017-11-11 14:59
Autor Wiadomość
multim
Temat założony przez niniejszego użytkownika
[WinAPI] Prostokąt nie aktualizuje swojej pozycji
» 2017-11-10 21:53:32
Tworzę pojedynczy prostokąt i chciałbym, żeby po zmianie rozmiaru okna nie zachowywał stałych współrzędnych, ale "podążał" za krawędzią okna. Gdzie popełniam błąd, co robię źle?
C/C++
#include <windows.h>

LPCWSTR ClassName = TEXT( "Klasa Okienka" );

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
void CreatePBs( HDC & hdc, HBRUSH * brush, HPEN * pen );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
    MSG Komunikat;
    WNDCLASSEX wc = {
        sizeof( WNDCLASSEX ),
        0,
        WndProc,
        0,
        0,
        hInstance,
        0,
        LoadCursor( NULL, IDC_ARROW ),
        ( HBRUSH )( COLOR_WINDOW + 0 ),
        NULL,
        ClassName,
        0
    };
   
    if( !RegisterClassEx( & wc ) )
    {
        MessageBox( NULL, TEXT( "Błąd rejestracji tego okna!" ), TEXT( "Problem..." ),
        MB_ICONEXCLAMATION | MB_OK );
        return 1;
    }
   
    HWND hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, ClassName, TEXT( "Oto okienko" ), WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInstance, 0 );
   
    if( hwnd == NULL )
    {
        MessageBox( NULL, TEXT( "Błąd utworzenia okna." ), TEXT( "Problem..." ), MB_ICONEXCLAMATION );
        UnregisterClass( ClassName, hInstance );
        return 1;
    }
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
   
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
    UnregisterClass( ClassName, hInstance );
   
    return Komunikat.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT cr;
    HBRUSH brush[ 16 ];
    HPEN pen[ 16 ];
    switch( msg )
    {
    case WM_CLOSE:
        //if ( MessageBox( hwnd, TEXT( "Czy chcesz wyjść z programu?" ), TEXT(" Wyjście "), MB_ICONQUESTION | MB_YESNO ) == IDYES )
        DestroyWindow( hwnd );
        return 0;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    case WM_SIZE:
        GetClientRect( hwnd, & cr );
        UpdateWindow( hwnd );
        break;
    case WM_PAINT:
        {
            hdc = BeginPaint( hwnd, & ps );
            HBRUSH bk = CreateSolidBrush( 0xC0C0C0 );
            CreatePBs( hdc, brush, pen );
            HBRUSH OldBrush =( HBRUSH ) SelectObject( hdc, bk );
            HPEN OldPen =( HPEN ) SelectObject( hdc, pen[ 9 ] );
           
            GetClientRect( hwnd, & cr );
            Rectangle( hdc, cr.left, cr.top, cr.right, cr.bottom );
            EndPaint( hwnd, & ps );
            break;
        }
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
    }
   
    return 0;
}

void CreatePBs( HDC & hdc, HBRUSH * brush, HPEN * pen )
{
    COLORREF color[ 16 ] =
    {
        0x000000, 0x777777,
        0x000080, 0x0000FF,
        0x004000, 0x00FF00,
        0x008080, 0x00FFFF,
        0x800000, 0xFF0000,
        0x800040, 0xFF00FF,
        0x808040, 0xFFFF00,
        0x806060, 0xFFFFFF
    };
   
   
    for( int i = 0; i < 16; i++ )
    {
        brush[ i ] = CreateSolidBrush( color[ i ] );
        pen[ i ] = CreatePen( PS_SOLID, 1, color[ i ] );
    }
}

screen
screen
P-166705
Luq
» 2017-11-10 22:46:12
Zamiast UpdateWindow(hwnd) użyj InvalidateRect(hwnd, nullptr, TRUE).

Jak tworzysz obiekty GDI, to musisz je później usunąć przez DeleteObject. Twój aktualny kod ma sporo wycieków pamięci.
P-166708
multim
Temat założony przez niniejszego użytkownika
» 2017-11-11 08:55:15
Ad. 1. Dziękuję, teraz prostokąt się nie powiela. Ale miałem na myśli, żeby za pomocą współrzędnych ClientRect sterować rozmiarami tego prostokąta. Zauważyłem, że nie miałem dodanych styli CS_VREDRAW i CS_HREDRAW w strukturze okienka.

Czy kod jest teraz poprawny? Tzn. czy zapobiegłem wyciekom pamięci i czy nie ma innych błędów?
C/C++
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT cr;
    HBRUSH brush[ 16 ];
    HPEN pen[ 16 ];
    enum colors { black, gray, darkred, red, darkgreen, green,
        darkyellow, yellow, darkblue, blue, purple, pink,
        seal, lightblue, darkgray, white } clr;
    switch( msg )
    {
    case WM_CLOSE:
        //if ( MessageBox( hwnd, TEXT( "Czy chcesz wyjść z programu?" ), TEXT(" Wyjście "), MB_ICONQUESTION | MB_YESNO ) == IDYES )
        DestroyWindow( hwnd );
        return 0;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    case WM_PAINT:
        {
            hdc = BeginPaint( hwnd, & ps );
            HBRUSH bkMenu = CreateSolidBrush( 0xC0C0C0 );
            CreatePBs( hdc, brush, pen );
            HBRUSH OldBrush =( HBRUSH ) SelectObject( hdc, brush[ 15 ] );
            HPEN OldPen =( HPEN ) SelectObject( hdc, pen[ 0 ] );
           
            //Rysowanie dużej ramki
            GetClientRect( hwnd, & cr );
            Rectangle( hdc, cr.left, cr.top, cr.right, cr.bottom );
           
            //Rysowanie małej ramki
            SelectObject( hdc, bkMenu );
            SelectObject( hdc, pen[ blue ] );
            Rectangle( hdc, cr.right - 100, 1, cr.right - 1, cr.bottom - 1 );
           
            //Usuwanie obiektów GDI
            SelectObject( hdc, OldBrush );
            SelectObject( hdc, OldPen );
            for( int i = 0; i < 16; i++ )
            {
                DeleteObject( brush[ i ] );
                DeleteObject( pen[ i ] );
            }
            DeleteObject( OldBrush );
            DeleteObject( bkMenu );
            DeleteObject( OldPen );
            EndPaint( hwnd, & ps );
            break;
        }
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
    }
   
    return 0;
}
P-166711
Luq
» 2017-11-11 10:55:13
C/C++
DeleteObject( OldBrush );
DeleteObject( OldPen );
Te linijki są zbędne.
P-166713
multim
Temat założony przez niniejszego użytkownika
» 2017-11-11 14:59:44
Dziękuję za pomoc.
P-166731
« 1 »
  Strona 1 z 1