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

📄 tcp2comdlg.cpp

📁 TCP到串口的数据转发应用程序
💻 CPP
字号:
// Tcp2ComDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Tcp2Com.h"
#include "Tcp2ComDlg.h"
#include ".\tcp2comdlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


char Char2Hex( char ch )
{
	if( 0<=ch && ch <= 9 )
		ch += '0';
	else if( 10<= ch && ch <= 15 )
	{
		ch -= 10;
		ch += 'A';
	}
	return ch;
}
char Hex2Char( char ch )
{
	if( '0'<=ch && ch<='9' )
		ch -= '0';
	else if( 'A'<=ch && ch<='F')
	{
		ch -= 'A';
		ch += 10;
	}
	else if( 'a'<=ch && ch<='f' )
	{
		ch -= 'a';
		ch += 10;
	}
	return ch;
}
CString Byte2HexStr( const char *pbuf, int nLen )
{
	CString res;
	for(int i=0; i<nLen; ++i)
	{
		unsigned char ch = static_cast<unsigned char>(pbuf[i]);
		res.AppendChar( Char2Hex( 0x0F&(ch>>4) ) );
		res.AppendChar( Char2Hex( 0x0F&ch ) );
	}
	return res;
}
int HexStr2Byte( const CString& str, char *pbuf )
{
	int nLen = 0;
	for( int i=0; i<str.GetLength()-1; i+=2 )
	{
		char hight = Hex2Char( str[i] );
		if( str[i] == hight )
			return 0;
		char low = Hex2Char( str[i+1] );
		if( str[i+1]==low )
			return 0;
		pbuf[nLen++] = ( (hight<<4)&0xF0 ) | (low&0x0F) ;
	}
	return nLen;
}

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CTcp2ComDlg 对话框



CTcp2ComDlg::CTcp2ComDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTcp2ComDlg::IDD, pParent)
	, m_strServer(_T("127.0.0.1"))
	, m_nPort(1001)
	, m_socket(this)
	, m_strNO(_T("101"))
	, m_nSerialRecvCnt(0)
	, m_nTimer(0)
	, m_tmrComRecv(0)
	, m_nComRecvTimeout(2)
	, m_bHex1(FALSE)
	, m_bHex2(FALSE)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTcp2ComDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT_SERVER, m_strServer);
	DDX_Text(pDX, IDC_EDIT_PORT, m_nPort);
	DDV_MinMaxInt(pDX, m_nPort, 0, 65535);
	DDX_Text(pDX, IDC_EDIT_NO, m_strNO);
	DDX_Control(pDX, IDC_COMBO_BAND, m_cbxBand);
	DDX_Control(pDX, IDC_COMBO_DATABIT, m_cbxDataBit);
	DDX_Control(pDX, IDC_COMBO_JYBIT, m_cbxJyBit);
	DDX_Control(pDX, IDC_COMBO_STOPBIT, m_cbxStopBit);
	DDX_Control(pDX, IDC_COMBO_SERIAL_PORT, m_cbxSerial);
	DDX_Control(pDX, IDC_LIST1, m_lcTcpRecv);
	DDX_Control(pDX, IDC_LIST2, m_lcComRecv);
	DDX_Text(pDX, IDC_EDIT_RECV_TMR, m_nComRecvTimeout);
	DDV_MinMaxInt(pDX, m_nComRecvTimeout, 1, 100);
	DDX_Check(pDX, IDC_CHECK1, m_bHex1);
	DDX_Check(pDX, IDC_CHECK2, m_bHex2);
	DDX_Control(pDX, IDC_CHECK1, m_btnHex1);
	DDX_Control(pDX, IDC_CHECK2, m_btnHex2);
}

BEGIN_MESSAGE_MAP(CTcp2ComDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_START, OnBnClickedButtonStart)
	ON_BN_CLICKED(IDC_BUTTON_STOP, OnBnClickedButtonStop)
	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
	ON_MESSAGE(WM_COMM_RXCHAR, OnSerialRecvChar)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_QUIT, OnBnClickedButtonQuit)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST1, OnNMDblclkList1)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST2, OnNMDblclkList2)
	ON_BN_CLICKED(IDC_CHECK1, OnBnClickedCheck1)
	ON_BN_CLICKED(IDC_CHECK2, OnBnClickedCheck2)
END_MESSAGE_MAP()


// CTcp2ComDlg 消息处理程序

BOOL CTcp2ComDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将\“关于...\”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
//
	for(int i=1; i<=4; ++i )
	{
		CString tmp;
		tmp.Format("COM%d", i);
		m_cbxSerial.AddString(tmp);
	}
	m_cbxSerial.SelectString(0,"COM1");

//
	for(long i=1200; i<=115200; i *=2 )
	{
		CString tmp;
		tmp.Format("%d", i);
		m_cbxBand.AddString(tmp);
	}
	m_cbxBand.SelectString(0, "2400");
//
	for(int i=5; i<=8; ++i )
	{
		CString tmp;
		tmp.Format("%d", i);
		m_cbxDataBit.AddString(tmp);
	}
	m_cbxDataBit.SelectString(0,"8");
//
	m_cbxJyBit.AddString("奇校验");
	m_cbxJyBit.AddString("偶校验");
	m_cbxJyBit.AddString("无");
	m_cbxJyBit.SelectString(0,"无");
//
	m_cbxStopBit.AddString("1");
	m_cbxStopBit.AddString("2");
	m_cbxStopBit.SelectString(0, "1");
//
	m_lcTcpRecv.SetExtendedStyle(
		LVS_EX_FLATSB
		|LVS_EX_FULLROWSELECT
		|LVS_EX_GRIDLINES
		|LVS_EX_HEADERDRAGDROP
		|LVS_EX_MULTIWORKAREAS);
	i = 0;
	m_lcTcpRecv.InsertColumn( i++, "文本形式内容", LVCFMT_LEFT, 200 );
	m_lcTcpRecv.InsertColumn( i++, "十六进制内容", LVCFMT_LEFT, 400 );
//
	m_lcComRecv.SetExtendedStyle(
		LVS_EX_FLATSB
		|LVS_EX_FULLROWSELECT
		|LVS_EX_GRIDLINES
		|LVS_EX_HEADERDRAGDROP
		|LVS_EX_MULTIWORKAREAS);
	i = 0;
	m_lcComRecv.InsertColumn( i++, "文本形式内容", LVCFMT_LEFT, 200 );
	m_lcComRecv.InsertColumn( i++, "十六进制内容", LVCFMT_LEFT, 400 );
	return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

void CTcp2ComDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CTcp2ComDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(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 CTcp2ComDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CTcp2ComDlg::OnConnectSucess()
{
	MessageBox("连接成功");
}
void CTcp2ComDlg::OnConnectFail()
{
	m_socket.Close();
	GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
	MessageBox("连接失败");
}

void CTcp2ComDlg::OnClose()
{
	m_nSerialRecvCnt = 0;
	m_socket.Close();
	m_serial.StopMonitoring();
	GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(FALSE);
	MessageBox("连接关闭");
}
void CTcp2ComDlg::OnBnClickedButtonStart()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	GetDlgItem(IDC_BUTTON_START)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE);
	// 打开串口
	CString tmp;
	m_cbxSerial.GetWindowText(tmp);
	unsigned int portnr = atoi( tmp.Right(1) );
	//
	m_cbxBand.GetWindowText(tmp);
	unsigned int baud = atoi(tmp);
	//
	m_cbxJyBit.GetWindowText(tmp);
	char parity = 'N';
	if( "奇校验"==tmp )
		parity = 'O';
	else if( "偶校验"==tmp )
		parity = 'E';
	//
	m_cbxDataBit.GetWindowText(tmp);
	unsigned int databits = atoi(tmp);
	//
	m_cbxStopBit.GetWindowText(tmp);
	unsigned int stopsbits = atoi(tmp);
	//
	if(FALSE==m_serial.InitPort(this, portnr, baud, parity, databits, stopsbits ))
	{
		m_cbxSerial.GetWindowText(tmp);
		MessageBox(tmp+"打开失败");
		GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
		return;
	}
	m_serial.StartMonitoring();
	// 打开网络
	m_socket.NO(m_strNO);
	m_socket.Create( );
	SOCKADDR_IN Addr;
	memset( &Addr, 0, sizeof(SOCKADDR_IN) );
	Addr.sin_family = AF_INET;
	Addr.sin_port = htons(m_nPort);
	Addr.sin_addr.S_un.S_addr = inet_addr(m_strServer);
	m_socket.Connect( (SOCKADDR*)&Addr, sizeof(SOCKADDR_IN) );
	m_nTimer = SetTimer(1, 50, NULL);
}

void CTcp2ComDlg::OnBnClickedButtonStop()
{
	// TODO: 在此添加控件通知处理程序代码
	m_socket.Close();
	m_serial.KillMonitoring();
	GetDlgItem(IDC_BUTTON_START)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
	KillTimer(m_nTimer);
}

void CTcp2ComDlg::OnCancel()
{
	// TODO: 在此添加专用代码和/或调用基类
}

void CTcp2ComDlg::OnOK()
{
	// TODO: 在此添加专用代码和/或调用基类
}

void CTcp2ComDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	CString s;
	GetDlgItem(IDC_EDIT1)->GetWindowText(s);
	char buf[CMySocket::MAX_BUF_LEN];
	int nLen = 0;
	if( m_btnHex1.GetCheck() )
	{
		nLen = HexStr2Byte( s, buf );
	}
	else
	{
		strcpy(buf, s);
		nLen = s.GetLength();
	}
	if(nLen>0)
	{
		m_socket.SendSvr(buf, nLen);
		GetDlgItem(IDC_EDIT1)->SetWindowText("");
	}
	else
	{
		MessageBox("没有要发送的字符或十六进制转换失败");
	}
}

void CTcp2ComDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	CString s;
	GetDlgItem(IDC_EDIT2)->GetWindowText(s);
	char buf[CMySocket::MAX_BUF_LEN];
	int nLen = 0;
	if( m_btnHex2.GetCheck() )
	{
		nLen = HexStr2Byte( s, buf );
	}
	else
	{
		strcpy(buf, s);
		nLen = s.GetLength();
	}
	if(nLen>0)
	{
		m_serial.WriteToPort(buf, nLen);
		GetDlgItem(IDC_EDIT2)->SetWindowText("");
	}
	else
	{
		MessageBox("没有要发送的字符或十六进制转换失败");
	}
}
LRESULT CTcp2ComDlg::OnSerialRecvChar( WPARAM wParam, LPARAM lParam )
{
	CString tmp;
	m_cbxSerial.GetWindowText(tmp);
	unsigned int portnr = atoi( tmp.Right(1) );
	if(portnr = (unsigned int)lParam)
	{
		// 收到一个字符
		m_serialRecvBuf[m_nSerialRecvCnt++] = (char)wParam;
		m_tmrComRecv = m_nComRecvTimeout;
	}
	return 0;
}


void CTcp2ComDlg::OnReceive()// TCP收到
{
	char buf[CMySocket::MAX_BUF_LEN ];
	int nLen = m_socket.RecvSvr(buf);
	if( nLen>0 )
	{
		//
		buf[nLen]=0;
		TRACE("TCP Recv(cnt=%d)%s\n", nLen, buf);
		int nItem = m_lcTcpRecv.GetItemCount();
		m_lcTcpRecv.InsertItem(nItem, buf);
		m_lcTcpRecv.SetItemText(nItem , 1, Byte2HexStr(buf, nLen));
		m_lcTcpRecv.Scroll(CSize(0,25));
		//
		m_serial.WriteToPort(buf, nLen);
	}
}

void CTcp2ComDlg::OnTimer(UINT nIDEvent)// COM收到
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(m_tmrComRecv>0)
	{
		--m_tmrComRecv;
		if(0==m_tmrComRecv)
		{
			if(m_nSerialRecvCnt>0)
			{
				//
				m_serialRecvBuf[m_nSerialRecvCnt]=0;
				TRACE("COM Recv(cnt=%d)%s\n", m_nSerialRecvCnt, m_serialRecvBuf);
				int nItem = m_lcComRecv.GetItemCount();
				m_lcComRecv.InsertItem(nItem, m_serialRecvBuf);
				m_lcComRecv.SetItemText(nItem , 1, Byte2HexStr(m_serialRecvBuf, m_nSerialRecvCnt));
				m_lcComRecv.Scroll(CSize(0,25));

				//
				m_socket.SendSvr(m_serialRecvBuf, m_nSerialRecvCnt);
				m_nSerialRecvCnt = 0;
			}
		}
	}
	CDialog::OnTimer(nIDEvent);
}

void CTcp2ComDlg::OnBnClickedButtonQuit()
{
	// TODO: 在此添加控件通知处理程序代码
	OnBnClickedButtonStop( );
	CDialog::OnCancel();
}

void CTcp2ComDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	DWORD dwPos = ::GetMessagePos();
	CPoint point((int)LOWORD(dwPos), (int)HIWORD(dwPos));
	m_lcTcpRecv.ScreenToClient(&point);
	int nCurSel = m_lcTcpRecv.HitTest(point);
	if(-1!=nCurSel)
	{
		CString tmp;
		if(m_bHex1)
		{
			tmp = m_lcTcpRecv.GetItemText( nCurSel, 1);
		}
		else
		{
			tmp = m_lcTcpRecv.GetItemText( nCurSel, 0);
		}
		GetDlgItem(IDC_EDIT1)->SetWindowText( tmp );
	}
	*pResult = 0;
}

void CTcp2ComDlg::OnNMDblclkList2(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	DWORD dwPos = ::GetMessagePos();
	CPoint point((int)LOWORD(dwPos), (int)HIWORD(dwPos));
	m_lcComRecv.ScreenToClient(&point);
	int nCurSel = m_lcComRecv.HitTest(point);
	if(-1!=nCurSel)
	{
		CString tmp;
		if(m_bHex2)
		{
			tmp = m_lcComRecv.GetItemText( nCurSel, 1);
		}
		else
		{
			tmp = m_lcComRecv.GetItemText( nCurSel, 0);
		}
		GetDlgItem(IDC_EDIT2)->SetWindowText( tmp );
	}
	*pResult = 0;
}

void CTcp2ComDlg::OnBnClickedCheck1()
{
	// TODO: 在此添加控件通知处理程序代码
	CString s;
	GetDlgItem(IDC_EDIT1)->GetWindowText(s);
	if( m_btnHex1.GetCheck() )
	{
		GetDlgItem(IDC_EDIT1)->SetWindowText( Byte2HexStr(s, s.GetLength()) );
	}
	else
	{
		char buf[CMySocket::MAX_BUF_LEN];
		int nLen = HexStr2Byte( s, buf );
		if(nLen>0)
		{
			buf[nLen]=0;
			GetDlgItem(IDC_EDIT1)->SetWindowText(buf);
		}
	}
}

void CTcp2ComDlg::OnBnClickedCheck2()
{
	// TODO: 在此添加控件通知处理程序代码
	CString s;
	GetDlgItem(IDC_EDIT2)->GetWindowText(s);
	if( m_btnHex2.GetCheck() )
	{
		GetDlgItem(IDC_EDIT2)->SetWindowText( Byte2HexStr(s, s.GetLength()) );
	}
	else
	{
		char buf[CMySocket::MAX_BUF_LEN];
		int nLen = HexStr2Byte( s, buf );
		if(nLen>0)
		{
			buf[nLen]=0;
			GetDlgItem(IDC_EDIT2)->SetWindowText(buf);
		}
	}}

⌨️ 快捷键说明

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