마우스를 움직임에 따라서 그림을 다시 그릴 때
Invalidate함수를 호출하는 것을 부적절할 수 있습니다.
왜냐하면 Invalidate는 전체 화면을 다시 그리기 때문입니다.
최소한으로 화면을 갱신하기 위해서는 이전에 그림이 있던 곳을 지우고
그림이 새로 움직인 위치에 그림을 표시해주면 됩니다.
이러한 처리를 하기에 적절한 곳은 OnMouseMove함수입니다.
왜냐하면 OnDraw함수에서는 그림을 움직임으로써 어느 부분을 새로 그려야 하는지
알 수가 없기 때문입니다.
물론 OnDraw함수에서 GetClipRect라는 함수를 사용하여 다시그리게 될 영역을
한정해 줄 수는 있습니다. 이렇게 하기 위해서는
InvalidateRect함수를 사용해서 무효화영역을 설정해 주어야 합니다.
위 내용을 다음과 같이 3가지로 정리할 수 있습니다.
1) OnDraw함수에서 모든 영역을 그리는 방법 : 간단하나 필요없는 부분도 다시 그리게
되므로 비효율적일 수 있다.
2) MouseMove함수에서 InvalidateRect함수로 무효화영역을 설정한 후에
OnDraw함수에서 GetClipRect로 무효화 영역을 얻어서 이 부분에 대해서만
다시 그리기를 해주는 방법
3) MouseMove에서 Invalidate나 InvalidateRect함수를 전혀 사용하지 않고
직접 화면에 그려주는 방법. 물론 그림의 위치에 관한 정보가 갱신되어야 하고
프로그램이 최소화되었다가 복구될 때 전체 화면이 그려지게 되면 이것은
OnDraw함수에서 처리하게 됨.
위 내용 중에 1번을 사용하여 프로그램을 하나 짜 보았습니다.
간단하기 때문에 선택하였는데, 그림의 깜박거림은 거의 관찰되지 않았습니다.
2번이나 3번을 구현하게 되면 일반 상용프로그램과 같은 수준의 구현이
될 수 있을 것입니다.
이동중에 그림이 깜박 거리는 것은 위 3가지 방법들과는 별개로 double buffering과
OnEraseBkgnd함수에서 return FALSE를 사용하지 않았기 때문으로 보입니다.
위과 같이 화면 깜박임을 최소로 한 경우에도 위와 같은 소프트웨어적인 방법을
사용하여 화면 전체를 검은색과 흰색으로 교대로 표시하게 될 경우에 화면의 깜박거림을
볼 수 있는데, 이는 하드웨어(모니터, 그래픽카드, 메인보드, CPU, 칩셋 등)에 의한 영향일
것입니다.
메일 주소를 쪽지로 보내주시면 프로그램을 보내드리겠습니다.
- 추가답변
GetClipBox가 맞습니다. GetClipRgn함수도 있는데 이것은 GetClipBox보다
사용하기가 조금 어려울 것 같습니다.
http://www.codeproject.com/gdi/flickerfree.asp
위 사이트에 CDC클래스를 이용하여 Back Buffer를 CBitmap으로 구현한
좋은 클래스가 소개되어 있습니다. 참고하시기 바랍니다.
OnEraseBkgnd함수를 사용하고 안에서 return FALSE; 라고 작성했다면,
배경을 그리는 것은 OnDraw함수에서 해주어야 합니다.
그렇게 되어 있는지도 확인해보시기 바랍니다.
댓글