API

SetROP2 이용하여 반전효과 사용시 주의사항

디버그정 2011. 7. 12. 17:51

SetROP2에서 R2_NOT이나 R2_XORPEN를 줘서 반전효과를 이용하면
이전의 선들을 지우면서 이동할 수 있다.
그런데 기존에 인터넷에 돌아다니는 소스에는 좀 문제가 있다.
마우스 왼쪽 버튼 다운 메시지가 오면 파라미터로 전달된 좌표와 old x, old y 좌표를 일치시켜서 처리하는 식인데
이 경우 마우스 무브 첫 메시지 발생하고 그리는 과정에서 문제가 생긴다.

선을 그리는 함수의 좌표가 같은 경우, 가령 (100, 100) ~ (100, 100) 까지 선을 그린다고 하면
100, 100 위치에 선 굵기만한 점이 그려진다.
그래서 첫 마우스무브 메시지에서 일단 선굵기 크기의 점을 그리고 그 다음에 시작지점부터 마우스무브 좌표까지의 선을 그린다.
이 결과 첫 점 부분이 다시 반전이 되어 원래의 배경색이 된다. 굵은 선으로 테스트해 보면 그 결함이 쉽게 드러난다.
이를 수정하기 위해서는 따로 BOOL 변수를 두어서 첫 무브시에는 2번 그리는 처리를 하지 않아야 된다.

           

              < bad>                                          <good>

왼쪽 그림에서 선의 시작부분에 원형점 모양으로 뻥 뚫린다. 



// 소스 참조

~~~~~~~ WndProc~~~~~~~
static BOOL bLBtnDown = FALSE, bFirstMoveCheck = FALSE;


case WM_LBUTTONDOWN:
   xStart = LOWORD(lParam);
   yStart = HIWORD(lParam);
   bLBtnDown = TRUE;
   bFirstMoveCheck = TRUE;
   break;



case WM_MOUSEMOVE:
   if (bLBtnDown)
   {
    hdc = GetDC(hWnd);
    hPen = CreatePen(PS_SOLID, 20, RGB(255, 255, 0));
    hOldPen = (HPEN)SelectObject(hdc, hPen);
   
   // SetROP2(hdc, R2_NOT);
    SetROP2(hdc, R2_XORPEN);

    // 첫 마우스 무브시는 이전에 그린 것에 대한 처리를 하면 안된다.
    // 참고로 아래와 같이 처리하지 않고 WM_LBUTTONUP 메시지 처리부분에서 x = xStart, y = yStart 이렇게 대입하고
    // 아래와 같은 조건문 없이 처리하는 방식이 있는데 이 방법은 문제가 있다.
    // 왜냐하면 첫 마우스무브 메시지에서 일단 선굵기만한 점을 그리고
    // (선그리기 함수의 시작좌표와 끝좌표가 같으면 선굵기의 점을 그린다.)
    // 그 다음에 시작지점부터 마우스무브된 좌표까지의 선을 그린다.
    // 그 결과 앞서 그려진 점 부분이 다시 반전이 되어 원래의 배경색이 된다.
    // 굵은 선으로 테스트해 보면 그 결함이 쉽게 드러난다.
    if (bFirstMoveCheck)
    {
     bFirstMoveCheck = FALSE;
    }
    else
    { 
     MoveToEx(hdc, xStart, yStart, NULL); // 이전에 그린 선 다시 그려줌으로써 배경그림으로 다시 복귀함.
     LineTo(hdc, x, y);
    }

    x = LOWORD(lParam);
    y = HIWORD(lParam);
    MoveToEx(hdc, xStart, yStart, NULL);
    LineTo(hdc, x, y);
    
    SelectObject(hdc, hOldPen);
    DeleteObject(hPen);
    ReleaseDC(hWnd, hdc);  
   }
   break;