390 likes | 908 Views
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.
E N D
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
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);
Review: CBitmap • 사용법 : Brush에 맵핑 리소스 아이디 CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1); CBrush brush(&bitmap); dc.SelectObject(&brush); dc.Rectangle(0,0,200,200);
Review: BITMAP 정보 보기 • 비트맵 정보 intCBitmap::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);
pSrcDC (메모리 디바이스 컨텍스트) ySrc xSrc (스크린 디바이스 컨텍스트) y nWidth x nHeight Review: Bitmap Block Transfer 그림을 복사하는 방법 SRCCOPY, • 비트맵 출력 함수 BOOL BitBlt (int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) ; nWidth nHeight
여태까지 그림 그리는 방법은… • 그림을 다시 그릴 때 그리는 과정이 보인다. • 특히 느린 컴퓨터를 사용할 때.. • 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);
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; }
마우스 마우스 장치 드라이버 시스템 메시지 대기열 응용 프로그램 메시지 대기열 메시지 핸들러 메시지 메시지 메시지 루프 마우스 기초 (1/2) • 마우스 처리 • 윈도우 운영체제는 마우스와 관련된 모든 변화를 메시지 형태로 프로그램에게 전달한다.
마우스 기초 (2/2) • 마우스 메시지 전달 • 마우스 메시지는 마우스 커서 밑에 있는 윈도우가 받는다. 마우스 메시지를 프레임 윈도우로 전달 마우스 메시지를 뷰로 전달
메시지 발생 시점 WM_LBUTTONDOWN 왼쪽 버튼을 누를 때 WM_LBUTTONUP 왼쪽 버튼을 뗄 때 WM_LBUTTONDBLCLK 왼쪽 버튼을 더블 클릭할 때 WM_MBUTTONDOWN 가운데 버튼을 누를 때 WM_MBUTTONUP 가운데 버튼을 뗄 때 WM_MBUTTONDBLCLK 가운데 버튼을 더블 클릭할 때 WM_RBUTTONDOWN 오른쪽 버튼을 누를 때 WM_RBUTTONUP 오른쪽 버튼을 뗄 때 WM_RBUTTONDBLCLK 오른쪽 버튼을 더블 클릭할 때 WM_MOUSEMOVE 마우스를 움직일 때 클라이언트 영역 마우스 메시지 (1/5) • 클라이언트 영역 마우스 메시지
클라이언트 영역 마우스 메시지 (1/5) • 메시지 발생 과정 (왼쪽마우스의 경우) 마우스를 움직일 때 왼쪽 버튼 클릭 왼쪽 버튼 클릭 + 드래그 왼쪽 버튼 더블 클릭 WM_MOUSEMOVE WM_LBUTTONDOWN WM_LBUTTONDOWN WM_LBUTTONDOWN WM_MOUSEMOVE WM_LBUTTONUP WM_MOUSEMOVE WM_LBUTTONUP WM_MOUSEMOVE WM_MOUSEMOVE WM_LBUTTONDBLCLK WM_MOUSEMOVE WM_MOUSEMOVE WM_LBUTTONUP WM_MOUSEMOVE WM_LBUTTONUP
메시지 메시지맵 매크로 메시지 핸들러 WM_LBUTTONDOWN ON_WM_LBUTTONDOWN() OnLButtonDown WM_LBUTTONUP ON_WM_LBUTTONUP() OnLButtonUp WM_LBUTTONDBLCLK ON_WM_LBUTTONDBLCLK() OnLButtonDblClk WM_MBUTTONDOWN ON_WM_MBUTTONDOWN() OnMButtonDown WM_MBUTTONUP ON_WM_MBUTTONUP() OnMButtonUp WM_MBUTTONDBLCLK ON_WM_MBUTTONDBLCLK() OnMButtonDblClk WM_RBUTTONDOWN ON_WM_RBUTTONDOWN() OnRButtonDown WM_RBUTTONUP ON_WM_RBUTTONUP() OnRButtonUp WM_RBUTTONDBLCLK ON_WM_RBUTTONDBLCLK() OnRButtonDblClk WM_MOUSEMOVE ON_WM_MOUSEMOVE() OnMouseMove 클라이언트 영역 마우스 메시지 (2/5) • 클라이언트 영역 마우스 메시지 핸들러
윈도우 메시지 핸들러 추가법 • CChildView의 Properties 창에서 추가할 수 있다
비트 매스크 의미 MK_CONTROL Ctrl 키가 눌렸을 때 MK_SHIFT Shift 키가 눌렸을 때 MK_LBUTTON 마우스 왼쪽 버튼이 눌렸을 때 MK_MBUTTON 마우스 가운데 버튼이 눌렸을 때 MK_RBUTTON 마우스 오른쪽 버튼이 눌렸을 때 클라이언트 영역 마우스 메시지 (3/5) • 메시지 핸들러 형태 • nFlags • 메시지가 생성될 때의 키보드나 마우스 버튼의 상태를 나타내는 비트 매스크 afx_msg void On##### (UINT nFlags, CPoint point) ;
클라이언트 영역 마우스 메시지 (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); }
클라이언트 영역 마우스 메시지 (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 을 그리기 위해서는 • 시작점, 끝점을 기억한다. • 마우스 버튼 Down 시 • 시작점을 입력 • 마우스 버튼 Up 시 • 끝점을 입력 • Line 긋기
연습: line 긋는 프로그램2 • 화면에 마우스를 이용하여 line을 긋는다. • 마우스가 움직일 때 중간 과정을 보여준다 • Line 을 그리기 위해서는 • 시작점, 끝점을 기억한다. • 마우스 버튼 Down 시 • 시작점을 입력 • 마우스 Move 시 • 끝점을 입력 • Line 긋기 • 마우스 버튼 Up 시 • 끝점을 입력 • Line 긋기
문제점? • 마우스가 밖으로 나가 버리면???
API 함수 MFC 함수 의미 SetCapture() CWnd::SetCapture() 마우스 캡처를 시작한다. ReleaseCapture() 없음 마우스 캡처를 해제한다. GetCapture() CWnd::GetCapture() 어느 윈도우가 현재 마우스 캡처를 하고 있는지 알아낸다. 마우스 캡쳐 • 용도 • 마우스 캡처를 하면 마우스 커서의 위치에 관계없이 마우스 메시지를 받을 수 있다. • 관련 함수
메시지 발생 시점 WM_NCLBUTTONDOWN 왼쪽 버튼을 누를 때 WM_NCLBUTTONUP 왼쪽 버튼을 뗄 때 WM_NCLBUTTONDBLCLK 왼쪽 버튼을 더블 클릭할 때 WM_NCMBUTTONDOWN 가운데 버튼을 누를 때 WM_NCMBUTTONUP 가운데 버튼을 뗄 때 WM_NCMBUTTONDBLCLK 가운데 버튼을 더블 클릭할 때 WM_NCRBUTTONDOWN 오른쪽 버튼을 누를 때 WM_NCRBUTTONUP 오른쪽 버튼을 뗄 때 WM_NCRBUTTONDBLCLK 오른쪽 버튼을 더블 클릭할 때 WM_NCMOUSEMOVE 마우스를 움직일 때 비 클라이언트 영역 마우스 메시지 (1/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 비 클라이언트 영역 마우스 메시지 (2/4) • 비 클라이언트 영역 마우스 메시지 핸들러
비 클라이언트 영역 마우스 메시지 (3/4) • 메시지 핸들러 형태 • nHitTest • 메시지가 생성될 때의 마우스 커서 위치를 나타내는 상수값 다음 페이지 표 참조 • point • 메시지가 생성될 때의 마우스 커서 위치(스크린 좌표) • 클라이언트 좌표로 변환하려면 CWnd::ScreenToClient() 함수를 사용 afx_msg void OnNc* (UINT nHitTest, CPoint point) ;
상수값 의미 HTCAPTION 타이틀바 HTCLIENT 클라이언트 영역 HTCLOSE 종료 버튼 HTHSCROLL 가로 스크롤 바 HTMENU 메뉴 HTMAXBUTTON 또는 HTZOOM 최대화 버튼 HTMINBUTTON 또는 HTREDUCE 최소화 버튼 HTSYSMENU 시스템 메뉴 HTVSCROLL 세로 스크롤 바 비 클라이언트 영역 마우스 메시지 (4/4) • nHitTest
이외 마우스와 관련된 것들 • 집에서 읽어 볼 것: 교재 pp 214~220 • 마우스 포인터의 모양 지정: • 마우스 동작 범위 지정 HCURSOR SetCursor (HCURSOR hCursor) ; ::ClipCursor (lpRect pRect) ;
휴강 공고 • 3월 31일(화요일), 4월 2일(목요일)은 수업이 없음! • 보강 계획: 차후 공고