본문 바로가기

Study Memos/Windows Programming

WM_PAINT(Section 24)

참고> blog.naver.com/tipsware/221119932350

 

1. Windows 운영체제는 특정 Window의 일부 또는 전체 영역을 다시 그릴 필요가 있다고 판단하면 해당 WIndow에 WM_PAINT 메시지를 전송함
-> Window가 다른 Window에 의해 영역이 가려지는 경우, 모니터 바깥으로 Window가 나가는 경우 등 Window를 다시 그려야 하는 상황이 종종 발생.
But, 정작 해당 Window의 응용 프로그램은 다시 그려야됨을 알지 못하기 때문에 Windows 운영체제가 WM_PAINT로 알려줌.

 

2. Windows 운영체제는 윈도우의 기본적인 동작을 관리하기 위해서 윈도우의 특정 영역에만 그림을 그릴 수 있도록 허용하고 있음.
-> ex) 윈도우의 타이틀바나 윈도우의 테투리 영역은 기본적으로 운영체제가 관리하기 때문에 이 영역에 직접 그림을 그릴 수 없음. 물론, 고급 기술을 사용하면 가능하긴 함.

3. 무효화 영역: 모니터 밖으로 나간 윈도우의 영역
-> 윈도우가 다시 모니터 안쪽으로 다시 이동해서 무효화되었던 영역이 다시 유효 영역이 되더라도 해당 영역에 그려져있던 그림은 이미 지워졌기 때문에 윈도우에 표시되지 않음.
4. 무효화 영역의 복구
-> Windows 운영체제는 무효화된 영역이 유효 영역으로 변경되는 경우, 응용 프로그램이 스스로 지워졌던 그림을 복구할 수 있도록 복구가 필요한 영역의 정보를 담은 WM_PAINT 메시지를 해당 응용 프로그램에 전달
-> 윈도우에 어떤 정보를 지속적으로 출력하고 싶다면 WM_PAINT 메시지를 처리하는 작업을 해야 함.

 

5. WM_PAINT에서 그림을 그리는 작업은 윈도우 전체가 아닌 윈도우의 일부분 일수도 있기 때문에 GetDC 함수가 아닌 BeginPaint 함수를 사용해서 DC를 얻어와야 함.

6. BeginPaint 함수가 사용하는 tagPAINTSTRUCT 구조체의 멤버 변수 중 fErase 값이 0이 아니면 윈도우의 배경을 WM_PAINT에서 그려야 함.
-> 보통 윈도우 배경을 그리는 작업은 WM_ERASEBKGND 메시지에서 처리
-> WM_ERASEBKGND 와 WM_PAINT 둘 다 그리기를 시도할 경우, WM_ERASEBKGND 작업은 무시됨.

7. 필요한 영역만 그림을 그릴 수 있는 DC 핸들 값은 BeginPaint 함수를 통해 얻을 수 있다.
-> ex) PAINTSTRUCT ps;
HDC h_dc = BeginPaint(hWnd, &ps);

-> h_dc를 새로 선언할 필요 없이 ps.hdc를 사용해도 됨.

 

8. EndPaint: BeginPaint 함수 이후 그리기 작업이 모두 끝나면 EndPaint 함수를 사용하여 dc를 반환해야 함.

9. WM_PAINT 메시지에 대한 처리 작업은 중복해서 이루어지면 안 되기 때문에 WM_PAINT 메시지를 직접 처리했다면 DefWindowProc 함수가 호출되지 않도록 return 문을 사용하여 WndProc 함수를 종료시켜야 함.

10. 작업의 우선 순위 측면에서 시스템이 화면에 어떤 것을 그리는 작업보다는 실제 처리 작업에 우선 순위를 부여하는 경우가 많음
-> 메시지가 많이 발생해서 작업에 부하가 생기면 Windows 운영체제는 그리기와 관련된 메시지(WM_PAINT, ...)들은 다 무시하고 일반 메시지부터 처리
-> 그리는 작업은 어차피 맨 마지막 그리기만 화면에 남으므로, WM_PAINT 메시지가 100번 중복 발생해도 다 무시하고 한번만 그리기 작업을 수행

11. Windows 시스템은 WM_PAINT 같이 우선순위가 낮은 메시지들은 "메시지 큐"에 넣지 않고 'FLAG 메시지'로 구분하여 "메시지 테이블"로 관리

12. WM_PAINT에서 DC를 얻기 위해 BeginPaint 함수 대신 GetDC 함수를 사용해도 되지만, 이렇게 하면 다시 그려야 할 부분뿐만 아니라 매번 윈도우 영역 전체를 다시 그리기 때문에 비효율적임. 느려진다..
-> 또 다른 이유로, BeginPaint 함수를 사용하면 WM_PAINT 메시지의 상태 값이 1에서 0으로 변경되어 WM_PAINT 메시지가 처리되었음을 알려주지만,
GetDC 함수를 사용하면 이 플래그 값을 바꿔주지 않기 때문에 WM_PAINT 메시지가 또다시 발생하는 것처럼 동작함. 즉, CPU가 수행 가능한
만큼의 속도로 계속 반복해서 WM_PAINT가 발생하기 때문에 프로그램이 아무런 작업도 하지 않는데 40% 정도의 CPU를 사용하게 됨.
-> 따라서, WM_PAINT 메시지 처리 루틴에서는 GetDC 함수를 절대 사용하면 안 되고 BeginPaint 함수를 사용해서 DC를 사용해야 함.

반응형

'Study Memos > Windows Programming' 카테고리의 다른 글

BitBlt (Section 26)  (0) 2020.09.16
WM_CREATE (Section 25)  (0) 2020.09.16
사각형 그리기 (Section 23)  (0) 2020.09.15
POINT (Section 22)  (0) 2020.09.07
GetDC & ReleaseDC (Section 21)  (0) 2020.09.07