[MFC] 6장: 마우스 입력

2011. 2. 25. 01:41

[ 교재 ]

열혈강의 Visual C++ 2008 MFC 윈도우 프로그래밍

저자 최호성 / 출판사 프리렉

6장: 마우스 입력

1. 마우스 메시지

윈도우에서 중요한 입력도구: 마우스

마우스 버튼은 기본적으로 좌, 우 그리고 중간에 휠이 존재.(요즘은 터치도 있다 ^^)

매번 하던 대로 MFC 응용 프로그램 프로젝트를 생성.

 

마우스 이동 시:

마우스 움직일 때마다 발생 - OnMouseMove

Point: 좌표

RedrawWindow: 윈도우 다시 그리기

윈도우를 그리는 OnPaint 함수를 추가해서

텍스트로 현재 마우스 좌표를 알려주는 코드를 삽입

마우스를 움직이면 좌표로 알려 줌

 

마우스 휠:

휠과 관련된 OnMouseWheel 함수를 보자

zDelta 값은 휠을 움직이는 속도를 알려준다.

디버그 모드로 보면 zDelta 값이 지정된 것을 확인할 수 있다

 

2. 마우스 움직임의 조합

  • 마우스 더블클릭 시:

더블클릭 시 사용할 OnLButtonDblClk

알림 창에서 TEST 문자열이 나타나도록 만듦

더블클릭 시 TEST 창 나타남

 

주요 마우스 이벤트 정리:

  • WM_MOUSEMOVE: 마우스 움직임에 따라 발생하는 메시지
  • WM_LBUTTONDOWN: 왼쪽 버튼을 눌렀을 때 발생
  • WM_LBUTTONUP: 누르고 떼었을 때 발생
  • WM_MOUSEWHEEL: 마우스 휠을 위/아래로 움직일 때 발생
  • WM_LBUTTONDBLCLK: 더블 클릭했을 때 발생

 

새로운 프로젝트 생성:

마우스 콤비네이션을 뜻하는 MouseCombi 프로젝트 생성

 

중단점 설정:

실제로 마우스 동작을 알아 보기 위해서

  • 마우스 누름
  • 누른 버튼 뗌
  • 더블 클릭

에 대해 각각 중단점을 설정

디버그 모드로 보면 클릭, 그리고 땠을 때의 결과가 나타남.

물론 더블클릭도 나타남.

뷰윈도우의…

멤버변수로 문자열 좌표 기억하는 것과 드래그 시작 여부를 구분하는 변수를 선언

함수 생성자에 문자열 출력할 좌표와 드래그 여부를 false로 설정.

드래그 여부에 따라 문자가 ---- 에서 DRAG 로 바뀌고, 그 밑에는 실제로 드래그에 쓰일 '내 컴퓨터' 문자를 생성

이렇게 생성 됨(아직 드래그 하는 중이 아니라서 ---- 와 같은 모양)

마우스 왼쪽 버튼을 눌렀을 때 드래그가 시작되어야 하므로 OnLButtonDown에 내용을 넣는다.

실제 드래그가 될 지점은 사각형 공간이므로 위에서 생성했던 '내 컴퓨터' 텍스트의 위치를 기준으로 사각형 공간을 생성해 주고, 이 안에서 마우스가 클릭되면 드래그가 시작(true)된다고 프로그램에 알려줌

실제로 테스트 해 보면 DRAG 문자로 바뀜

그리고 마우스 버튼이 놓아졌을 때 드래그를 멈춰야 하기 때문에 OnLButtonUp 함수에서 이를 설정해 줌.

마지막으로 놓은 위치에서 텍스트가 멈춰(그 자리에 위치)야 하기 때문에 현재 point 좌표를 텍스트의 좌표로 넘겨 줌

내 컴퓨터를 드래그 해서 놓은 모습. 그 자리에 텍스트가 멈춰선 것을 확인할 수 있다

하지만 DRAG 중에 이 텍스트가 따라다니지 않아 보기가 좋지 않다. 아래에서 이를 구현한다.

마우스가 움직일 때 발생하는 메시지를 핸들링하는 OnMouseMove 함수 선택

마우스가 드래그 될 때 좌표를 저장해 준다

(플래그는 초기화 하지 않아서 드래그 중인 상황이 계속 유지된다)

드래그 중에 마우스를 따라서 내 컴퓨터 텍스트가 따라 다니게 됨

 

드래그 앤 드롭의 ABC:

  1. WM_LBUTTONDOWN (클릭시작) – 위치 선정
  2. WM_MOUSEMOVE (마우스 이동) – 이동
  3. WM_LBUTTONUP (왼쪽 버튼에서 손가락을 뗌) – 위치 선정

 

3. 마우스 이벤트의 추적

지금까지 한 실습에는 버그 존재: 드래그 시 윈도우 벗어나면 제 역할을 못함 (텍스트에서 마우스를 떼고 있어도 눌린 것처럼 반응)

왜 발생했을까?

Mouse: 윈도우 특정적이다. 윈도우 범위를 벗어나면 해당 윈도우의 메시지를 받지 못한다.(마우스 이동하고, 뗀 것을 인식하지 못한다)

해결 방법은?

마우스 캡쳐(capture): 마우스 메시지를 윈도우 범위 밖에서 받을 수 있지만 버튼이 손가락에서 떼어졌을 때 좌표 계산을 잘못하면 그 개체가 다시 선택할 수 없는 상태로 변할 수 있다. (완전한 해결책이 아니라는 뜻이다.)

윈도우 범위를 벗어났을 때 적절한 처리를 해 주는 것을 고려하는 것이 좋다.

예를 들어: 왼쪽으로 갔을 때 사라졌다 -> MouseMove시 point 값이 음수일 때 적용하지 않으면 됨

왼쪽 버튼이 눌러졌을 때 캡쳐 시작

마우스 왼쪽 단추를 놓았을 때 캡쳐 해제

마우스가 범위를 벗어나도 캡쳐에 의해 계속 인식되고 있음을 확인할 수 있다

하지만 위에서 말했던 단점은 그대로 존재한다.

화면 왼쪽 바깥에 나갔을 때 강제로 x좌표를 0으로 함으로써 문제를 막는 코드

드래그 앤 드롭시 내 컴퓨터 텍스트가 더 이상 왼쪽으로 가지 않게 되어 컨트롤하기 수월하다

 

트래킹 윈도우 생성:

클래스 추가

MFC 클래스 추가

CTrackWnd 클래스 추가

클래스뷰에 등록된 것을 확인 가능

WM_CREATE 메시지를 받아올 OnCreate 메시지 핸들러 함수 추가

트래킹에 사용될 윈도우 생성. STATIC 윈도우에서 메시지를 캐치하려면 SS_NOTIFY 를 사용한다.

작은 차일드 윈도우가 생성된 것을 확인. 여기서 마우스 트래킹(마우스 올라온 것을 확인) 할 예정.

차일드윈도우 안에서 마우스가 움직이면 동작할 OnMouseMove 함수 추가

마우스가 움직이면 트래킹 중이라는 텍스트 메시지를 내보낸다.

실제로 차일드윈도우 안에서 마우스를 움직이면 Tracking 이라는 표시 나옴

하지만 마우스가 차일드 윈도우를 벗어나도 여전히 트래킹 중이라고 나옴. 수정 필요

마우스가 나갔을 때 알아차리려면(원래대로 돌아오려면) 마우스가 나가는 시점을 등록해 줘야 함.

차일드 클래스의 멤버 함수로 트래킹 중임을 구분하는 m_bTrack 을 선언

트래킹윈도우(차일드 윈도우) 생성자 함수 추가

윈도우 생성 시 트래킹 바로 시작할 필요 없기에 트래킹 여부 false 값을 넣어 줌

마우스가 트래킹 상태가 아니면(!m_bTrack)

트래킹을 시도하면 되겠죠.

={0} : 초기화

dwFlags = TME_LEAVE : 윈도우 영역을 벗어나면 WM_MOUSELEAVE를 전달해 달라는 뜻

m_hWnd: 윈도우의 핸들을 줘야 함

::_Track… : 함수 호출

트래킹에 성공하면 위 함수(TrackMouseEvent)가 True를 리턴함

트래킹에 성공하면(m_bTrack) 트래킹 상태를 표시.

마우스가 바깥으로 벗어나면

텍스트를 원래대로 TRACK TEST로 돌려 놓고, m_bTrack 상태를 false로 설정.

영역 안에서는 트래킹되고,

벗어나면 초기 상태(TRACK TEST 텍스트)로 돌아옴

 

결론:

위 사진에서 '실제'로 휴지통이 존재할까? 아니다. 단지 사용자들이 인터페이스 측면에서 접근하기 쉽도록 저 자리에 휴지통처럼 생긴 아이콘을 배치했을 뿐이다.

"있어 보인다" 는 게 정말 정말 중요. (User Interface 측면에서)

실제와는 상관이 전혀 없더라도, 그렇게(눈으로 볼 수 있게) 보여야 함!!

,