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;
}
}