频道栏目
读书频道 > 软件开发 > C++ > Visual C++网络编程开发与实战
3.4.2 具体实现
2012-12-10 13:34:19     我来说两句
收藏   我要投稿
本书由浅入深地讲解了使用Visual C++开发网络项目的基本知识,并通过具体的实例来讲解项目的实现流程。全书分为15章,以案例为对象展示网络项目的实现过程并分析技术难点,主要内容包括VC++网络开发基本应用、传...  立即去当当网订购

1. 窗体IDD_HOST

(1) 首先设计窗体IDD_HOST,设置其Caption属性的值为“Telnet服务器”,如图3-14所示。


 

(2) 为此窗体添加实现代码,首先在文件ClientSocket.h中定义需要的类和函数。具体实现代码如下:
class CTelnetView;     //定义类CTelnetView
class CClientSocket : public CAsyncSocket
{
// 属性
public:

public:
CClientSocket(CTelnetView *cView);  //类CClientSocket的构造函数
virtual ~CClientSocket();
// 虚函数
public:
CTelnetView *cView;
//{{AFX_VIRTUAL(CClientSocket)
public:
virtual void OnClose(int nErrorCode);    //声明关闭连接方法
virtual void OnConnect(int nErrorCode);     //声明连接方法
virtual void OnOutOfBandData(int nErrorCode);   //声明带外数据处理方法
virtual void OnReceive(int nErrorCode);     //声明接收数据的方法
virtual void OnSend(int nErrorCode);      //声明发送数据的方法
//}}AFX_VIRTUAL
protected:
};

(3) 在文件ClientSocket.cpp中,实现了文件ClientSocket.h中定义的各个方法。具体代码如下:

//定义关闭连接方法
void CClientSocket::OnClose(int nErrorCode)
{
CAsyncSocket::OnClose(nErrorCode);
if(!IsWindow(cView->m_hWnd)) return;
if(!IsWindowVisible(cView->m_hWnd)) return;
cView->GetDocument()->OnCloseDocument();

}
//定义连接方法
void CClientSocket::OnConnect(int nErrorCode)
{
CAsyncSocket::OnConnect(nErrorCode);
}
//定义带外数据处理方法
void CClientSocket::OnOutOfBandData(int nErrorCode)
{
ASSERT(FALSE); //Telnet should not have OOB data
CAsyncSocket::OnOutOfBandData(nErrorCode);
}

//定义接收数据方法
void CClientSocket::OnReceive(int nErrorCode)
{
cView->ProcessMessage(this);
}

//定义发送数据方法
void CClientSocket::OnSend(int nErrorCode)
{
CAsyncSocket::OnSend(nErrorCode);
}

(4) 在文件CTelnetView.h中实现CTelnetView类的编写,具体代码如下:

class CTelnetDoc;
class CClientSocket;
//下一个bit组为命令
const unsigned char IAC = 255;
//作为一种请求发送给另一方来启动某个选项
const unsigned char DO = 253;
//响应保证是连接最终保持与这种没有任何选项的状态
const unsigned char DON’T = 254;
//表示发送或接收一方希望执行某个选项
const unsigned char WILL = 251;
//响应保证是连接最终保持与这种没有任何选项的状态
const unsigned char WONT = 252;
//开始选项协商
const unsigned char SB = 250;
//选项协商结束
const unsigned char SE = 240;
//判断标识
const unsigned char IS = '0';
const unsigned char SEND = '1';
const unsigned char INFO = '2';
const unsigned char VAR = '0';
const unsigned char VALUE = '1';
const unsigned char ESC = '2';
const unsigned char USERVAR = '3';

#define bufferLines 30
#define dtX 8
#define dtY 13
//设置输入输出缓冲区的大小为1024KB
#define ioBuffSize 1024

class CTelnetView : public CScrollView
{
protected: // create from serialization only
CTelnetView();
DECLARE_DYNCREATE(CTelnetView)

COLORREF cTextColor;
COLORREF cBackgroundColor;

CString cHostName;
//定义并声明和远程访问相关的变量和方法
public:
CClientSocket *cSock;
void ArrangeReply(CString strOption);
//正常传输的字符串
CString m_strNormalText;
//选择响应方法
void RespondToOptions();
//处理信息流程的方法
void ProcessOptions();
//设置临时计数器 
int TempCounter;
//字符串选择
CString m_strOptions;
//字符串行表选择
CStringList m_ListOptions;
//协商标识变量
BOOL bNegotiating;
BOOL bOptionsSent;
CString m_strResp;
CString m_strLine;
unsigned char m_bBuf[ioBuffSize];
BOOL GetLine(unsigned char *bytes, int nBytes, int &ndx);
void DispatchMessage(CString strText);
void ProcessMessage(CClientSocket *cSocket);

char cText[100][bufferLines];
long cCursX;
CString m_strline;
//绘制清除窗口
void DrawCursor(CDC *pDC, BOOL pDraw);
void DoDraw(CDC *pDC);
void ClearWindows(CDC *pDc);
//当前的坐标
int CurrentXX;
int CurrentYY;

//测试程序
BOOL IfOutput;
private:
void MessageReceived(LPCSTR pText);

// 属性
public:
CTelnetDoc* GetDocument();
public:

//重写父类的虚函数
//{{AFX_VIRTUAL(CTelnetView)
public:
virtual void OnDraw(CDC *pDC);  // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT &cs);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo *pInfo);
virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo);
virtual void OnEndPrinting(CDC *pDC, CPrintInfo *pInfo);
//}}AFX_VIRTUAL

// Implementation
public:
int Find(CString str, char ch);
virtual ~CTelnetView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext &dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CTelnetView)
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnEraseBkgnd(CDC *pDC);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnFileNew();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

(5) 在文件CTelnetView.cpp中,实现了文件CTelnetView.h中定义的各个方法。因为文件CTelnetView.cpp的代码比较多,所以接下来将按照步骤进行详细剖析。
① 使用include指令引入包含文件,并定义BEGIN_MESSAGE_MAP消息映射,具体实现代码如下:

#include "stdafx.h"
#include "CTelnet.h"

#include "CTelnetDoc.h"
#include "CTelnetView.h"
#include "MainFrm.h"
#include "ClientSocket.h"
#include "Process.h"

#include "HostDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern CMultiDocTemplate *pDocTemplate;

IMPLEMENT_DYNCREATE(CTelnetView, CScrollView)
BEGIN_MESSAGE_MAP(CTelnetView, CScrollView)
//{{AFX_MSG_MAP(CTelnetView)
ON_WM_CHAR()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_KEYDOWN()

//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
ON_COMMAND(ID_FILE_NEW, OnFileNew)

END_MESSAGE_MAP()

② 定义CTelnetView类的构造函数CTelnetView(),用于实现初始化工作。具体实现代码如下:
CTelnetView::CTelnetView()
{
cTextColor = RGB(0, 200, 000);     //设置字体颜色,此处是绿色
cBackgroundColor = RGB(000, 000, 000);    //设置背景颜色,此处是黑色
cSock = NULL;
bOptionsSent = FALSE;
TempCounter = 0;
cCursX = 0;
CurrentXX = 0;         //初始窗口的位置
CurrentYY = 0;

IfOutput = false;
// OffsetNum = 0;
for(int x=0; x<80; x++)
{
for(int y=0; y<bufferLines; y++)
{
cText[x][y] = ' ';
}
}
}

③ 定义CTelnetView类的构造函数CTelnetView(),如果cSock为空则释放。具体代码如下:
CTelnetView::~CTelnetView()
{
if(cSock != NULL)
delete cSock;
cSock = NULL;
}

④ 定义函数PreCreateWindow(),设定窗口的风格,CREATESTRUCT是窗口的风格数据结构。具体代码如下:
BOOL CTelnetView::PreCreateWindow(CREATESTRUCT &cs)
{
return CScrollView::PreCreateWindow(cs);
}

⑤ 定义函数OnDraw(CDC *pDC)以及DoDraw(CDC *pDC),实现窗口绘制,具体代码如下:
void CTelnetView::OnDraw(CDC *pDC)
{
CTelnetDoc *pDoc = GetDocument();
ASSERT_VALID(pDoc);

pDC->SelectObject(GetStockObject(ANSI_FIXED_FONT));

DrawCursor(pDC, FALSE);
DoDraw(pDC);
DrawCursor(pDC, TRUE);
}

void CTelnetView::DoDraw(CDC *pDC)
{
CString strLine;
BOOL bSkip = FALSE;
CRect clip;
pDC->GetClipBox(clip);
clip.top -= dtY;

pDC->SetTextColor(cTextColor);
// pDC->SetBkColor(cBackgroundColor);

// CurrentXX = 0;
char text[2] = {0x00, 0x00};

for(int y=0; y<bufferLines; y++)
{
//if(y*dtY >= clip.top)
//{
for(int x=0; x<80; x++)
{
text[0] = cText[x][y];
if(text[0] == 27)
bSkip = TRUE;
if(!bSkip)
strLine += text[0];
if(text[0]=='m' && bSkip)
bSkip = FALSE;
}
pDC->TextOut(0, y*dtY, strLine);
strLine.Empty();
//}
}
}

⑥ 定义函数OnInitialUpdate(),用于计算当前视图的初始化位置,具体代码如下:
void CTelnetView::OnInitialUpdate()
{
CSize sizeTotal;

// TODO: calculate the total size of this view
sizeTotal.cx = dtX * 80 + 3;
sizeTotal.cy = dtY * bufferLines + 3;
SetScrollSizes(MM_TEXT, sizeTotal);
//SetWindowPos(NULL, 0,0, sizeTotal.cx, sizeTotal.cy, SWP_NOMOVE);

CScrollView::OnInitialUpdate();
}

⑦ 定义函数OnPreparePrinting ()等,用于实现打印功能,具体代码如下:
BOOL CTelnetView::OnPreparePrinting(CPrintInfo *pInfo)
{
// 默认打印准备
return DoPreparePrinting(pInfo);
}

void CTelnetView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CTelnetView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

// CTelnetView diagnostics

#ifdef _DEBUG
void CTelnetView::AssertValid() const
{
CScrollView::AssertValid();
}

void CTelnetView::Dump(CDumpContext &dc) const
{
CScrollView::Dump(dc);
}

⑧ 定义函数GetDocument(),用于在非调试环境下运行此函数,具体代码如下:
CTelnetDoc* CTelnetView::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTelnetDoc)));
return (CTelnetDoc*)m_pDocument;
}
#endif //_DEBUG

⑨ 定义函数ProcessMessage(),用于接受并分析数据,具体代码如下:
//接收分析数据
void CTelnetView::ProcessMessage(CClientSocket *pSock)
{
if(!IsWindow(m_hWnd)) return;
if(!IsWindowVisible()) return;
//保存数据到m_bBuf
int nBytes = pSock->Receive(m_bBuf, ioBuffSize);
if(nBytes != SOCKET_ERROR)
{
int ndx = 0;
//每次读入一行数据
while(GetLine(m_bBuf, nBytes, ndx) != TRUE);
//进行协商
ProcessOptions();
MessageReceived(m_strNormalText);
}
m_strLine.Empty();
m_strResp.Empty();
}

⑩ 定义函数ProcessOptions(),用于设置协商的方法,具体代码如下:
//进行协商
void CTelnetView::ProcessOptions()
{
CString m_strTemp;
CString m_strOption;
unsigned char ch;
int ndx;
int ldx;
//将初始扫描完成变量设置为假
BOOL bScanDone = FALSE;
//给临时变量赋值为当前行
m_strTemp = m_strLine;
//根据状态来判定,当数据在扫描并且还有数据时进行下面的协商
while(!m_strTemp.IsEmpty() && bScanDone!=TRUE)
{
ndx = m_strTemp.Find(IAC);
if(ndx != -1)
{
m_strNormalText += m_strTemp.Left(ndx);
ch = m_strTemp.GetAt(ndx + 1);
switch(ch)
{
case DO:
case DONT:
case WILL:
case WONT:
m_strOption = m_strTemp.Mid(ndx, 3);
m_strTemp  = m_strTemp.Mid(ndx + 3);
m_strNormalText = m_strTemp.Left(ndx);
m_ListOptions.AddTail(m_strOption);
break;
case IAC:
m_strNormalText = m_strTemp.Left(ndx);
m_strTemp   = m_strTemp.Mid(ndx + 1);
break;
case SB:
m_strNormalText = m_strTemp.Left(ndx);
ldx = Find(m_strTemp, SE);
m_strOption = m_strTemp.Mid(ndx, ldx);
m_ListOptions.AddTail(m_strOption);
m_strTemp  = m_strTemp.Mid(ldx);
//AfxMessageBox(m_strOption, MB_OK);
break;
default:
bScanDone = TRUE;
}
}
else
{
m_strNormalText = m_strTemp;
bScanDone = TRUE;
}
}
RespondToOptions();
}

⑪ 定义函数RespondToOptions(),用于设置选项协议状态,具体代码如下:
void CTelnetView::RespondToOptions()
{
CString strOption;
while(!m_ListOptions.IsEmpty())
{
strOption = m_ListOptions.RemoveHead();
ArrangeReply(strOption);
}
DispatchMessage(m_strResp);
m_strResp.Empty();
}

⑫ 定义函数ArrangeReply(),用于设置回应选项状态,具体代码如下:
void CTelnetView::ArrangeReply(CString strOption)
{
unsigned char Verb;
unsigned char Option;
unsigned char Modifier;
unsigned char ch;
BOOL bDefined = FALSE;

if(strOption.GetLength() < 3) return;

Verb = strOption.GetAt(1);
Option = strOption.GetAt(2);

switch(Option)
{
case 1: //回显
case 3: // Suppress Go-Ahead
bDefined = TRUE;
break;
}

m_strResp += IAC;

if(bDefined == TRUE)
{
switch(Verb)
{
case DO:
ch = WILL;
m_strResp += ch;
m_strResp += Option;
break;
case DONT:
ch = WONT;
m_strResp += ch;
m_strResp += Option;
break;
case WILL:
ch = DO;
m_strResp += ch;
m_strResp += Option;
break;
case WONT:
ch = DONT;
m_strResp += ch;
m_strResp += Option;
break;
case SB:
Modifier = strOption.GetAt(3);
if(Modifier == SEND)
{
ch = SB;
m_strResp += ch;
m_strResp += Option;
m_strResp += IS;
m_strResp += IAC;
m_strResp += SE;
}
break;
}
}
else
{
switch(Verb)
{
case DO:
ch = WONT;
m_strResp += ch;
m_strResp += Option;
break;
case DONT:
ch = WONT;
m_strResp += ch;
m_strResp += Option;
break;
case WILL:
ch = DONT;
m_strResp += ch;
m_strResp += Option;
break;
case WONT:
ch = DONT;
m_strResp += ch;
m_strResp += Option;
break;
}
}
}

⑬ 定义函数DispatchMessage(),用于发送数据,具体代码如下:
//发送数据
void CTelnetView::DispatchMessage(CString strText)
{
ASSERT(cSock);
cSock->Send(strText, strText.GetLength());
}

⑭ 定义函数GetLine(),用于获得一行数据,具体代码如下:
//获得一行数据
BOOL CTelnetView::GetLine(unsigned char *bytes, int nBytes, int &ndx)
{
BOOL bLine = FALSE;
while (bLine==FALSE && ndx<nBytes)
{
unsigned char ch = bytes[ndx];

//原来设计的时候要去掉回车换行的,但是后来发现不能去掉
switch(ch)
{
case '\r': //
m_strLine += "\r"; //回车
break;
case '\n': //行结尾
m_strLine += "\n";
break;
default:   //其他数据
m_strLine += ch;
break;
}
ndx ++;
if (ndx == nBytes)
{
bLine = TRUE;
}
}
return bLine;
}

⑮ 定义函数MessageReceived(),用于实现数据处理,具体代码如下:
//数据处理
void CTelnetView::MessageReceived(LPCSTR pText)
{
BOOL bSkip = FALSE;
int loop=0;
CString tempStr = "0123456789;";
CString tempStr2;
int ColorVal;
int tempY = 0;

CDC *pDC = GetDC();
OnPrepareDC(pDC);
DrawCursor(pDC, FALSE);

CRect clip;
pDC->GetClipBox(clip);

CMainFrame *frm = (CMainFrame*)GetTopLevelFrame();
//设置颜色
pDC->SetTextColor(cTextColor);
pDC->SetBkColor(cBackgroundColor);

pDC->SelectObject(GetStockObject(ANSI_FIXED_FONT));
int length = strlen(pText);
char text[2] = {0x00, 0x00};
while(loop < length)
{
switch(pText[loop])
{

case 8: //删除
CurrentXX--;
if(CurrentXX < 0) CurrentXX = 0;
loop++;
break;

case 9: //Tab键
CurrentXX++; //
loop++;
break;

case 13: //换行CR
m_strline.Empty();
CurrentXX = 0;
loop++;
break;

case 27:
loop++;
//分析紧接着27的字符是否是91,如果不是91,则这两个字符都不作处理,直接跳出
if (pText[loop]!=91)
{
loop++;
break;
}
//如果是91,则接下来的数据则是系统相关数据
else
{
loop++;
while (tempStr.Find(pText[loop]) != -1)
{
tempStr2 += pText[loop];
loop++;
}
if (pText[loop]=='m') //如果接下来的数据是m,则分析前面获得的字符串
{
//循环获得字符串中的值,其中字符串中的值都是以分号隔开的
while (tempStr2 != "")
{
if (tempStr2.Find(";") != -1)
{
ColorVal = atoi(tempStr2.Mid(0,tempStr2.Find(";")));
tempStr2 = tempStr2.Mid(tempStr2.Find(";") + 1);
}
else
{
ColorVal = atoi(tempStr2);
tempStr2.Empty();
}
//获得一个值
//改变前景颜色,这个颜色可以按照一定的规则自定义
if (ColorVal>29 && ColorVal<38)
//cTextColor = RGB(0,0,255);
//设置背景颜色
if (ColorVal>39 && ColorVal<48)
//cBackgroundColor = RGB(0,255,ColorVal);
//恢复基本设置
if (ColorVal==0)
{
//cBackgroundColor = RGB(0,0,0);
//cTextColor = RGB(255,255,255);
}
//如果为1,则设置前景色
//if ColorVal==1
//表示要反色
//if ColorVal==7
}
}
//如果为字符K,表示要画一条背景色的矩形区域
if (pText[loop] == 'K')
{
int x, y;
CString myStr;
//保持原来的坐标
//画出矩形区域,因为以背景色画,所以相当于移动光标
//将坐标变量改变到目前的位置
x = CurrentXX;
y = CurrentYY;
for (int l=CurrentXX; l<80; l++)
{
cText[l][CurrentYY] = ' ';
myStr += ' ';
}
pDC->TextOut(x*dtX, y*dtY, myStr);
CurrentXX = x;
CurrentYY = y;
}
//如果字符为C,表示要改变当前的横坐标
if (pText[loop] == 'C')
{
//获得横坐标的改变量
if (tempStr2.Find(";") != -1)
{
ColorVal = atoi(tempStr2.Mid(0, tempStr2.Find(";")));
tempStr2 = tempStr2.Mid(tempStr2.Find(";") + 1);
}
else
{
ColorVal = atoi(tempStr2);
tempStr2.Empty();
}
//然后增建坐标值,注意这里要加上字符宽度
CurrentXX = CurrentXX + ColorVal;
}
//如果字符为H,表示重新设置横坐标和纵坐标
if (pText[loop] == 'H')
{
//获得纵坐标值,在服务器发送的过程中,先发送纵坐标值
TRACE0("H");
int tX=0, tY=0;
//char buffer3[20];
tY = atoi(tempStr2.Mid(0, tempStr2.Find(";")));
tempStr2 = tempStr2.Mid(tempStr2.Find(";") + 1);
//获得横坐标值,注意这里获得的值是没有加字符宽度的
tX = atoi(tempStr2);
if (tX>0 && tY>0)
{
CurrentYY = tY - 1;
CurrentXX = tX - 1;
}
}
//如果为字符J,表示要清除整个屏幕
if (pText[loop] == 'J')
{
ClearWindows(pDC);
}
}
loop++;
IfOutput = false;
break;

case 0:
loop++;

case 10: //换行
{
CurrentYY = CurrentYY + 1;
if (CurrentYY >= bufferLines)
{
for(int row=0; row<bufferLines; row++)
{
for(int  col=0; col<80; col++)
{
cText[col][row] = cText[col][row+1];
}
}
for(int  col=0; col<80; col++)
{
cText[col][bufferLines-1] = ' ';
}
CurrentYY = CurrentYY - 1;
DoDraw(pDC);
}
}
loop++;
break;
default: //输出数据
{
cText[CurrentXX][CurrentYY] = pText[loop];
m_strline.Empty();
for (int i=0; i<80; i++)
{
if (cText[i][CurrentYY] != 27)
m_strline += cText[i][CurrentYY];
else
break;
}
pDC->TextOut(0, CurrentYY*dtY, m_strline);
CurrentXX++;
}
tempStr2.Empty();
loop++;
break;
}
}
DrawCursor(pDC, TRUE);
ReleaseDC(pDC);
}

⑯ 定义函数OnChar(),用于实现按键处理,具体代码如下:
//按键处理
void CTelnetView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
//发出回车键
if (nChar == VK_RETURN)
{
DispatchMessage("\r\n");
}
else
{
DispatchMessage(nChar);
}
}

⑰ 定义函数DrawCursor(),用于在屏幕上绘制光标,具体代码如下:
//画光标
void CTelnetView::DrawCursor(CDC *pDC, BOOL pDraw)
{
COLORREF color;
CMainFrame *frm = (CMainFrame*)GetTopLevelFrame();
if(pDraw) //draw
{
color = cTextColor;
}
else //erase
{
color = cBackgroundColor;
}
CRect rect(CurrentXX * dtX + 2, CurrentYY * dtY + 1,
CurrentXX * dtX + dtX - 2, CurrentYY * dtY + dtY -1);
pDC->FillSolidRect(rect, color);
}

void CTelnetView::OnSize(UINT nType, int cx, int cy)
{
CScrollView::OnSize(nType, cx, cy);
if(IsWindow(m_hWnd))
{
if(IsWindowVisible())
{
//ScrollToPosition(
CPoint(0, bufferLines * 1000)); //go way past the end
}
}
}

⑱ 定义函数OnEraseBkgnd(),用于清除背景颜色,具体代码如下:
BOOL CTelnetView::OnEraseBkgnd(CDC* pDC)
{
CRect clip;
pDC->GetClipBox(clip);
CMainFrame *frm = (CMainFrame*)GetTopLevelFrame();
pDC->FillSolidRect(clip, cBackgroundColor);
return TRUE;
}

⑲ 定义函数Find(),用于查找指定的字符,具体代码如下:
//查找字符
int CTelnetView::Find(CString str, char ch)
{
char *data = str.GetBuffer(0);
int len = str.GetLength();
int i = 0;
for(i=0; i<len; i++){
if(data[i] == ch)
break;
}
str.ReleaseBuffer();
return i;
}

定义函数OnKeyDown(),用于实现方向键处理,具体代码如下:
//方向键处理
void CTelnetView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
unsigned char myChar[3];
// TODO: Add your message handler code here and/or call default
//左方向键
if (nChar == 37)
{
myChar[0] = 27;
myChar[1] = 91;
myChar[2] = 68;

DispatchMessage(myChar);
}
//右方向键
else if (nChar == 39)
{
myChar[0] = 27;
myChar[1] = 91;
myChar[2] = 67;
DispatchMessage(myChar);
}
//上方向键
else if (nChar == 38)
{
myChar[0] = 27;
myChar[1] = 91;
myChar[2] = 65;
DispatchMessage(myChar);
}
//下方向键
else if (nChar == 40)
{
myChar[0] = 27;
myChar[1] = 91;
myChar[2] = 66;
DispatchMessage(myChar);
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
//MessageBox((char*)nChar);
}

定义函数ClearWindows (),用于清除屏幕元素,具体代码如下:
//清除屏幕
void CTelnetView::ClearWindows(CDC *pDc)
{
 for(int x=0; x<80; x++)
 {
  for(int y=0; y<bufferLines; y++)
  {
   cText[x][y] = ' ';
  }
 }
 DoDraw(pDc);
 CurrentYY = 0;
 CurrentXX = 0;
}

定义函数OnFileNew(),用于创建新的Socket,并实现与服务器的连接。具体代码如下:
void CTelnetView::OnFileNew()
{
BOOL bOK;

//弹出设定服务器对话框
CHostDialog host;
host.DoModal();
cHostName = host.m_HostName;

//创建socket
cSock = new CClientSocket(this);

if(cSock != NULL)
{
bOK = cSock->Create();
if(bOK == TRUE)
{
cSock->AsyncSelect(
FD_READ | FD_WRITE | FD_CLOSE | FD_CONNECT | FD_OOB);
//连接服务器
cSock->Connect(cHostName, 23);
//设定标题
GetDocument()->SetTitle(cHostName);
Sleep(90);
}
else
{
ASSERT(FALSE); 
delete cSock;
cSock = NULL;
}
}
else
{
AfxMessageBox("不能创建socket", MB_OK);
}
}

到此为止,整个项目的核心代码就介绍完毕了。为节省本书的篇幅,没有对其他代码进行讲解,读者只需参考本书的附带光盘即可了解。

项目执行后的初始界面如图3-15所示。


 

依次单击“文件”→“连接远程服务器”命令后,弹出“Telnet服务器”对话框,如图3-16所示。


 

在如图3-16所示的对话框中输入一个远程BBS地址后,即可访问此BBS服务器,如图3-17所示。


 

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:3.4.1 规划类
下一篇:Visual C++音频视频技术开发与实战
相关文章
图文推荐
排行
热门
最新书评
文章
下载
读书
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站