// TCLToolsDlg.cpp : 实现文件 // #include "stdafx.h" #include "TCLTools.h" #include "TCLToolsDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CTCLToolsDlg 对话框 BOOL GetSysSerialPort(std::vector& vtports) { HKEY hKey; LSTATUS lReg = 0; DWORD dwMaxValLen = 0; DWORD dwValNum = 0; lReg = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey); if (lReg != ERROR_SUCCESS) { return FALSE; } lReg = RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValNum, &dwMaxValLen, NULL, NULL, NULL); if (lReg != ERROR_SUCCESS) { return FALSE; } if (vtports.size()) { vtports.clear(); } LPSTR lpValName, lpComNum; DWORD dwValName, dwValSize = 6; for (DWORD i = 0; i < dwValNum; i++) { dwValName = dwMaxValLen + 1; dwValSize = 6; lpValName = (LPSTR)VirtualAlloc(NULL, dwValName, MEM_COMMIT, PAGE_READWRITE); lReg = RegEnumValueA(hKey, i, lpValName, &dwValName, NULL, NULL, NULL, NULL); if ((lReg != ERROR_SUCCESS) && (lReg != ERROR_NO_MORE_ITEMS)) { continue; } lpComNum = (LPSTR)VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_READWRITE); lReg = RegQueryValueExA(hKey, lpValName, NULL, NULL, (LPBYTE)lpComNum, &dwValSize); if (lReg != ERROR_SUCCESS) { continue; } vtports.push_back(lpComNum); VirtualFree(lpValName, 0, MEM_RELEASE); VirtualFree(lpComNum, 0, MEM_RELEASE); } return TRUE; } bool ReadKeyFromFile(std::string file, std::string &data) { FILE* pf = NULL; if (fopen_s(&pf, file.c_str(), _T("rb")) == 0) { if (pf) { fseek(pf, 0, SEEK_END); size_t fs = ftell(pf); fseek(pf, 0, SEEK_SET); byte* pdata = (byte*)malloc(fs); if (pdata) { fread(pdata, fs, 1, pf); fclose(pf); data.append((char*)pdata, fs); free(pdata); return true; } fclose(pf); } } return false; } CTCLToolsDlg::CTCLToolsDlg(CWnd* pParent /*=NULL*/) : CDialog(CTCLToolsDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CTCLToolsDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_PORTS, m_cbSerial); DDX_Control(pDX, IDC_COMBO_CMDS, m_cbCommands); DDX_Control(pDX, IDC_COMBO_BUADRATE, m_cb_baudrate); } BEGIN_MESSAGE_MAP(CTCLToolsDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_DEVICECHANGE() //}}AFX_MSG_MAP ON_BN_CLICKED(BTN_OPEN_PORT, &CTCLToolsDlg::OnBnClickedOpenPort) ON_BN_CLICKED(BTN_EXEC_CMD, &CTCLToolsDlg::OnBnClickedExecCmd) ON_BN_CLICKED(BTN_OPEN_FILE, &CTCLToolsDlg::OnBnClickedOpenFile) ON_BN_CLICKED(BTN_RELOAD_CMD, &CTCLToolsDlg::OnBnClickedReloadCmd) ON_BN_CLICKED(IDC_CHECK_HB, &CTCLToolsDlg::OnBnClickedCheckHb) ON_BN_CLICKED(IDC_CHECK_BH, &CTCLToolsDlg::OnBnClickedCheckBh) END_MESSAGE_MAP() // CTCLToolsDlg 消息处理程序 BOOL CTCLToolsDlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 GetSysSerialPort(m_vtPorts); InitSerialCombobox(); InitCommandCombobox(); m_cbCommands.SetCurSel(0); CString strCOM = AfxGetApp()->GetProfileString("TCLTools","COM", ""); if ( strCOM.Find("COM") != -1 ) { m_cbSerial.SelectString(0, strCOM); } else { m_cbSerial.SetCurSel(0); } m_cb_baudrate.AddString(_T("1200")); m_cb_baudrate.AddString(_T("2400")); m_cb_baudrate.AddString(_T("4800")); m_cb_baudrate.AddString(_T("9600")); m_cb_baudrate.AddString(_T("19200")); m_cb_baudrate.AddString(_T("38400")); m_cb_baudrate.AddString(_T("57600")); m_cb_baudrate.AddString(_T("115200")); m_cb_baudrate.AddString(_T("460800")); m_cb_baudrate.AddString(_T("921600")); m_cb_baudrate.AddString(_T("230400")); m_cb_baudrate.SelectString(0, _T("115200")); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CTCLToolsDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 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; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CTCLToolsDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } BOOL CTCLToolsDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwData) { switch (nEventType) { // 串口拨掉; case DBT_DEVICEREMOVECOMPLETE: break; // 串口插入; case DBT_DEVICEARRIVAL: { GetSysSerialPort(m_vtPorts); InitSerialCombobox(); break; } default: break; } return TRUE; } void CTCLToolsDlg::InitSerialCombobox() { m_cbSerial.ResetContent(); for (std::vector::iterator it = m_vtPorts.begin(); it != m_vtPorts.end(); it++) { m_cbSerial.AddString(it->c_str()); } } void CTCLToolsDlg::InitCommandCombobox() { // 获取当前选择的命令; CString strText; int nCurSel = m_cbCommands.GetCurSel(); if ( nCurSel != CB_ERR ) m_cbCommands.GetLBText(nCurSel, strText); // 清空; m_cbCommands.ResetContent(); std::vector ExternalCMDParams = g_tclCommand.GetExternalCMDParams(); std::vector InternalCMDParams = g_tclCommand.GetInternalCMDParams(); std::vector CMDParams(ExternalCMDParams); for ( std::vector::iterator it = InternalCMDParams.begin(); it != InternalCMDParams.end(); it++ ) { if ( !IsCommandExist(*it, CMDParams) ) { CMDParams.push_back(*it); } } for ( std::vector::iterator it = CMDParams.begin(); it != CMDParams.end(); it++ ) { m_cbCommands.AddString(it->name.c_str()); } nCurSel = m_cbCommands.SelectString(0, strText); if ( nCurSel == CB_ERR ) m_cbCommands.SetCurSel(0); } void CTCLToolsDlg::OnBnClickedOpenPort() { // TODO: 在此添加控件通知处理程序代码 CString strText; GetDlgItemText(BTN_OPEN_PORT, strText); if ( strText.Compare(_T("打开串口")) == 0 ) { int nCurSel = m_cbSerial.GetCurSel(); if ( nCurSel != CB_ERR ) { m_cbSerial.GetLBText(nCurSel,strText); AfxGetApp()->WriteProfileString("TCLTools","COM", strText); if ( g_tclCommand.IsOpen()) g_tclCommand.Close(); CString strBaudRate = _T(""); nCurSel = m_cb_baudrate.GetCurSel(); if ( nCurSel == CB_ERR ) { MessageBox("请选择波特率", "错误!", MB_ICONEXCLAMATION); return; } m_cb_baudrate.GetLBText(nCurSel, strBaudRate); if ( g_tclCommand.Open(atol(strText.Mid(3).GetString()), atoi(strBaudRate)) ) { SetDlgItemText(BTN_OPEN_PORT, _T("关闭串口")); m_cbSerial.EnableWindow(FALSE); //g_tclCommand.SetTimeouts(10, 50, 3000, 10, 1500); } else { MessageBox("打开串口失败", "错误!", MB_ICONEXCLAMATION); } } else { MessageBox("请选择串口", "错误!", MB_ICONEXCLAMATION); } } else { SetDlgItemText(BTN_OPEN_PORT, _T("打开串口")); m_cbSerial.EnableWindow(); if ( g_tclCommand.IsOpen()) g_tclCommand.Close(); } } bool CTCLToolsDlg::IsCommandExist(CommandParam &cmd, std::vector &vtCMDParams) { bool bExist = false; for (std::vector::iterator it = vtCMDParams.begin(); it != vtCMDParams.end(); it++ ) { if ( _tcsicmp(it->name.c_str(), cmd.name.c_str()) == 0 ) { bExist = true; break; } } return bExist; } void CTCLToolsDlg::OnBnClickedExecCmd() { // TODO: 在此添加控件通知处理程序代码 ClearEdit(); CString strText; int nCurSel = m_cbCommands.GetCurSel(); if ( nCurSel != CB_ERR ) { CString strCMDName; m_cbCommands.GetLBText(nCurSel, strCMDName); SetDlgItemText(IDC_STATIC_RESULT, strCMDName + _T("->执行结果:")); if ( g_tclCommand.IsOpen() ) { bool bStatus = false; CommandParam cmdpara; g_tclCommand.GetCommandParams(strCMDName.GetString(), cmdpara); if ( cmdpara.nOption == CMDOPT_Set ) { // 需要选择文件; GetDlgItemText(IDC_EDIT_KEY, strText); if ( !PathFileExists(strText) ) { if ( MessageBox("Set指令没有选择Key文件,是否继续?", "警告!", MB_YESNO) == IDNO ) return; bStatus = g_tclCommand.SendCommand(strCMDName.GetString(), cmdpara); } else { std::string data; if ( ReadKeyFromFile(strText.GetString(), data) ) { // 默认读取内容; BOOL bCheckHB = ((CButton*)GetDlgItem(IDC_CHECK_HB))->GetCheck(); BOOL bCheckBH = ((CButton*)GetDlgItem(IDC_CHECK_BH))->GetCheck(); if ( !bCheckBH && !bCheckHB ) {// 原始文件内容; g_tclCommand.SendCommand(strCMDName.GetString(), cmdpara, (LPVOID)data.c_str(), data.size()); } else if ( !bCheckBH && bCheckHB ) {// 将文件内容按十六进制转字节; // 去除所有空格; utils::trim(data); std::string strBytes = utils::HexStringToBytes(data,2); g_tclCommand.SendCommand(strCMDName.GetString(), cmdpara, (LPVOID)strBytes.c_str(), strBytes.size()); } else if ( bCheckBH && !bCheckHB ) {// 将文件内容按字节转十六进制; } } } } else { bStatus = g_tclCommand.SendCommand(strCMDName.GetString(), cmdpara); } // 设置状态; if ( cmdpara._rtnStatus == 0x0A ) { SetDlgItemText(IDC_EDIT_STATUS, "成功"); } else if ( cmdpara._rtnStatus == 0x0E ) { SetDlgItemText(IDC_EDIT_STATUS, "命令错误或不可执行"); } else if ( cmdpara._rtnStatus == 0x0F ) { SetDlgItemText(IDC_EDIT_STATUS, "链路层数据错误"); } else { SetDlgItemText(IDC_EDIT_STATUS, "不可识别的错误"); } // 设置原字符串显示; SetDlgItemText(IDC_EDIT_ERROR, cmdpara._rtnError.c_str()); // 设置单字节值; if ( cmdpara.nOption == CMDOPT_Get && cmdpara._rtnData.size() < 3) { if ( cmdpara._rtnData.size() == 1) SetDlgItemInt(IDC_EDIT_INT, (byte)cmdpara._rtnData[0]); else if ( cmdpara._rtnData.size() == 2) SetDlgItemInt(IDC_EDIT_INT, (byte)cmdpara._rtnData[0] << 8 | (byte)cmdpara._rtnData[1]); } #if 0 // 设置原字符串显示; if ( cmdpara.nOption == CMDOPT_Get ) { SetDlgItemText(IDC_EDIT_STR, cmdpara._rtnData.c_str()); } // 设置16进制字符串显示; if ( cmdpara.nOption == CMDOPT_Get ) { SetDlgItemText(IDC_EDIT_HEX, utils::BytesToHexString((byte*)cmdpara._rtnData.c_str(), cmdpara._rtnData.size(), ' ').c_str()); } #else SetDlgItemText(IDC_EDIT_STR, utils::BytesToHexString((byte*)cmdpara._cmdContext.c_str(), cmdpara._cmdContext.size(), ' ').c_str()); SetDlgItemText(IDC_EDIT_HEX, utils::BytesToHexString((byte*)cmdpara._rtnContext.c_str(), cmdpara._rtnContext.size(), ' ').c_str()); #endif } else { MessageBox("串口未打开", "错误!", MB_ICONEXCLAMATION); } } } void CTCLToolsDlg::ClearEdit() { SetDlgItemText(IDC_EDIT_STATUS, ""); SetDlgItemText(IDC_EDIT_INT, ""); SetDlgItemText(IDC_EDIT_STR, ""); SetDlgItemText(IDC_EDIT_HEX, ""); } void CTCLToolsDlg::OnBnClickedOpenFile() { // TODO: 在此添加控件通知处理程序代码 char szFilters[] = "所有文件类型(*.*)\0*.*\0\0"; CFileDialog OpenDlg(TRUE); OpenDlg.m_ofn.lpstrTitle = "Open File"; OpenDlg.m_ofn.lpstrFilter = szFilters; if (IDOK == OpenDlg.DoModal()) { SetDlgItemText(IDC_EDIT_KEY, OpenDlg.GetPathName()); } } void CTCLToolsDlg::OnOK() { // TODO: 在此添加专用代码和/或调用基类 //CDialog::OnOK(); } void CTCLToolsDlg::OnCancel() { // TODO: 在此添加专用代码和/或调用基类 CDialog::OnCancel(); } void CTCLToolsDlg::OnBnClickedReloadCmd() { // 重新加载外部命令文件; g_tclCommand.SetExternalCMDParams("cmds.dat"); InitCommandCombobox(); } void CTCLToolsDlg::OnBnClickedCheckHb() { // TODO: 在此添加控件通知处理程序代码 BOOL bCheckHB = ((CButton*)GetDlgItem(IDC_CHECK_HB))->GetCheck(); BOOL bCheckBH = ((CButton*)GetDlgItem(IDC_CHECK_BH))->GetCheck(); if ( bCheckBH && bCheckHB ) { // 不可以同时使用2种相斥的方式; ((CButton*)GetDlgItem(IDC_CHECK_HB))->SetCheck(FALSE); } } void CTCLToolsDlg::OnBnClickedCheckBh() { // TODO: 在此添加控件通知处理程序代码 BOOL bCheckHB = ((CButton*)GetDlgItem(IDC_CHECK_HB))->GetCheck(); BOOL bCheckBH = ((CButton*)GetDlgItem(IDC_CHECK_BH))->GetCheck(); if ( bCheckBH && bCheckHB ) { // 不可以同时使用2种相斥的方式; ((CButton*)GetDlgItem(IDC_CHECK_BH))->SetCheck(FALSE); } }