⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modemdlg.cpp

📁 WINDOWS mscomm modem 编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	   case 5:
		    dcb.BaudRate=14400;
			break;
	   case 6:
            dcb.BaudRate=19200;
			break;
	   case 7:
		    dcb.BaudRate=38400;
			break;
	   case 8:
		    dcb.BaudRate=57600;
			break;
	   default:
		    dcb.BaudRate=9600; 
			break;
	}

	switch(m_nDataBits)      // 每字节位数
	{
	   case 0:
		    dcb.ByteSize=5;
			break;
	   case 1:
		    dcb.ByteSize=6;
			break;
	   case 2:
		    dcb.ByteSize=7;
			break;
	   case 3:
		    dcb.ByteSize=8;
			break;
	   default:
		    dcb.ByteSize=8;
			break;
	}		

	dcb.fParity = TRUE;
	switch(m_nParity) // 校验设置
	{
	case 0: 
		dcb.Parity=NOPARITY;
		break;

	case 1: 
		dcb.Parity=EVENPARITY;
		break;

	case 2: 
		dcb.Parity=ODDPARITY;
		break;

	default:
		dcb.Parity=NOPARITY;
		break;
	}

	switch(m_nStopBits) // 停止位
	{
	case 0: 
		dcb.StopBits=ONESTOPBIT;
		break;

	case 1: 
		dcb.StopBits=ONE5STOPBITS;
		break;

	case 2:
		dcb.StopBits=TWOSTOPBITS;
		break;

	default:
		dcb.StopBits=ONE5STOPBITS;
		break;;
	}

	// 硬件流控制设置
	dcb.fOutxCtsFlow = TRUE;
	dcb.fRtsControl = TRUE;

	// XON/XOFF流控制设置
	dcb.fInX=dcb.fOutX = TRUE;
	dcb.XonChar = XON;
	dcb.XoffChar = XOFF;
	dcb.XonLim = 50;
	dcb.XoffLim = 50;

	return SetCommState(m_hCom, &dcb);
}

//WM_COMMNOTIFY消息处理函数,只处理接收到数据消息,即EV_RXCHAR消息
LRESULT CModemDlg::OnCommNotify(WPARAM wParam, LPARAM lParam)
{
	CString str;
	int nLength, nTextLength;
    DWORD dwModemStatus=0;

	//如果不是EV_RXCHAR消息,该函数直接返回
	if((m_bPortOpened==FALSE) || (wParam & EV_RXCHAR)!=EV_RXCHAR) 
	{
		//使m_hPostMsgEvent成为有信号,即允许发送下一个WM_COMMNOTIFY消息
		SetEvent(m_hPostMsgEvent); 
		return 0L;
	}

	//从串口读128字节数据
	nLength=ReadComm(buf,128);
	
	// 进入在线状态后,如果未设置定时器,则设置一个定时器
	// 若超过定时器间隔时间没有串口事件,则WM_TIMER消息被触发,挂断连接
	if(!m_bSetTimer&&m_bOnLine)
	{
		SetTimer(1,3000,0);  // 设置定时器间隔为3000ms
		m_bSetTimer=TRUE;
	}
	else if(m_bSetTimer&&m_bOnLine)  
	{
		KillTimer(1);        // 3000ms内有串口事件时,则清除上次所设定时器
	    SetTimer(1,3000,0);  // 重新设置定时器为3000ms
	}
    
	if((m_bOnLine==FALSE)&&(m_bPortOpened==TRUE))
	{
	    CString strTemp;
	    strTemp.Format("%s",buf);

		//两个Modem建立连接后,会向串口返回“CONNECTXXXXX”字符串,
		//若起始接收字符串中有“C”则判断Modem已处于在线状态
		if(strTemp.Find("C")!=-1)
		{
		   m_bOnLine=TRUE;
		   m_btnDial.SetWindowText(_T("挂断(&H)"));
		   m_btnOpenPort.EnableWindow(FALSE);
		   m_btnClosePort.EnableWindow(TRUE);
		   m_btnSend.EnableWindow(TRUE);
		}
	}

	if(nLength)
	{
		nTextLength=m_editReceive.GetWindowTextLength();
		m_editReceive.SetSel(nTextLength,nTextLength); //移动插入光标到正文末尾

		for(int i=0;i<nLength;i++)
		{
			switch(buf[i])
			{
			case '\r': // 回车
				if(!m_bNewLine) 
					break;

			case '\n': // 换行
				str+="\r\n";
				break;

			case '\b': // 退格
				m_editReceive.SetSel(-1, 0);
				m_editReceive.ReplaceSel(str);
				nTextLength=m_editReceive.GetWindowTextLength();
				m_editReceive.SetSel(nTextLength-1,nTextLength);
				m_editReceive.ReplaceSel(""); //回退一个字符
				str="";
				break;

			case '\a': // 振铃 
				MessageBeep((UINT)-1);
				break;

			default : 
				str+=buf[i];
			}
		}
		m_editReceive.SetSel(-1, 0);
		m_editReceive.ReplaceSel(str); // 向编辑视图中插入收到的字符
	}

	//使m_hPostMsgEvent成为有信号,即允许发送下一个WM_COMMNOTIFY消息
	SetEvent(m_hPostMsgEvent);  
	return 0L;
}

// 从串行口输入缓冲区中读入指定数量的字符
DWORD CModemDlg::ReadComm(char *buf, DWORD dwLength)
{
	DWORD length=0;
	COMSTAT ComStat;
	DWORD dwErrorFlags;

	ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
	length=min(dwLength, ComStat.cbInQue);
	ReadFile(m_hCom,buf,length,&length,&m_osRead);

	return length;
}

// 将指定数量的字符从串行口输出
DWORD CModemDlg::WriteComm(char *buf, DWORD dwLength)
{
	BOOL fState;
	DWORD length=dwLength;
	COMSTAT ComStat;
	DWORD dwErrorFlags;

	ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
	fState=WriteFile(m_hCom,buf,length,&length,&m_osWrite);

	if(!fState)
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE);// 等待
		}
		else
			length=0;
	}

	return length;
}

// 工作者线程,负责监视串行口
UINT CommProc(LPVOID pParam)
{
	OVERLAPPED os;
	DWORD dwMask, dwTrans;
	COMSTAT ComStat;
	DWORD dwErrorFlags;

	CModemDlg *pModemDlg=(CModemDlg*)pParam;

	memset(&os, 0, sizeof(OVERLAPPED));
	os.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);

	if(os.hEvent==NULL)
	{
		AfxMessageBox("Can't create event object!");
		return (UINT)-1;
	}
	while(pModemDlg->m_bPortOpened)
	{
		dwMask=0;

		// 异步操作,等待串口事件,事件结果在dwMask中
		if(!WaitCommEvent(pModemDlg->m_hCom, &dwMask, &os)) 
		{
			if(GetLastError()==ERROR_IO_PENDING)  
			{			    
				GetOverlappedResult(pModemDlg->m_hCom, &os, &dwTrans, TRUE);            
			}
			else                                     //等待串口事件时出错
			{
				CloseHandle(os.hEvent);
				return (UINT)-1;
			}
		}
		
		//清除串口可能发生的错误
		ClearCommError(pModemDlg->m_hCom,&dwErrorFlags,&ComStat);

		if(ComStat.cbInQue)
		{
			// 无限等待WM_COMMNOTIFY消息被处理完
			WaitForSingleObject(pModemDlg->m_hPostMsgEvent, INFINITE);
			ResetEvent(pModemDlg->m_hPostMsgEvent);
            
			// 向对话框发送WM_COMMNOTIFY消息
			PostMessage(pModemDlg->ghWnd, WM_COMMNOTIFY, dwMask, 0); 
			continue;
		}
		
	}
	CloseHandle(os.hEvent);
	return 0;
}

//“关闭串口”按钮处理函数
void CModemDlg::OnBtnClosePort() 
{
	if(!m_bPortOpened)
		return;
	else
	{
		m_bPortOpened=FALSE;
	    m_btnOpenPort.EnableWindow(TRUE);
        m_btnClosePort.EnableWindow(FALSE);
	    m_btnDial.EnableWindow(FALSE);
	    m_btnSend.EnableWindow(FALSE);

	     //结束CommProc线程中WaitSingleObject函数的等待
         SetEvent(m_hPostMsgEvent); 

		 //结束CommProc线程中WaitCommEvent的等待
		 SetCommMask(m_hCom, 0); 

		 //等待辅助线程终止
	     WaitForSingleObject(m_pThread->m_hThread, INFINITE);
	     m_pThread=NULL;
	     CloseHandle(m_hCom);
	}
}

//“拨号”按钮处理函数
void CModemDlg::OnBtnDial() 
{
	int k=0;
	CString strTemp;

	//若Modem处于离线状态,则拨号
	if(m_bOnLine==FALSE)
	{
	   UpdateData(TRUE);
	   m_btnDial.SetWindowText(_T("挂  断(&H)"));
	   m_strPhoneNum="ATDT"+m_strPhoneNum+"\r";
	   nStrLen=m_strPhoneNum.GetLength();
	   for(k=0;k<nStrLen;k++)
	   {
	       buf[k]=m_strPhoneNum.GetAt(k);
	   }
	   WriteComm(buf,nStrLen);
	}
    //若Modem处于在线状态,则挂断
	else
	{
	   m_bOnLine=FALSE;
	   m_bSetTimer=FALSE;
	   m_btnDial.SetWindowText(_T("拨  号(&D)"));
	   m_btnSend.EnableWindow(FALSE);
	   //发送换码序列“+++”,切换到在线命令状态
	   Sleep(1000);
	   for(k=0;k<3;k++)
	   {
	       buf[k]='+';
	   }
	   Sleep(1000);
	   WriteComm(buf,3);
	   Sleep(5000);
	   //发送挂断命令
	   strTemp="ATH\r";
	   nStrLen=strTemp.GetLength();
	   for(k=0;k<nStrLen;k++)
	   {
	      buf[k]=strTemp.GetAt(k);
	   }
	   WriteComm(buf,nStrLen);
	}
}

//“发送”按钮处理函数
void CModemDlg::OnBtnSend() 
{
	UpdateData(TRUE);
	int k=0;
	nStrLen=m_strSend.GetLength();
	if(nStrLen>128)
	{
	   AfxMessageBox(_T("发送数据超出接收缓冲区大小!"),MB_ICONINFORMATION | MB_OK,NULL);
	   return;
	}
	for(k=0;k<nStrLen;k++)
	{
	   buf[k]=m_strSend.GetAt(k);
	}
	WriteComm(buf,nStrLen);	
}

// WM_TIMER消息处理函数
void CModemDlg::OnTimer(UINT nIDEvent) 
{
	if(m_bSetTimer)  
	{
		KillTimer(1);  // 清除定时器1
	    OnBtnDial();   // 挂断
	}
	
	CDialog::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -