// WcsMainDialog.cpp : 实现文件 // #include "stdafx.h" #include "Agv.h" #include "AgvMainDialog.h" #include "ModuleProcess.h" #include "afxdialogex.h" #include "tlhelp32.h"//加上头文件 #define TRAY_ICON_ID 666 // CAgvMainDialog 对话框 IMPLEMENT_DYNAMIC(CAgvMainDialog, CDialogEx) CAgvMainDialog::CAgvMainDialog(CWnd* pParent /*=NULL*/) : CDialogEx(IDD_WCS_MAIN_DIALOG, pParent) { //m_nSubDlg = 3; } CAgvMainDialog::~CAgvMainDialog() { } void CAgvMainDialog::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_MODULE, m_ModuleListCtrl); DDX_Control(pDX, IDC_EDIT_LOG, m_EditMultiLine); } BEGIN_MESSAGE_MAP(CAgvMainDialog, CDialogEx) ON_MESSAGE(WM_SYSTEMTRAY, &CAgvMainDialog::OnSystemtray) ON_COMMAND(ID_TRAY_SHOW, &CAgvMainDialog::OnTrayShow) ON_COMMAND(ID_TRAY_EXIT, &CAgvMainDialog::OnTrayExit) ON_WM_CLOSE() ON_NOTIFY(NM_RCLICK, IDC_LIST_MODULE, &CAgvMainDialog::OnNMRClickListModule) ON_MESSAGE(WM_UPDATE_MODULE_STATUS, &CAgvMainDialog::OnUpdateModule) ON_NOTIFY(NM_DBLCLK, IDC_LIST_MODULE, &CAgvMainDialog::OnNMDblclkListModule) END_MESSAGE_MAP() // CAgvMainDialog 消息处理程序 void CAgvMainDialog::OnTrayShow() { AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOWNORMAL); SetForegroundWindow(); } void CAgvMainDialog::OnTrayExit() { NOTIFYICONDATA nid; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = m_hWnd; // 窗口句柄 nid.uID = TRAY_ICON_ID; // 托盘图标的唯一标识符 Shell_NotifyIcon(NIM_DELETE, &nid); OnOK(); } unsigned int __stdcall FastCallback(LPVOID param) { char acUrl[128] = { 0 }; GetPrivateProfileString("WMS-SERVER", "FAST", "0.0.0.0", acUrl, 128, theApp.m_strConfigFile); CString strUrl = acUrl; CHttpClient client; while (true) { client.FastCallBack(strUrl, ""); Sleep(2000); } return 0; } void CAgvMainDialog::AddLog2Edit(CString strMsg) { CString str; m_EditMultiLine.GetWindowText(str); if (str.GetLength() > 2048) { str = ""; //自动清理日志 } str += strMsg; str += "\r\n"; m_EditMultiLine.SetWindowText(str); m_EditMultiLine.LineScroll(m_EditMultiLine.GetLineCount()); } BOOL CAgvMainDialog::OnInitDialog() { CDialogEx::OnInitDialog(); //ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW, 1);//任务栏隐藏 m_ModuleListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); //设置系统托盘 NotifyIcon.cbSize = sizeof(NOTIFYICONDATA); NotifyIcon.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME); //NotifyIcon.hIcon = m_hIcon; //上面那句也可以 NotifyIcon.hWnd = m_hWnd; lstrcpy(NotifyIcon.szTip, _T("WDQ-WCS-PLATFORM")); NotifyIcon.uCallbackMessage = WM_SYSTEMTRAY; NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; NotifyIcon.uID = TRAY_ICON_ID; Shell_NotifyIcon(NIM_ADD, &NotifyIcon); //添加系统托盘 m_ModuleListCtrl.InsertColumn(0, "名称", 0, 150); m_ModuleListCtrl.InsertColumn(1, "模块名", 0, 200); m_ModuleListCtrl.InsertColumn(2, "运行状态", 0, 80); m_ModuleListCtrl.InsertColumn(3, "启动次数", 0, 80); m_ModuleListCtrl.InsertColumn(4, "路径", 0, 400); StartHttpServer(); (HANDLE)_beginthreadex(NULL, 0, FastCallback, this, 0, NULL); InitModule(); RefresModuleShow(); //static CFont fontList; //fontList.CreatePointFont(120, "宋体"); //m_ModuleListCtrl.SetFont(&fontList); //m_ModuleListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } afx_msg LRESULT CAgvMainDialog::OnSystemtray(WPARAM wParam, LPARAM lParam) { //wParam接收的是图标的ID,而lParam接收的是鼠标的行为 // if(wParam!=IDR_MAINFRAME) // return 1; switch (lParam) { case WM_RBUTTONDOWN://右键起来时弹出快捷菜单 { CMenu menuexit; //menu.LoadMenuW(IDR_MENU1); //加载菜单资源 menuexit.LoadMenuA(IDR_MENU); CMenu *pPopup=menuexit.GetSubMenu(0); CPoint mypoint; GetCursorPos(&mypoint); //ClientToScreen(&mypoint);//将客户区坐标转换为屏幕坐标 //SetForegroundWindow(); PostMessage(WM_NULL,0,0); //显示右键菜单,由视类窗口拥有。 pPopup->TrackPopupMenu(TPM_LEFTALIGN,mypoint.x,mypoint.y,this); break; } } return 0; } BOOL CAgvMainDialog::StartHttpServer() { char acIp[64] = { 0 }; GetPrivateProfileString("WCS-SERVER", "IP", "0.0.0.0", acIp, 63, theApp.m_strConfigFile); int nPort = (short)GetPrivateProfileInt("WCS-SERVER", "PORT", 0, theApp.m_strConfigFile); httpServerListener = new HttpServiceListener(this); BOOL bRet = httpService.Create(acIp, nPort, httpServerListener, this); if (bRet) { GetDlgItem(IDC_STATIC_SERVER_STATUS)->SetWindowText("***HTTP Server Start Succeed***"); } else { GetDlgItem(IDC_STATIC_SERVER_STATUS)->SetWindowText("***HTTP Server Start Failed***"); } return bRet; } CString CAgvMainDialog::UTF8ToMultiByte(const std::string& utf8String) { int len = MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), -1, NULL, 0); std::wstring wideString(len, L'\0'); MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), -1, &wideString[0], len); len = WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), -1, NULL, 0, NULL, NULL); CString multiByteString; multiByteString.GetBufferSetLength(len); WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), -1, multiByteString.GetBuffer(), len, NULL, NULL); multiByteString.ReleaseBuffer(); return multiByteString; } void CAgvMainDialog::InitModule() { //读取数量 time_t lNowTime = 0; time(&lNowTime); int lPort = 7000 + lNowTime % 1000 * 10;//端口号每次启动都变化下,最多不会超过10个模块 int lCount = GetPrivateProfileInt("AGV-MODULE", "COUNT", 0, theApp.m_strConfigFile); for (int i = 0; i < lCount; i++) { char acCnNameKey[64] = { 0 }, acCnName[64] = { 0 }, acNameKey[64] = { 0 }, acName[64] = { 0 }, acPathKey[64] = { 0 }, acPath[256] = { 0 }, acPipe[256] = { 0 }, acLastStatusKey[64] = {0}; sprintf_s(acCnNameKey, "CN_NAME_%d", i); sprintf_s(acNameKey, "NAME_%d", i); sprintf_s(acPathKey, "PATH_%d", i); sprintf_s(acLastStatusKey, "LAST_STATUS_%d", i); //中文名称,仅显示用 GetPrivateProfileString("AGV-MODULE", acCnNameKey, "", acCnName, sizeof(acCnName) - 1, theApp.m_strConfigFile); //名称--同时作为消息标识 GetPrivateProfileString("AGV-MODULE", acNameKey, "", acName, sizeof(acName)-1, theApp.m_strConfigFile); //模块启动路径 GetPrivateProfileString("AGV-MODULE", acPathKey, "", acPath, sizeof(acPath)-1, theApp.m_strConfigFile); CString strPath(acPath); if (strPath.Find(":") <= 0) { strPath = theApp.m_strBaseDir + "\\" + strPath; } int lLastStatus = GetPrivateProfileInt("AGV-MODULE", acLastStatusKey, 0, theApp.m_strConfigFile); CModuleProcess* pModule = new CModuleProcess(this, strPath, acName, i); CString strPipeName; strPipeName.Format("%d", lPort++); pModule->SetPipeName(strPipeName); m_mapAllNormal[acName] = pModule; sprintf_s(acPipe, "PIPE_%s", acName); WritePrivateProfileString("AGV-MODULE", acPipe, strPipeName, theApp.m_strConfigFile); CString strChName = UTF8ToMultiByte(acCnName); int lItem = m_ModuleListCtrl.InsertItem(65535, strChName); m_ModuleListCtrl.SetItemText(lItem, 1, acName); m_ModuleListCtrl.SetItemText(lItem, 4, strPath); m_ModuleListCtrl.SetItemData(lItem, (DWORD_PTR)pModule); //主程序启动时,默认杀死插件模块进程 int nPos = strPath.ReverseFind('\\'); CString fileName = strPath.Right(strPath.GetLength() - nPos - 1); KillProcess(fileName); int nDebug = GetPrivateProfileInt("AGV-MODULE", "DEBUG", 0, theApp.m_strConfigFile); m_nDebug = nDebug; if (lLastStatus == 1 || nDebug == 1)//0不启动,1启动 { pModule->Start(nDebug); } } return ; } void CAgvMainDialog::RefresModuleShow() { for (int i = 0; i < m_ModuleListCtrl.GetItemCount(); i++) { CModuleProcess* pModule = (CModuleProcess*)m_ModuleListCtrl.GetItemData(i); CString strText; strText.Format("%d", pModule->m_lReStartCount); int lStatus = pModule->GetStatus(); if (0 == lStatus) { m_ModuleListCtrl.SetItemText(i, 2, "已停止"); } else if (1 == lStatus) { m_ModuleListCtrl.SetItemText(i, 2, "已启动"); } else if (2 == lStatus) { m_ModuleListCtrl.SetItemText(i, 2, "启动中"); } else { m_ModuleListCtrl.SetItemText(i, 2, "异常"); } if (m_nDebug == 1) { m_ModuleListCtrl.SetItemText(i, 2, "调试模式"); } m_ModuleListCtrl.SetItemText(i, 3, strText); } } void CAgvMainDialog::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); } CModuleProcess* CAgvMainDialog::GetModuleByName(CString strName) { for (int i = 0; i < m_ModuleListCtrl.GetItemCount(); i++) { CModuleProcess* pModule = (CModuleProcess*)m_ModuleListCtrl.GetItemData(i); if (pModule->GetModuleName() == strName) { return pModule; } } return NULL; } void CAgvMainDialog::OnNMRClickListModule(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR); int lIndex = pNMLV->iItem; if (lIndex == -1) { *pResult = 0; return; } CModuleProcess* pModule = (CModuleProcess*)m_ModuleListCtrl.GetItemData(lIndex); CMenu menu; menu.CreatePopupMenu(); // 添加菜单项 int lModuleStatus = pModule->GetStatus(); if (0 == lModuleStatus) { menu.AppendMenu(MF_STRING, 100, _T("启动模块")); } else if (1 == lModuleStatus) { menu.AppendMenu(MF_STRING, 101, _T("停止运行")); } else { menu.AppendMenu(MF_STRING, 101, _T("强制停止")); } // 添加更多菜单项... char acLastStatusKey[64] = { 0 }; sprintf_s(acLastStatusKey, "LAST_STATUS_%d", pModule->m_lModuleIndex); // 显示弹出菜单 CPoint point; GetCursorPos(&point); int nCmdID = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, this); // 处理用户选择的菜单项 switch (nCmdID) { case 100: // 执行菜单项1的操作 pModule->Start(); WritePrivateProfileString("AGV-MODULE", acLastStatusKey, "1", theApp.m_strConfigFile); break; case 101: // 执行菜单项2的操作 pModule->Stop(); WritePrivateProfileString("AGV-MODULE", acLastStatusKey, "0", theApp.m_strConfigFile); break; // 处理更多菜单项... } menu.DestroyMenu(); RefresModuleShow(); *pResult = 0; } LRESULT CAgvMainDialog::OnUpdateModule(WPARAM wparam, LPARAM lparam) { RefresModuleShow(); return 0; } void CAgvMainDialog::OnNMDblclkListModule(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR); int lIndex = pNMLV->iItem; if (lIndex == -1) { *pResult = 0; return; } CModuleProcess* pModule = (CModuleProcess*)m_ModuleListCtrl.GetItemData(lIndex); int lModuleStatus = pModule->GetStatus(); if (lModuleStatus == 1) { pModule->SendDataToModule(MAIN_2_MODULE_SHOWWINDOW, NULL, 0); } *pResult = 0; } /* 可进行调试,查看进程的名字 在需要关闭进程的地方调用KillProcess(_T("要关闭的进程的名字"));即可。 */ void CAgvMainDialog::KillProcess(CString sExeName) { //CreateToolhelp32Snapshot()得到系统进程的一个快照 HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapShot == 0) return; PROCESSENTRY32 thePE; thePE.dwSize = sizeof(PROCESSENTRY32); //遍历正在运行的第一个系统进程 bool Status = Process32First(hSnapShot, &thePE); bool bHaveFlag = false; //找到进程名状态 DWORD ProcessID = 0; while (Status) { //遍历正在运行的下一个系统进程 Status = Process32Next(hSnapShot, &thePE); //找到相应的进程 **.exe // if(0 == wcscmp(thePE.szExeFile,L"")) CString sFindName = thePE.szExeFile;//进程中的进程名 CString sTemp = sExeName.Mid(0, sFindName.GetLength());//要关闭的进程名 if (sFindName == sTemp) { bHaveFlag = true; ProcessID = thePE.th32ProcessID; //结束指定的进程 ProcessID if (!TerminateProcess(OpenProcess (PROCESS_TERMINATE || PROCESS_QUERY_INFORMATION, false, ProcessID), 0)) { //AfxMessageBox(L"无法终止指定的进程!", MB_ICONWARNING || MB_OK); } else { //AfxMessageBox(L"进程结束!", MB_ICONWARNING || MB_OK); break; } } } CloseHandle(hSnapShot); }