mfc 와 마우스
DESCRIPTION
MFC 와 마우스. Department of Digital Contents Sang Il Park. Review: Rgn: 다각형 영역 객체. 다각형 (Polygon). 점들의 집합으로 정의됨. Review: CRgn: 다각형 영역 객체. 사용방법. 점의 배열. 점 갯수. style. CRgn rgn rgn.CreatePolygonRgn( CPoint * pt, int nNumber, int nStyle) dc.PaintRgn(&rgn);. nStyle: ALTERNATE or WINDING. - PowerPoint PPT PresentationTRANSCRIPT
MFC 와 마우스
Department of Digital Contents
Sang Il Park
Review: Rgn: 다각형 영역 객체
• 다각형 (Polygon)
점들의 집합으로 정의됨점들의 집합으로 정의됨
Review: CRgn: 다각형 영역 객체
• 사용방법
CRgn rgnrgn.CreatePolygonRgn( CPoint * pt, int nNumber, int nStyle)
dc.PaintRgn(&rgn);
점의 배열 점 갯수 style
nStyle: ALTERNATE or WINDING
Review: CRgn: 다각형 영역 체
• 예제
CRgn rgn;CPoint ptVertex[5];ptVertex[0] = CPoint(180,80);ptVertex[1] = CPoint(100,160);ptVertex[2] = CPoint(120,260);ptVertex[3] = CPoint(240,260);ptVertex[4] = CPoint(260,160);
rgn.CreatePolygonRgn( ptVertex, 5, ALTERNATE);dc.PaintRgn(&rgn);
CRgn rgn;CPoint ptVertex[5];ptVertex[0] = CPoint(180,80);ptVertex[1] = CPoint(100,160);ptVertex[2] = CPoint(120,260);ptVertex[3] = CPoint(240,260);ptVertex[4] = CPoint(260,160);
rgn.CreatePolygonRgn( ptVertex, 5, ALTERNATE);dc.PaintRgn(&rgn);
Review: CBitmap
• 사용법 : Brush 에 맵핑
CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap);dc.SelectObject(&brush);dc.Rectangle(0,0,200,200);
리소스 아이디
6
Review: BITMAP 정보 보기
• 비트맵 정보
int CBitmap::GetBitmap (BITMAP* pBitMap) ;int CBitmap::GetBitmap (BITMAP* pBitMap) ;
struct BITMAP { int bmType; int bmWidth; // 비트맵의 폭 ( 픽셀 단위 ) int bmHeight; // 비트맵의 높이 ( 픽셀 단위 ) int bmWidthBytes; BYTE bmPlanes; BYTE bmBitsPixel; LPVOID bmBits;};
Review: Bitmap Block Transfer
• 한 점씩 그리지 않고 한꺼번에 메모리로 보낸다(Block)
(Transfer)• 절차 :
– 원래의 도화지가 있다 CPaintDC dc; – 또 다른 도화지 준비 CDC memDc;
CDC::CreateCompatibleDC(..);– 그 도화지에 그림 그리기 CDC::SelectObject(…);– 원래의 도화지로 그린거 오려붙이기
dc.BitBlt(…);Bit Block Transfer (BitBlt)
Review: Bitmap Block Transfer
CPaintDC dc(this);
CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1);BITMAP bmpInfo;bitmap.GetBitmap(&bmpInfo);
CDC memDc;memDc.CreateCompatibleDC(&dc);memDc.SelectObject(&bitmap);
dc.BitBlt(100, 100, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY);
CPaintDC dc(this);
CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1);BITMAP bmpInfo;bitmap.GetBitmap(&bmpInfo);
CDC memDc;memDc.CreateCompatibleDC(&dc);memDc.SelectObject(&bitmap);
dc.BitBlt(100, 100, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY);
9
Review: Bitmap Block Transfer
• 비트맵 출력 함수
BOOL BitBlt (int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) ;
( 스크린 디바이스 컨텍스트 )
pSrcDC( 메모리 디바이스 컨텍스트 )
x
ynWidth
nHeight
xSrc
ySrcnWidth
nHeight
그림을 복사하는 방법SRCCOPY,
좀 더 진보된 그리기 방법 :Double Buffering
여태까지 그림 그리는 방법은…
• 그림을 다시 그릴 때 그리는 과정이 보인다 .– 특히 느린 컴퓨터를 사용할 때 .. – Why???
• 그림을 다시 그릴 때 깜박거린다 .– 원래 내용을 무효화 (invalidate) 한다
= 먼저 하얗게 지운다
Double Buffering
• 두 개의 Device Context( 도화지 ) 를 이용함 . – 1. 그림을 그리는 용도 (Back Buffer)– 2. 그림을 보여주는 용도 (Front Screen Buffer)
Memory 에 그림그리고 넘겨주기
• 절차 :– 1. 메모리 DC 만들기 (CreateCompatibleDC)– 2. 그림그릴 메모리 만들기
(CreateCompatibleBitmap)– 3. DC 와 Bitmap 을 연결 (SelectObject)– 4. 그림 그리기– 5. 그려진 그림을 화면 DC 로 BitBlt
한꺼번에
그림을 다른 도화지에 그리고 , 도화지를 빠르게 바꿔 치기 한다 Double Buffering
Memory 에 그림그리고 넘겨주기
CPaintDC dc(this);
CRect rect;GetClientRect(&rect);
CDC memDC;memDC.CreateCompatibleDC(&dc);CBitmap bitmap;bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());memDC.SelectObject(&bitmap);
memDC.Rectangle(0,0,100,100);
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
CPaintDC dc(this);
CRect rect;GetClientRect(&rect);
CDC memDC;memDC.CreateCompatibleDC(&dc);CBitmap bitmap;bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());memDC.SelectObject(&bitmap);
memDC.Rectangle(0,0,100,100);
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
한꺼번에
Double Buffering using bitmap
• 그림이 빨리 그려진다 .
• 그러나 여전히 깜박인다 ??? 화면을 매번 깨끗이 지우기 때문 ! “ 화면을 지울 필요가 있다” 라는 메시지를 받아서 지우지 말자고 하자 .
해결책 : WM_ERASEBKGND 메시지 핸들러를 만들어 아무 일도 하지 말자고 한다 . ( 뒷 장 참고 )
WM_ERASEBKGND 핸들러 추가
• WM_ERASEBKGND: 화면을 지울 때 ( 하얗게 칠할 때 ) 불리는 메시지
WM_ERASEBKGND 핸들러 추가
• WM_ERASEBKGND: 화면을 지울 때 ( 하얗게 칠할 때 ) 불리는 메시지
• 화면을 지우지 않게 하기 위해 아무일도 하지 않고 그냥 return
BOOL CChildView::OnEraseBkgnd(CDC* pDC){
// TODO: Add your message handler code here and/or call default
// return CWnd::OnEraseBkgnd(pDC);return true;
}
BOOL CChildView::OnEraseBkgnd(CDC* pDC){
// TODO: Add your message handler code here and/or call default
// return CWnd::OnEraseBkgnd(pDC);return true;
}
MFC 와 마우스
19
마우스 기초 (1/2)
• 마우스 처리– 윈도우 운영체제는 마우스와 관련된 모든 변화를 메시지
형태로 프로그램에게 전달한다 .
마우스
마우스장치
드라이버
시스템메시지대기열
응용 프로그램메시지대기열
메시지 메시지 메시지핸들러
메시지루프
20
마우스 기초 (2/2)
• 마우스 메시지 전달– 마우스 메시지는 마우스 커서 밑에 있는 윈도우가
받는다 .
마우스 메시지를프레임 윈도우로 전달
마우스 메시지를뷰로 전달
21
클라이언트 영역 마우스 메시지 (1/5)
• 클라이언트 영역 마우스 메시지
메시지
WM_LBUTTONDOWNWM_LBUTTONDOWN
WM_LBUTTONUPWM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_MBUTTONDOWN
WM_MBUTTONUP
WM_MBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
WM_MOUSEMOVEWM_MOUSEMOVE
발생 시점
왼쪽 버튼을 누를 때왼쪽 버튼을 누를 때
왼쪽 버튼을 뗄 때왼쪽 버튼을 뗄 때
왼쪽 버튼을 더블 클릭할 때
가운데 버튼을 누를 때
가운데 버튼을 뗄 때가운데 버튼을 더블 클릭할 때
오른쪽 버튼을 누를 때
오른쪽 버튼을 뗄 때오른쪽 버튼을 더블 클릭할 때
마우스를 움직일 때마우스를 움직일 때
클라이언트 영역 마우스 메시지 (1/5)
• 메시지 발생 과정 ( 왼쪽마우스의 경우 )
WM_LBUTTONDOWNWM_LBUTTONDOWNWM_LBUTTONUPWM_LBUTTONUP
WM_MOUSEMOVEWM_MOUSEMOVE
마우스를 움직일 때 왼쪽 버튼 클릭 왼쪽 버튼 클릭+ 드래그
왼쪽 버튼 더블 클릭
WM_MOUSEMOVEWM_MOUSEMOVE
WM_MOUSEMOVEWM_MOUSEMOVE
WM_MOUSEMOVEWM_MOUSEMOVE
WM_MOUSEMOVEWM_MOUSEMOVE
WM_LBUTTONDOWNWM_LBUTTONDOWNWM_MOUSEMOVEWM_MOUSEMOVE
WM_LBUTTONUPWM_LBUTTONUP
WM_MOUSEMOVEWM_MOUSEMOVE
WM_MOUSEMOVEWM_MOUSEMOVE
WM_LBUTTONDOWNWM_LBUTTONDOWNWM_LBUTTONUPWM_LBUTTONUP
WM_LBUTTONDBLCLKWM_LBUTTONDBLCLKWM_LBUTTONUPWM_LBUTTONUP
23
클라이언트 영역 마우스 메시지 (2/5)
• 클라이언트 영역 마우스 메시지 핸들러
메시지
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_MBUTTONDOWN
WM_MBUTTONUP
WM_MBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
WM_MOUSEMOVE
메시지맵 매크로
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDBLCLK()
ON_WM_MOUSEMOVE()
메시지 핸들러
OnLButtonDown
OnLButtonUp
OnLButtonDblClkOnMButtonDown
OnMButtonUp
OnMButtonDblClkOnRButtonDown
OnRButtonUp
OnRButtonDblClkOnMouseMove
윈도우 메시지 핸들러 추가법
• CChildView 의 Properties 창에서 추가할 수 있다
25
클라이언트 영역 마우스 메시지 (3/5)
• 메시지 핸들러 형태
– nFlags• 메시지가 생성될 때의 키보드나 마우스 버튼의 상태를 나타내는
비트 매스크
afx_msg void On##### (UINT nFlags, CPoint point) ;
비트 매스크 의미
MK_CONTROL Ctrl 키가 눌렸을 때
MK_SHIFT Shift 키가 눌렸을 때
MK_LBUTTON 마우스 왼쪽 버튼이 눌렸을 때
MK_MBUTTON 마우스 가운데 버튼이 눌렸을 때
MK_RBUTTON 마우스 오른쪽 버튼이 눌렸을 때
26
클라이언트 영역 마우스 메시지 (3/5)
• 메시지 핸들러 형태
– nFlags
afx_msg void On##### (UINT nFlags, CPoint point) ;
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{ if(nFlags & MK_SHIFT){ // 만약 Shift 키가 눌렸다면 ... }
CWnd ::OnLButtonDown(nFlags, point);}
27
클라이언트 영역 마우스 메시지 (4/5)
• 메시지 핸들러 형태
– point• 메시지가 생성될 때의 마우스 커서 위치 ( 클라이언트 좌표 )
afx_msg void On##### (UINT nFlags, CPoint point) ;
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{ CClientDC dc(this);
CPoint pt = point;dc.Rectangle(pt.x-100, pt.y+100, pt.x+100, pt.y-100);
CWnd ::OnLButtonDown(nFlags, point);}
연습 : line 긋는 프로그램
• 화면에 마우스를 이용하여 line 을 긋는다 .
• Line 을 그리기 위해서는 – 시작점 , 끝점을 기억한다 .
1.마우스 버튼 Down 시 • 시작점을 입력
2.마우스 버튼 Up 시 • 끝점을 입력• Line 긋기
연습 : line 긋는 프로그램 2
• 화면에 마우스를 이용하여 line 을 긋는다 .• 마우스가 움직일 때 중간 과정을 보여준다
• Line 을 그리기 위해서는 – 시작점 , 끝점을 기억한다 . 1.마우스 버튼 Down 시
• 시작점을 입력2.마우스 Move 시
• 끝점을 입력• Line 긋기
3.마우스 버튼 Up 시• 끝점을 입력• Line 긋기
문제점 ?
• 마우스가 밖으로 나가 버리면 ???
31
마우스 캡쳐
• 용도– 마우스 캡처를 하면 마우스 커서의 위치에 관계없이
마우스 메시지를 받을 수 있다 .
• 관련 함수
API 함수 MFC 함수 의미
SetCapture() CWnd::SetCapture()
마우스 캡처를 시작한다 .
ReleaseCapture()
없음 마우스 캡처를 해제한다 .
GetCapture() CWnd::GetCapture()
어느 윈도우가 현재 마우스 캡처를 하고 있는지 알아낸다 .
32
비 클라이언트 영역 마우스 메시지 (1/4)
• 비 클라이언트 영역 마우스 메시지
메시지 발생 시점
WM_NCLBUTTONDOWN 왼쪽 버튼을 누를 때
WM_NCLBUTTONUP 왼쪽 버튼을 뗄 때
WM_NCLBUTTONDBLCLK 왼쪽 버튼을 더블 클릭할 때
WM_NCMBUTTONDOWN 가운데 버튼을 누를 때
WM_NCMBUTTONUP 가운데 버튼을 뗄 때
WM_NCMBUTTONDBLCLK 가운데 버튼을 더블 클릭할 때
WM_NCRBUTTONDOWN 오른쪽 버튼을 누를 때
WM_NCRBUTTONUP 오른쪽 버튼을 뗄 때
WM_NCRBUTTONDBLCLK 오른쪽 버튼을 더블 클릭할 때
WM_NCMOUSEMOVE 마우스를 움직일 때
33
비 클라이언트 영역 마우스 메시지 (2/4)
• 비 클라이언트 영역 마우스 메시지 핸들러
메시지 메시지맵 매크로 메시지 핸들러
WM_NCLBUTTONDOWN ON_WM_NCLBUTTONDOWN()
OnNcLButtonDown
WM_NCLBUTTONUP ON_WM_NCLBUTTONUP() OnNcLButtonUp
WM_NCLBUTTONDBLCLK
ON_WM_NCLBUTTONDBLCLK()
OnNcLButtonDblClk
WM_NCMBUTTONDOWN ON_WM_NCMBUTTONDOWN()
OnNcMButtonDown
WM_NCMBUTTONUP ON_WM_NCMBUTTONUP() OnNcMButtonUp
WM_NCMBUTTONDBLCLK
ON_WM_NCMBUTTONDBLCLK()
OnNcMButtonDblClk
WM_NCRBUTTONDOWN ON_WM_NCRBUTTONDOWN()
OnNcRButtonDown
WM_NCRBUTTONUP ON_WM_NCRBUTTONUP() OnNcRButtonUp
WM_NCRBUTTONDBLCLK
ON_WM_NCRBUTTONDBLCLK()
OnNcRButtonDblClk
WM_NCMOUSEMOVE ON_WM_NCMOUSEMOVE() OnNcMouseMove
34
비 클라이언트 영역 마우스 메시지 (3/4)
• 메시지 핸들러 형태
– nHitTest• 메시지가 생성될 때의 마우스 커서 위치를 나타내는 상수값
다음 페이지 표 참조
– point• 메시지가 생성될 때의 마우스 커서 위치 ( 스크린 좌표 )
– 클라이언트 좌표로 변환하려면 CWnd::ScreenToClient() 함수를 사용
afx_msg void OnNc* (UINT nHitTest, CPoint point) ;
35
비 클라이언트 영역 마우스 메시지 (4/4)
• nHitTest
상수값 의미HTCAPTION 타이틀바HTCLIENT 클라이언트 영역
HTCLOSE 종료 버튼
HTHSCROLL 가로 스크롤 바
HTMENU 메뉴
HTMAXBUTTON 또는 HTZOOM 최대화 버튼
HTMINBUTTON 또는 HTREDUCE 최소화 버튼
HTSYSMENU 시스템 메뉴
HTVSCROLL 세로 스크롤 바
이외 마우스와 관련된 것들
• 집에서 읽어 볼 것 : 교재 pp 214~220
– 마우스 포인터의 모양 지정 :
– 마우스 동작 범위 지정
HCURSOR SetCursor (HCURSOR hCursor) ;
::ClipCursor (lpRect pRect) ;
휴강 공고
• 3 월 31 일 ( 화요일 ), 4 월 2 일 ( 목요일 ) 은 수업이 없음 !
• 보강 계획 : 차후 공고