// MFC_ContainerDlg.cpp : implementation file // #include "stdafx.h" #include #include #include #include #include #include "MFC_Container.h" #include "MFC_ContainerDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif //! convert string key-value pairs to map. std::unordered_map<_tstring, _tstring> string2map(LPCTSTR str); //!export a PNG file to temp folder _tstring export_res(); // CMFC_ContainerDlg dialog CMFC_ContainerDlg::CMFC_ContainerDlg(CWnd* pParent /*=NULL*/) : CDialog(IDD_MFC_CONTAINER_DIALOG, pParent) , m_currentLat(0) , m_currentLon(0) , m_direct (0) , m_nTimer(1) , m_bInited (false) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); srand((unsigned int)time(0)); m_direct = rand() % 360; } void CMFC_ContainerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_QTAXVIEWER_PLANETOSM, m_map); DDX_Control(pDX, IDC_LIST_MSG, m_list_msg); DDX_Control(pDX, IDC_STATIC_MOUSEMOVE, m_static_msg); } BEGIN_MESSAGE_MAP(CMFC_ContainerDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_SIZE() ON_BN_CLICKED(IDC_BUTTON_PLAY, &CMFC_ContainerDlg::OnBnClickedButtonPlay) ON_BN_CLICKED(IDC_BUTTON_PAUSE, &CMFC_ContainerDlg::OnBnClickedButtonPause) ON_WM_TIMER() END_MESSAGE_MAP() // CMFC_ContainerDlg message handlers BOOL CMFC_ContainerDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon GetDlgItem(IDC_BUTTON_PAUSE)->EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFC_ContainerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFC_ContainerDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } //MFC framework is old enough, that it does not support automatically size-management. void CMFC_ContainerDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); if (cx && cy) { if (IsWindow(this->GetSafeHwnd())) { if (IsWindow(this->m_map.GetSafeHwnd())) { m_map.MoveWindow(0, 80, cx, cy-80); CWnd * w = GetDlgItem(IDC_LIST_MSG); CRect rect; w->GetWindowRect(&rect); ScreenToClient(&rect); if (w) w->MoveWindow(rect.left, rect.top, cx - rect.left-4, rect.Height()); } } } } BEGIN_EVENTSINK_MAP(CMFC_ContainerDlg, CDialog) ON_EVENT(CMFC_ContainerDlg, IDC_QTAXVIEWER_PLANETOSM, 9, CMFC_ContainerDlg::evt_MessageQtaxviewerPlanetosm, VTS_BSTR) END_EVENTSINK_MAP() void CMFC_ContainerDlg::evt_MessageQtaxviewerPlanetosm(LPCTSTR p0) { std::unordered_map<_tstring, _tstring> paras = string2map(p0); CString add_msg = p0; if (paras[_T("name")] == _T("MOUSE_MOVE")) { m_static_msg.SetWindowText(add_msg); } else { int ct = m_list_msg.GetCount(); m_list_msg.InsertString(ct, add_msg); m_list_msg.SetCurSel(ct); while (m_list_msg.GetCount() >= 1024) m_list_msg.DeleteString(0); } } void CMFC_ContainerDlg::OnBnClickedButtonPlay() { //if not inited, load icons if (m_bInited == false) { m_bInited = true; //load png _tstring fm = export_res(); if (fm.size()) { CString cmd; cmd.Format(_T("function=add_resource;name=arrow;" "filename=%s;centerx=31;centery=31;" ), fm.c_str() ); m_map.osm_layer_call_function(_T("geomarker"), cmd); } } this->SetTimer(m_nTimer, 200, 0); GetDlgItem(IDC_BUTTON_PLAY)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_PAUSE)->EnableWindow(TRUE); } void CMFC_ContainerDlg::OnBnClickedButtonPause() { this->KillTimer(m_nTimer); GetDlgItem(IDC_BUTTON_PLAY)->EnableWindow(TRUE); GetDlgItem(IDC_BUTTON_PAUSE)->EnableWindow(FALSE); } void CMFC_ContainerDlg::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent == m_nTimer) { this->KillTimer(m_nTimer); const double pi = 3.14159265355; double s = 180 * (30.0 / 6300) / pi; double dx = s * cos(m_direct/180.0*pi) / cos (m_currentLat * pi /180.0); double dy = s * sin(m_direct / 180.0*pi); m_currentLat += dy; m_currentLon += dx; if (m_currentLat <= -85) { m_currentLat = -85; m_direct = rand() % 90 + 45; } else if (m_currentLat >= 85) { m_currentLat = 85; m_direct = -(rand() % 90 + 45); } m_currentLon += 360 * 2; m_currentLon = fmod(m_currentLon+180, 360)-180; CString cmd; cmd.Format(_T("function=update_icon;name=point1;" "lat=%.8lf;lon=%.8lf;" "icon=arrow;scale=0.5;rotate=%.2lf;smooth=1;" ), m_currentLat, m_currentLon, 90-m_direct ); m_map.osm_layer_call_function(_T("geomarker"), cmd); cmd.Format(_T("function=update_props;name=point1;" "lat=%.8lf;lon=%.8lf;direct=%.8lf;" ), m_currentLat, m_currentLon, m_direct ); m_map.osm_layer_call_function(_T("geomarker"), cmd); //Lines m_list_old_lats.push_front(m_currentLat); m_list_old_lons.push_front(m_currentLon); const int maxsz = 128; while (m_list_old_lats.size() > maxsz) { m_list_old_lats.pop_back(); m_list_old_lons.pop_back(); } int c = 0; double lastlat = m_currentLat, lastlon = m_currentLon; for ( std::list::iterator latp = m_list_old_lats.begin(), lonp = m_list_old_lons.begin(); latp != m_list_old_lats.end() && lonp != m_list_old_lons.end(); ++latp, ++lonp, ++c ) { cmd.Format(_T("function=update_line;name=line%d;" "lat0=%.7lf;lon0=%.7lf;lat1=%.7lf;lon1=%.7lf;" "style_pen=1;color_pen=255,0,0,%d;width_pen=%d;" ), c, lastlat, lastlon, *latp, *lonp, int((1 - c * 1.0/ maxsz)*255), int((1 - c * 1.0 / maxsz) * 6)+1 ); m_map.osm_layer_call_function(_T("geomarker"), cmd); lastlat = *latp, lastlon = *lonp; } m_map.osm_set_center_pos(m_currentLat, m_currentLon); if (rand()%10==1) m_direct += rand()%100/10.0-5.0; this->SetTimer(m_nTimer, 100, 0); } CDialog::OnTimer(nIDEvent); } //---------------------------------- std::unordered_map<_tstring, _tstring> string2map(LPCTSTR str) { std::unordered_map<_tstring, _tstring> res_map; size_t szLen = _tcslen(str); std::vector pArrBuf; pArrBuf.resize(szLen + 1); _tcscpy_s(pArrBuf.data(), szLen + 1, str); std::vector vec_pairs; //record each pairs' begin vec_pairs.push_back(0); for (int i = 0; i < szLen; ++i) { if (pArrBuf[i] == ';') { vec_pairs.push_back(i + 1); pArrBuf[i] = 0; } } //for each pairs, split by '=' size_t pairs = vec_pairs.size(); for (size_t i = 0; i < pairs; ++i) { size_t cur_pair = vec_pairs[i]; if (pArrBuf[cur_pair] == 0) continue; int pec = cur_pair; while (pec < szLen) { if (pArrBuf[pec] == 0) break; if (pArrBuf[pec] == _T('=')) { pArrBuf[pec] = 0; _tstring key = &pArrBuf[cur_pair]; _tstring val = &pArrBuf[pec + 1]; res_map[key] = val; } else ++pec; } } return std::move(res_map); } _tstring export_res() { _tstring fm; HINSTANCE hInst = AfxGetResourceHandle(); HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(IDB_PNG_MARK), _T("PNG")); // type if (!hRsrc) return std::move(fm); // load resource into memory DWORD len = SizeofResource(hInst, hRsrc); BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc); if (!lpRsrc) return std::move(fm); // Allocate global memory on which to create stream HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len); BYTE* pmem = (BYTE*)GlobalLock(m_hMem); memcpy(pmem, lpRsrc, len); IStream* pstm; CreateStreamOnHGlobal(m_hMem, FALSE, &pstm); // save to file const DWORD dwSize = MAX_PATH; TCHAR tempPath[dwSize]; if (GetTempPath(dwSize, tempPath) < dwSize) { _tstring filename = tempPath; filename += _T("\\qplanetosm_mfc_png.png"); CFile file; if (file.Open(filename.c_str(), CFile::modeCreate | CFile::modeWrite)) { file.Write(pmem, len); file.Close(); fm = filename; } } // free/release stuff GlobalUnlock(m_hMem); pstm->Release(); FreeResource(lpRsrc); return std::move(fm); }