www.pudn.com > Paint_SockAPI.rar > ChildView.cpp


/* 
* Copyright (c) 2003,Rainsoft Studio 
* All rights reserved. 
* 
* 文件名称:CChildView.CPP 
* 文件标识:03-02 
* 摘要:白板程序 
* 
* 当前版本:1.0 
* 作者:try2it.com 
* 完成日期:2003年07月30日 
* 
* 取代版本:0.9 
* 原作者:try2it.com 
* 完成日期:2003年07月28日 
*/ 
 
#include "stdafx.h" 
#include "Paint.h" 
#include "ChildView.h" 
#include "MainFrm.h" 
#include "SetPenDlg.h" 
#include "AddrDlg.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
#define MSG_LEN 50 // 与recv函数的接收数据长度一致,否则容易出错 
void* pThis; // CChildView指针 
// 客户连接队列 
CNetworking::CConnectionList ConnectionList; 
BOOL bFlag = FALSE; 
CPoint oldpoint; 
// 回调函数,接收数据时触发 
void ReceiveCallback (DWORD ptr) 
{ 
	char buff[MSG_LEN] = ""; 
	char tmpstr[MSG_LEN]; 
	CConnection* c = reinterpret_cast  (ptr); 
    CChildView *pthis = (CChildView*) pThis; 
	c->Receive (buff, MSG_LEN); 
	// 如果客户发数据给服务器 
	// 则服务器帮助转发给其他客户 
	for (int i=0; iSend(buff, MSG_LEN); 
		} 
	} 
	int nType, x, y, PenWidth; 
	sscanf(buff, "%d,%d,x:%d,y:%d", &nType, &PenWidth, &x, &y); 
	sprintf(tmpstr, "X=%d,Y=%d", x, y); 
	pthis->SendMessage(WM_SETSTATUS, WPARAM(0), LPARAM(tmpstr)); 
	// 如果是鼠标按下 
	if (nType == 1) 
		oldpoint = CPoint(x, y); 
    else if(nType == 2) 
	{ 
       // 创建画笔 
		HPEN hPen = CreatePen(PS_SOLID, PenWidth, RGB(0xFF, 0x00, 0x00)); 
		// 选进DC 
		::SelectObject(pthis->m_hMemDC, hPen); 
		// 画线 
		::MoveToEx(pthis->m_hMemDC, oldpoint.x, oldpoint.y, NULL); 
		::LineTo(pthis->m_hMemDC, x, y); 
		// 重绘图形,参数一定要FALSE,否则闪烁很严重 
		// 保存旧坐标 
		oldpoint = CPoint(x, y); 
		pthis->Invalidate(FALSE); 
	}else  
	{ 
        // 创建画笔 
		HPEN hPen = CreatePen(PS_SOLID, PenWidth, RGB(255, 255, 255)); 
		// 选进DC 
		::SelectObject(pthis->m_hMemDC, hPen); 
		// 画线 
		::MoveToEx(pthis->m_hMemDC, oldpoint.x, oldpoint.y, NULL); 
		::LineTo(pthis->m_hMemDC, x, y); 
		// 重绘图形,参数一定要FALSE,否则闪烁很严重 
		// 保存旧坐标 
		oldpoint = CPoint(x, y); 
		pthis->Invalidate(FALSE); 
 
	} 
} 
// 关闭连接时触发 
void CloseCallback (DWORD ptr) 
{ 
	char tmpstr[225]; 
	char			cip[15]; 
	unsigned int	cp = 0; 
	CConnection* c = reinterpret_cast  (ptr); 
	c->PeerInfo(cip, 15, &cp); 
	sprintf(tmpstr, "%s:%d关闭了连接", cip, cp); 
	// 如果是服务器,则删除保存的客户端信息 
	for (int i=0; iSendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr));   
} 
 
// 服务器端接受连接时触发 
void AcceptCallback (DWORD ptr) 
{ 
	char			cip[15]; 
	unsigned int	cp = 0; 
	CNetworking*	net = reinterpret_cast  (ptr); 
 
    // 如果连接已经建立,用Connection保存了服务器端和客户端的连接 
	// 如果要进行多用户连接,这需要一个Connection队列或数组保存 
	// 所有来自客户端的连接 
 
    // 保存客户的连接 
	CConnection* c = net->GetAccepted (); 
	ConnectionList.Add(c); 
	c->PeerInfo (&cip[0], 15, &cp); 
	c->SetReceiveFunc (ReceiveCallback); 
	c->SetCloseFunc (CloseCallback); 
 
	char			ci[128]; 
	sprintf (ci, "接受了%s:%d的连接!", cip, cp); 
    CChildView *pthis = (CChildView*) pThis; 
	pthis->SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(ci));   
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CChildView 
 
CChildView::CChildView() 
{ 
	m_port = DEFAULT_PORT;   // 默认端口号 
	memcpy(m_addr, "", 64); 
	Connection = NULL; 
	pand=0; 
	pThis = this; 
} 
 
CChildView::~CChildView() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CChildView,CWnd ) 
	//{{AFX_MSG_MAP(CChildView) 
	ON_WM_PAINT() 
	ON_WM_MOUSEMOVE() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_RBUTTONDBLCLK() 
	ON_WM_SIZE() 
	ON_COMMAND(ID_SETPEN, OnSetpen) 
	ON_COMMAND(ID_LISTEN, OnListen) 
	ON_UPDATE_COMMAND_UI(ID_LISTEN, OnUpdateListen) 
	ON_COMMAND(ID_CONNECT, OnConnect) 
	ON_UPDATE_COMMAND_UI(ID_CONNECT, OnUpdateConnect) 
	ON_COMMAND(ID_ERASE, OnErase) 
	ON_MESSAGE(WM_SETSTATUS, OnSetStatus) 
	ON_WM_SETFOCUS() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CChildView message handlers 
 
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)  
{ 
	if (!CWnd::PreCreateWindow(cs)) 
		return FALSE; 
 
	cs.dwExStyle |= WS_EX_CLIENTEDGE; 
	cs.style &= ~WS_BORDER; 
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,  
		::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); 
 
	return TRUE; 
} 
 
void CChildView::OnSize(UINT nType, int cx, int cy) 
{ 
	CWnd::OnSize(nType, cx, cy); 
	Invalidate(FALSE); 
} 
void CChildView::OnPaint()  
{ 
    HDC hdc; 
	PAINTSTRUCT ps; 
 
    ::SelectObject(m_hMemDC, m_hBitmap); 
    hdc = ::BeginPaint(m_hWnd, &ps); 
	// 获取位图尺寸 
	BITMAP bm; 
	::GetObject(m_hBitmap, sizeof(bm), &bm); 
	// 将内存DC中的位图显示在屏幕上 
	::BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, m_hMemDC, 0, 0, SRCCOPY); 
    ::EndPaint(m_hWnd, &ps); 
} 
 
void CChildView::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
	// 获取按下鼠标时的位置 
	m_oldpoint = point; 
	char tmpstr[MSG_LEN]; 
	sprintf(tmpstr, "X=%d,Y=%d", point.x, point.y); 
	SendMessage(WM_SETSTATUS, WPARAM(0), LPARAM(tmpstr)); 
	sprintf(tmpstr, "%d,%d,x:%d,y:%d", 1, m_PenWidth, point.x, point.y); 
	// 发送鼠标按下的位置 
	if (Connection && Connection->IsConnected()) 
	{ 
		Connection->Send(tmpstr, MSG_LEN); 
	} 
    else 
	{ 
		// 如果是服务器端,则发送到所有客户端 
		for (int i=0; iSend(tmpstr, MSG_LEN); 
		} 
	} 
} 
void CChildView::OnMouseMove(UINT nFlags, CPoint point) 
{ 
	// 按下左键移动开始画图 
	if (nFlags == MK_LBUTTON) 
	{ 
        
		if(pand==1) 
		{ 
         // 创建画笔 
		HPEN hPen = CreatePen(PS_SOLID, 20, RGB(255, 255, 255)); 
		// 选进DC 
		::SelectObject(m_hMemDC, hPen); 
		// 画线 
		::MoveToEx(m_hMemDC, m_oldpoint.x, m_oldpoint.y, NULL); 
		::LineTo(m_hMemDC, point.x, point.y); 
		// 重绘图形,参数一定要FALSE,否则闪烁很严重 
		// 保存旧坐标 
		m_oldpoint = point; 
		Invalidate(FALSE); 
///////////////////////////////////////////////////////////////////// 
 
		char tmpstr[MSG_LEN]; 
	    sprintf(tmpstr, "X=%d,Y=%d ", point.x, point.y); 
        SendMessage(WM_SETSTATUS, WPARAM(0), LPARAM(tmpstr)); 
	    sprintf(tmpstr, "%d,%d,x:%d,y:%d ", 3, 20, point.x, point.y); 
		// 发送鼠标位置 
		if (Connection && Connection->IsConnected()) 
		{ 
			Connection->Send(tmpstr, MSG_LEN); 
		} 
		else 
		{ 
			// 如果是服务器端,则发送到所有客户端 
			for (int i=0; iSend(tmpstr, MSG_LEN); 
			} 
		} 
 
///////////////////////////////////////////////////////////////////// 
 
		}else 
		{ 
		// 创建画笔 
		HPEN hPen = CreatePen(PS_SOLID, m_PenWidth, RGB(0x00, 0x00, 0xFF)); 
		// 选进DC 
		::SelectObject(m_hMemDC, hPen); 
		// 画线 
		::MoveToEx(m_hMemDC, m_oldpoint.x, m_oldpoint.y, NULL); 
		::LineTo(m_hMemDC, point.x, point.y); 
		// 重绘图形,参数一定要FALSE,否则闪烁很严重 
		// 保存旧坐标 
		m_oldpoint = point; 
		Invalidate(FALSE); 
 
		char tmpstr[MSG_LEN]; 
	    sprintf(tmpstr, "X=%d,Y=%d ", point.x, point.y); 
        SendMessage(WM_SETSTATUS, WPARAM(0), LPARAM(tmpstr)); 
	    sprintf(tmpstr, "%d,%d,x:%d,y:%d ", 2, m_PenWidth, point.x, point.y); 
		// 发送鼠标位置 
		if (Connection && Connection->IsConnected()) 
		{ 
			Connection->Send(tmpstr, MSG_LEN); 
		} 
		else 
		{ 
			// 如果是服务器端,则发送到所有客户端 
			for (int i=0; iSend(tmpstr, MSG_LEN); 
			} 
		} 
		} 
	} 
 
   
 
} 
 
void CChildView::OnRButtonDblClk(UINT nFlags, CPoint point) 
{ 
	// 擦除所画内容 
	::FillRect(m_hMemDC, &m_ClientRect, HBRUSH(RGB(0xFF,0xFF,0xFF))); 
	Invalidate(FALSE); 
} 
 
BOOL CChildView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)  
{ 
	HDC hdc; 
	// 创建设备描述表 
	hdc = ::GetDC(m_hWnd); 
    // 创建内存设备描述表 
	m_hMemDC = ::CreateCompatibleDC(hdc); 
	// 获取客户区尺寸 
	::GetClientRect(pParentWnd->m_hWnd, &m_ClientRect); 
	m_ClientRect.right =1024; 
	m_ClientRect.bottom=768; 
	// 创建空白位图 
	m_hBitmap = ::CreateCompatibleBitmap(hdc, m_ClientRect.right-m_ClientRect.left, m_ClientRect.bottom-m_ClientRect.top); 
	// 释放设备描述表 
	::ReleaseDC(m_hWnd, hdc); 
	// 将位图与设备描述表关联 
	::SelectObject(m_hMemDC, m_hBitmap); 
	// 设置背景 
	::FillRect(m_hMemDC, &m_ClientRect, HBRUSH(RGB(0xFF,0xFF,0xFF))); 
    // 屏幕画笔默认宽度 
	m_PenWidth = 0; 
 
	Networking.GetLocalIP(m_addr, 64); 
 
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); 
} 
 
BOOL CChildView::DestroyWindow()  
{ 
	// 释放内存设备描述表 
    ::DeleteDC(m_hMemDC); 
	// 释放位图句柄 
	::DeleteObject(m_hBitmap); 
	return CWnd ::DestroyWindow(); 
} 
 
void CChildView::OnSetpen()  
{ 
	// 打开设置画笔对话框 
	CSetPenDlg SetPenDlg; 
	SetPenDlg.DoModal();	 
} 
// 建立或取消侦听 
void CChildView::OnListen()  
{ 
	char tmpstr[225];  
    if (Connection && Connection->IsConnected()) 
	{  
		sprintf(tmpstr, "您正在与别的机器连接,不可以再作为服务器!"); 
		AfxMessageBox (tmpstr, NULL, MB_OK | MB_ICONINFORMATION); 
        return; 
	} 
	if (Networking.IsListening ()) 
	{ 
		Networking.StopListen (); 
		sprintf (tmpstr, "结束在端口%i已建立的侦听!", m_port); 
		SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr)); 
	} 
	else 
	{ 
		// 建立侦听 
		if (!Networking.Listen (m_port)) 
		{ 
			sprintf (tmpstr, "不能在端口%i建立侦听", m_port); 
			AfxMessageBox (tmpstr, NULL, MB_OK | MB_ICONSTOP); 
		} 
		else 
		{ 
			// 设置接受回调函数 
			Networking.SetAcceptFunc (AcceptCallback); 
			sprintf (tmpstr, "在端口%i建立侦听成功!", m_port); 
            SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr)); 
		} 
	} 
} 
	 
// 更改菜单,在旁边打勾否 
void CChildView::OnUpdateListen(CCmdUI* pCmdUI)  
{ 
	if (Networking.IsListening()) 
		pCmdUI->SetCheck(TRUE); 
    else 
		pCmdUI->SetCheck(FALSE); 
} 
 
void CChildView::OnConnect()  
{ 
	char tmpstr[225]; 
	// 如果已经作为服务器了,就不可以再做客户机了 
    if (Networking.IsListening()) 
	{ 
		sprintf(tmpstr, "您已经作为服务器,不可以再作客户机!"); 
		AfxMessageBox (tmpstr, NULL, MB_OK | MB_ICONINFORMATION); 
		return; 
	} 
	// 如果已连接,则断开 
	if (Connection) 
	{ 
		Connection->Disconnect (); 
		Connection = NULL; 
		sprintf(tmpstr, "与%s的连接已断开!", m_addr); 
		SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr)); 
	} 
	else 
	{ 
		// 对话框 
        CAddrDlg AddrDlg; 
		AddrDlg.DoModal(); 
		// 如果IP地址没有设,则退出 
		if (strlen(m_addr)<7) return; 
     
		Connection = new CConnection (); 
		Connection->SetReceiveFunc (ReceiveCallback); 
		Connection->SetCloseFunc (CloseCallback); 
 
		if (Connection->Connect (m_addr, m_port)) 
		{ 
			sprintf(tmpstr, "与%s的连接建立成功!", m_addr); 
			SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr)); 
		} 
		else 
		{ 
			sprintf(tmpstr, "不能与%s建立连接!", m_addr); 
			AfxMessageBox (tmpstr, NULL, MB_OK | MB_ICONINFORMATION); 
 
			delete Connection; 
			Connection = NULL; 
		} 
	} 
} 
// 更新连接菜单 
void CChildView::OnUpdateConnect(CCmdUI* pCmdUI)  
{ 
	if (Connection) 
		pCmdUI->SetCheck(TRUE); 
	else 
		pCmdUI->SetCheck(FALSE); 
} 
 
void CChildView::OnErase()  
{ 
	// 擦除所画内容 
	::FillRect(m_hMemDC, &m_ClientRect, HBRUSH(RGB(0xFF,0xFF,0xFF))); 
	Invalidate(FALSE); 
} 
// WM_SETSTATUS消息处理函数,自定义 
// 在静态函数中调用CMainFrame*的指针总是失败,古通过发送消息 
// 间接设置状态条 
LRESULT CChildView::OnSetStatus(WPARAM wParam, LPARAM lParam) 
{ 
	CMainFrame* pFrame = (CMainFrame*)AfxGetApp()->GetMainWnd(); 
	pFrame->m_wndStatusBar.SetPaneText(int(wParam), LPCTSTR(lParam), TRUE); 
	return 1; 
} 
 
void CChildView::ShowLocalIP() 
{ 
	char tmpstr[225]=""; 
	sprintf(tmpstr, "%s:%s", "本机IP", m_addr); 
    SendMessage(WM_SETSTATUS, WPARAM(1), LPARAM(tmpstr)); 
} 
 
void CChildView::OnSetFocus(CWnd *pOldWnd) 
{ 
	if (!bFlag) 
	{ 
		ShowLocalIP(); 
		bFlag = TRUE; 
	} 
}