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? #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: 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 ] ); } }
|
|
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. |
|
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? 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: 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 ] ); GetClientRect( hwnd, & cr ); Rectangle( hdc, cr.left, cr.top, cr.right, cr.bottom ); SelectObject( hdc, bkMenu ); SelectObject( hdc, pen[ blue ] ); Rectangle( hdc, cr.right - 100, 1, cr.right - 1, cr.bottom - 1 ); 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; }
|
|
Luq |
» 2017-11-11 10:55:13 DeleteObject( OldBrush ); DeleteObject( OldPen );
Te linijki są zbędne. |
|
multim Temat założony przez niniejszego użytkownika |
» 2017-11-11 14:59:44 Dziękuję za pomoc. |
|
« 1 » |