Win32 샘플 4 - 단일 윈도우/다중 뷰
하나의 창에 여러 개의 뷰를 표시하는 예제로써 아래의 그림과 같이 메뉴를 사용하여 뷰를 추가하거나 제거할 수 있다. 이 예제에서는 최대 8개 까지 뷰를 생성할 수 있도록 했지만 뷰의 개수는 어플리케이션을 개발할 때 얼마든 지 추가하는 것이 가능하다.
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample04_01.png[그림 4-1] 단일 윈도우 내 뷰 분할 기능
뷰 정보 설정
분할되는 뷰의 위치 및 맵에 대한 정보를 관리하는 클래스이다.
class CWndMapView {
public :
double m_centerx; // 맵의 중심 경도
double m_centery; // 맵의 중심 위도
double m_zoom; // 확대 축소 비율
double m_degree; // 회전 각도
int m_viewx, m_viewy, m_viewh, m_vieww; // 윈도우 좌표계의 뷰의 위치와 크기
CWndMapView() :
m_centerx( 0 ),
m_centery( 0 ),
m_zoom( 1 ),
m_degree( 0 )
{
}
int setViewport() {
return hencSetViewport( m_viewx, m_viewy, m_vieww, m_viewh );
}
int setMapParameter() {
return hencSetMapParameter( m_centerx, m_centery, m_zoom, m_degree );
}
int getMapParameter() {
return hencGetMapParameter( m_centerx, m_centery, m_zoom, m_degree );
}
};
윈도우 정보 설정
MAX_VIEW 크기 만큼의 뷰에 대한 배열을 가지는 윈도우 정보를 관리하는 클래스이다.
#define MAX_VIEW 8 // 뷰의 최대 개수
class CWndInfo {
public :
HWND m_hwnd; // 뷰가 배치되는 윈도우 핸들
int m_mousex, m_mousey; // 마우스 커서의 위치
int m_cntView; // 표시될 뷰의 개수
CWndMapView m_map[ MAX_VIEW ]; // 뷰 배열
CWndInfo() :
m_hwnd( 0 ),
m_mousex( 0 ),
m_mousey( 0 )
{
}
~CWndInfo() {
}
int getViewCount() {
return m_cntView;
}
CWndMapView &map( int no ) {
return m_map[ no ];
}
};
뷰 개수 변경
WM_COMMAND의 처리 함수인 onCommand()에서 각 메뉴에 따라 뷰 개수 값을 설정한 후 arrangeView() 함수를 실행하여 뷰의 개수에 따라 각 뷰의 위치 및 크기를 조정한다.
LRESULT onCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int wmId = LOWORD(wParam);
int wmEvent = HIWORD(wParam);
// 메뉴의 선택 영역을 구문 분석합니다.
switch (wmId) {
case IDM_MAKE_VIEW1 :
g_wndInfo.m_cntView = 1; // 단일 뷰
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MAKE_VIEW4 : // 4 뷰
g_wndInfo.m_cntView = 4;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MAXVIEW : // 최대 뷰(이 예제에서는 8개)
g_wndInfo.m_cntView = MAX_VIEW;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MORE_VIEW : // 뷰 1개 추가
if( ++ g_wndInfo.m_cntView >= MAX_VIEW )
g_wndInfo.m_cntView = MAX_VIEW;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_LESS_VIEW : // 뷰 1개 감소
if( -- g_wndInfo.m_cntView < 1 )
g_wndInfo.m_cntView = 1;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
}
return 0;
}
void arrangeViews( CWndInfo &info ) {
RECT r;
GetClientRect( info.m_hwnd, &r );
int w = r.right;
int h = r.bottom;
int row = 2;
int col = ( info.getViewCount() + row - 1 ) / row;
if( info.getViewCount() == 1 ) {
row = 1;
col = 1;
}
if( info.getViewCount() == 2 ) {
row = 1;
col = 2;
}
for( int i = 0; i < info.getViewCount(); i++ ) {
int wx = i % col * w / col;
int wy = i / col * h / row;
info.map( i ).m_viewx = wx;
info.map( i ).m_viewy = wy;
if( i == info.getViewCount() - 1 )
info.map( i ).m_vieww = w - info.map( i ).m_viewx;
else
info.map( i ).m_vieww = w / col;
info.map( i ).m_viewh = h / row;
}
}
뷰 이벤트 처리
마우스 클릭, 휠, 드래그 등의 이벤트를 처리하여 각 뷰마다 중심 위치와 확대/축소의 정도, 회전각 등을 다르게 설정한다. 각 뷰에 대한 처리를 개별적으로 처리하기 위해서는 마우스 이벤트가 발생한 뷰를 찾아내야 하는데 아래의 getMapViewOfPos()에서 그 절차가 구현되어 있다.
CWndMapView *getMapViewOfPos( CWndInfo &info, int x, int y ) {
for( int i = 0; i < info.getViewCount(); i++ ) {
CWndMapView &map = info.map( i ); // 뷰의 정보를 가져옴
if( x >= map.m_viewx ) // 마우스 커서의 위치가 뷰에 설정된 영역 정보 내에 있으면
if( x < map.m_viewx + map.m_vieww )
if( y >= map.m_viewy )
if( y < map.m_viewy + map.m_viewh )
return ↦ // 해당 뷰를 반환
}
return NULL;
}
그 다음은 마우스 왼쪽 버튼에 대한 처리로 각 뷰의 중심 위치를 이동시키는 절차를 구현한 것이다. 오른쪽 버튼이나 휠등의 나머지 이벤트에 대한 처리도 전체 코드를 참조하여 어떻게 동작하는 지 살펴보면 될 것이다.
LRESULT CALLBACK onLbuttonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
{
CWndMapView *mapview = getMapViewOfPos( info, x, y ); // 마우스 커서 위치의 뷰를 찾기
if( mapview == NULL )
return 0;
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
double dx = x;
double dy = y;
hencWinPosToMapPos( dx, dy );
mapview->m_centerx = dx;
mapview->m_centery = dy;
updateViewport( hWnd, mapview );
}
return 0;
}
int updateViewport( HWND hWnd, CWndMapView *map ) // 선택된 뷰만 업데이트
{
PFMCOUNTER_START( p );
hencSelect( hWnd );
map->setViewport();
map->setMapParameter();
hencClearViewport();
hencRender();
drawOnGL( hWnd, map );
HDC hdc = GetDC( hWnd );
glMapToDC( hWnd, hdc, map );
ReleaseDC( hWnd, hdc );
return 0;
}
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample04_02.png[그림 4-2] 2 분할
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample04_03.png[그림 4-3] 3 분할
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample04_04.png[그림 4-4] 4 분할
보관된 원본 이미지가 없어 표시할 수 없습니다. 위 코드와 설명을 참고해 주십시오.
win32_sample04_05.png[그림 4-5] 8 분할
WinMain.cpp
// WinMain.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#define MAX_LOADSTRING 100
#define CNT_INITIAL_VIEW 1
// 전역 변수:
HINSTANCE g_hInstance; // 현재 인스턴스입니다.
TCHAR g_szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
TCHAR g_szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
CWndInfo g_wndInfo;
void viewRedrawAll() {
InvalidateRect( g_wndInfo.m_hwnd, NULL, FALSE );
}
void loadMap() {
hencLoad( _T( "SHP\\CNTRY92.SENC" ) );
CLoadENC loadEnc;
loadEnc.setMessage( EMI_CAPTION, _T( "Loading. . ." ) );
hencLoadFileListFromCatalogFile( _T( "SENC\\CATALOG.SENC" ), loadEnc.m_listFn );
dlgProgress( g_wndInfo.m_hwnd, &loadEnc );
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
debugviewClearLog();
debugPrintf( __FUNCTION___T( "() START.\n" ) );
if( 0 > hencInit() ) {
MessageBox( GetDesktopWindow(), _T( "전자해도 커널을 초기화 할 수 없습니다." ), _T( "FATAL" ), MB_ICONERROR | MB_OK );
return -1;
}
g_hInstance = hInstance;
LoadString(hInstance, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SAMPLE, g_szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if ( !InitInstance( hInstance, nCmdShow ) )
return FALSE;
loadMap();
viewRedrawAll();
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SAMPLE));
MSG msg;
while ( GetMessage( &msg, NULL, 0, 0 ) ) {
if ( TranslateAccelerator( msg.hwnd, hAccelTable, &msg ) )
continue;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
hencDeinit();
debugPrintf( __FUNCTION___T( "() DONE.\n" ) );
return (int) msg.wParam;
}
void arrangeViews( CWndInfo &info ) {
//debugPrintf( __FUNCTION___T( "()\n" ) );
RECT r;
GetClientRect( info.m_hwnd, &r );
int w = r.right;
int h = r.bottom;
int row = 2;
int col = ( info.getViewCount() + row - 1 ) / row;
if( info.getViewCount() == 1 ) {
row = 1;
col = 1;
}
if( info.getViewCount() == 2 ) {
row = 1;
col = 2;
}
for( int i = 0; i < info.getViewCount(); i++ ) {
int wx = i % col * w / col;
int wy = i / col * h / row;
info.map( i ).m_viewx = wx;
info.map( i ).m_viewy = wy;
if( i == info.getViewCount() - 1 )
info.map( i ).m_vieww = w - info.map( i ).m_viewx;
else
info.map( i ).m_vieww = w / col;
info.map( i ).m_viewh = h / row;
}
}
ATOM MyRegisterClass(HINSTANCE hInstance) {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SAMPLE);
wcex.lpszClassName = g_szWindowClass;
wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_SAMPLE ) );
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_SAMPLE ) );
return RegisterClassEx(&wcex);
}
struct MONITOR_SELECT {
int found;
int m_monitorWant;
RECT m_rectMonitor;
HMONITOR m_monitor;
};
BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData ) {
MONITORINFO info;
info.cbSize = sizeof( info );
GetMonitorInfo( hMonitor, &info );
int num = 0;
if( info.dwFlags & MONITORINFOF_PRIMARY )
num = 0;
else
num = 1;
debugPrintf(
_T( "MONITOR=%d, %dx%d~%dx%d, %s\n" ),
hMonitor, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom,
num ? _T( "Secondary" ) : _T( "Primary" )
);
MONITOR_SELECT *ms = (MONITOR_SELECT *)dwData;
if( num == ms->m_monitorWant ) {
ms->m_monitor = hMonitor;
ms->m_rectMonitor = *lprcMonitor;
ms->found = 1;
return FALSE;
}
return TRUE;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
HWND hWnd;
g_hInstance = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
MONITOR_SELECT ms;
ms.m_monitorWant = 0;
ms.found = 0;
debugPrintf( _T( "g_monitor %d\n" ), ms.m_monitorWant );
EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, (LPARAM )&ms );
int x = 0, y = 0, w = 0, h = 0;
if( ms.found ) {
x = ms.m_rectMonitor.left;
y = ms.m_rectMonitor.top;
w = ms.m_rectMonitor.right - ms.m_rectMonitor.left;
h = ms.m_rectMonitor.bottom - ms.m_rectMonitor.top - 40;
debugPrintf( _T( "monitor %d at %d,%d size=%d,%d\n" ), ms.m_monitorWant, x, y, w, h );
}
{
hWnd = CreateWindow(
g_szWindowClass,
g_szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd) {
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
//ShowWindow(hWnd, SW_MAXIMIZE );
UpdateWindow(hWnd);
}
return TRUE;
}
LRESULT onDestory(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
hencDelete( hWnd );
KillTimer( hWnd, 1 );
PostQuitMessage(0);
return 0;
}
void drawOnGL( HWND hwnd, CWndMapView *map ) {
}
void drawOnDC( HWND hwnd, CWndMapView *map, HDC hdc ) {
int x = map->m_viewx;
int y = map->m_viewy;
int w = map->m_vieww;
int h = map->m_viewh;
{
CAutoSelectObject brush( hdc, GetStockObject( NULL_BRUSH ) );
CAutoSelectObject pen( hdc, CreatePen( PS_SOLID, 1, RGB(0,0,0) ) );
Rectangle( hdc, x, y, x + w, y + h );
}
}
void drawOnDCAll( HWND hWnd, HDC hdc ) {
CWndInfo &info = g_wndInfo;
for( int i = 0; i < info.getViewCount(); i++ ) {
CWndMapView &map = info.map( i );
map.setViewport();
map.setMapParameter();
drawOnDC( hWnd, &map, hdc );
}
}
int glMapToDCAll( HWND hWnd, HDC hdc ) {
// Capture & Draw & Copy for flicker free..
RECT r;
GetClientRect( hWnd, &r );
int w = r.right;
int h = r.bottom;
{
CAutoDeleteGdiObject bitmap( hencCaptureBuffer() );
{
CAutoBitmapDC hdcMem( bitmap );
drawOnDCAll( hWnd, hdcMem );
BitBlt( hdc, 0, 0, w, h, hdcMem, 0, 0, SRCCOPY );
}
}
//*////////////////////////////////////////////////////////////////////////////////////////////////
return 0;
}
int glMapToDC( HWND hWnd, HDC hdc, CWndMapView *map ) {
RECT r;
GetClientRect( hWnd, &r );
int w = r.right;
int h = r.bottom;
{
CAutoDeleteGdiObject bitmap( hencCaptureBuffer() );
{
CAutoBitmapDC hdcMem( bitmap );
drawOnDC( hWnd, map, hdcMem );
BitBlt(
hdc,
map->m_viewx,
map->m_viewy,
map->m_vieww,
map->m_viewh,
hdcMem,
map->m_viewx,
map->m_viewy,
SRCCOPY
);
}
}
//*////////////////////////////////////////////////////////////////////////////////////////////////
return 0;
}
int updateViewport( HWND hWnd, CWndMapView *map ) {
PFMCOUNTER_START( p );
hencSelect( hWnd );
map->setViewport();
map->setMapParameter();
hencClearViewport();
hencRender();
//debugPrintf( __FUNCTION___T( "() Viewport=%d,%d ~ %d, %d\n" ), map->m_viewx, map->m_viewy, map->m_vieww, map->m_viewh );
drawOnGL( hWnd, map );
HDC hdc = GetDC( hWnd );
glMapToDC( hWnd, hdc, map );
ReleaseDC( hWnd, hdc );
return 0;
}
LRESULT onPaint( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) {
PFMCOUNTER_START( p );
PAINTSTRUCT ps;
CWndInfo &info = g_wndInfo;
HDC hdc = BeginPaint(hWnd, &ps);
//debugPrintf( _T( " hWnd=0x%x, HDC=0x%X\n" ), hWnd, hdc );
RECT r;
GetClientRect( hWnd, &r );
int w = r.right;
int h = r.bottom;
hencSelect( hWnd );
hencClearBackground();
for( int i = 0; i < info.getViewCount(); i++ ) {
CWndMapView &map = info.map( i );
map.setViewport();
map.setMapParameter();
hencRender();
drawOnGL( hWnd, &map );
}
glMapToDCAll( hWnd, hdc );
EndPaint(hWnd, &ps);
return 0;
}
LRESULT onCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int wmId = LOWORD(wParam);
int wmEvent = HIWORD(wParam);
// 메뉴의 선택 영역을 구문 분석합니다.
switch (wmId) {
case IDM_MAKE_VIEW1 :
g_wndInfo.m_cntView = 1;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MAKE_VIEW4 :
g_wndInfo.m_cntView = 4;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MAXVIEW :
g_wndInfo.m_cntView = MAX_VIEW;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_MORE_VIEW :
if( ++ g_wndInfo.m_cntView >= MAX_VIEW )
g_wndInfo.m_cntView = MAX_VIEW;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_LESS_VIEW :
if( -- g_wndInfo.m_cntView < 1 )
g_wndInfo.m_cntView = 1;
arrangeViews( g_wndInfo );
InvalidateRect( hWnd, NULL, FALSE );
break;
case IDM_NEW_WINDOW :
{
HWND hWnd = CreateWindow(
g_szWindowClass,
g_szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
g_hInstance,
NULL
);
ShowWindow(hWnd, SW_NORMAL );
UpdateWindow(hWnd);
}
break;
case IDM_ABOUT:
dlgAbout( hWnd );
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT onSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
arrangeViews( g_wndInfo );
return 0;
}
LRESULT onCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
TCHAR buf[256];
LPCREATESTRUCT cs = (LPCREATESTRUCT )lParam;
CWndInfo &info = g_wndInfo;
info.m_hwnd = hWnd;
info.m_cntView = CNT_INITIAL_VIEW;
_stprintf_s( buf, 256, _T( "HNS ENC 0x%X" ), hWnd );
SetWindowText( hWnd, buf );
HDC hdc = GetDC( hWnd );
hencCreate( hWnd );
{
CWndMapView &map = info.map( 0 );
map.m_centerx = 0;
map.m_centery = 0;
map.m_zoom = 1;
map.m_degree = 0;
}
{
CWndMapView &map = info.map( 1 );
map.m_centerx = 126.411160;
map.m_centery = 37.369847;
map.m_zoom = 467.774752;
map.m_degree = 0;
}
{
CWndMapView &map = info.map( 2 );
map.m_centerx = 129.023807;
map.m_centery = 35.091644;
map.m_zoom = 7081.278033;
map.m_degree = 0;
}
{
CWndMapView &map = info.map( 3 );
map.m_centerx = 129.217037;
map.m_centery = 35.164078;
map.m_zoom = 753.355915;
map.m_degree = 0;
}
return 0;
}
CWndMapView *getMapViewOfPos( CWndInfo &info, int x, int y ) {
for( int i = 0; i < info.getViewCount(); i++ ) {
CWndMapView &map = info.map( i );
if( x >= map.m_viewx )
if( x < map.m_viewx + map.m_vieww )
if( y >= map.m_viewy )
if( y < map.m_viewy + map.m_viewh )
return ↦
}
return NULL;
}
LRESULT CALLBACK onMbuttonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_MBUTTONDOWN %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_startx = info.m_mousex = x;
info.m_starty = info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview == NULL )
return 0;
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
double dx = x;
double dy = y;
hencWinPosToMapPos( dx, dy );
//debugPrintf( _T( "WinPos%d,%d -> MapPos%f,%f\n" ), x, y, dx, dy );
updateViewport( hWnd, mapview );
return 0;
}
LRESULT CALLBACK onLbuttonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_LBUTTONDOWN %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_startx = info.m_mousex = x;
info.m_starty = info.m_mousey = y;
{
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview == NULL )
return 0;
//debugPrintf( __FUNCTION___T( "() Viewport=%d,%d ~ %d, %d\n" ), mapview->m_viewx, mapview->m_viewy, mapview->m_vieww, mapview->m_viewh );
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
double dx = x;
double dy = y;
hencWinPosToMapPos( dx, dy );
//debugPrintf( _T( "WinPos %d,%d -> MapPos %f,%f\n" ), x, y, dx, dy );
mapview->m_centerx = dx;
mapview->m_centery = dy;
updateViewport( hWnd, mapview );
}
return 0;
}
LRESULT CALLBACK onLbuttonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_LBUTTONUP %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
return 0;
}
LRESULT CALLBACK onRbuttonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_RBUTTONDOWN %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_startx = info.m_mousex = x;
info.m_starty = info.m_mousey = y;
return 0;
}
LRESULT CALLBACK onLbuttonDoubleClick(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_LBUTTONDBLCLK %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview ) {
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
double mx, my, mx2, my2;
hencGetMapArea( mx, my, mx2, my2 );
hencSetMapArea( mx, my, mx2, my2 );
mapview->getMapParameter();
updateViewport( hWnd, mapview );
//InvalidateRect( hWnd, NULL, FALSE );
}
return 0;
}
LRESULT CALLBACK onRbuttonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_RBUTTONUP %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview == NULL )
return 0;
return 0;
}
LRESULT CALLBACK onRbuttonDoubleClick(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
//debugPrintf( _T( "WM_RBUTTONDBLCLK %d,%d\n" ), x, y );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview ) {
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
mapview->m_degree = 0;
updateViewport( hWnd, mapview );
}
return 0;
}
LRESULT CALLBACK onMouseWheel(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
POINT pt = { x, y };
ScreenToClient( hWnd, &pt );
x = pt.x;
y = pt.y;
//debugPrintf( _T( "WM_MOUSEWHEEL %d,%d delta=%d\n" ), x, y, zDelta );
CWndInfo &info = g_wndInfo;
info.m_mousex = x;
info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview ) {
if( wParam & MK_MBUTTON ) {
if( zDelta > 0 )
mapview->m_degree += 5;
else
mapview->m_degree -= 5;
}
else {
if( zDelta > 0 )
mapview->m_zoom *= 2.0;
else
mapview->m_zoom /= 2.0;
}
updateViewport( hWnd, mapview );
//InvalidateRect( hWnd, NULL, FALSE );
}
return 0;
}
LRESULT CALLBACK onMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
int x = GET_X_LPARAM( lParam );
int y = GET_Y_LPARAM( lParam );
CWndInfo &info = g_wndInfo;
int deltax = info.m_mousex - x;
info.m_mousex = x;
info.m_mousey = y;
CWndMapView *mapview = getMapViewOfPos( info, x, y );
if( mapview ) {
hencSelect( hWnd );
mapview->setViewport();
mapview->setMapParameter();
double dx = x;
double dy = y;
hencWinPosToMapPos( dx, dy );
if( MK_RBUTTON & wParam ) {
mapview->m_degree -= deltax;
updateViewport( hWnd, mapview );
//InvalidateRect( hWnd, NULL, FALSE );
}
}
return 0;
}
LRESULT CALLBACK onKeyDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
return 0;
}
LRESULT CALLBACK onTimer(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
InvalidateRect( hWnd, NULL, FALSE );
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_TIMER :
return onTimer( hWnd, message, wParam, lParam );
case WM_KEYDOWN :
return onKeyDown( hWnd, message, wParam, lParam );
case WM_MBUTTONDOWN :
return onMbuttonDown( hWnd, message, wParam, lParam );
case WM_LBUTTONDOWN :
return onLbuttonDown( hWnd, message, wParam, lParam );
case WM_LBUTTONUP :
return onLbuttonUp( hWnd, message, wParam, lParam );
case WM_LBUTTONDBLCLK :
return onLbuttonDoubleClick( hWnd, message, wParam, lParam );
case WM_RBUTTONDOWN :
return onRbuttonDown( hWnd, message, wParam, lParam );
case WM_RBUTTONUP :
return onRbuttonUp( hWnd, message, wParam, lParam );
case WM_RBUTTONDBLCLK :
return onRbuttonDoubleClick( hWnd, message, wParam, lParam );
case WM_MOUSEWHEEL :
return onMouseWheel( hWnd, message, wParam, lParam );
case WM_MOUSEMOVE :
return onMouseMove( hWnd, message, wParam, lParam );
case WM_SIZE :
return onSize( hWnd, message, wParam, lParam );
case WM_CREATE :
return onCreate( hWnd, message, wParam, lParam );
case WM_COMMAND:
return onCommand( hWnd, message, wParam, lParam );
case WM_PAINT:
return onPaint( hWnd, message, wParam, lParam );
case WM_ERASEBKGND :
break;
case WM_DESTROY:
return onDestory( hWnd, message, wParam, lParam );
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}