489 lines
12 KiB
C++
489 lines
12 KiB
C++
// 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<LPNMITEMACTIVATE>(pNMHDR);
|
||
// TODO: 在此添加控件通知处理程序代码
|
||
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(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<LPNMITEMACTIVATE>(pNMHDR);
|
||
// TODO: 在此添加控件通知处理程序代码
|
||
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(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);
|
||
}
|