Win32 샘플 2 - 해도의 이동/확대/축소
이 예제는 마우스 클릭을 통한 전자해도의 중심위치 이동과 마우스 휠을 통한 확대와 축소 기능의 구현 예를 보여준다. 전자해도의 초기화 과정은 단일 윈도우에 전자해도 그리기에서 살펴본 바와 동일하다.
마우스 왼쪽 버튼에 의한 중심위치 이동
윈도우 프로시져에서 WM_LBUTTONDOWN 메시지의 처리부에서 다음과 같이 hencWinPosToMapPos() 함수를 사용하여 윈도우 좌표를 위경도 좌표로 변환한 후 hencSetCenter() 함수로 중심 위치를 재설정한다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message) {
case WM_LBUTTONDOWN :
{
hencSelect( hWnd );
double xLongitude = GET_X_LPARAM(lParam);
double yLatitude = GET_Y_LPARAM(lParam);
hencWinPosToMapPos( xLongitude, yLatitude );
hencSetCenter( xLongitude, yLatitude );
InvalidateRect( hWnd, NULL, FALSE );
}
break;
...
}
return 0;
}
마우스 휠에 의한 확대와 축소
마우스 휠을 올리면 1.5배 확대, 마우스 휠을 내리면 1.5배 축소하도록 한다. hencGetScale()로 현재 확대 축소 비율를 획득하고 hencSetScale()로 현재 확대 축소 비율을 설정할 수 있다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message) {
...
case WM_MOUSEWHEEL :
{
hencSelect( hWnd );
double dScale = hencGetScale();
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
if( zDelta > 0 ) {
dScale /= 1.5;
if( dScale < 500 )
dScale = 500;
}
if( zDelta < 0 ) {
dScale *= 1.5;
if( dScale > 20000000 )
dScale = 20000000;
}
hencSetScale( dScale );
InvalidateRect( hWnd, NULL, FALSE );
}
break;
...
}
return 0;
}
현재 중심위치 및 확대 축소 비율의 표시
GDI의 DC 핸들을 사용하여 해도 위에 현재 위치 및 확대 축소 비율을 표시하는 예를 보여준다. hencCopyBuffer() 다음에 아래 코드와 같은 방식으로 사용하면 된다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message) {
...
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT r;
GetClientRect( hWnd, &r );
hencSelect( hWnd );
hencSetViewport( 0, 0, r.right - r.left, r.bottom - r.top );
hencClearBackground();
hencRender();
hencCopyBuffer();
SetBkMode( hdc, TRANSPARENT );
SetTextColor( hdc, RGB(255,0,255) );
hdcPrintf( hdc, 0, 0, _T( "Center=%f,%f Scale=%f" ), hencGetCenterX(), hencGetCenterY(), hencGetScale() );
EndPaint(hWnd, &ps);
}
break;
}
return 0;
}
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample02_01.png[그림 2-1] 이동 전
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample02_02.png[그림 2-2] 이동 후
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample02_03.png[그림 2-3] 축소
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample02_04.png[그림 2-4] 확대
Sample.cpp
// Sample.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include "Sample.h"
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
TCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
TCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
// 이 코드 모듈에 들어 있는 함수의 정방향 선언입니다.
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
MSG msg;
HACCEL hAccelTable;
// 전역 문자열을 초기화합니다.
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SAMPLE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 응용 프로그램 초기화를 수행합니다.
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SAMPLE));
// 기본 메시지 루프입니다.
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
hencDeinit();
return (int) msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 목적: 창 클래스를 등록합니다.
//
// 설명:
//
// Windows 95에서 추가된 'RegisterClassEx' 함수보다 먼저
// 해당 코드가 Win32 시스템과 호환되도록
// 하려는 경우에만 이 함수를 사용합니다. 이 함수를 호출해야
// 해당 응용 프로그램에 연결된
// '올바른 형식의' 작은 아이콘을 가져올 수 있습니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SAMPLE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SAMPLE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 설명:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
if( 0 > hencInit() ) {
MessageBox( GetDesktopWindow(), _T( "hnsEnc 초기화 실패" ), _T( "오류" ), MB_OK );
return FALSE;
}
TCHAR szBaseDir[1024];
getPgmDir( GetModuleHandle( NULL ), szBaseDir, 1000 );
SetCurrentDirectory( szBaseDir );
hencLoad( _T( "SHP\\CNTRY92.SENC" ) ); // Load 세계지도 배경 SENC. index=0
hencLoad( _T( "SENC\\KR1A0000.SENC" ) ); // Load 한국 지도 SENC. index=1
hencLoad( _T( "SENC\\KR1B0000.SENC" ) ); // Load 한국 지도 SENC. index=2
hencLoad( _T( "SENC\\KR1C0000.SENC" ) ); // Load 한국 지도 SENC. index=3
hencLoad( _T( "SENC\\KR1D0000.SENC" ) ); // Load 한국 지도 SENC. index=4
hencLoad( _T( "SENC\\KR1E0000.SENC" ) ); // Load 한국 지도 SENC. index=5
hencLoad( _T( "SENC\\KR1EN000.SENC" ) ); // Load 한국 지도 SENC. index=6
hencLoad( _T( "SENC\\KR1ES000.SENC" ) ); // Load 한국 지도 SENC. index=7
hencLoad( _T( "SENC\\KR1F0000.SENC" ) ); // Load 한국 지도 SENC. index=8
hencLoad( _T( "SENC\\KR1G0000.SENC" ) ); // Load 한국 지도 SENC. index=9
hencLoad( _T( "SENC\\KR1H0000.SENC" ) ); // Load 한국 지도 SENC. index=10
hencLoad( _T( "SENC\\KR1I0000.SENC" ) ); // Load 한국 지도 SENC. index=11
hencLoad( _T( "SENC\\KR1J0000.SENC" ) ); // Load 한국 지도 SENC. index=12
hencLoad( _T( "SENC\\KR1K0000.SENC" ) ); // Load 한국 지도 SENC. index=13
hencLoad( _T( "SENC\\KR1L0000.SENC" ) ); // Load 한국 지도 SENC. index=14
hencLoad( _T( "SENC\\KR1M0000.SENC" ) ); // Load 한국 지도 SENC. index=15
hencLoad( _T( "SENC\\KR1N0000.SENC" ) ); // Load 한국 지도 SENC. index=16
hencLoad( _T( "SENC\\KR1O0000.SENC" ) ); // Load 한국 지도 SENC. index=17
hencLoad( _T( "SENC\\KR1P0000.SENC" ) ); // Load 한국 지도 SENC. index=18
HWND hWnd;
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 목적: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 응용 프로그램 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message) {
case WM_LBUTTONDOWN :
{
hencSelect( hWnd );
double xLongitude = GET_X_LPARAM(lParam);
double yLatitude = GET_Y_LPARAM(lParam);
hencWinPosToMapPos( xLongitude, yLatitude );
hencSetCenter( xLongitude, yLatitude );
InvalidateRect( hWnd, NULL, FALSE );
}
break;
case WM_MOUSEWHEEL :
{
hencSelect( hWnd );
double dScale = hencGetScale();
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
if( zDelta > 0 ) {
dScale /= 1.5;
if( dScale < 500 )
dScale = 500;
}
if( zDelta < 0 ) {
dScale *= 1.5;
if( dScale > 20000000 )
dScale = 20000000;
}
hencSetScale( dScale );
InvalidateRect( hWnd, NULL, FALSE );
}
break;
case WM_CREATE :
hencCreate( hWnd );
hencSelect( hWnd );
hencSetCenter( 132, 37 );
hencSetScale( 1500000 );
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 메뉴 선택을 구문 분석합니다.
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT r;
GetClientRect( hWnd, &r );
hencSelect( hWnd );
hencSetViewport( 0, 0, r.right - r.left, r.bottom - r.top );
hencClearBackground();
hencRender();
hencCopyBuffer();
SetBkMode( hdc, TRANSPARENT );
SetTextColor( hdc, RGB(255,0,255) );
hdcPrintf( hdc, 0, 0, _T( "Center=%f,%f Scale=%f" ), hencGetCenterX(), hencGetCenterY(), hencGetScale() );
EndPaint(hWnd, &ps);
}
break;
case WM_ERASEBKGND :
return TRUE;
case WM_DESTROY:
hencDelete( hWnd );
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}