230 likes | 372 Views
Lecture 2. Drawing. WM_PAINT message. The paint message is sent to the window if: any portion of the window is invalid there are no other messages waiting to be handled Part of the window becomes invalid if: window was hidden and is shown
E N D
Lecture 2 Drawing
WM_PAINT message • The paint message is sent to the window if: • any portion of the window is invalid • there are no other messages waiting to be handled • Part of the window becomes invalid if: • window was hidden and is shown • some part of the window was hidden and becomes visible • window is moved or resized • application calls the InvalidateRect function
WM_PAINT handler • must be able to restore entire window area • can use the PAINTSTRUCT variable to check area that must be repainted • can draw on entire window (windows ignores drawing outside the invalid region) • should never access dynamic data like ‘current time’, ‘number of users’, etc., it should use values saved by other message handlers
case WM_PAINT: PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); • BeginPaint gets device context for painting • The ps variable contains additional information about requested painting (e.g. area to be painted) • hdc is the device context handle EndPaint(hWnd, &ps); • EndPaint releases painting resources and validates entire window area
Resizing windows • When the window is enlarged there are two possibilities: • entire window area is invalidated • only the “new” area of the window is invalidated • When window is shrank there are two possibilities: • entire window area is invalidated • window area is valid • Application can request each behavior when it creates window (this is window class style option)
Window background • Window background is handled automatically by Windows • Background color is requested at window creation time (actually background brush is requested) • BeginPaint function sends the WM_ERASEBKGND message • WM_ERASEBKGND default handler (by DefWindowProc) restores window background to the requested color • You can write your own WM_ERASEBKGND message handler
Drawing outside WM_PAINT • Do not call BeginPaint in other message handlers • Call GetDC( hWnd ) to get device context for the window • Call ReleaseDC( hWnd, hdc ) at the end of painting: WM_LBUTTONDOWN: HDC hdc = GetDC( hWnd ); SetPixel( hdc, LOWORD(lParam),HIWORD(lParam), RGB( 255, 0, 0 )); ReleaseDC( hWnd, hdc ); // !!! save the point so that WM_PAINT // handler can paint it
Device contexts • Drawing, printing, plotting is done via device contexts • You can get device context using: • BeginPaint function (WM_PAINT) • GetDC function (other than WM_PAINT) • GetWindowDC function • CreateCompatibleDC function (memory device context) • You must free the DC when finished using; call EndPaint, ReleaseDC, DeleteDC (depending on how you got the DC)
Drawing on device context • Functions used for drawing: • Rectangle( HDC hdc, int left, int top, int right, int bottom ); • Ellipse( HDC hdc, int left, int top, int right, int bottom ); • MoveToEx( HDC hdc, int x, int y, POINT *oldPoint ); • LineTo( HDC hdc, int x, int y ); • TextOut( HDC hdc, int x, int y, char *str, int len ); • DrawText( HDC hdc, char *str, int len, RECT *r, UINT format); • Arc( ... ); • Pie( ... ); • PolyDraw( ... ); • Polyline( ... ); • RoundRect( ... );
Device context objects • PEN - used for drawing lines and outlines of rectangles, ellipses etc. • BRUSH - used for filling ellipses, rectangles etc. • FONT - used for drawing text • BITMAP - used for bitmap operations • REGION - used for managing non-rectangular areas
Drawing is always done using currently selected pen, brush etc. • To change object used for drawing: • get device context handle • create new drawing object (or get existing one) • select it to the device context • draw something on the screen • select previously selected object to the device context • delete created object • free the device context • Previously selected object must be restored to the device context before the device context is freed
Using PENs HPEN pen = CreatePen( PS_SOLID, 3, RGB( 255, 0, 0 )); HPEN oldPen = SelectObject( dc, pen ); MoveToEx( 100, 100, NULL ); LineTo( 200, 200 ); SelectObject( oldPen ); //!!!!! DeleteObject( pen ); • Draws red (RGB(255,0,0)) line, 3 pixels wide (second parameter of CreatePen) from point (100, 100) to (200, 200)
Using BRUSHes • Create brush using • CreateSolidBrush( COLORREF color ); • CreateBrushIndirect( LOGBRUSH *log ); HBRUSH brush = CreateSolidBrush( RGB( 255, 0, 0 )); HBRUSH oldBrush = SelectObject( dc, brush ); Rectangle( hdc, 100, 100, 200, 200 ); SelectObject( oldBrush ); //!!!!! DeleteObject( brush );
NULL pen and brush • Functions like Rectangle, Ellipse draw the outline of the object using PEN and fill the interior with current BRUSH • It is possible to select NULL brush or NULL pen to the DC • To get handle to NULL object use GetStockObject function
Stock objects • Some pens, brushes and fonts are created by Windows and are called stock objects HBRUSH brush = GetStockObject( NULL_BRUSH ); HBRUSH oldBrush = SelectObject( hdc, brush ); Ellipse( hdc, 100, 100, 200, 200 ); SelectObject( hdc, oldBrush ); Draws empty circle (not filled with any brush) • You don’t have to call DeleteObject for stock objects, but you still have to select previously selected object to the device context
Font functions • CreateFont • CreateFontIndirect • SelectObject • SetTextColor • SetBkColor • SetBkMode (OPAQUE or TRANSPARENT) • GetTextMetrics
CreateFontIndirect void OnPaint( HWND hWnd, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); LOGFONT lf; memset( &lf, 0, sizeof( lf )); strcpy( lf.lfFaceName, "Arial" ); lf.lfHeight = 25; HFONT font = CreateFontIndirect( &lf ); HFONT oldFont = (HFONT)SelectObject( hdc, font ); TextOut( hdc, 0, 0, "TEST", strlen( "TEST" )); SelectObject( hdc, oldFont ); DeleteObject( font ); EndPaint(hWnd, &ps); }
Querying selected font • GetTextMetrics typedef struct tagTEXTMETRIC { /* tm */ int tmHeight; int tmAscent; int tmDescent; int tmInternalLeading; int tmExternalLeading; int tmAveCharWidth; int tmMaxCharWidth; int tmWeight; BYTE tmItalic;
TEXTMETRIC cont. BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmFirstChar; BYTE tmLastChar; BYTE tmDefaultChar; BYTE tmBreakChar; BYTE tmPitchAndFamily; BYTE tmCharSet; int tmOverhang; int tmDigitizedAspectX; int tmDigitizedAspectY; } TEXTMETRIC;
Text size on the screen • BOOL GetTextExtentPoint32( HDC hdc, char *str, int len, SIZE *lpSize ); - gets the size of the text • GetTabbedTextExtent • GetCharWidth32 - return width of characters • GetCharABCWidths - return A, B, C widths of characters
Text output functions • TextOut - simple function for outputting text • ExtTextOut - more control over the way the text is drawn • TabbedTextOut - for drawing text with \t characters • DrawText - multiple lines of text