多人在线的网络聊天室
服务器端程序:
从CSocket派生CClientSocket类,用于实现对客户端消息的转发。
CClientSocket类的头文件以及实现文件如下:
CClientSocket类头文件:(.h文件)
class CClientSocketList;
class CClientSocket : public CSocket
{
// Attributes
public:
CClientSocketList* List;
CClientSocket* Front;
CClientSocket* Next;
// Operations
public:
CClientSocket(CClientSocketList*);
virtual ~CClientSocket();
// Overrides
public:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CClientSocket)
public:
virtual void OnReceive(int nErrorCode);
virtual void OnClose(int nErrorCode);
//}}AFX_VIRTUAL
// Generated message map functions
//{{AFX_MSG(CClientSocket)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
// Implementation
protected:
};
CClientSocket类CPP文件:
#include "ClientSocketList.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CClientSocket
CClientSocket::CClientSocket(CClientSocketList* tmp)
{
Front=0;
Next=0;
List=tmp;
}
CClientSocket::~CClientSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CClientSocket, CSocket)
//{{AFX_MSG_MAP(CClientSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/
// CClientSocket member functions
void CClientSocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
List->Sends(this); //调用CClientSocketList类的Sends函数
//向每一个客户端发送消息
CSocket::OnReceive(nErrorCode);
}
void CClientSocket::OnClose(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CSocket::OnClose(nErrorCode);
}
其中用到一个CClientSocketList类,为一个Generic Class类,代表客户端Socket列表。它是一个自定义类。我们将在下面实现它。
CClientSocketList类头文件如下:
#include "ClientSocket.h"
class CClientSocketList
{
public:
BOOL Add(CClientSocket*);
BOOL Sends(CClientSocket*);
CClientSocket* Head;
CClientSocketList();
virtual ~CClientSocketList();
};
CClientSocketList类的CPP文件如下:
#include "stdafx.h"
#include "ChatRoomServer.h"
#include "ClientSocketList.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
CClientSocketList::CClientSocketList()
{
Head=0;
}
CClientSocketList::~CClientSocketList()
{
}
BOOL CClientSocketList::Sends(CClientSocket *tmp)
{
char buff[1000];
int n;
CClientSocket* curr=Head;
n=tmp->Receive(buff,1000);
buff[n]=0;
while(curr)
{
curr->Send(buff,n);
curr=curr->Next;
}
return true;
}
BOOL CClientSocketList::Add(CClientSocket *add)
{
CClientSocket* tmp=Head;
if(!Head)
{
Head=add;
return true;
}
while(tmp->Next) tmp=tmp->Next;
tmp->Next=add;
return true;
}
这还只是完成了客户端的Socket类,我们还要创建一个服务器的侦听Socket类。我们称之为CListenSocket类。
同样,我们将从CSocket派生它。
CListenSocket类头文件:
#include "ClientSocketList.h"
/
// CListenSocket command target
class CListenSocket : public CSocket
{
// Attributes
public:
// Operations
public:
CClientSocketList CCSL;
CListenSocket();
virtual ~CListenSocket();
// Overrides
public:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListenSocket)
public:
virtual void OnAccept(int nErrorCode);
//}}AFX_VIRTUAL
// Generated message map functions
//{{AFX_MSG(CListenSocket)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
// Implementation
protected:
};
CListenSocket类CPP文件:
#include "stdafx.h"
#include "ChatRoomServer.h"
#include "ListenSocket.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CListenSocket
CListenSocket::CListenSocket()
{
}
CListenSocket::~CListenSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CListenSocket, CSocket)
//{{AFX_MSG_MAP(CListenSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/
// CListenSocket member functions
void CListenSocket::OnAccept(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CClientSocket* tmp=new CClientSocket(&CCSL);
Accept(*tmp);
CCSL.Add(tmp);
CSocket::OnAccept(nErrorCode);
}
所有工程中需要的类都被完成以后。我们开始完成主窗体的代码。
为启动服务,停止服务,退出窗口三个按钮添加消息响应函数。
CChatRoomServerDlg类的头文件完成后如下:
#include "ListenSocket.h"
#include "ClientSocketList.h"
class CChatRoomServerDlg : public CDialog
{
// Construction
public:
CChatRoomServerDlg(CWnd* pParent = NULL); // standard constructor
CListenSocket ListenSocket;
// Dialog Data
//{{AFX_DATA(CChatRoomServerDlg)
enum { IDD = IDD_CHATROOMSERVER_DIALOG };
CButton m_IDC_BTN_STOP;
CButton m_IDC_BTN_START;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChatRoomServerDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CChatRoomServerDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonStart();
afx_msg void OnButtonStop();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
我们将要实现它。
CChatRoomServerDlg类的CPP文件如下:
#include "stdafx.h"
#include "ChatRoomServer.h"
#include "ChatRoomServerDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CChatRoomServerDlg dialog
CChatRoomServerDlg::CChatRoomServerDlg(CWnd* pParent )
: CDialog(CChatRoomServerDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChatRoomServerDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChatRoomServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChatRoomServerDlg)
DDX_Control(pDX, IDC_BUTTON_STOP, m_IDC_BTN_STOP);
DDX_Control(pDX, IDC_BUTTON_START, m_IDC_BTN_START);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChatRoomServerDlg, CDialog)
//{{AFX_MSG_MAP(CChatRoomServerDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_START, OnButtonStart)
ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CChatRoomServerDlg message handlers
BOOL CChatRoomServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_IDC_BTN_STOP.EnableWindow(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CChatRoomServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CChatRoomServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChatRoomServerDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CChatRoomServerDlg::OnButtonStart()
{
// TODO: Add your control notification handler code here
m_IDC_BTN_START.EnableWindow(FALSE);
ListenSocket.Create(4848);
ListenSocket.Listen();
m_IDC_BTN_STOP.EnableWindow(TRUE);
}
void CChatRoomServerDlg::OnButtonStop()
{
// TODO: Add your control notification handler code here
m_IDC_BTN_STOP.EnableWindow(FALSE);
ListenSocket.Close();
m_IDC_BTN_START.EnableWindow(TRUE);
}
至此服务器端代码全部完成,我们将接下来再接再厉,完成客户端代码。
客户端代码:
从CSocket派生一个CServerSocket类,用以接收和转发服务器的消息。
CServerSocket类的头文件和CPP文件如下:
CServerSocket.h文件:
class CChatRoomClientDlg;
class CServerSocket : public CSocket
{
// Attributes
public:
CChatRoomClientDlg* myDlg;
CString NikeName;
// Operations
public:
CServerSocket();
virtual ~CServerSocket();
// Overrides
public:
BOOL SetDlg(CChatRoomClientDlg* tmp);
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CServerSocket)
public:
virtual void OnReceive(int nErrorCode);
//}}AFX_VIRTUAL
// Generated message map functions
//{{AFX_MSG(CServerSocket)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
// Implementation
protected:
};
CServerSocket类的CPP文件如下:
#include "stdafx.h"
#include "ChatRoomClient.h"
#include "ServerSocket.h"
#include "ChatRoomClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CServerSocket
CServerSocket::CServerSocket()
{
NikeName="";
myDlg=0;
}
CServerSocket::~CServerSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CServerSocket, CSocket)
//{{AFX_MSG_MAP(CServerSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/
// CServerSocket member functions
BOOL CServerSocket::SetDlg(CChatRoomClientDlg *tmp)
{
myDlg=tmp;
return TRUE;
}
void CServerSocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
myDlg->GetMessage();
CSocket::OnReceive(nErrorCode);
}
在启动客户端的程序时,我们将会预先弹出一个连接窗口以获取服务器的IP和用户的昵称。
于是我们想到工程中添加一个对话框资源,为该对话框资源关联一个类。
CConnectedDlg类:
CConnectedDlg类的头文件如下:
#include "ServerSocket.h"
/
// CConnectedDlg dialog
class CConnectedDlg : public CDialog
{
// Construction
public:
CConnectedDlg(CServerSocket* tmp,CWnd* pParent = NULL); // standard constructor
CServerSocket* myServerSocket;
// Dialog Data
//{{AFX_DATA(CConnectedDlg)
enum { IDD = IDD_DIALOG_CONNECTDLG };
CString m_IDC_EDIT_ADDRESS;
CString m_IDC_EDIT_NIKNAME;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CConnectedDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CConnectedDlg)
// NOTE: the ClassWizard will add member functions here
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CConnectedDlg类的CPP文件如下所示:
#include "stdafx.h"
#include "ChatRoomClient.h"
#include "ConnectedDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CConnectedDlg dialog
CConnectedDlg::CConnectedDlg(CServerSocket* tmp,CWnd* pParent )
: CDialog(CConnectedDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CConnectedDlg)
m_IDC_EDIT_ADDRESS = _T("");
m_IDC_EDIT_NIKNAME = _T("");
//}}AFX_DATA_INIT
myServerSocket=tmp;
}
void CConnectedDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CConnectedDlg)
DDX_Text(pDX, IDC_EDIT_ADDRESS, m_IDC_EDIT_ADDRESS);
DDX_Text(pDX, IDC_EDIT_NIKNAME, m_IDC_EDIT_NIKNAME);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CConnectedDlg, CDialog)
//{{AFX_MSG_MAP(CConnectedDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CConnectedDlg message handlers
void CConnectedDlg::OnOK()
{
UpdateData(TRUE);
char * address;
int n;
if(!myServerSocket->Create())
{
myServerSocket->Close();
AfxMessageBox("Socket创建错误!!");
return;
}
n=m_IDC_EDIT_ADDRESS.GetLength();
address=new char[n+1];
sprintf(address,"%s",m_IDC_EDIT_ADDRESS.GetBuffer(n));
address[n]=0;
if(!myServerSocket->Connect(address,4848))
{
myServerSocket->Close();
AfxMessageBox("网络连接错误,请重新检查服务器地址填写是否正确!");
return;
}
myServerSocket->NikeName=m_IDC_EDIT_NIKNAME;
CDialog::OnOK();
}
然后我们重写对话框中按钮的消息响应函数:
代码如下:
CChatRoomClient类的头文件:
#include "ServerSocket.h"
class CChatRoomClientDlg : public CDialog
{
// Construction
public:
BOOL GetMessage();
CChatRoomClientDlg(CServerSocket*,CWnd* pParent = NULL); // standard constructor
CServerSocket* myServerSocket;
// Dialog Data
//{{AFX_DATA(CChatRoomClientDlg)
enum { IDD = IDD_CHATROOMCLIENT_DIALOG };
CListBox m_IDC_LIST_CHAT;
CString m_IDC_EDIT_MESSAGE;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChatRoomClientDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CChatRoomClientDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonSend();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CChatRoomClient类的CPP文件:
#include "stdafx.h"
#include "ChatRoomClient.h"
#include "ChatRoomClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CChatRoomClientDlg dialog
CChatRoomClientDlg::CChatRoomClientDlg(CServerSocket *tmp,CWnd* pParent )
: CDialog(CChatRoomClientDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChatRoomClientDlg)
m_IDC_EDIT_MESSAGE = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
myServerSocket=tmp;
}
void CChatRoomClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChatRoomClientDlg)
DDX_Control(pDX, IDC_LIST1, m_IDC_LIST_CHAT);
DDX_Text(pDX, IDC_EDIT_MESSAGE, m_IDC_EDIT_MESSAGE);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChatRoomClientDlg, CDialog)
//{{AFX_MSG_MAP(CChatRoomClientDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_SEND, OnButtonSend)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CChatRoomClientDlg message handlers
BOOL CChatRoomClientDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CChatRoomClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CChatRoomClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChatRoomClientDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BOOL CChatRoomClientDlg::GetMessage()
{
char buffer[1000];
int count;
count=myServerSocket->Receive(buffer,1000);
buffer[count]=0;
m_IDC_LIST_CHAT.AddString(buffer);
return TRUE;
}
void CChatRoomClientDlg::OnButtonSend()
{
// TODO: Add your control notification handler code here
int n;
char message[1000];
UpdateData(TRUE);
m_IDC_EDIT_MESSAGE=myServerSocket->NikeName+":"+m_IDC_EDIT_MESSAGE;
n=m_IDC_EDIT_MESSAGE.GetLength();
sprintf(message,"%s",m_IDC_EDIT_MESSAGE.GetBuffer(n));
message[n]=0;
if(!myServerSocket->Send(message,n+1))
{
AfxMessageBox("网络传输错误!");
}
}
此刻问题还没有完。由于主程序的启动窗体是CChatRoomClientDlg,而我们所需要的启动窗体是CConnectedDlg。所以我们必须在应用程序类CChatRoomClientApp类的InitInstance()函数中进行一些修改,也就是所谓初始化工作。
代码如下:
ChatRoomClient类的实现文件,其中包含CChatRoomClientApp::InitInstance();函数。
其代码如下:
#include "stdafx.h"
#include "ChatRoomClient.h"
#include "ChatRoomClientDlg.h"
#include "ServerSocket.h"
#include "ConnectedDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CServerSocket curSocket;
/
// CChatRoomClientApp
BEGIN_MESSAGE_MAP(CChatRoomClientApp, CWinApp)
//{{AFX_MSG_MAP(CChatRoomClientApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/
// CChatRoomClientApp construction
CChatRoomClientApp::CChatRoomClientApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/
// The one and only CChatRoomClientApp object
CChatRoomClientApp theApp;
/
// CChatRoomClientApp initialization
BOOL CChatRoomClientApp::InitInstance()
{
if(!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
CConnectedDlg cdlg(&curSocket);
if(cdlg.DoModal()==IDCANCEL)
return FALSE;
CChatRoomClientDlg dlg(&curSocket);
m_pMainWnd = &dlg;
curSocket.SetDlg(&dlg);
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}