WinAPI 49 UI (3)

CJB_ny·2022년 9월 27일
0

WinAPI

목록 보기
50/79
post-thumbnail

오늘 배운거 👍👍👍

  • 재귀함수로 접근?

  • Level 순회

  • Level 순회로 접근 할 시 나중에 검사하는 애가 우선순위가 높다 라고 생각하게 된다.(재귀함수로 접근할 시 문제점 생각)

  • Level 순회 & Queue ❗❗❗


UI 자식 UI보유할 경우를 생각해서

설계를 할 것이다.

1번 버튼을 클릭을 해도 부모 UI한테 이벤트가 가는 상황이다.

그러면 1번 클릭시 -> 부모한테도 + 1번 버튼(자식) 한테도 둘다 알려줄까?

보통 일상적으로 경험하기에 부모한테는 이벤트 전달 해주지 않는다.

현재 update에서 이런식으로 도는데 vecUI는 최상위 부모만을 기준으로 클릭이벤트를 확인하고있다.

저기 클릭이벤트를 확인 하는 부분을 자식도 다같이 확인 받을 수 있게 함수를 만들어 주도록 하자.

저 vecUI안에 부모가 자식들을 다 가지고있기로 약속했으니까.

마우스 올라갔을 때 기준으로 타겟팅이 된 녀석을 반환을 할 함수이다.

타겟팅된 녀석으로만 이벤트르를 처리를 해주면된다.

이런식으로 target으로 현재 타겟을 확인하다가 자식 UI도 확인을 하다가 조건에 걸리면은 target을 변경해주어야 한다.

이런식으로 접근을 할것이다.

레벨 순회

이런방식으로 순회를 할 것인데 이게 'Level 순회' 라고한다 (다했던 거임)

레벤 순회로 접근을 할 것인데 GetTargetUi함수를 재귀함수로 접근을 한다고했다.

이런 레벨 순회로 할 경우 마지막에 검사하는 레벨이 우선순위가 높다.

=> 생각하기 편하다.

이런 레벨 순회로 검사를 하는 경우에는 재귀함수로 구현하지 않는다.

큐 활용

"queue"를 활용할 것이다.

큐와 대칭되는 구조는 Stack이다.

ㅇㅇ.

우리는 1 -> 2 -> 3 -> ... -> 9 접근 해야함.

FIFO => Queue

동작방식 ❗❗❗

부모를 찾아서 큐에넣고 확인 => 자식이 있을 경우 자식들을 큐에 넣는다.

1번은 확인이 끝났고 2번 확인을 한다.

2번은 꺼내서 제거가 됬고 2번의 자식을 큐에 넣는다.

이렇게.

3번 확인후 7번을 그다음에 넣는다.

이 순서로 접근을 하면은 1 -> 2 -> .. -> 9 원하던 Level순회이다.

Queue container필요

일시적으로 Queue역할을 할 Container가 필요하다.

데이터를 넣고 바로 빼고 이거 반복할 것인데 제일 효율 좋은 애가 누구인가??

"리스트"를 큐처럼 쓰면 되는거 아닌가?

데이터를 집어넣고 앞에있는거 삭제할 때 동일한 효율을 낼 수 있는 녀석.

큐는 오히려 기능이 제한되어있다.

그래서 리스트를 큐처럼 사용하고 queue가 텅 빌때까지 반복할 것이다.

이까지하면 큐에서의 첫번째 데이터를 '가져오는 작업'까지는 굿.

지우지는 않았다 아직.

이렇게 pop해주고 자식이 있다면 보유하고있는 자식을 싹다 큐에다가 집어넣어준다.

현재 이 while문이 끝났다는 것은 부모(본인)포함 모든 UI를 싹다 뒤져봤다는 소리이다.

처음에 targetUI를 nullptr로 해주고 이게 만약 그대로 nullptr이면 아무것도 타겟팅 된게 아니다.

이제 86번째 줄에서 조건체크를 통해서 targetUI = ui를 해줄 것이다.

조건 체크

IsMoiseOn함수를 호출해서 마우스가 위에있는지를 확인을 할 것이다.

그런데 있다고해서 바로 MouseOn함수를 호출하지는 않을 것이다.

왜냐하면은 현재 front()로 꺼내온 ui녀석이 targetUI라는 확신이 없다.

그래서 바로 호출은 하지 않고 이녀석이 targetUI이지 않을가..??하고 일단 변경만 해준다.

그리고 else문에서 awayLbtn일 경우 ui->lbtnDown = false;로 해주는 부분은

이번프레임에 마우스를 땐 상황이라면은 이전프레임에 마우스를 눌렸을 수도 있으니까.

이거는 모든 UI가 검사를 받아야한다.

그래서 이상태로 while문을 싹 돌고나면은 마지막에 targetUI가 들고있는 주소가

가장 낮은 계층인 상태에서 마우스가 위에 올라가있기 때문에

현재 targetUI를 타겟팅 하고 있다고 볼 수 있다. 그리고 그것을 반환해 줄 것이다.

update에서 바로 이렇게 체크를 할게 아니라

GetTargetUI를 호출 해야한다.

이제 이녀석에 대해서 이벤트 체크를 해주면 된다.

마우스 체크 검사 코드

	for (size_t i = 0; i < vecUI.size(); ++i)
	{
		UI* ui = dynamic_cast<UI*>(vecUI[i]);

		// 튀어 나온게 targetUI이다.
		ui = GetTargetUI(ui);


		// 마우스 UI에 있는지 체크
		if (ui->IsMouseOn())
		{
			// UI위에있다고 얼려준다.
			ui->MouseOn();

			// 경우는 두가지로 나뉨.
			if (tapLbtn)
			{
				ui->MouseLbtnDown();
				ui->_lbtnDown = true;
			}
			else if (awayLbtn)
			{
				ui->MouseLbtnUp();

				// 클릭할 경우
				if (ui->_lbtnDown)
				{
					ui->MouseLbtnClick();
				}

				ui->_lbtnDown = false;
			}
		}
		else
		{
			// 마우스 위에 있지 않을 경우
			// 왼쪽버튼 때면, 눌렸던 체크를 다시 해제한다.
			if (awayLbtn)
			{
				ui->_lbtnDown = false;
			}
		}
	}

IsMouseOn 체크는 하지 않을 것이다.

당연히 타겟팅 함수 호출 하는 과정에서 타겟팅(마우스 위에 올라가있는)되었으니까 튀어 나온 부분이니까

모순이 생기는 부분

현재 이부분에서 ui->lbtnDown부분에 걸리지가 않는 문제가있는데

update를 돌다가 GetTargetUI를 호출하는 과정에서

ui를 이렇게 눌렀다! 그리고 마우스를 밖에서 땟다면은

한 때는 targetUI라서

true가 됬지만 바깥에서 마우스가 때졌기 때문에

이부분에서는 걸리지 않는다는 것이다.

애초에 지금 이 조건 체크를 하는게 targetUi가 nullptr이 아닐 경우에 체크를 하고있으니까

그러니까 ui->_lbtnDown = false로 되돌아 가지도 못한 것이고

그래서 그런 녀석들을 위해서 GetTargetUI에서

이렇게 다 false로 밀어 주었었다.

그래야 타겟팅된 UI 밖에서 마우스를 땟어도 타겟팅 되었던 ui의 마우스가 때진 상태로 인식이 될 것이니까

피해를 보는 쪽은 타겟팅 된 UI사이즈 안에서 눌럿다가 땟었을 때 클릭이벤트 호출이 안된다.

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

0개의 댓글