Mapping Mode
학습 목표
- Mapping Mode 이해하기
- 논리좌표와 물리좌표의 차이점 이해하기
- WindowsPort와 ViewPort 차이점 이해하기
- Primary DC의 설정 방법 익히기
Mapping Mode의 이해
논리 좌표와 물리 좌표
논리좌표
물리좌표
- 실제 Display장치(Window)에 표현되는 좌표단위와 체계
- 지금까지는 논리적 단위와 물리적 단위의 두 체계가 같았기 때문에 문제가 없었음
p.X += 20;
OffsetRect(&m_Rect, 100, 0);
// 20과 100의 단위 ? Pixel (논리와 물리좌표 같이 설정됨)
매핑 방식의 변경
DC :
- 펜이나 브러쉬, 폰트 같은 것들 외에도 많은 정보를 지님
- 물리적(Device) 좌표 체계에 대한 정보를 가지고 있음
SetMapMode함수 :
매핑모드의 결정
- 미리 설정된 몇 가지의 단위 체계를 선택하여 변경하는 방법
- 임의의 단위로 설정하여 변경하는 방법
(예 1)
SetMapMode(hdc,MM_LOMETRIC);
OffsetRect(&m_Rect, 100, 0);
- 논리적 단위 1을 물리적 단위 0.1mm로 매핑함
- 100*0.1mm = 10mm 이동
(예 2)
SetMapMode(hdc,MM_HIMETRIC);
OffsetRect(&m_Rect, 100, 0);
- 논리적 단위 1을 물리적 단위 0.01mm로 매핑함
100*0.01mm = 1mm 이동
임의의 단위로 설정하여 변경하는 방법
- MM_ANISOTROPIC
- MM_ISOTROPIC
다음 함수의 사용 수반
- SetWindowExtEx
- SetViewportExtEx
논리적(WindowPort)에서 물리적(ViewPort)로의 매핑공식
xViewPort/xViewExt = xWindowPort / xWinExt
xWindowPort = xWinExt * (xViewPort/xViewExt)
Case 1 : xWindow = 50 * 10/100 = 5의 위치
Case 2 : xWindow = 500 * 10/100 = 50의 위치
xViewPort = xViewExt *(xWindowPort / xWinExt)
Case 1 : xViewPort = 100 * 5/50 = 10의 위치
Case 2 : xViewPort = 100 * 50/500 = 10의 위치
LPtoDP (Logic-> Device)
DPtoLP (Device-> Logic)
Case 1의 경우
SetMapMode(hdc, MM_ISOTROPIC);
SetViewportExtEx(hdc, 50, 50, NULL);
SetWindowExtEx(hdc, 100, 100, NULL);
SetMapMode(hdc, MM_ISOTROPIC);
SetViewportExtEx(hdc, 500, 500, NULL);
SetWindowExtEx(hdc, 100, 100, NULL);
MM_ISOTROPIC은 원
MM_ANISOTROPIC은 타원
상대적 비율의 개념
- 물리적 뷰포트/논리적 윈도우포트
- 논리적 크기가 고정되면, 물리적 크기가 작아질수록 상대적으로 작게 보여지며, 물리적 크기가 클수록 상대적으로 크게 보임
// 윈도우 크기 변화에 따른 실제적인 매핑모드 설정
SetMapMode(hdc, MM_ISOTROPIC);
GetClientRect(hWnd, &r);
SetViewportExtEx(hdc, r.right, r.bottom, NULL);
SetWindowExtEx(hdc, 760, 510, NULL);
// 글자 크기 단위의 좌표체계
SetMapMode(hdc, MM_ANISOTROPIC);
SetViewportExtEx(hdc, charSize.cs, charSize.cy, NULL);
SetWindowExtEx(hdc, 1, 1, NULL);
* charSize는 GetTextExtentPoint32()나 GetTextMetrics()함수로 알아냄
* 모니터의 해상도나 기타 시스템 정보는 GetSystemMetrics()나 GetDeviceCaps()로 알아냄
논리좌표와 물리좌표 사이의 변환
- 마지막 매핑모드를 설정한 프로그램에서, 윈도우 크기가 변경된 후에는 마우스르르 클릭하여 드래깅해도 바가 움직이지 않음
- 실제 마우스가 눌려진 위치가 논리적인 Bar의 영역에 있지 않기 때문
- 마우스가 눌려지면 시스템은 WM_LBUTTONDOWN과 함께 좌표를 전달하는데, 이때 전달되는 좌표는 무조건 Device좌표임
- 이때의 마우스 Device 좌표는 실제 프로그램에서 처리되고 있는 수치(논리적 좌표)와 일치하지 않음
- 윈도우와 관련하여 시스템에 의해 WndProc에 전달되는 모든 좌표는 항상 언제나 Client 공간내로 국한되는 Device좌표로 통일되어 있음
- WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP 등이 이에 해당함 (GetClientRect도 마찬가지)
- case WM_LBUTTONDOWN :
p = MakePoint(lParam);
if(PtInRect(&m_BarRect, p))
m_bFlag = TRUE;
break;
- 마우스가 눌렸을 때 이 위치가 바의 영역에 있는가를 검사하는 항상 참이 될 수 없음
- 따라서 이때 Device좌표를 Logic좌표로 변화해야 할 필요가 있음
- DPtoLP(), LPtoDP()함수 제공
- DPtoLP()를 사용하여 윈도우 시스템에 의해 전달된 Device좌표를 논리좌표로 변환
Primary DC의 설정과 사용
- 지금까지 모든 DC에 관한 설정 변경, 예를 들면 펜이나 브러쉬를 설정하는 경우에 프로그램에서 매번 SelectObject를 그때그때 설정해 줌
- 실제로 시스템은 BeginPaint나 GetDC에 의해 얻어지는 DC설정에 대해 그 상태를 매번 보존하지 않음
- 항상 기본적인 상태의 DC를 반환해주는데, 좀 더 정확히는 이를 Default DC라고 함
- 앞의 예에서 WM_SIZE에서 처리했던 DC에 대한 Mapping Mode 설정은 해당 메시지가 처리된 후 끝나면서 그 설정 상태가 보존되지 않음 => DC를 얻어 처리하는 모든 곳에서 그런 Mapping Mode설정을 일일이 해주어야 함
=> DC 설정 상태의 보존성이 요구됨
==>> Primary DC의 설정과 사용을 허용
- Primary DC의 설정은 WinMain에서 다음과 같이 Window Style에 그 속성을 설정
wc.style = CS_HREDRAW | CS_VREDREDRAW | CS_OWNDC;
시스템은 그 DC의 변경 상태를 유지시켜줌
특정 부분에서 한번만 속성 설정
주의 사항 : Primary DC를 사용하면서 GetDC로 설정을 변경하는 경우에는 ReleaseDC를 호출하지 않음
상세한 예시는 비트맵파트에서 다룸