fast/Platform/AgvMainDialog.cpp
2025-01-20 10:30:01 +08:00

489 lines
12 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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);
}