📄 scommdlg.cpp
字号:
// the minimized window.
HCURSOR CSCOMMDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
static long rxdatacount=0; //该变量用于接收字符计数
//接收数据处理
//函数功能:
LONG CSCOMMDlg::OnCommunication(WPARAM ch, LPARAM port)
{
if (port <= 0 || port > 4)
{
return -1;
}
rxdatacount ++; //接收的字节计数
CString strTemp;
strTemp.Format("%ld", rxdatacount);
strTemp="接收:"+strTemp;
m_ctrlRXCOUNT.SetWindowText(strTemp); //显示接收计数
//停止显示数据标志 0不停止1停止
if (m_bStopDispRXData) //如果选择了“停止显示”接收数据,则返回
{
return -1; //注意,这种情况下,计数仍在继续,只是不显示
}
/////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// 在接收编辑框中显示接收到的数据 /////////////////////////////////
////////////////////////////两种方案: 1.按"自动清空", 显示50 行后, 清屏继续显示//////////
//////////////////////////// 2.没有按"自动清空", 显示400行后, 清屏继续显示//////////
//////////////////////////// 3.按"十六进制显示", 显示BCD码 //////////
//////////////////////////// 4.没有按"十六进制显示", 显示ASCII码 //////////
////////////////////////////注意: 接收到的字符, 一直显示在编辑框的最后 //////////
/////////////////////////////////////////////////////////////////////////////////////////////
//若设置了“自动清空”,则达到50行后,自动清空接收编辑框中显示的数据
int ret;
int line;
ret = m_ctrlAutoClear.GetCheck(); //检测"自动清空" 单选复选框 选中状态 0未选中1选中
if (ret == 1)
{
line = m_ctrlReceiveData.GetLineCount();
if (line >= 50)
{
m_ReceiveData.Empty(); //将接收数据字符串 全部清空
UpdateData(FALSE); //将成员变量的值传给对应的控件, 并显示
}
}
else //如果没有“自动清空”,数据行达到400后,也自动清空
//因为数据过多,影响接收速度,显示是最费CPU时间的操作
{
line = m_ctrlReceiveData.GetLineCount();
if (line >= 400)
{
m_ReceiveData.Empty();
m_ReceiveData = "***The Length of the Text is too long, Emptied Automaticly!!!***\r\n"; //显示提示, 并将坐标移动到本行的开头
//m_ReceiveData = "***The Length of the Text is too long, Emptied Automaticly!!!***\n";
UpdateData(FALSE);
}
}
//如果选择了"十六进制显示",则显示十六进制值
CString str;
ret = m_ctrlHexReceieve.GetCheck();
if (ret == 1)
{
str.Empty();
str.Format("%02X ",ch);
}
else //如果没有选择"十六进制显示", 则显示ASCII值
{
str.Empty();
str.Format("%c",ch);
}
//以下是将接收的字符加在字符串的最后,这里费时很多
//但考虑到数据需要保存成文件,所以没有用List Control
//将接收的字符接在字符串的末尾, 并在接收编辑框中显示出来, 是在编辑框的末尾坐标显示刚刚接收到的字符, 不是刷屏显示全部
int nLen = m_ctrlReceiveData.GetWindowTextLength(); //获取编辑框控件中的字符总个数
m_ctrlReceiveData.SetSel(nLen, nLen); //移动到编辑框控件的末尾, 坐标设置
m_ctrlReceiveData.ReplaceSel(str); //添加文本
m_ReceiveData += str;
return 0;
}
//清空接收区
void CSCOMMDlg::OnButtonClearReciArea()
{
// TODO: Add your control notification handler code here
m_ReceiveData.Empty();
UpdateData(FALSE);
}
//打开/关闭串口
void CSCOMMDlg::OnButtonOpenport()
{
// TODO: Add your control notification handler code here
m_bOpenPort = !m_bOpenPort; //m_bOpenPort 串口状态 1关0开
int ret1;
if (m_bOpenPort == TRUE) //此时串口是打开的, 欲将串口关闭
{
//检测"自动发送" 普通复选框的状态
//如果选中了, 提示关闭, 后返回;
//如果没有选中, 继续执行
ret1 = m_ctrlAutoSend.GetCheck(); //检测 普通复选框 "自动发送"状态, 0未选中, 1选中
if (ret1)
{
m_bOpenPort = !m_bOpenPort; //如果自动发送选中, 则将m_bOpenPort设置为0, 即串口打开
AfxMessageBox("请先关掉自动发送");
return;
}
//设置按键按钮的显示内容
m_ctrlOpenPort.SetWindowText("打开串口");
//m_Port.StopMonitoring();
m_Port.ClosePort();//关闭串口
//状态栏(自己做的一个静态文本)
CString str;
str.Empty();
str.Format("当前状态: COM%d已关闭", m_nCom);
m_ctrlPortStatus.SetWindowText(str);
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
}
else //此时串口是关闭的, 欲将串口打开
{
ret1 = m_ctrlAutoSend.GetCheck(); //检测 普通复选框 "自动发送"状态, 0未选中, 1选中
if (ret1)
{
m_bOpenPort = TRUE;
AfxMessageBox("请先关掉自动发送");
return;
}
m_ctrlOpenPort.SetWindowText("关闭串口");
CString strStatus;
BOOL ret;
ret = m_Port.InitPort(this, m_nCom, m_nBaud, m_cParity, m_nDatabits, m_nStopbits, m_dwCommEvents, 512);
if (ret)
{
m_Port.StartMonitoring();
m_ctrlIconOpenoff.SetIcon(m_hIconRed);
strStatus.Empty();
strStatus.Format("当前状态: COM%d已打开,%dbps,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
//"当前状态:串口打开,无奇偶校验,8数据位,1停止位");
m_ctrlPortStatus.SetWindowText(strStatus);
}
else
{
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
strStatus.Empty();
strStatus.Format("当前状态: COM%d被占用或没有发现此串口", m_nCom);
AfxMessageBox(strStatus);
//状态栏(自己做的一个静态文本)
m_ctrlPortStatus.SetWindowText(strStatus);
}
}
}
//停止/继续显示接收数据
void CSCOMMDlg::OnButtonStopdisp()
{
// TODO: Add your control notification handler code here
m_bStopDispRXData = !m_bStopDispRXData; //停止显示数据标志 0不停止1停止
if (m_bStopDispRXData)
{
m_ctrlStopDisp.SetWindowText("继续显示");
}
else
{
m_ctrlStopDisp.SetWindowText("停止显示");
}
}
//将一个字符串作为十六进制串转化为一个字节数组,字节间可用空格分隔,
//返回转换后的字节数组长度,同时字节数组长度自动设置。
int CSCOMMDlg::Str2Hex(CString str, char *data)
{
/*int t,t1;
int rlen=0,len=str.GetLength();
//data.SetSize(len/2);
for(int i=0;i<len;)
{
char l,h=str[i];
if(h==' ')
{
i++;
continue;
}
i++;
if(i>=len)
break;
l=str[i];
t=HexChar(h);
t1=HexChar(l);
if((t==16)||(t1==16))
break;
else
t=t*16+t1;
i++;
data[rlen]=(char)t;
rlen++;
}
return rlen;*/
int len, i, k=0;
unsigned char buf[1024], tmpbuf[1024];
len = str.GetLength(); //字符串总的长度
memset(buf, 0, sizeof(buf ));
memset(tmpbuf, 0, sizeof(tmpbuf));
for (i=0; i<len; i++)
{
//前一个字符 范围在['0', '9']或['a', 'f']或['A', 'F']
//后一个字符 范围在['0', '9']或['a', 'f']或['A', 'F']
if ((((str[i]>=0X30) && (str[i]<=0X39)) || ((str[i]>='A') && (str[i]<='Z')) || ((str[i]>='a') && (str[i]<='z'))) && (((str[i+1]>=0X30) && (str[i+1]<=0X39)) || ((str[i+1]>='A') && (str[i+1]<='Z')) || ((str[i+1]>='a') && (str[i]<='z'))))
{
buf[k] = str[i];
buf[k+1] = str[i+1];
k += 2;
i ++;
}
else if ((((str[i]>=0X30) && (str[i]<=0X39)) || ((str[i]>='A') && (str[i]<='Z')) || ((str[i]>='a') && (str[i]<='z'))) && (str[i+1]==' '))
{
break;
}
}
ASCToBCD(tmpbuf, buf, k);
memcpy(data, tmpbuf, k/2);
return k/2;
}
long TX_count=0;
//手动发送 处理函数
void CSCOMMDlg::OnButtonManualsend()
{
// TODO: Add your control notification handler code here
if (m_Port.m_hComm == NULL)
{
m_ctrlAutoSend.SetCheck(0);
CString str;
str.Empty();
str.Format("COM%d没有打开,请打开串口", m_nCom);
AfxMessageBox(str);
return;
}
else
{
//将控件的值传给对应的成员变量
UpdateData(TRUE);
int ret;
//检测"16进制发送" 普通复选框按钮, 是否选中, 如果选中, 将发送编辑框中的数据按16进制数发送到选择串口
ret = m_ctrlHexSend.GetCheck();
if (ret == 1)
{
char data[512];
int len = Str2Hex(m_strSendData, data);
m_Port.WriteToPort(data, len);
TX_count += len;//(long)((m_strSendData.GetLength()+1)/3);
//m_Port.WriteToPort(hexdata);
}
else
{
m_Port.WriteToPort((LPCTSTR)m_strSendData); //发送数据
TX_count += m_strSendData.GetLength();
}
CString strTemp;
strTemp.Empty();
strTemp.Format("发送:%d", TX_count);
m_ctrlTXCount.SetWindowText(strTemp);
}
}
//自动发送" 普通复选框 选中处理函数
void CSCOMMDlg::OnCheckAutosend()
{
// TODO: Add your control notification handler code here
m_bAutoSend = !m_bAutoSend; //自动发送标志, 0不自动发送, 1自动发送
if (m_bAutoSend == TRUE)
{
if (m_Port.m_hComm == NULL)
{
m_bAutoSend = !m_bAutoSend;
m_ctrlAutoSend.SetCheck(0);
CString str;
str.Empty();
str.Format("COM%d没有打开,请打开串口", m_nCom);
AfxMessageBox(str);
return;
}
else
{
SetTimer(1, m_nCycleTime, NULL);
}
}
else
{
KillTimer(1);
}
}
//定时器 超时的消息处理
void CSCOMMDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CString strStatus;
switch (nIDEvent)
{
default:
break;
case 1: //选中"自动发送" 普通普选框后, 到达定时器极限时, 发送数据到串口;之后在从新计数, 从新发送, 一直到取消"自动发送"为止.
OnButtonManualsend(); //手动发送消息处理函数
break;
case 2:
m_strCurPath = m_strBak;
m_ctrlSavePath.SetWindowText(m_strCurPath);
KillTimer(2);
m_ctrlSaveData.EnableWindow(TRUE);
break;
case 3:
m_ctrlManualSend.EnableWindow(TRUE); //"手动发送" 允许
m_ctrlAutoSend.EnableWindow(TRUE); //"自动发送" 允许
m_ctrlSendFile.EnableWindow(TRUE); //"发送文件" 允许
m_strSendFilePathName = m_strTempSendFilePathName;
m_ctrlEditSendFile.SetWindowText(m_strSendFilePathName);//m_strSendFilePathName
KillTimer(3);
//恢复串口的原本设置, 串口缓冲区为512字节
if(!(m_ctrlAutoSend.GetCheck()))
{
BOOL ret;
ret = m_Port.InitPort(this, m_nCom, m_nBaud, m_cParity, m_nDatabits, m_nStopbits, m_dwCommEvents, 512);
if (ret)
{
m_Port.StartMonitoring();
//strStatus.Format("STATUS:COM%d OPENED,%d,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
m_ctrlIconOpenoff.SetIcon(m_hIconRed);
strStatus.Empty();
strStatus.Format("当前状态: COM%d已打开,%dbps,%c,%d,%d", m_nCom, m_nBaud, m_cParity, m_nDatabits, m_nStopbits);
m_ctrlPortStatus.SetWindowText(strStatus);
}
else
{
AfxMessageBox("Failed to reset send buffer size!");
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
strStatus.Empty();
strStatus.Format("当前状态: COM%d已关闭", m_nCom);
m_ctrlPortStatus.SetWindowText(strStatus);
}
}
break;
case 4:
m_animIcon.ShowNextImage();
break;
case 5: //显示时间 静态文本 处理
//str = CurrentTime.Format("%Y年%m月%d日 星期%w\n%X");
int ret;
CString str;
CString str1[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
CTime CurrentTime = CTime::GetCurrentTime();
str = CurrentTime.Format("%Y年%m月%d日 ");
ret = CurrentTime.GetDayOfWeek();
str += str1[ret-1];
str += CurrentTime.Format("\n%X");
m_ctrltime.SetWindowText(str);
break;
}
CDialog::OnTimer(nIDEvent);
}
//当自动发送周期编辑框的内容改变时, 调用此函数
void CSCOMMDlg::OnChangeEditCycletime()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
/*CEdit *pEdit=(CEdit*)GetDlgItem(IDC_EDIT_CYCLETIME);
CString strText;
pEdit->GetWindowText(strText);
m_nCycleTime = atoi(strText);*/
UpdateData(1);
m_nCycleTime = atoi((LPCTSTR)m_strCycleTime);
/*CString strText;
strText.Empty();
strText.Format("m_nCycleTime=%dms", m_nCycleTime);
MessageBox(strText);*/
}
//"发送编辑框"的内容改变时, 调用此函数
void CSCOMMDlg::OnChangeEditSend()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
UpdateData(TRUE);
}
void CSCOMMDlg::OnButtonClearrecasenda()
{
// TODO: Add your control notification handler code here
m_strSendData.Empty();
UpdateData(FALSE);
}
void CSCOMMDlg::SetPortParameter()
{
CString strStatus;
BOOL ret;
ret = m_Port.InitPort(this, m_nCom, m_nBaud, m_cParity, m_nDatabits, m_nStopbits, m_dwCommEvents, 512);
if (ret)
{
/*strStatus.Empty();
strStatus.Format("ret=%d, m_bOpenPort=%d", ret, m_bOpenPort);
MessageBox(strStatus);*/
//依靠 标志 m_bOpenPort 串口状态, 来设置状态栏该显示的提示
if (m_bOpenPort == FALSE) //m_bOpenPort 串口状态 1关0开
{
m_Port.StartMonitoring();
m_ctrlIconOpenoff.SetIcon(m_hIconRed);
//strStatus.Format("STATUS:COM%d OPENED,%d,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
strStatus.Empty();
strStatus.Format("当前状态: COM%d已打开,%dbps,%c,%d,%d", m_nCom, m_nBaud, m_cParity, m_nDatabits, m_nStopbits);
m_ctrlPortStatus.SetWindowText(strStatus);
}
else
{
//m_Port.StopMonitoring();
m_Port.ClosePort();
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
strStatus.Empty();
//strStatus.Format("STATUS:COM%d CLOSED,%d,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
strStatus.Format("当前状态: COM%d已关闭", m_nCom);
m_ctrlPortStatus.SetWindowText(strStatus);
}
}
else
{
m_ctrlIconOpenoff.SetIcon(m_hIconOff);
strStatus.Empty();
strStatus.Format("当前状态: COM%d被占用或没有发现此串口", m_nCom);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -