5 // PNG
\82Æ
\82©
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
\97p
7 #pragma comment(lib, "gdiplus.lib")
11 #pragma comment(lib, "shlwapi.lib")
14 #pragma comment(lib, "comctl32.lib")
16 #pragma comment(lib, "Comdlg32.lib")
20 #include "GVONavish.h"
21 #include "GVOConfig.h"
22 #include "GVOGameProcess.h"
23 #include "GVOWorldMap.h"
25 #include "GVOShipRouteList.h"
26 #include "GVORenderer.h"
27 #include "GVOTexture.h"
28 #include "GVOShipRouteManageView.h"
31 //
\83f
\83o
\83b
\83O
\8e\9e\82Ì
\95`
\89æ
\83p
\83t
\83H
\81[
\83}
\83\93\83X
\91ª
\92è
\97p
\81B
32 //#define GVO_PERF_CHECK
36 //
\83O
\83\8d\81[
\83o
\83\8b\95Ï
\90\94:
37 HINSTANCE g_hinst; //
\8c»
\8dÝ
\82Ì
\83C
\83\93\83^
\81[
\83t
\83F
\83C
\83X
42 //
\8aÖ
\90\94\83v
\83\8d\83g
\83^
\83C
\83v
\90é
\8c¾
43 static ATOM MyRegisterClass( HINSTANCE hInstance );
44 static BOOL InitInstance( HINSTANCE, int );
45 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
46 BOOL CALLBACK aboutDlgProc( HWND, UINT, WPARAM, LPARAM );
47 static LRESULT s_mainLoop();
50 //
\83\81\83b
\83Z
\81[
\83W
\83n
\83\93\83h
\83\89
51 static bool s_onCreate( HWND, LPCREATESTRUCT );
52 static void s_onMove( HWND, WORD, WORD );
53 static void s_onSize( HWND, UINT, WORD, WORD );
54 static void s_onMouseWheel( HWND, int16_t, UINT, int16_t, int16_t );
55 static void s_onMouseMove( HWND, UINT, int16_t, int16_t );
56 static void s_onMouseLeftButtonDown( HWND, UINT, int16_t, int16_t );
57 static void s_onMouseLeftButtonUp( HWND, UINT, int16_t, int16_t );
58 static void s_onMouseLeftButtonDoubleClick( HWND, UINT, int16_t, int16_t );
59 static void s_onMouseRightButtonUp( HWND, UINT, int16_t, int16_t );
60 static void s_onPaint( HWND );
63 //
\83A
\83v
\83\8a\8f\88\97\9d
64 static std::wstring s_getMapFileName();
65 static void s_updateFrame(HWND);
66 static void s_updateWindowTitle( HWND, POINT, double );
67 static void s_toggleKeepForeground( HWND );
68 static void s_popupMenu( HWND, int16_t, int16_t );
69 static void s_popupCoord( HWND, int16_t, int16_t );
70 static void s_closeShipRoute();
73 //
\83\8d\81[
\83J
\83\8b\95Ï
\90\94
74 static LPCWSTR const k_appName = L"GVONavish"; //
\83A
\83v
\83\8a\83P
\81[
\83V
\83\87\83\93\96¼
75 static LPCWSTR const k_version = L"ver 1.3"; //
\83o
\81[
\83W
\83\87\83\93\94Ô
\8d\86
76 static LPCWSTR const k_copyright = L"copyright(c) 2014 @MandhelingFreak"; //
\92\98\8dì
\8c \95\
\8e¦
\81i
\82¢
\82¿
\82¨
\81[
\81j
78 static LPCWSTR const k_windowClassName = L"GVONavish"; //
\83\81\83C
\83\93 \83E
\83B
\83\93\83h
\83E
\83N
\83\89\83X
\96¼
79 static const LPCWSTR k_configFileName = L"GVONavish.ini"; //
\90Ý
\92è
\83t
\83@
\83C
\83\8b\96¼
80 static LPCWSTR const k_appMutexName = L"Global\\{7554E265-3247-4FCA-BC60-5AA814658351}";
81 static HANDLE s_appMutex;
83 static Gdiplus::GdiplusStartupInput s_gdisi;
84 static ULONG_PTR s_gdiToken;
86 static GVOConfig s_config( k_configFileName );
87 static GVOGameProcess s_gvoGameProcess;
88 static GVORenderer s_renderer;
89 static GVOWorldMap s_worldMap;
90 const std::wstring && k_routeListFilePath = g_makeFullPath(L"RouteList.dat");
91 static std::unique_ptr<GVOShipRouteList> s_shipRouteList;
92 static POINT s_latestSurveyCoord;
93 static GVOVector s_latestShipVector;
94 static double s_latestShipVelocity;
95 static DWORD s_latestTimeStamp;
96 static const DWORD k_surveyCoordLostThreshold = 5000;
97 static std::unique_ptr<GVOShipRouteManageView> s_shipRouteManageView;
100 static std::unique_ptr<GVOTexture> s_shipTexture;
102 static UINT s_pollingInterval = 1000; //
\8fó
\91Ô
\8aÄ
\8e\8b\8aÔ
\8au
\81i1
\95b
\81j
103 static bool s_isDragging = false; //
\83h
\83\89\83b
\83O
\8fó
\91Ô
\83t
\83\89\83O
104 static SIZE s_clientSize; //
\83N
\83\89\83C
\83A
\83\93\83g
\97Ì
\88æ
\82Ì
\91å
\82«
\82³
105 static POINT s_dragOrg; //
\83h
\83\89\83b
\83O
\8c´
\93_
\81i
\88Ú
\93®
\97Ê
\8eZ
\8fo
\97p
\81j
107 #ifdef GVO_PERF_CHECK
108 typedef std::deque<double> PerfCountList;
109 static PerfCountList s_perfCountList;
116 int APIENTRY _tWinMain( _In_ HINSTANCE hInstance,
117 _In_opt_ HINSTANCE hPrevInstance,
118 _In_ LPTSTR lpCmdLine,
121 UNREFERENCED_PARAMETER( hPrevInstance );
122 UNREFERENCED_PARAMETER( lpCmdLine );
124 ::SetLastError( NOERROR );
125 s_appMutex = ::CreateMutex( NULL, TRUE, k_appMutexName );
126 if ( ::GetLastError() == ERROR_ALREADY_EXISTS ) {
127 HWND hwnd = ::FindWindow( k_windowClassName, NULL );
129 ::SetForegroundWindow( hwnd );
134 ::CoInitialize( NULL );
136 ::timeGetDevCaps( &tc, sizeof(tc) );
137 ::timeBeginPeriod( tc.wPeriodMin );
138 INITCOMMONCONTROLSEX icc = { sizeof(icc), ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES };
139 ::InitCommonControlsEx( &icc );
140 GdiplusStartup( &s_gdiToken, &s_gdisi, NULL );
143 MyRegisterClass( hInstance );
145 //
\83A
\83v
\83\8a\83P
\81[
\83V
\83\87\83\93\82Ì
\8f\89\8aú
\89»
\82ð
\8eÀ
\8ds
\82µ
\82Ü
\82·:
146 if ( !InitInstance( hInstance, nCmdShow ) ) {
150 //
\83\81\83C
\83\93 \83\81\83b
\83Z
\81[
\83W
\83\8b\81[
\83v:
151 const LRESULT retVal = s_mainLoop();
153 s_shipRouteList->saveToFile( k_routeListFilePath );
154 s_gvoGameProcess.teardown();
157 Gdiplus::GdiplusShutdown( s_gdiToken );
158 ::timeEndPeriod( tc.wPeriodMin );
163 static ATOM MyRegisterClass( HINSTANCE hInstance )
165 WNDCLASSEX wcex = { sizeof(wcex) };
167 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
168 wcex.lpfnWndProc = WndProc;
169 wcex.hInstance = hInstance;
170 wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDR_MAINFRAME ) );
171 wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
172 wcex.hbrBackground = (HBRUSH)::GetStockObject( BLACK_BRUSH );
173 wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME);
174 wcex.lpszClassName = k_windowClassName;
175 wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_SMALL ) );
177 return RegisterClassEx( &wcex );
180 static BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
182 if ( !s_worldMap.loadFromFile( s_config.m_mapFileName ) ) {
183 std::wstring fileName = s_getMapFileName();
184 if ( !s_worldMap.loadFromFile( fileName ) ) {
186 L"
\83}
\83b
\83v
\89æ
\91\9c\82ð
\8aJ
\82¯
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B",
188 MB_ICONERROR | MB_SETFOREGROUND | MB_OK );
191 s_config.m_mapFileName = fileName;
196 g_hinst = hInstance; //
\83O
\83\8d\81[
\83o
\83\8b\95Ï
\90\94\82É
\83C
\83\93\83X
\83^
\83\93\83X
\8f\88\97\9d\82ð
\8ai
\94[
\82µ
\82Ü
\82·
\81B
199 if ( s_config.m_keepForeground ) {
200 exStyle |= WS_EX_TOPMOST;
203 style |= WS_OVERLAPPEDWINDOW;
204 style |= WS_CLIPCHILDREN;
205 style |= WS_CLIPSIBLINGS;
206 hwnd = CreateWindowEx( exStyle, k_windowClassName, k_appName, style,
207 s_config.m_windowPos.x, s_config.m_windowPos.y,
208 s_config.m_windowSize.cx, s_config.m_windowSize.cy,
209 NULL, NULL, hInstance, NULL );
216 g_hdcMain = ::GetDC( g_hwndMain );
218 s_renderer.setup( &s_config, g_hdcMain, &s_worldMap );
220 s_shipRouteList.reset( new GVOShipRouteList() );
221 s_shipRouteList->loadFromFile( k_routeListFilePath );
222 s_pollingInterval = s_config.m_pollingInterval;
223 s_gvoGameProcess.setup( s_config );
225 s_updateWindowTitle( hwnd, s_config.m_initialSurveyCoord, s_renderer.viewScale() );
227 ShowWindow( hwnd, nCmdShow );
228 UpdateWindow( hwnd );
233 static LRESULT s_mainLoop()
238 hAccelTable = LoadAccelerators( g_hinst, MAKEINTRESOURCE( IDR_MAINFRAME ) );
241 if ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
242 if ( msg.message == WM_QUIT ) {
245 if ( !TranslateAccelerator( msg.hwnd, hAccelTable, &msg ) ) {
246 TranslateMessage( &msg );
247 DispatchMessage( &msg );
251 std::vector<HANDLE> handles;
253 //
\8aÄ
\8e\8b\82·
\82é
\83n
\83\93\83h
\83\8b\82ð
\92Ç
\89Á
\82·
\82é
\81B
254 if ( s_gvoGameProcess.processHandle() ) {
255 handles.push_back( s_gvoGameProcess.processHandle() );
257 //handles.push_back( s_pollingTimerEvent );
258 handles.push_back( s_gvoGameProcess.dataReadyEvent() );
260 if ( handles.empty() ) {
265 DWORD const waitResult = ::MsgWaitForMultipleObjects( handles.size(), &handles[0], FALSE, INFINITE, QS_ALLINPUT );
266 if ( handles.size() <= waitResult ) {
270 //
\8aÄ
\8e\8b\82·
\82é
\83n
\83\93\83h
\83\8b\82É
\91Î
\89\9e\82·
\82é
\81B
271 HANDLE const activeHandle = handles[waitResult];
273 if ( activeHandle == s_gvoGameProcess.processHandle() ) {
274 //
\83Q
\81[
\83\80\83v
\83\8d\83Z
\83X
\82ª
\8fI
\97¹
\82µ
\82½
\81B
275 s_gvoGameProcess.clear();
279 if ( activeHandle == s_gvoGameProcess.dataReadyEvent() ) {
280 s_updateFrame( g_hwndMain );
284 return (int)msg.wParam;
288 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
300 s_updateFrame( hwnd );
304 s_onMove( hwnd, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
307 s_onSize( hwnd, wp, LOWORD( lp ), HIWORD( lp ) );
312 wmEvent = HIWORD( wp );
313 //
\91I
\91ð
\82³
\82ê
\82½
\83\81\83j
\83\85\81[
\82Ì
\89ð
\90Í:
316 ::DialogBox( g_hinst, MAKEINTRESOURCE( IDD_ABOUTBOX ), hwnd, aboutDlgProc );
319 DestroyWindow( hwnd );
321 case IDM_TOGGLE_TRACE_SHIP:
322 s_config.m_traceShipPositionEnabled = !s_config.m_traceShipPositionEnabled;
323 s_renderer.enableTraceShip( s_config.m_traceShipPositionEnabled );
325 case IDM_ERASE_SHIP_ROUTE:
326 s_shipRouteList->clearAllItems();
328 case IDM_TOGGLE_KEEP_FOREGROUND:
329 s_toggleKeepForeground( hwnd );
331 case IDM_TOGGLE_SPEED_METER:
332 s_config.m_speedMeterEnabled = !s_config.m_speedMeterEnabled;
333 s_renderer.enableSpeedMeter( s_config.m_speedMeterEnabled );
334 ::InvalidateRect( hwnd, NULL, FALSE );
336 case IDM_TOGGLE_VECTOR_LINE:
337 s_config.m_shipVectorLineEnabled = !s_config.m_shipVectorLineEnabled;
338 s_renderer.setVisibleShipRoute( s_config.m_shipVectorLineEnabled );
341 if ( s_renderer.viewScale() != 1.0 ) {
342 s_renderer.resetViewScale();
346 if ( s_renderer.zoomIn() ) {
347 #ifdef GVO_PERF_CHECK
348 s_perfCountList.clear();
350 s_updateWindowTitle( hwnd, s_latestSurveyCoord, s_renderer.viewScale() );
351 ::InvalidateRect( hwnd, NULL, FALSE );
355 if ( s_renderer.zoomOut() ) {
356 #ifdef GVO_PERF_CHECK
357 s_perfCountList.clear();
359 s_updateWindowTitle( hwnd, s_latestSurveyCoord, s_renderer.viewScale() );
360 ::InvalidateRect( hwnd, NULL, FALSE );
363 case IDM_SHOW_SHIPROUTEMANAGEVIEW:
364 if ( !s_shipRouteManageView.get() ) {
365 s_shipRouteManageView.reset( new GVOShipRouteManageView() );
366 if ( !s_shipRouteManageView->setup( *s_shipRouteList.get() ) ) {
367 ::MessageBox( hwnd, L"
\82È
\82ñ
\82©
\82¦
\82ç
\81[
\82Å
\82·", L"
\83G
\83\89\81[", MB_OK | MB_ICONERROR );
371 s_shipRouteManageView->activate();
375 case IDM_TOGGLE_DEBUG_AUTO_CRUISE:
376 s_config.m_debugAutoCruiseEnabled = !s_config.m_debugAutoCruiseEnabled;
377 s_gvoGameProcess.enableDebugAutoCruise( s_config.m_debugAutoCruiseEnabled );
379 case IDM_DEBUG_CLOSE_ROUTE:
382 case IDM_DEBUG_INTERVAL_NORMAL:
383 s_pollingInterval = 1000;
384 s_gvoGameProcess.setPollingInterval( s_pollingInterval );
386 case IDM_DEBUG_INTERVAL_HIGH:
387 s_pollingInterval = 1;
388 s_gvoGameProcess.setPollingInterval( s_pollingInterval );
392 return DefWindowProc( hwnd, message, wp, lp );
397 s_onMouseWheel( hwnd, HIWORD( wp ), LOWORD( wp ), int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
400 s_onMouseMove( hwnd, wp, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
403 s_onMouseLeftButtonDown( hwnd, wp, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
406 s_onMouseLeftButtonUp( hwnd, wp, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
409 s_onMouseRightButtonUp( hwnd, wp, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
411 case WM_LBUTTONDBLCLK:
412 s_onMouseLeftButtonDoubleClick( hwnd, wp, int16_t( LOWORD( lp ) ), int16_t( HIWORD( lp ) ) );
416 if ( !s_onCreate( hwnd, reinterpret_cast<LPCREATESTRUCT>(lp) ) ) {
421 if ( s_shipRouteManageView.get() ) {
422 s_shipRouteManageView.reset();
424 s_renderer.teardown();
425 PostQuitMessage( 0 );
428 return DefWindowProc( hwnd, message, wp, lp );
434 static bool s_onCreate( HWND hwnd, LPCREATESTRUCT /*cs*/ )
440 static void s_onMove( HWND hwnd, WORD /*cx*/, WORD /*cy*/ )
442 const DWORD style = ::GetWindowLong( hwnd, GWL_STYLE );
443 if ( style & WS_MAXIMIZE ) {
447 ::GetWindowRect( hwnd, &rc );
448 s_config.m_windowPos.x = rc.left;
449 s_config.m_windowPos.y = rc.top;
453 static void s_onSize( HWND hwnd, UINT state, WORD cx, WORD cy )
459 ::GetWindowRect( hwnd, &rc );
460 s_config.m_windowSize.cx = rc.right - rc.left;
461 s_config.m_windowSize.cy = rc.bottom - rc.top;
469 if ( s_clientSize.cx != cx || s_clientSize.cy != cy ) {
470 s_clientSize.cx = cx;
471 s_clientSize.cy = cy;
472 s_renderer.setViewSize( s_clientSize );
477 static void s_onMouseWheel( HWND hwnd, int16_t delta, UINT vkey, int16_t x, int16_t y )
479 bool isChanged = false;
482 isChanged = s_renderer.zoomIn();
485 isChanged = s_renderer.zoomOut();
489 #ifdef GVO_PERF_CHECK
490 s_perfCountList.clear();
492 s_updateWindowTitle( hwnd, s_latestSurveyCoord, s_renderer.viewScale() );
493 ::InvalidateRect( hwnd, NULL, FALSE );
498 static void s_onMouseMove( HWND hwnd, UINT vkey, int16_t x, int16_t y )
500 if ( s_isDragging ) {
501 const int dx = x - s_dragOrg.x;
502 const int dy = y - s_dragOrg.y;
503 const int threshold = 1; //
\8a´
\93x
\82ª
\97Ç
\82·
\82¬
\82é
\82Æ
\92Ç
\8f]
\82ª
\8aÈ
\92P
\82É
\90Ø
\82ê
\82Ä
\82µ
\82Ü
\82¤
\82Ì
\82Å
\93K
\93\96\82É
\91Î
\8dô
504 if ( s_config.m_traceShipPositionEnabled ) {
505 if ( ::abs( dx ) <= threshold && ::abs( dy ) < threshold ) {
509 const POINT offset = { -dx, -dy };
511 s_renderer.offsetFocusInViewCoord( offset );
512 ::InvalidateRect( hwnd, NULL, FALSE );
516 s_config.m_traceShipPositionEnabled = false;
517 s_renderer.enableTraceShip( s_config.m_traceShipPositionEnabled );
525 static void s_onMouseLeftButtonDown( HWND hwnd, UINT vkey, int16_t x, int16_t y )
527 if ( s_isDragging ) {
531 ::SetCapture( hwnd );
539 static void s_onMouseLeftButtonUp( HWND hwnd, UINT vkey, int16_t x, int16_t y )
541 if ( s_isDragging ) {
543 s_isDragging = false;
553 static void s_onMouseLeftButtonDoubleClick( HWND hwnd, UINT vkey, int16_t x, int16_t y )
555 if ( s_isDragging ) {
559 s_popupCoord( hwnd, x, y );
564 static void s_onMouseRightButtonUp( HWND hwnd, UINT vkey, int16_t x, int16_t y )
566 if ( s_isDragging ) {
570 s_popupMenu( hwnd, x, y );
575 static void s_onPaint( HWND hwnd )
577 #ifdef GVO_PERF_CHECK
578 const int64_t perfBegin = g_queryPerformanceCounter();
580 s_renderer.render( s_latestShipVector, s_latestShipVelocity, s_shipTexture.get(), s_shipRouteList.get() );
581 ::ValidateRect( hwnd, NULL );
583 #ifdef GVO_PERF_CHECK
584 const int64_t perfEnd = g_queryPerformanceCounter();
585 const int64_t freq = g_queryPerformanceFrequency();
586 const double deltaPerSec = (double(perfEnd - perfBegin) / double(freq)) * 1000.0;
587 s_perfCountList.push_back(deltaPerSec);
589 const double ave = std::accumulate( s_perfCountList.begin(), s_perfCountList.end(), 0.0 ) / s_perfCountList.size();
590 if ( 100 < s_perfCountList.size() ) {
591 s_perfCountList.pop_front();
595 s = std::wstring( L"
\95`
\89æ
\91¬
\93x:" ) + std::to_wstring( ave ) + L"(ms)\n";
596 ::SetWindowText( hwnd, s.c_str() );
601 //
\83}
\83b
\83v
\89æ
\91\9c\82ð
\91I
\91ð
\82³
\82¹
\82é
602 static std::wstring s_getMapFileName()
604 wchar_t dir[MAX_PATH] = { 0 };
605 ::GetModuleFileName( g_hinst, dir, _countof( dir ) );
606 ::PathRemoveFileSpec( dir );
608 wchar_t filePath[MAX_PATH] = { 0 };
609 OPENFILENAME ofn = { sizeof(ofn) };
610 ofn.lpstrTitle = L"
\83}
\83b
\83v
\89æ
\91\9c\83t
\83@
\83C
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81B";
611 ofn.lpstrInitialDir = &dir[0];
612 ofn.lpstrFilter = L"
\83C
\83\81\81[
\83W
\83t
\83@
\83C
\83\8b\0L" L"*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff" L"\0"
613 L"
\91S
\82Ä
\82Ì
\83t
\83@
\83C
\83\8b\0" L"*.*" L"\0\0";
614 ofn.Flags = OFN_READONLY | OFN_FILEMUSTEXIST;
615 ofn.nMaxFile = _countof( filePath );
616 ofn.lpstrFile = &filePath[0];
617 if ( !::GetOpenFileName( &ofn ) ) {
624 static void s_updateFrame( HWND hwnd )
626 std::vector<GVOGameStatus> gameStats;
627 gameStats = s_gvoGameProcess.getState();
628 if ( gameStats.empty() ) {
632 //
\83Q
\81[
\83\80\83v
\83\8d\83Z
\83X
\82Ì
\83A
\83C
\83R
\83\93\83e
\83N
\83X
\83`
\83\83\81[
\82ª
\96¢
\8dì
\90¬
\82È
\82ç
\82Î
\8dì
\90¬
\82ð
\8e\8e\82Ý
\82é
633 if ( !s_shipTexture.get() ) {
634 const GVOImage * image = s_gvoGameProcess.shipIconImage();
636 s_shipTexture.reset( s_renderer.createTextureFromImage( *image ) );
640 for ( std::vector<GVOGameStatus>::const_iterator it = gameStats.begin(); it != gameStats.end(); ++it ) {
641 const GVOGameStatus& status = *it;
642 s_latestSurveyCoord = status.m_surveyCoord;
643 s_latestShipVector = status.m_shipVector;
644 s_latestShipVelocity = status.m_shipVelocity;
645 s_config.m_initialSurveyCoord = s_latestSurveyCoord;
646 s_renderer.setShipPositionInWorld( s_latestSurveyCoord );
647 if ( (s_latestTimeStamp + k_surveyCoordLostThreshold) < status.m_timeStamp ) {
650 s_latestTimeStamp = status.m_timeStamp;
651 s_shipRouteList->addRoutePoint( s_worldMap.normalizedPoint( s_latestSurveyCoord ) );
653 #ifndef GVO_PERF_CHECK
654 s_updateWindowTitle( hwnd, s_latestSurveyCoord, s_renderer.viewScale() );
656 ::InvalidateRect( hwnd, NULL, FALSE );
660 static void s_updateWindowTitle( HWND hwnd, POINT surveyCoord, double viewScale )
662 std::vector<wchar_t> buf( 4096 );
663 ::swprintf( &buf[0], buf.size(), L"%d,%d - (%.1f%%) - %s %s",
664 surveyCoord.x, surveyCoord.y,
668 ::SetWindowText( hwnd, &buf[0] );
672 static void s_toggleKeepForeground( HWND hwnd )
674 if ( ::GetWindowLong( hwnd, GWL_EXSTYLE ) & WS_EX_TOPMOST ) {
675 ::SetWindowPos( hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
676 s_config.m_keepForeground = false;
679 ::SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
680 s_config.m_keepForeground = true;
685 static void s_popupMenu( HWND hwnd, int16_t x, int16_t y )
687 HMENU hmenu = ::LoadMenu( g_hinst, MAKEINTRESOURCE( IDR_POPUPMENU ) );
688 HMENU popupMenu = ::GetSubMenu( hmenu, 0 );
690 ::CheckMenuItem( popupMenu, IDM_TOGGLE_TRACE_SHIP, s_config.m_traceShipPositionEnabled ? MF_CHECKED : MF_UNCHECKED );
691 ::CheckMenuItem( popupMenu, IDM_TOGGLE_KEEP_FOREGROUND, s_config.m_keepForeground ? MF_CHECKED : MF_UNCHECKED );
692 ::CheckMenuItem( popupMenu, IDM_TOGGLE_SPEED_METER, s_config.m_speedMeterEnabled ? MF_CHECKED : MF_UNCHECKED );
693 ::CheckMenuItem( popupMenu, IDM_TOGGLE_VECTOR_LINE, s_config.m_shipVectorLineEnabled ? MF_CHECKED : MF_UNCHECKED );
696 MENUITEMINFO mii = { sizeof(mii) };
697 mii.fMask = MIIM_TYPE | MIIM_ID;
698 mii.fType = MFT_STRING;
700 //
\83f
\83o
\83b
\83O
\97p
\8e©
\93®
\8dq
\8ds
\82Ì
\90Ø
\82è
\91Ö
\82¦
701 mii.wID = IDM_TOGGLE_DEBUG_AUTO_CRUISE;
702 mii.dwTypeData = L"[DEBUG]
\8e©
\93®
\8dq
\8ds
\82ð
\97L
\8cø";
703 ::InsertMenuItem( popupMenu, ::GetMenuItemCount( popupMenu ), TRUE, &mii );
704 ::CheckMenuItem( popupMenu, IDM_TOGGLE_DEBUG_AUTO_CRUISE, s_config.m_debugAutoCruiseEnabled ? MF_CHECKED : MF_UNCHECKED );
706 mii.wID = IDM_DEBUG_CLOSE_ROUTE;
707 mii.dwTypeData = L"[DEBUG]
\8dq
\98H
\82ð
\95Â
\82¶
\82é";
708 ::InsertMenuItem( popupMenu, ::GetMenuItemCount( popupMenu ), TRUE, &mii );
710 mii.wID = IDM_DEBUG_INTERVAL_NORMAL;
711 mii.dwTypeData = L"[DEBUG]
\8dX
\90V
\8aÔ
\8au -
\95W
\8f\80";
712 ::InsertMenuItem( popupMenu, ::GetMenuItemCount( popupMenu ), TRUE, &mii );
714 mii.wID = IDM_DEBUG_INTERVAL_HIGH;
715 mii.dwTypeData = L"[DEBUG]
\8dX
\90V
\8aÔ
\8au -
\8d\82\95p
\93x";
716 ::InsertMenuItem( popupMenu, ::GetMenuItemCount( popupMenu ), TRUE, &mii );
719 //
\83\81\83j
\83\85\81[
\95\
\8e¦
\92\86\82Í
\83\81\83b
\83Z
\81[
\83W
\83|
\83\93\83v
\82©
\82ç
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\82Ì
\82Å
\83^
\83C
\83}
\81[
\82Å
\8dX
\90V
\82ð
\8aÄ
\8e\8b\82µ
\82Ä
\82¨
\82
\81B
720 const UINT_PTR timerID = ::SetTimer( hwnd, 0, s_pollingInterval, NULL );
721 s_updateFrame( hwnd );
724 ::ClientToScreen( hwnd, &p );
725 ::TrackPopupMenu( popupMenu, TPM_NONOTIFY | TPM_NOANIMATION | TPM_LEFTALIGN | TPM_TOPALIGN,
726 p.x, p.y, 0, hwnd, NULL );
727 ::DestroyMenu( popupMenu );
729 ::KillTimer( hwnd, timerID );
733 static void s_popupCoord( HWND hwnd, int16_t x, int16_t y )
738 static void s_closeShipRoute()
740 s_shipRouteList->closeRoute();
744 BOOL CALLBACK aboutDlgProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
749 std::wstring versionString = std::wstring(k_appName) + L" " + k_version;
750 std::wstring copyRightString = std::wstring( k_copyright );
752 ::SetDlgItemText( hwnd, IDC_VERSION_LABEL, versionString.c_str() );
753 ::SetDlgItemText( hwnd, IDC_COPYRIGHT_LABEL, copyRightString.c_str() );
757 switch ( LOWORD( wp ) ) {
760 ::EndDialog( hwnd, 0 );