设置静态文本框控件的背景色,文本框中字体、颜色:
HBRUSH CUDPDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here if (pWnd->GetDlgCtrlID()==IDC_STATIC_TITLE) { //设置绘图dc的背景模式为透明模式. pDC->SetBkMode(TRANSPARENT);//设置透明窗口, pDC->SetTextColor(RGB(255,255, 0));//设置背景颜色为(蓝色) //pWnd->SetFont(cFont);//设置字体 HBRUSH B = CreateSolidBrush(RGB(125,125,255)); return (HBRUSH) B;//作为约定,返回背景色对应的刷子句柄 //return (HBRUSH)::GetStockObject(RGB(125,125,255)); // 设置背景色 GetDlgItem(IDC_STATIC_TITLE)->GetParent()->RedrawWindow();//不重叠 } if (pWnd->GetDlgCtrlID()==IDC_RECV_LEN1) { //设置绘图dc的背景模式为透明模式. pDC->SetTextColor(RGB(255,0, 0));//设置文本颜色为(红色) //pWnd->SetFont(cFont);//设置字体 HBRUSH B = CreateSolidBrush(RGB(255,255,255)); return (HBRUSH) B;//作为约定,返回背景色对应的刷子句柄 GetDlgItem(IDC_RECV_LEN1)->GetParent()->RedrawWindow();//不重叠 } // TODO: Return a different brush if the default is not desired return hbr; }
设置文本框内文本的字体:
void CUDPDlg::SetEditFont() { CFont font; LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); lf.lfHeight=-14; //字体大小 font.CreateFontIndirect(&lf); GetDlgItem(IDC_RECV_LEN1)->SetFont (&cfont);
}
主对话框的源文件中:
CFont cfont; //这个是全局的。放到include的下面就可以了 int size=16; unsigned char iPbuf[2];//2个字节用于存放ip最后一段的值 CString strDataWrong="故障";//故障显示 #define BUFFER_LEN 512//接收缓存大小 #define RIGHT_LEN 6//下发的数据长度 unsigned char rightdata[RIGHT_LEN];//无符号字符缓存 unsigned int port;//端口号 CHAR recBuf[BUFFER_LEN];//接收缓存
数据的一些 初始化:
// CUDPDlg dialog CUDPDlg::CUDPDlg(CWnd* pParent /*=NULL*/) : CDialog(CUDPDlg::IDD, pParent) { //{{AFX_DATA_INIT(CUDPDlg) m_localPortNum =12345;//本地端口号 m_peerPortNum = 1234;//远端端口号 m_disp1 = _T(""); m_disp2 = _T(""); m_s_1 = _T(""); m_dataToSend = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); //初始化socket对象为无效 m_pSocket = NULL; //socket连接状态,未连接 m_bIsConnected = FALSE; }
对话框的初始大小设定:
void CUDPDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); SetWindowPos(NULL,0,0,900,680,SWP_NOMOVE | SWP_NOZORDER);
初始化函数:
//加载通信状态图标 m_hIconOff = AfxGetApp()->LoadIcon(IDI_ICON_OFF); m_hIconOn = AfxGetApp()->LoadIcon(IDI_ICON_ON); //设置下发到的ip地址,目的ip m_peerIPaddr.SetAddress(1,1,1,1); //m_localIPaddr.SetAddress(127,0,0,1);//本地ip //获取本地ip并显示ip到界面 GetDispIP(); //设置要发送的数据,添加ip两个字节,变量 // m_Edit2.SetWindowText("F5A0A10506075F"); //设置界面显示的字体,蓝色背景 cfont.CreateFont(16,0,0,0,FW_SEMIBOLD,FALSE,FALSE,0, ANSI_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH&FF_SWISS,"Arial"); //获取静态文本框的指针变量 CWnd* pWnd = GetDlgItem(IDC_STATIC_TITLE); //设置字体 pWnd->SetFont(&cfont); //设置40个文本框显示的字体 SetEditFont(); return TRUE; // return TRUE unless you set the focus to a control }
//获取本地ip并显示ip到界面 GetDispIP();
int CUDPDlg::GetDispIP() { int nRetCode; CString m_sHostName,m_sIPAddress; //1 nRetCode = StartUp(); TRACE1("StartUp RetCode: %d\n", nRetCode); //2获取主机名 nRetCode = GetLocalHostName(m_sHostName); TRACE1("GetLocalHostName RetCode: %d\n", nRetCode); //3根据主机名获取ip赋值到m_sIPAddress nRetCode = GetIPAddress(m_sHostName, m_sIPAddress); //显示本地地址m_sIPAddress m_localIPaddr.SetWindowText(m_sIPAddress); TRACE1("GetIPAddress RetCode: %d\n", nRetCode); //4 nRetCode = CleanUp(); TRACE1("CleanUp RetCode: %d\n", nRetCode); UpdateData(FALSE); return 0; }
上面程序中获取本地ip用到的函数:
int CUDPDlg::StartUp() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // Couldn't find a usable WinSock DLL. */ return err; } // Confirm that the WinSock DLL supports 2.0. // Note that if the DLL supports versions greater // than 2.0 in addition to 2.0, it will still return // 2.0 in wVersion since that is the version we // requested. if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) { // Couldn't find a usable WinSock DLL. WSACleanup( ); return WSAVERNOTSUPPORTED; } // The WinSock DLL is acceptable return 0; } int CUDPDlg::CleanUp() { int nRetCode; nRetCode = WSACleanup(); if (nRetCode != 0) { // An error occured. return WSAGetLastError(); } return 0; } int CUDPDlg::GetLocalHostName(CString &sHostName) { char szHostName[256]; int nRetCode; nRetCode = gethostname(szHostName, sizeof(szHostName)); if (nRetCode != 0) { // An error has occurred sHostName = _T("Not available");; return WSAGetLastError(); } sHostName = szHostName; return 0; } int CUDPDlg::GetIPAddress(const CString &sHostName, CString &sIPAddress) { struct hostent FAR *lpHostEnt = gethostbyname (sHostName); if (lpHostEnt == NULL) { // An error occurred. sIPAddress = _T(""); return WSAGetLastError(); } LPSTR lpAddr = lpHostEnt->h_addr_list[0]; if (lpAddr) { struct in_addr inAddr; // iPbuf[0]=127; // iPbuf[0] = inAddr.S_un.S_un_b.s_b4; memmove (&inAddr, lpAddr, 4); short iPsend=(short)(inAddr.S_un.S_un_b.s_b4); ShortToBytes(SendAone,iPsend); //short变成2字节 iPbuf[0] =SendAone[0]; iPbuf[1] =SendAone[1]; //ciPbuf[0] =SendAone[0];har sendip; //sendip=inAddr.s_b4;//LPSTR是一个字符串指针类型 sIPAddress = inet_ntoa (inAddr); if (sIPAddress.IsEmpty()) sIPAddress = _T("Not available"); } return 0; }
定时器函数:
void CUDPDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default switch(nIDEvent) { case 1: { //判断变量,如果变为1,则 连接成功,为0,则连接失败,弹出提示。 // if (1) // { // AfxMessageBox("连接失败,请重新检查!"); // KillTimer(1); // } break; } case 2: { //AfxMessageBox("定时器2!"); //数据包发送 OnBtnSendData(); break; } default: break; } CDialog::OnTimer(nIDEvent); }
建立网络连接按钮:
void CUDPDlg::OnBtnCtrlConn() { // TODO: Add your control notification handler code here //如果(有m_pSocket对象存在) if (NULL != m_pSocket) { //关闭socket链接 m_pSocket->Close(); //删除socket对象 delete m_pSocket; //清零处理 m_pSocket = NULL; } //如果没链接,则链接 if (!m_bIsConnected) { //置位链接标志 m_bIsConnected = TRUE; // UpdateData(TRUE); // BYTE field[4]; //目的地址 m_peerIPaddr.GetAddress(field[0], field[1], field[2], field[3]); //目的地址 m_strPeerIPaddr.Format(TEXT("%d.%d.%d.%d"), field[0], field[1], field[2], field[3]); //服务器的功能:监听本地port //创建socket对象 m_pSocket = new CUdpSocket(this);//接收显示数据 //创建socket链接 m_pSocket->Create(m_localPortNum, SOCK_DGRAM);//本地端口号,udp //连接目的ip,port: //也可以不绑定socket连接,只需要在接收数据的时候解析 源ip和port就可以了。 //绑定socket链接() m_pSocket->Bind(m_peerPortNum, m_strPeerIPaddr);//端口,ip //按钮文本 GetDlgItem(IDC_BTNCTRLCONN)->SetWindowText(TEXT("断开连接")); //定时发送 SetTimer(2,3000,NULL); } else//如果连接,则断开连接 { KillTimer(2); //复位链接标志 countOne=0; m_bIsConnected = FALSE; //按钮文本 GetDlgItem(IDC_BTNCTRLCONN)->SetWindowText(TEXT("建立连接")); } //本地端口号 GetDlgItem(IDC_LOCALPORTNUM)->EnableWindow(!m_bIsConnected); //本地ip GetDlgItem(IDC_LOCALIPADDR)->EnableWindow(!m_bIsConnected); //目的端口号 GetDlgItem(IDC_PEERPORTNUM)->EnableWindow(!m_bIsConnected); //目的ip GetDlgItem(IDC_PEERIPADDR)->EnableWindow(!m_bIsConnected); //发送按钮 GetDlgItem(IDC_BTNSENDDATA)->EnableWindow(m_bIsConnected); //发送文本框 GetDlgItem(IDC_DATATOSEND)->EnableWindow(m_bIsConnected); }
发送数据按钮:
void CUDPDlg::OnBtnSendData() { // TODO: Add your control notification handler code here UpdateData(TRUE); //判断是否有CUdpSocket对象,是否链接 if (NULL == m_pSocket || !m_bIsConnected) { AfxMessageBox(TEXT("尚未打开端口!")); return; } //要发送的数据 char m_Array[6]; m_Array[0]= (char)0xF5; m_Array[1]= (char)0xA0; // sockaddr_in m_clientAddr // m_Array[3]= m_clientAddr.sin_addr.S_un.S_un_b.s_b4; m_Array[2]= iPbuf[0];//高字节 m_Array[3]= iPbuf[1];//低字节 //校验 char result=0; for(int i=1; i<4; i++) { result=result^m_Array[i]; } m_Array[4]=result; m_Array[5]=(char)0x5F; //帧尾 //CString m_send1="F5 A0 A1 01 01 5F 5F"; //通过socket发送到网络 //要发送的数据,数据长度,目的端口号,目的ip // m_pSocket->SendTo(COleVariant(m_Array), 7, //m_dataToSend.GetLength() // m_peerPortNum, m_strPeerIPaddr); m_pSocket->SendTo(m_Array, 6, //m_dataToSend.GetLength() m_peerPortNum, m_strPeerIPaddr); //可以取本地ip的最后一个整数值,变成2个字节,发送出去。 }
void CUDPDlg::OnReceive(CUdpSocket *psock) { int len = sizeof(SOCKADDR_IN); // 接收区,slen是缓冲区写到的位置 int r_d_len=6; //清空接收缓存 ZeroMemory(recBuf, sizeof(recBuf)); CString SAddress;//接收数据来源的ip地址,port,BUFFER_LEN缓存长度,RcvBuffer接收的缓存m_localPortNum //接收数据 recBytes=psock->ReceiveFrom(recBuf,BUFFER_LEN,SAddress,m_peerPortNum,0); //recBytes =psock->ReceiveFrom(recBuf, BUFFER_LEN, (SOCKADDR*)&m_clientAddr, &len, 0); if (0 == recBytes) { AfxMessageBox(TEXT("UDP连接已经关闭!")); } else if (SOCKET_ERROR == recBytes) { AfxMessageBox(TEXT("接收数据失败!")); } else if (recBytes>=83) { // for (int i=0;i<recBytes;i++) // { // rightdata[i]=recBuf[i]; // } //将recBuf中的数据写入缓存 //校验 char result=0; for(int j=1; j<82; j++) { result=result^recBuf[j]; } //检测帧头是否正确 //if (rightdata[0]==(char)0xF5 && rightdata[1]==(char)0xA1 && rightdata[4]==result ) if (recBuf[0]==(char)0xF5 && recBuf[1]==(char)0xA1 && recBuf[82]==result && recBuf[83]==(char)0x5F) { //解析数据 DataProcessing(); } } //清空接收缓存 for (int i=0; i<BUFFER_LEN; i++ ) { recBuf[i]=0; } }
数据解析部分:
void CUDPDlg::DataProcessing() { if (recBuf[2]==(char)0xff && recBuf[3]==(char)0xff ) { //显示故障 m_ctrOnOFF_1.SetIcon(m_hIconOff);//接收图标 SetDlgItemText(IDC_DISP_1,strDataWrong);//故障 wrong1++;//故障数 strTemp.Format("%d",wrong1); SetDlgItemText(IDC_S_1,strTemp);//显示故障数 return; } else//数据正确 { BYTE Hdata = *(char *)(recBuf+2); BYTE Ldata = *(char *)(recBuf+3); strTemp.Format("%d",wrong1); //无故障 SetDlgItemText(IDC_S_1,strTemp); //连接关闭图标 m_ctrOnOFF_1.SetIcon(m_hIconOn); //解析地址1的数据 int IpData=Hdata*256+Ldata; //直接显示到文本框 CString strData; strData.Format("%d",IpData); //刷新实时数据显示 SetDlgItemText(IDC_DISP_1,strData); //CString strTemp; //RcvBuffer接收缓存中保存接收到的数据。 //将接收到的数据以文本格式显示。 //%02x 中间放一个空格 //strTemp.Format("%02x %02x %02x %02x %02x %02x",rightdata[0],rightdata[1],rightdata[2],rightdata[3],rightdata[4],rightdata[5]); // void MakeUpper( ); //使所有小写字母变为大写 //strTemp.MakeUpper(); //将文本显示到文本框 //SetDlgItemText(IDC_DISP_1,strTemp); //显示计数countOne CString strlen; countOne++;//接收计数 strlen.Format(TEXT("%d"),countOne); ((CUDPDlg*)(AfxGetApp()->m_pMainWnd))->GetDlgItem(IDC_RECV_LEN1)->SetWindowText(strlen);//显示计数 //显示接收到的字节数 //CString strlen; //strlen.Format(TEXT("%d"),recBytes); //((CUDPDlg*)(AfxGetApp()->m_pMainWnd))->GetDlgItem(IDC_RECV_LEN1)->SetWindowText(strlen); } }
2个字节的短整形分解为两个字节
//2个字节的短整形分解为两个字节 void CUDPDlg::ShortToBytes(BYTE bytes[], SHORT num) { for(int i = 0; i < 2; i++) { bytes[i] = (BYTE)(num >> (8 - i * 8)); } }
清空显示:
void CUDPDlg::OnClear() { // TODO: Add your control notification handler code here countOne=0; CString strlen; strlen.Format(TEXT("%d"),countOne); ((CUDPDlg*)(AfxGetApp()->m_pMainWnd))->GetDlgItem(IDC_RECV_LEN1)->SetWindowText(strlen); m_ctrOnOFF_1.SetIcon(m_hIconOff);
CString strClear= " ";
SetDlgItemText(IDC_DISP_1,strClear);
}
主对话框的头文件:引入自己写的网络通信类头文件
#include "UdpSocket.h"
函数、变量、指针、数组 定义:
void ShortToBytes(BYTE bytes[], SHORT num); void DataProcessing(); void OnReceive(CUdpSocket *psock);//网络数据接收函数 CUDPDlg(CWnd* pParent = NULL); // standard constructor CUdpSocket *m_pSocket;//创建CUdpSocket类对象指针 int GetDispIP(); int GetIPAddress(const CString &sHostName, CString &sIPAddress); int GetLocalHostName(CString &sHostName); int CleanUp(); int StartUp(); char *pCirBuf;//缓存指针 int startPos,endPos;//头指针,尾指针 BYTE SendAone[2];//存放两个字节的数组 int recBytes;//接收字节计数 SOCKADDR_IN m_clientAddr;// HICON m_hIconOff;//断开连接图标 HICON m_hIconOn;//建立连接图标
// Implementation protected: HICON m_hIcon; CString m_strPeerIPaddr;//目的ip BOOL m_bIsConnected;//是否连接
重载的虚拟函数:
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
用于网络通信的 UdpSocket.h 文件中程序:
//主对话框类 class CUDPDlg; ///// // CUdpSocket command target class CUdpSocket : public CSocket { // Attributes public: // Operations public: CUdpSocket(); //重载构造函数 CUdpSocket(CUDPDlg* p_hwnd); virtual ~CUdpSocket(); // Overrides public: //创建主对话框类的指针变量p_dlgwnd CUDPDlg* p_dlgwnd; // SOCKADDR_IN m_clientAddr; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CUdpSocket) public: virtual void OnReceive(int nErrorCode); //}}AFX_VIRTUAL // Generated message map functions //{{AFX_MSG(CUdpSocket) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG // Implementation protected: };
CUdpSocket类的源文件中:
引入主对话框资源:
//引入主对话框资源 #include "UDPDlg.h"
重载构造函数:
// CUdpSocket CUdpSocket::CUdpSocket() { } //重载构造函数 CUdpSocket::CUdpSocket(CUDPDlg* p_hwnd) { //主对话框的句柄 p_dlgwnd=p_hwnd; } CUdpSocket::~CUdpSocket() { //socket是有效套接字,则关闭socket连接 if (INVALID_SOCKET != this->m_hSocket) { //关闭socket连接 Close(); } }
数据接收函数:
void CUdpSocket::OnReceive(int nErrorCode) { // TODO: Add your specialized code here and/or call the base class CSocket::OnReceive(nErrorCode); //触发主对话框实现文件中的函数 p_dlgwnd->OnReceive(this); }
主对话框垂直滚动条的响应函数:
void CUDPDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default SCROLLINFO scrollinfo; GetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); switch (nSBCode) { case SB_BOTTOM: ScrollWindow(0,(scrollinfo.nPos-scrollinfo.nMax)*10); scrollinfo.nPos = scrollinfo.nMax; SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); break; case SB_TOP: ScrollWindow(0,(scrollinfo.nPos-scrollinfo.nMin)*10); scrollinfo.nPos = scrollinfo.nMin; SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); break; case SB_LINEUP: scrollinfo.nPos -= 1; if (scrollinfo.nPos<scrollinfo.nMin) { scrollinfo.nPos = scrollinfo.nMin; break; } SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); ScrollWindow(0,10); break; case SB_LINEDOWN: scrollinfo.nPos += 1; if (scrollinfo.nPos>scrollinfo.nMax) { scrollinfo.nPos = scrollinfo.nMax; break; } SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); ScrollWindow(0,-10); break; case SB_PAGEUP: scrollinfo.nPos -= 5; if (scrollinfo.nPos<scrollinfo.nMin) { scrollinfo.nPos = scrollinfo.nMin; break; } SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); ScrollWindow(0,10*5); break; case SB_PAGEDOWN: scrollinfo.nPos += 5; if (scrollinfo.nPos>scrollinfo.nMax) { scrollinfo.nPos = scrollinfo.nMax; break; } SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); ScrollWindow(0,-10*5); break; case SB_ENDSCROLL: // MessageBox("SB_ENDSCROLL"); break; case SB_THUMBPOSITION: // ScrollWindow(0,(scrollinfo.nPos-nPos)*10); // scrollinfo.nPos = nPos; // SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); break; case SB_THUMBTRACK: ScrollWindow(0,(scrollinfo.nPos-nPos)*10); scrollinfo.nPos = nPos; SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL); break; } CDialog::OnVScroll(nSBCode, nPos, pScrollBar); }