9.19(수) 실습-2

2007/10/10 18:49

1. 그리기 모드를 사용하여 선그리기.
[ more.. | less.. ]

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static POINTS ptFrom, ptTo;

    switch( msg )
    {   
    case WM_CREATE:

        return 0;
    case WM_LBUTTONDOWN:
        ptFrom = MAKEPOINTS(lParam);
        ptTo   = MAKEPOINTS(lParam);
        {
            HDC hdc = GetDC(hwnd);
            Rectangle( hdc, 100, 100, 200, 200 );
            ReleaseDC(hwnd, hdc);
        }
        SetCapture( hwnd );
        return 0;
    case WM_LBUTTONUP:
        {
            if( GetCapture() == hwnd )
            {
                ReleaseCapture();
                HDC hdc = GetDC(hwnd);
                MoveToEx( hdc, ptFrom.x, ptFrom.y, 0 );
                LineTo( hdc, ptTo.x, ptTo.y );

                ReleaseDC( hwnd, hdc );
            }
        }
        return 0;

    case WM_MOUSEMOVE:
        if( wParam & MK_LBUTTON )
        {
            POINTS pt = MAKEPOINTS(lParam);

            HDC hdc = GetDC( hwnd );
            SetROP2( hdc, R2_NOTXORPEN );    // 그리기 모드를 반전 모드로 만든다.

            MoveToEx( hdc, ptFrom.x, ptFrom.y, 0 );
            LineTo( hdc, ptTo.x, ptTo.y );

            MoveToEx( hdc, ptFrom.x, ptFrom.y, 0 );
            LineTo( hdc, pt.x, pt.y );

            ptTo = pt;

            ReleaseDC( hwnd, hdc );
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

2. Region의 활용
[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static char str[] = "Clipping Region Test";
    static HRGN hRgnUp, hRgnDown;
    static int cx, cy;

    switch( msg )
    {   
    case WM_SIZE:
        cx = LOWORD(lParam);
        cy = HIWORD(lParam);
        DeleteObject( hRgnUp );
        DeleteObject( hRgnDown);
        hRgnUp = CreateRectRgn( 0, 0, cx, cy/2 );
        hRgnDown = CreateRectRgn( 0, cy/2, cx, cy );
        return 0;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint( hwnd, &ps );

            HFONT hFont = CreateFont(
                72, 0, 0, 0, FW_BOLD, 0, 0, 0, 0,
                0, 0, 0, 0, "Tahoma" );
            HFONT hFontOld = (HFONT)SelectObject( hdc, hFont );
            RECT rc = { 0, 0, cx, cy };

            SetTextColor( hdc, RGB(255, 0, 0) );
            SelectClipRgn( hdc, hRgnUp );
            DrawText( hdc, str, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER );

            DeleteObject( SelectObject(hdc, hFontOld) );
            EndPaint( hwnd, &ps );
        }
        return 0;


    case WM_LBUTTONDOWN:
        {
            HDC hdc = GetDC( hwnd );

            HRGN h1 = CreateEllipticRgn( 0, 0, 300, 300 );
            HRGN h2 = CreateRoundRectRgn( 200, 200, 400, 400, 30, 30 );
            HRGN h3 = CreateRectRgn( 0, 0, 0, 0 );
            CombineRgn( h3, h1, h2, RGN_XOR );

            // 영역의 활용 3. DC의 클리핑 영역 제한 - ( 텍스트의 색 부분 바꾸기 )
            char s[] = "asdasdasddddddiijijijioijoioijoijijojojojojoijoj";
            TextOut( hdc, 10, 20, s, strlen(s) );
            SelectClipRgn( hdc, h1 );
            SetTextColor( hdc, RGB(255, 0, 0) );
            TextOut( hdc, 10, 20, s, strlen(s) );

            // 영역의 활용 2. - Hitting Test( Region 영역 클릭 테스트 )
            //POINT pt = { LOWORD(lParam) , HIWORD(lParam) };
            POINTS pt = MAKEPOINTS( lParam );
            if( PtInRegion( h1, pt.x, pt.y ) )
                MessageBox( hwnd, "In Region", "", MB_OK );

            // 영역의 활용 1. - 비정형 윈도우(윈도우창 가리기)
            SetWindowRgn( hwnd, h2, TRUE );

            DeleteObject( SelectObject( hdc, GetStockObject( BLACK_BRUSH ) ) );
            DeleteObject( h1 );
            DeleteObject( h2 );
            DeleteObject( h3 );
            ReleaseDC( hwnd, hdc );

        }
        return 0;

    case WM_DESTROY:
        DeleteObject( hRgnUp );
        DeleteObject( hRgnDown );

        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}


3. WM_PAINT(1) : 마우스 움직일때마다 사각형 그리고 계속 그려주기.
[ more.. | less.. ]

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static vector<POINTS> v;

    switch( msg )
    {
    case WM_MOUSEMOVE:
        {
            POINTS pt = MAKEPOINTS( lParam );
            HDC hdc = GetDC( hwnd );
            Rectangle( hdc, pt.x, pt.y, pt.x + 50, pt.y + 50 );

            v.push_back( pt );
            ReleaseDC( hwnd, hdc );
        }
        return 0;
    case WM_PAINT:
        {
            //HDC hdc = GetDC( hwnd );
            //HideCaret( hwnd );
            // WM_PAINT를 처리 할떄는 반드시 무효화 영역을 유효화 영역으로
            // 변경해야 한다. 즉, QS_PAINT 플래그를 0으로 해야 한다.
            //ValidateRect( hwnd, 0 );
            //ShowCaret( hwnd );
            //ReleaseDC( hwnd, hdc );

            PAINTSTRUCT ps;
            HDC hdc = BeginPaint( hwnd, &ps );
            for( int i = 0; i < v.size(); ++i )
                Rectangle( hdc, v[i].x, v[i].y, v[i].x + 50, v[i].y + 50 );
            EndPaint( hwnd, &ps );
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

4. WM_PAINT2
[ more.. | less.. ]
// 화면에 스코어를 그리는 부분을 함수로 만들고 싶다.
// 1. HWND 를 받아서 내부적으로 DC를 구하자. ( BeginPaint, GetDC 문제가 생긴다. )
// 2. HDC를 받아서 바로 사용하자. - OK..
void DrawScore( HDC hdc, int x, int y, int score )
{
    // 여기서 x, y 좌표에 비트맵을 사용 score를 그려준다.
}
//-------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static char s[] = "hello";

    switch( msg )
    {
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint( hwnd, &ps );

            for( int i = 0; i < 500; i+=10)
                Rectangle( hdc, i, i, 1000-i, 1000-i );

            TextOut( hdc, 10, 10, s, strlen(s) );
            EndPaint( hwnd, &ps );
        }
        return 0;
    case WM_LBUTTONDOWN:
        {
            // 출력물이 변경되었다. !!!!
            strcpy( s, "xxxxx" );
            // 출력물을 다시 그려야 한다. - 어떻게 ??
            // 1. 강제로 무효화영역을 만들자. - 꼭 필요한 곳을 계산해서 무효화하라.
            // InvalidateRect( hwnd, 0, TRUE );
            //RECT rc = { 10, 10, 100, 40 };
            //InvalidateRect( hwnd, &rc, TRUE );

            // 2. WM_PAINT 가 복잡한 코드가 많다면 성능 저하가 발생할 수도 있다.
            // 간단한 그림은 직접 그리자. - 코드가 중복될 수 있는 단점은 있다.
            HDC hdc = GetDC( hwnd );
            TextOut( hdc, 10, 10, s, strlen(s) );
            ReleaseDC( hwnd, hdc );
        }
        return 0;
    case WM_RBUTTONDOWN:
        {
            strcpy( s, "xxxxx" );
            // 다시 그리기 위해 무효화 영역 발생 메시지Q에 넣어주기만 한다.
            InvalidateRect( hwnd, 0, TRUE );

            // if( msg Q has WM_PAINT ) WndProc( hwnd, WM_PAINT ); 즉시 반영!!
            UpdateWindow( hwnd );
            // 다른 작업을 한다. - 5분 걸린다고 가정.
            for( int i = 0; i < 100000000; ++i );
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }



Tags

API, 실습