WinAPI32 PeekMessage (1)

CJB_ny·2022년 8월 23일
0

WinAPI

목록 보기
5/79
post-thumbnail

물체가 여러개있고 존나 움직일때

WM_PAINT가 반복적으로 일어나야한다.

그래서 곂칠수도있고해서 다른 물체들 영향 받는다.

그 물체 하나가 움직였기 때문에

그 물체의 색상값들을 지워야함.

(픽셀 메모리 255 255 255?)

그래서 게임이라는 것은 매순간순간 렌더링 해주어야한다.

여기서 frame 개념이 나온것임.

초당 화면 렌더링 횟수가 60프레임이 되어야 끊김없다고 느껴진다.

물체가 몇개 있을 줄 모르니까

vector

이렇게.

vector자체는 전역변수이지만 관리는 힙에서 한다.

전역으로 좌상단 좌표일단 맨듬.

키 눌렸을때 이것을 기억하도록 하겠다.

얘는 마우스를 조금이라도 움직이면 감지를 하는 메세지이다.

이때는 오른쪽 하단을 기억 하도록 하겠다.

그러면 이런식으로 됨.

그런데 화면 ㅈㄴ 깜빡거림.

여기서 마우스 버튼을 땟을때 사각형을 추가를 하도록 할 것이다.

이따위로 해주도록 하자.

그리고 내가 새로 클릭하기전 까지는 그림을 그리면 안되니까

boolean값하나 만들어서

이렇게 해주자 그런데

마우스 왼쪽 누르고 당긴다음에 가만히 있으면 마지막에 그린거 그대로 그려진 상태로 가만히 있기때문에

버튼을 때고 false로 되돌린다음에 한면 InvalidateRect호출 해주어야.

무효화 영역이 발생했다고 알려주고

g_lButtonDown이 false이기 때문에 여기서 안그리게 된다.

vector안에 추가된 애들 그리기

이렇게 그려주도록 하자.

지금 ㅈㄴ 깜빡이는데 이게 사양이 낮아서 그런가?>

ㄴㄴ.

무효화 영역을 전체로 발생시켜서 그렇다? ㄴㄴ

화면 깔끔하게 다 지우고 존재하는 물체 다시 그리는게 '렌더링' 과정 이다.

이게깜빡이는 이유? ㄴㄴ.

깜빡이는 원인 ❓

현재내가 마우스만 움직이도

Invalidate호출한다. => 그때마다 WM_PAINT발생해서

여기서

싹다 다시 그려진다.

나의 지금 이화면도 거대한 픽셀 덩어리 이다.

픽셀하나하나에다가 색을 채우는 작업을 엄청나게 빠른 속도로 한다.(사람은 상상도 할 수 없을 정도로)

이렇게 추가를 하는 과정에서

이렇게 우리는 화면을 보고있다.

이거는 속도의 문제가 아니라 '타이밍'의 문제이다.

사람의 뇌는 초당 60~100번 내지의 움직임을 '인지'를 한다.

총알

1/60초 의 공백동안 총알이 날아가버림. 내 시야 내에서

그러면 총알은 없어진거처럼 느껴짐.

윈도우가

WM_PAINT를 통해서 50개의 사각형을 그릴때

내가 어느순간 그 장면을 볼 것이다.

(그리는 과정을)

윈도우는 다시 50개를 다 채우고 화면을 지우고

다시 50개 그리고 채우면 다시 지우고...

내가 만약 한 30개쯤 채웠을 때 화면을 봐서 그것을 인지를 했다 치자.

어쩔때는 50개를 다 그리고 봤을 수도있다.

이게 무수하게 반복이 된다. 어마어마 하게 빠른 속도로...

초고속 카메라로 찍으면 아마 하나 그리고 지우고 이게 보일텐데

우리가 인지하는 순간은 한순간 한순간이라 깜빡깜빡 거린다고 느껴지는 것이다.

그래서

해결하는 방법

이런 문제를 해결하기 위해서 어떻게 하냐하면은

그림이 그려질 '도화지'에 해당하는 '픽셀 데이터'를

2개를 관리를 할 것이다.

우리는 지금 그림을 그릴 '도화지'를 한장을 준비를 했기 때문이다.

화가가 그림 그리는 장면 감추고있다가 다 완성되고 보여주어야하는 것처럼

벡터에있는 50개의 사각형이 다 그려져야지 '완성' 아니노?

중간에 그리는 과정을 계속 보여주는게 아니라.

ㅇㅋ?

이런식으로 해서 깜빡거리는 현상을 해결할 수 있다.

그런데 이 프로그램에 더 큰 문제점은 '메세지'가 존재 하지 않으면

동작을 하지 않는다.

코드가 '이벤트'가 없으면은 '윈도우 메시지'가 존재 하지 않는다면

매순간순간 변경점을 체크를 해서 살아있는 것처럼 동작하게 해주어야한다.

순환이 되면서 돌아가야한다.

이런데에서 '구조적'인 문제가 발생한다.

이런 부분들을 해결하기 위해서 구조를 변경해야하는데

강제로 일정시간동안 메세지를 일정하게 발생시켜서 강제로 돌아가도록 하는 방법도 있다.

강제로 돌아가게 하기.

이렇게 전역으로 HWND하나 만들어서 여기서 할당받아서 사용하도록 해주고.

여기서 타이머를 부착시킬 녀석은 g_hWnd이다. 라고 타이머 달아줌.

해당 타이머의 id는 0, 지연시간을 최대한 없게 하기 위해 0, 호출 시킬 함수는 없으니까 nullptr

이렇게 타이머를 부착시키면 내가 설정한 시간(지연시간)

1000을 넣으면 1초임 그러면 단위는 ms이다.

이렇게하면 1초에 한번씩 메세지가

WM_TIMER라는 메세지가 들어온다.

메세지가 계속 발생을 해서 이안으로 들어오니까

여기서 이제 물체들이 움직이게 하거나 그런 것들을 수행하고

Invalidate를 적절하게 발생시켜서 다시 그려주게 하면 될 것이다.

근데 1초에 한번씩 호출되면 1프레임이다.

그그래서 프로그램 성능이 허용하는 최대 성능인 지연시간을 0으로 해준다.

내가 0으로 했다고 해도 실질적인 0초는 아니다.

또한 타이머 역시 커널오브젝트이기 때문에

프로그램 종료할때 제거 시켜달라고 요청해야한다.

아까 id값 0번 붙여준거 주면은 된다.

정리

타이머를 설정을 해서 우리 윈도우가 계속해서 일을 할 수 있도록

만들어 주었다.

메세지가없다고 가만히 있는 것이 아니라 계속해서 변환점을 돌릴 수 있게 '강제로' Timer를 만들어서 메세지를 발생시킴.

그런데 이게 ㅈㄴ 느리다.

윈도우에서 제공하는 '메세지큐'에다가 '메세지'를 집어놓고

집어 넣은 '메세지'를 꺼내와서 처리하기 위해서

'처리기 함수'로 보내고 '처리기 함수'에서 메세지를 처리를 해주는 과정이다.

이러한 과정을 매 프레임마다 실행시키는게 너무나도 느리고

'비효율적'이다.

그래서 이런 방법으로 클라를 구성하지 않을 것이고,

'윈도우 메세지 처리 기반 방식을 최대한 사용하지 않는 방식'으로 구현할 것이다.

윈도우 메세지를 처리하는게 프로그램인데

이것을 최대한 처리 하지 않겠다라는 말이 뭐노?

=> 방법이 있다.

우리는

이런 메세지를 처리하는 쪽을 거의 사용하지 않을 것이다.

처기리로밖에 처리할 수 없는 상황이 아닌이상

대부분의 경우 '메세지 처리기'없이 처리를 할 수 있다.

그래서 여기 '메세지 처리 기반 구조'를 조금 변경할 것이다.

설계방식 구조를 변경할 것이다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글