www.gusucode.com > VC++三子棋游戏源码(类似五子棋)-源码程序 > VC++三子棋游戏源码(类似五子棋)-源码程序\code\Client\GameView.cpp

    //Download by http://www.NewXing.com
// GameView.cpp : implementation file
//

#include "stdafx.h"
#include "SanQi.h"
#include "GameView.h"

#include "MainFrm.h"
//////////////////////////////////////////
#include "lock.h"

//////////////////////////////////////////
#define WINSOCK_VERSION 0x0101
const int WM_SOCKET_EVENT=WM_USER+103;
const int MAX_BUFLEN = 1024;
const int RECVMSG_BUFFER = MAX_BUFLEN*4;

#define SERVER_PORT	6666	//服务器端口
////////////////////////////////////////////

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

#define	INIT_CHESSINFO_TIMER	7000
#define TOKEN_ORDER_TIMER		7001
#define BLAST_DIE_TIMER			7010

//ExitGame
#define EXIT_GAME_TIMER			7501

//OffLine
#define OFFLINE_TIMER			8010
#define OFFLINE_LOADFILE_TIMER	(OFFLINE_TIMER+1)
#define OFFLINE_GETSTEPINFO_TIMER	(OFFLINE_TIMER+2)
#define OFFLINE_MOVESTEP_TIMER	(OFFLINE_TIMER+3)
/////////////////////////////////////////////////////////////////////////////
//Process Recv Message Thread
UINT CGameView::ProcessRecvMsgThread(LPVOID lpParam)
{
	TRACE("Enter ProcessRecvMsgThread(..) ...\n");

	CGameView *view = (CGameView *)lpParam;
	view->run();

	TRACE("Leave ProcessRecvMsgThread(..) ...\n");

	return 0;
}

//Flash the selecting Chess
UINT CGameView::FlashChessThread(LPVOID lpParam)
{
	TRACE("Enter FlashChessThread(..) ...\n");

	CGameView *view = (CGameView *)lpParam;
	view->FlashChess(INVALID_INDEX);	

	TRACE("Leave FlashChessThread(..) ...\n");

	return 0;
}

//Flash the falg that has been moved to another position
UINT CGameView::FlashPositionThread(LPVOID lpParam)
{
	TRACE("Enter FlashPositionThread(..) ...\n");

	CGameView *view = (CGameView *)lpParam;
	view->FlashPosition(INVALID_INDEX);	
	
	TRACE("Leave FlashPositionThread(..) ...\n");

	return 0;
}
/////////////////////////////////////////////////////////////////////////////
// CGameView

IMPLEMENT_DYNCREATE(CGameView, CView)

CGameView::CGameView()
{
	m_pChessInfo = NULL;

	m_strUserName = "";
	m_strPassword = "";
	m_strServerName = "127.0.0.1";
	m_intPort = SERVER_PORT;

	m_hSocket = INVALID_SOCKET;
	m_bConnectToServer = FALSE;
	m_nTableID = 1;
	m_nPosition = INVALID_INDEX;	
	
	InitControlData();
	m_strRecordHistory = "";

	//Sound
	m_pWaveSelect = NULL;
	m_pWaveComeIn = NULL;
	m_pWaveMineOK = NULL;
	m_pWaveReadyTo = NULL;
	m_pWaveMove = NULL;
	m_pWaveNoMove = NULL;
	m_pWaveEat = NULL;
	m_pWaveBeEat = NULL;
	m_pWaveEqual = NULL;
	m_pWaveDie = NULL;

	///
	for(int i=0;i<4;i++)
	{
		m_ptOrderIcon[i].x = -100;
		m_ptOrderIcon[i].y = -100;
	}

	//
	m_nLastPreSelIndex = INVALID_INDEX;
	m_bPreSelChess = FALSE;

	m_nMyColor = NO_COLOR;
	m_nCurColor = RED;

	//OffLine
	m_bOffLine = TRUE;
	m_bOffLineControl = FALSE;

	m_hRunThread = NULL;
	m_bRunState = FALSE;
}

CGameView::~CGameView()
{
	if( NULL != m_pChessInfo )
	{
		delete m_pChessInfo;
		m_pChessInfo = NULL;
	}
}


BEGIN_MESSAGE_MAP(CGameView, CView)
	//{{AFX_MSG_MAP(CGameView)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP

	//Socket Event...
	ON_MESSAGE(WM_SOCKET_EVENT, OnSocketEvent)
	//

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGameView drawing
void CGameView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CGameView diagnostics

#ifdef _DEBUG
void CGameView::AssertValid() const
{
	CView::AssertValid();
}

void CGameView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CGameView message handlers

int CGameView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_statusBarDlg.Create(this);

	///////
	//Chess Borad
	InitControlData();
	LoadWavRes();
	BuildChessBoard();
	InitButtonPosition();
	m_nButtonActionMode = OFFLINE;
	InitOrderIconPosition();
	///////

	return 0;
}

BOOL CGameView::OnEraseBkgnd(CDC* pDC) 
{
	DrawAll(pDC);

	return TRUE;	
}

void CGameView::SetWindowTitle()
{
	//SetWindowText
	CString strTmpText = g_strFileName;
	strTmpText.MakeReverse();
	strTmpText = strTmpText.SpanExcluding("\\");
	strTmpText.MakeReverse();
	CString strWindowText("");
	strWindowText.Format("[Game4War -- %s] -- Load file: < %s >,  Total steps: ( %d ) --> %d",m_strUserName,strTmpText,m_nTotalStepCount,m_nCurStepCount);
	::SetWindowText(AfxGetMainWnd()->m_hWnd,strWindowText);
}

LRESULT CGameView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch(message)
	{	
		case WM_COMMAND:
		{
			if(HIWORD(wParam) == BN_CLICKED)
			{
				int nButtonID = LOWORD(wParam);
				if(m_nButtonActionMode == INGAMES)//0,1,2
				{
					if(nButtonID == GAME_BUTTONID_0) 
					{
						OnBtStartGame();
					}
					else if(nButtonID == GAME_BUTTONID_1)
					{
						OnBtSaveChessInfo();
					}
					else if(nButtonID == GAME_BUTTONID_2)
					{
						OnBtLoadChessInfo();
					}
				}
				else if(m_nButtonActionMode == PLAYING_MOVE)
				{
					if(nButtonID == GAME_BUTTONID_1)
					{
						OnBtImpetratePeace();
					}
					else if(nButtonID == GAME_BUTTONID_2)
					{
						OnBtSurrender();
					}
				}
				else
				{
					if(nButtonID == GAME_BUTTONID_0) 
					{
						OnBtOpenFile();
					}
					else if(nButtonID == GAME_BUTTONID_1)
					{
						OnBtPreviousStep();
					}
					else if(nButtonID == GAME_BUTTONID_2)
					{
						OnBtNextStep();
					}
					else if(nButtonID == GAME_BUTTONID_3)
					{
						OnBtSaveChessInfo();
					}
				}
			}

			break;
		}
		
	default:
		{
			break;
		}
	}
	
	return CView::WindowProc(message, wParam, lParam);
}

BOOL CGameView::PreTranslateMessage(MSG* pMsg) 
{
	//Only for OffLine...
	if(!m_bOffLine) return FALSE;

	if(pMsg->message == WM_KEYDOWN)
	{
		switch(pMsg->wParam)
		{
			case VK_LEFT:
			{
				OnBtPreviousStep();

				break;
			}

			case VK_RIGHT:
			{
				OnBtNextStep();

				break;
			}
		}
	}
	
	return CView::PreTranslateMessage(pMsg);
}

void CGameView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	{
		SetPosition();
		SetBitmap();
		SetTextFont();	

		m_tColor_Dark = COLOR_DARK_GRAY;
		m_tColor_Yellow = COLOR_YELLOW;
		m_tColor_Black = COLOR_BLACK;
		m_tColor_Red = COLOR_RED;

		COLORREF tColorBk = RGB(160, 180, 220);
		m_tBkBrush.CreateSolidBrush(tColorBk);
			
		m_hHandCursor = LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDC_CURSOR_HAND));	
	}

	//Will Init All Chess Information	
	SetTimer(INIT_CHESSINFO_TIMER, 50, NULL);
	
	//Load the Chess info
	SetTimer(OFFLINE_LOADFILE_TIMER,5,NULL);

	///////////////////////////////////////////////////////////////
	//CommandLine:Server-Port:UserName:TableID-Position#
	CString strCommandLine = GetCommandLine();
//	strCommandLine = "CommandLine|127.0.0.1-6770|younggle|6-1";

	CString strServerName("127.0.0.1");
	int nPort = 0;
	if(strCommandLine.Find("|") != -1)	//OnLine
	{
		if(Connect(strServerName,nPort))
		{
			CString strComment("");
			strComment.Format("Connect Server [%s:%d] successfully!",strServerName,nPort);
			
			//Create ProcessRecvMsgThread(..) ....
			m_hRunThread = ::CreateThread(NULL,1024, 
						(LPTHREAD_START_ROUTINE)CGameView::ProcessRecvMsgThread,
						(LPVOID)this,0,NULL);	
			m_bRunState = (m_hRunThread != NULL);
			///		

			m_bOffLine = FALSE;
		}
	}
	else	//OffLine
	{
		ShowButtons(OFFLINE);

		m_bOffLine = TRUE;
		m_strChessInfoList.RemoveAll();
		m_curStepPosition = NULL;
		m_moveStepPosition = NULL;
				
		m_nTotalStepCount = 0;
		m_nCurStepCount = 0;
	}
	///////////////////////////////////////////////////////////////
}

void CGameView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	if(GetSafeHwnd() == NULL) return;
	
	CRect rect,oldRect;
	GetClientRect(&rect);
	if(rect.right-rect.left < 700 || rect.right-rect.left > 850)
	{
		::SendMessage(::AfxGetMainWnd()->m_hWnd,WM_SIZE,(WPARAM)cx,(LPARAM)cy);
		::SendMessage(::AfxGetMainWnd()->m_hWnd,WM_PAINT,0,0);
	}

	CWnd*	pWnd	=&m_statusBarDlg;
	SAFE_CHECKWND(pWnd)
	{
		RECT	rect,rt;
		memset(&rect, 0, sizeof(RECT));
		this->GetClientRect(&rect);
		pWnd->GetClientRect(&rt);
		rect.top	=rect.bottom - 18;	//18--Status Bar Height	
										

		pWnd->MoveWindow(&rect);
		m_statusBarDlg.SetStatus(" Ready");
	}
}

void CGameView::BuildChessBoard()
{
}

void CGameView::InvalidateGameRect()
{
	if( NULL == m_pChessInfo ) return;
	CHESS_STRUCT *pFirstChessInfo = &m_pChessInfo[0];
	CHESS_STRUCT *pLastChessInfo = &m_pChessInfo[TOTAL_POINTS - 1];

	int nDistance = 5;
	CRect	rect;
	rect.left = pFirstChessInfo->point.x - nDistance;
	rect.right = pLastChessInfo->point.x + CHESS_WIDTH + nDistance;
	rect.top = pFirstChessInfo->point.y - nDistance;
	rect.bottom = pLastChessInfo->point.y + CHESS_HEIGHT + nDistance;
				
	InvalidateRect(rect);
}

void CGameView::InvalidateOrderIconRect()
{
	int iWidthHeight = 32;

	for(int d=0;d<4;d++)
	{
		CRect	rect;
		memset(&rect, 0, sizeof(CRect));
		this->GetClientRect(&rect);
		rect.left = m_ptOrderIcon[d].x;
		rect.top = m_ptOrderIcon[d].y;
		rect.right = rect.left + 2*iWidthHeight;
		rect.bottom = rect.top + 2*iWidthHeight;
		InvalidateRect(&rect);
	}
}

void CGameView::LoadWavRes()
{
	if(m_pWaveSelect != NULL) return;

	HMODULE hmod = AfxGetResourceHandle(); 
	
	HRSRC hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_SELECT),_T("WAVE"));
	m_pWaveSelect = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_COMEIN),_T("WAVE"));
	m_pWaveComeIn = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_MINEOK),_T("WAVE"));
	m_pWaveMineOK = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_READYTO),_T("WAVE"));
	m_pWaveReadyTo = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_TAKEDOWN),_T("WAVE"));
	m_pWaveTakeDown = LoadResource(hmod,hSndResource);
	
	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_MOVE),_T("WAVE"));
	m_pWaveMove = LoadResource(hmod,hSndResource);
	
	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_NOMOVE),_T("WAVE"));
	m_pWaveNoMove = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_EAT),_T("WAVE"));
	m_pWaveEat = LoadResource(hmod,hSndResource);
	
	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_BEEAT),_T("WAVE"));
	m_pWaveBeEat = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_EQUAL),_T("WAVE"));
	m_pWaveEqual = LoadResource(hmod,hSndResource);

	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_SHOWCHESS),_T("WAVE"));
	m_pWaveShowChess = LoadResource(hmod,hSndResource);	
	
	hSndResource = FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE_DIE),_T("WAVE"));
	m_pWaveDie = LoadResource(hmod,hSndResource);
}

void CGameView::FreeWavRes()
{
	if(m_pWaveSelect)
	{
		FreeResource(m_pWaveSelect);
		m_pWaveSelect = NULL;		
	}
	if(m_pWaveMove)
	{
		FreeResource(m_pWaveMove);	
		m_pWaveMove = NULL;		
	}
	if(m_pWaveNoMove)
	{
		FreeResource(m_pWaveNoMove);		
		m_pWaveNoMove = NULL;
	}
	if(m_pWaveEat)
	{
		FreeResource(m_pWaveEat);
		m_pWaveEat = NULL;		
	}
	if(m_pWaveBeEat)
	{
		FreeResource(m_pWaveBeEat);	
		m_pWaveBeEat = NULL;		
	}
	if(m_pWaveEqual)
	{
		FreeResource(m_pWaveEqual);		
		m_pWaveEqual = NULL;
	}	
	if(m_pWaveShowChess)
	{
		FreeResource(m_pWaveShowChess);		
		m_pWaveShowChess = NULL;
	}
	if(m_pWaveDie)
	{
		FreeResource(m_pWaveDie);		
		m_pWaveDie = NULL;
	}
}

void CGameView::PlaySoundAction(int iResult)
{
	sndPlaySound(NULL,0);
}

void CGameView::InitTableInfo()
{
}

void CGameView::InitChessInfo()
{
	/*//
	00
	○━01━02━○━04━05━○
    ┃\│	│	┃	│	│/┃ 
	07─○━09━○━11━○─13
	┃	┃\│	┃	│/┃	┃
	14─15─○━○━○─19─20
	┃	┃	┃		┃	┃	┃
	○━○━○  24  ○━○━○
	┃	┃	┃		┃	┃	┃
	28─29─○━○━○─33─34
	┃	┃/│	┃	│\┃	┃
	35─○━37━○━39━○─41
	┃/│	│	┃	│	│\┃
	○━43━44━○━46━47━○
							48
	//*/


	////
	const int nBoardWidth = BOARD_WIDTH;
	const int nBoardHeight = BOARD_HEIGHT;
	const int nChessWidth = CHESS_WIDTH;
	const int nChessHeight = CHESS_HEIGHT;

	CRect rect;
	GetClientRect(&rect);
	int nCenterX = (rect.left + rect.right)/2;
	int nCenterY = (rect.top + rect.bottom)/2;
	
	const int nStartPosX = nCenterX - nBoardWidth/2;
	const int nStartPosY = nCenterY - nBoardHeight/2;
	const int nBoardBaseSize = BOARD_BASE_SIZE;
	////

	////
	if( NULL != m_pChessInfo )
	{
		delete m_pChessInfo;
		m_pChessInfo = NULL;
	}

	int nChessCount = TOTAL_POINTS;
	m_pChessInfo = new CHESS_STRUCT[nChessCount];
	
	const int nBasePoints = BASE_POINTS;
	const int nLinePoints = (nBasePoints * 2) + 1;
	int nPosArray[nLinePoints][nLinePoints];
	
	for(int i = 0; i < nLinePoints; i++)
	{
		for(int j=0; j < nLinePoints; j++)
		{
			nPosArray[i][j] = i*nLinePoints + j;
		}
	}
	
	int nIndex = 0;
	for(i = 0; i < nLinePoints; i++)
	{
		for(int j=0; j < nLinePoints; j++)
		{
			m_pChessInfo[nIndex].nIndex = nIndex;
			m_pChessInfo[nIndex].point = INVLID_POS;
			m_pChessInfo[nIndex].bRealPos = FALSE;
			m_pChessInfo[nIndex].tColor = NO_COLOR;
			m_pChessInfo[nIndex].tValue = NO_CHESS;
			m_pChessInfo[nIndex].nSelMode = NO_SELECTED;
			m_pChessInfo[nIndex].bFlashOn = FALSE;

			int nValue = nPosArray[i][j];

			if( ( 
					(i == j) || 
					(i == nLinePoints/2) || 
					(j == nLinePoints/2) || 
					((i+j) == (nLinePoints-1))						
				) && 
				(nValue != nLinePoints*nLinePoints/2)
			)
			{
				int nX = (nStartPosX + nBoardBaseSize * j) - nChessWidth/2;
				int nY = (nStartPosY + nBoardBaseSize * i) - nChessHeight/2;

				m_pChessInfo[nIndex].point = CPoint(nX, nY);
				m_pChessInfo[nIndex].bRealPos = TRUE;				
			}

			nIndex++;
		}
	}

	InvalidateGameRect();
	////
}

void CGameView::InitControlData()
{	
	m_nSrcSelIndex = INVALID_INDEX;
	m_nLastSrcSelIndex = INVALID_INDEX;
	m_bSelSrcChess = FALSE;

	m_nDestSelIndex = INVALID_INDEX;
	m_nLastDestSelIndex = INVALID_INDEX;
	m_bSelDestChess = FALSE;

	m_nFlashingIndex = INVALID_INDEX;
	
	m_bFlashChessThread = FALSE;
	m_bFlashPositionThread = FALSE;

	m_tGameStatus = OFFLINE;
	m_bCanMoveChess = TRUE;
	m_bPeaceAction = FALSE;

	m_bTakenOrderOnOff = TRUE;
	m_nLeftTime = 1;
	m_bDelayTime = FALSE;

	for(int i=0;i<4;i++)
	{
		nDelayCount[i] = 0;
	}
}

void CGameView::LoadChessData(int direction,int ChessColor,
								 CString strChessInfo /* = ""*/)
{
}

/////////////////////////////////////////////////////////////////
void  CGameView::SetPosition()
{
}

void  CGameView::SetBitmap()
{
	BMP_COMMENT.DeleteObject();
	BMP_COMMENT.LoadBitmap(IDB_COMMENT);

	/////////////////////////////////////
	///*
	BMP_RED_CHESS.DeleteObject();
	BMP_RED_CHESS.LoadBitmap(IDB_RED_CHESS);

	BMP_BLUE_CHESS.DeleteObject();
	BMP_BLUE_CHESS.LoadBitmap(IDB_BLUE_CHESS);
	//*/

	BMP_SRCMOVEFLAG.DeleteObject();
	BMP_SRCMOVEFLAG.LoadBitmap(IDB_SRCMOVEFLAG);

	BMP_TOKENORDER.DeleteObject();
	BMP_TOKENORDER.LoadBitmap(IDB_TOKEN_ORDER);

	BMP_LEFTTIME.DeleteObject();
	BMP_LEFTTIME.LoadBitmap(IDB_LEFT_TIME);
}

void CGameView::SetTextFont()
{
	LOGFONT lf;
	memset(&lf,0,sizeof(LOGFONT));
	lf.lfHeight=16;
	lf.lfWeight=14;
	m_textFont.CreateFontIndirect(&lf);
}

void CGameView::TransparentBlt(CDC * pDestDc, int x, int y, int w, int h,
									CBitmap * pBmp, int sx, int sy, COLORREF crTransparent)
{
	CDC memDC, maskDC, tempDC;
	maskDC.CreateCompatibleDC(pDestDc);
	CBitmap maskBitmap;
	
	//add these to store return of SelectObject() calls
	CBitmap* pOldMemBmp = NULL;
	CBitmap* pOldMaskBmp = NULL;
	
	memDC.CreateCompatibleDC(pDestDc);
	tempDC.CreateCompatibleDC(pDestDc);
	CBitmap bmpImage;
	bmpImage.CreateCompatibleBitmap( pDestDc, w, h);
	pOldMemBmp = memDC.SelectObject( &bmpImage );

	CBitmap * oldBmp = tempDC.SelectObject(pBmp);
	
	memDC.BitBlt( 0,0,w, h, &tempDC, sx, sy, SRCCOPY );
	
	// Create monochrome bitmap for the mask
	maskBitmap.CreateBitmap(w, h, 1, 1, NULL);
	pOldMaskBmp = maskDC.SelectObject( &maskBitmap );
	memDC.SetBkColor(crTransparent);
	
	// Create the mask from the memory DC
	maskDC.BitBlt(0, 0, w, h, &memDC, 0, 0, SRCCOPY);
	
	memDC.SetBkColor(RGB(0,0,0));
	memDC.SetTextColor(RGB(255,255,255));
	memDC.BitBlt(0, 0, w, h, &maskDC, 0, 0, SRCAND);
	
	// Set the foreground to black. See comment above.
	pDestDc->SetBkColor(RGB(255,255,255));
	pDestDc->SetTextColor(RGB(0,0,0));
	pDestDc->BitBlt(x, y, w, h, &maskDC, 0, 0, SRCAND);
	
	// Combine the foreground with the background
	pDestDc->BitBlt(x, y, w, h, &memDC, 0, 0, SRCPAINT);
	
	tempDC.SelectObject(oldBmp);
	if (pOldMaskBmp) maskDC.SelectObject( pOldMaskBmp );
	if (pOldMemBmp)  memDC.SelectObject( pOldMemBmp );
}

void CGameView::InitButtonPosition()
{
	int iWidth = BUTTON_WIDTH;
	int iHeight = BUTTON_HEIGHT;	
	int iOneStep = 0;
	int iX = 0;
	int iY = 0;
	
	for(int i=0;i<4;i++)
	{
		int startX = iX + 3*iOneStep + iWidth/2; 
		int startY = iY + 6*iOneStep + (iHeight + 5)*i - iHeight;

		m_ptButtonPos[i].x = startX;
		m_ptButtonPos[i].y = startY;
	}

	///////////////////////////	
	RECT	rect;
	memset(&rect, 0, sizeof(RECT));

	for(i=0; i<4;i++)
	{
		rect.left = m_ptButtonPos[i].x;
		rect.right = rect.left + BUTTON_WIDTH;
		rect.top = m_ptButtonPos[i].y;
		rect.bottom = rect.top + BUTTON_HEIGHT;
		m_btGameButtons[i].Create("三棋游戏",
						          WS_VISIBLE|WS_CHILD|WS_EX_CLIENTEDGE
								| WS_EX_STATICEDGE,
								  rect, this, GAME_BUTTONID_0+i);

		//Set Button property		
		m_btGameButtons[i].SetFlat(FALSE);
		m_btGameButtons[i].SetColor(CButtonST::BTNST_COLOR_FG_IN, RGB(255,0,0));
		m_btGameButtons[i].SetColor(CButtonST::BTNST_COLOR_FG_OUT, RGB(255,0,0));
		m_btGameButtons[i].ShowWindow(SW_HIDE);
		m_btGameButtons[i].EnableWindow(FALSE);
		m_btGameButtons[i].SetWindowText("");
	}	
	//////////////////////////////
}

void CGameView::ShowButtons(GAMESTATUS nMode)
{
	m_nButtonActionMode = nMode;

	int color = (int)(0xffffffff - 10L);
	COLORREF rgb = RGB(255, 255, 255);

	if(m_bOffLine)
	{
		m_nButtonActionMode = OFFLINE;

		//0,1,2,3				
		//m_btGameButtons[0].SetWindowText("打开文件");
		m_btGameButtons[0].SetBitmaps(IDB_OPENFILE,rgb,color);
		m_btGameButtons[0].ShowWindow(SW_SHOW);
		m_btGameButtons[0].EnableWindow(TRUE);

		//m_btGameButtons[1].SetWindowText(" 上一步 ");
		m_btGameButtons[1].SetBitmaps(IDB_PREVSTEP,rgb,color);
		m_btGameButtons[1].ShowWindow(SW_SHOW);
		m_btGameButtons[1].EnableWindow(FALSE);

		//m_btGameButtons[2].SetWindowText(" 下一步 ");
		m_btGameButtons[2].SetBitmaps(IDB_NEXTSTEP,rgb,color);
		m_btGameButtons[2].ShowWindow(SW_SHOW);
		m_btGameButtons[2].EnableWindow(FALSE);

		//m_btGameButtons[3].SetWindowText("保存棋谱");
		m_btGameButtons[3].SetBitmaps(IDB_SAVEINFOS,rgb,color);
		m_btGameButtons[3].ShowWindow(SW_SHOW);
		m_btGameButtons[3].EnableWindow(FALSE);
	}
	else if(nMode == PLAYING_MOVE)	//(In Game)
	{
		//1,2
		//m_btGameButtons[1].SetWindowText("祈求和平");
		m_btGameButtons[1].SetBitmaps(IDB_HOPEPEACE,rgb,color);
		m_btGameButtons[1].ShowWindow(SW_SHOW);
		m_btGameButtons[1].EnableWindow(TRUE);

		//m_btGameButtons[2].SetWindowText("缴械投降");
		m_btGameButtons[2].SetBitmaps(IDB_SURRENDER,rgb,color);
		m_btGameButtons[2].ShowWindow(SW_SHOW);
		m_btGameButtons[2].EnableWindow(TRUE);
	}
	else if(nMode == READY)	//(m_bWaitForGame)
	{
		for(int i=0; i<4;i++)
		{
			m_btGameButtons[i].ShowWindow(SW_HIDE);
			m_btGameButtons[i].EnableWindow(FALSE);
		}
	}
	else if(nMode == INGAMES)	//(m_bReadyToGame)
	{
		//0,1,2
		//m_btGameButtons[0].SetWindowText("大军出征");		
		m_btGameButtons[0].SetBitmaps(IDB_STARTGAME,rgb,color);
		m_btGameButtons[0].ShowWindow(SW_SHOW);
		m_btGameButtons[0].EnableWindow(TRUE);

		//m_btGameButtons[1].SetWindowText("保存阵图");
		m_btGameButtons[1].SetBitmaps(IDB_SAVEINFO,rgb,color);
		m_btGameButtons[1].ShowWindow(SW_SHOW);
		m_btGameButtons[1].EnableWindow(TRUE);

		//m_btGameButtons[2].SetWindowText("载入阵图");
		m_btGameButtons[2].SetBitmaps(IDB_LOADINFO,rgb,color);
		m_btGameButtons[2].ShowWindow(SW_SHOW);
		m_btGameButtons[2].EnableWindow(TRUE);
	}	
}

void CGameView::InitOrderIconPosition()
{
	int iOneStep = 0;
	int iPosX = 0;
	int iPosY = 0;

	
	int nStartPosX = iPosX - 4*iOneStep;
	int nStartPosY = iPosY + 7*iOneStep;
	m_ptOrderIcon[0].x = nStartPosX;
	m_ptOrderIcon[0].y = nStartPosY;

	nStartPosX = iPosX - 6*iOneStep;
	nStartPosY = iPosY - 4*iOneStep;
	m_ptOrderIcon[1].x = nStartPosX;
	m_ptOrderIcon[1].y = nStartPosY;
	
	nStartPosX = iPosX + 4*iOneStep;
	nStartPosY = iPosY - 7*iOneStep;
	m_ptOrderIcon[2].x = nStartPosX;
	m_ptOrderIcon[2].y = nStartPosY;
	
	nStartPosX = iPosX + 6*iOneStep;
	nStartPosY = iPosY + 4*iOneStep;
	m_ptOrderIcon[3].x = nStartPosX;
	m_ptOrderIcon[3].y = nStartPosY;
}

void CGameView::DrawAll(CDC *pDC)
{
	CDC memDC;
	CBitmap bitmap;
	CBitmap* pOldBitmap;	

	if( memDC.CreateCompatibleDC(pDC) )
	{		
		CRect rect;
		GetClientRect(&rect);		
		
		if(bitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom))				
		{
			pOldBitmap = memDC.SelectObject(&bitmap);

			const int nBoardWidth = BOARD_WIDTH;
			const int nBoardHeight = BOARD_HEIGHT;

			rect.bottom = rect.bottom;
			memDC.FillRect(&rect,&m_tBkBrush);			

			////////////////////////////////////////////////
			//把要画图的代码放在这里
			DrawBkGround(&memDC);
			DrawChessBoard(&memDC);

			DrawAllChessMan(&memDC, m_pChessInfo);
			////////////////////////////////////////////////
		
			pDC->BitBlt(rect.left, rect.top, rect.right, rect.bottom,
						&memDC, 0, 0, SRCCOPY);

			memDC.SelectObject( pOldBitmap ); 
			bitmap.DeleteObject();
			memDC.DeleteDC();
			ReleaseDC(&memDC);
		}
	}			
}

void CGameView::DrawBkGround(CDC *pDC)
{
}

void CGameView::DrawChessBoard(CDC *pDC)
{
	//画棋盘

	////
	const int nBoardWidth = BOARD_WIDTH;
	const int nBoardHeight = BOARD_HEIGHT;
	const int nBoardBaseSize = BOARD_BASE_SIZE;

	CRect rect;
	GetClientRect(&rect);
	int nCenterX = (rect.left + rect.right)/2;
	int nCenterY = (rect.top + rect.bottom)/2;

	const int nStartPosX = nCenterX - nBoardWidth/2;
	const int nStartPosY = nCenterY - nBoardHeight/2;
	////
	
	const COLORREF tRectColor = RGB(32, 32, 32);
	const COLORREF tLineColor = RGB(240, 240, 240);

	int nBaseCount = BASE_POINTS;

	//画外边框, 中间边框, 内边框
	for(int nIndex = 0; nIndex < nBaseCount; nIndex++)
	{
		int nPosX = nStartPosX + (nBoardBaseSize * nIndex);
		int nPosY = nStartPosY + (nBoardBaseSize * nIndex);
		int nWidth = nBoardWidth - (nBoardBaseSize * nIndex * 2);
		int nHeight = nBoardHeight - (nBoardBaseSize * nIndex * 2);

		int nStep = 0;
		pDC->Draw3dRect(nPosX+nStep, nPosY+nStep, 
						nWidth-nStep*2, nHeight-nStep*2, 
						tLineColor, tLineColor);

		nStep = 1;
		pDC->Draw3dRect(nPosX+nStep, nPosY+nStep, 
						nWidth-nStep*2, nHeight-nStep*2, 
						tRectColor, tRectColor);
		nStep = 2;
		pDC->Draw3dRect(nPosX+nStep, nPosY+nStep, 
						nWidth-nStep*2, nHeight-nStep*2, 
						tRectColor, tRectColor);

		nStep = -1;
		pDC->Draw3dRect(nPosX+nStep, nPosY+nStep, 
						nWidth-nStep*2, nHeight-nStep*2, 
						tRectColor, tRectColor);
		nStep = -2;
		pDC->Draw3dRect(nPosX+nStep, nPosY+nStep, 
						nWidth-nStep*2, nHeight-nStep*2, 
						tRectColor, tRectColor);
	}

	//画直连线(顺时针画)
	{
		CPen	tPen;
		tPen.CreatePen(PS_SOLID, 3, tRectColor);
		CPen*	pOldPen		=(CPen*)pDC->SelectObject(&tPen);
		
		int nDistanceX = nBoardBaseSize * (nBaseCount - 1);
		int nDistanceY = nBoardBaseSize * (nBaseCount - 1);

		int nFromPosX = nStartPosX;
		int nFromPosY = nStartPosY;
		int nToPosX = nStartPosX + nDistanceX;
		int nToPosY = nStartPosY + nDistanceY;

		pDC->MoveTo(nFromPosX, nFromPosY);
		pDC->LineTo(nToPosX, nToPosY);

		pDC->MoveTo(nFromPosX+nBoardWidth/2, nFromPosY);
		pDC->LineTo(nToPosX+nDistanceX/2, nToPosY);

		pDC->MoveTo(nFromPosX+nBoardWidth, nFromPosY);
		pDC->LineTo(nToPosX+nDistanceX, nToPosY);

		pDC->MoveTo(nFromPosX+nBoardWidth, nFromPosY+nBoardHeight/2);
		pDC->LineTo(nToPosX+nDistanceX, nToPosY+nDistanceX/2);

		pDC->MoveTo(nFromPosX+nBoardWidth, nFromPosY+nBoardHeight);
		pDC->LineTo(nToPosX+nDistanceX, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX+nBoardWidth/2, nFromPosY+nBoardHeight);
		pDC->LineTo(nToPosX+nDistanceX/2, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX, nFromPosY+nBoardHeight);
		pDC->LineTo(nToPosX, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX, nFromPosY+nBoardHeight/2);
		pDC->LineTo(nToPosX, nToPosY+nDistanceX/2);

		pDC->SelectObject(pOldPen);
		tPen.DeleteObject();
	}
	{
		CPen	tPen;
		tPen.CreatePen(PS_SOLID, 1, tLineColor);
		CPen*	pOldPen		=(CPen*)pDC->SelectObject(&tPen);
		
		int nDistanceX = nBoardBaseSize * (nBaseCount - 1);
		int nDistanceY = nBoardBaseSize * (nBaseCount - 1);

		int nFromPosX = nStartPosX;
		int nFromPosY = nStartPosY;
		int nToPosX = nStartPosX + nDistanceX;
		int nToPosY = nStartPosY + nDistanceY;

		int nOffSet = 2;
		pDC->MoveTo(nFromPosX+nOffSet, nFromPosY+nOffSet);
		pDC->LineTo(nToPosX-nOffSet, nToPosY-nOffSet);

		pDC->MoveTo(nFromPosX+nBoardWidth/2, nFromPosY+nOffSet);
		pDC->LineTo(nToPosX+nDistanceX/2, nToPosY-nOffSet);

		pDC->MoveTo(nFromPosX+nBoardWidth-nOffSet, nFromPosY+nOffSet);
		pDC->LineTo(nToPosX+nDistanceX, nToPosY);

		pDC->MoveTo(nFromPosX+nBoardWidth-nOffSet, nFromPosY+nBoardHeight/2);
		pDC->LineTo(nToPosX+nDistanceX+nOffSet, nToPosY+nDistanceX/2);

		pDC->MoveTo(nFromPosX+nBoardWidth-nOffSet, nFromPosY+nBoardHeight-nOffSet);
		pDC->LineTo(nToPosX+nDistanceX, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX+nBoardWidth/2, nFromPosY+nBoardHeight-nOffSet);
		pDC->LineTo(nToPosX+nDistanceX/2, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX+nOffSet, nFromPosY+nBoardHeight-nOffSet);
		pDC->LineTo(nToPosX, nToPosY+nDistanceX);

		pDC->MoveTo(nFromPosX+nOffSet, nFromPosY+nBoardHeight/2);
		pDC->LineTo(nToPosX-nOffSet, nToPosY+nDistanceX/2);

		pDC->SelectObject(pOldPen);
		tPen.DeleteObject();
	}
}

void CGameView::DrawAllChessMan(CDC *pDC, void *pChessInfo)
{
	if( NULL == pChessInfo ) return;

	CHESS_STRUCT *ptChessInfo = (CHESS_STRUCT *)pChessInfo;
	int nChessCount = TOTAL_POINTS;
	for(int nIndex = 0; nIndex < nChessCount; nIndex++)
	{
		CHESS_STRUCT *pInfo = &ptChessInfo[nIndex];

		BOOL bRealPos = pInfo->bRealPos;
		if( !bRealPos ) continue;

		BOOL bFlashOn = pInfo->bFlashOn;
		if( bFlashOn ) continue;

		DrawChessMan(pDC, pInfo);
	}
}

void CGameView::DrawChessMan(CDC *pDC, void *pChessInfo)
{
	if( NULL == pChessInfo ) return;

	CHESS_STRUCT *ptChessInfo = (CHESS_STRUCT *)pChessInfo;

	int nStartPosX = ptChessInfo->point.x;
	int nStartPosY = ptChessInfo->point.y;

	CHESS_COLOR tColor = ptChessInfo->tColor;
	CHESS_VALUE tValue = ptChessInfo->tValue;
	int nSelMode = ptChessInfo->nSelMode;
	
	CDC memDC;	
	memDC.CreateCompatibleDC(pDC);

	switch(tColor) {
	case RED:
		{
			memDC.SelectObject(BMP_RED_CHESS);

			break;
		}
	case BLUE:
		{
			memDC.SelectObject(BMP_BLUE_CHESS);

			break;
		}
	default:
		{			
		}
	}

	pDC->StretchBlt(nStartPosX, nStartPosY, CHESS_WIDTH, CHESS_HEIGHT, &memDC, 
					0, CHESS_HEIGHT*tValue, CHESS_WIDTH, CHESS_HEIGHT,SRCCOPY);
		
	if(nSelMode == PRE_SELECTED)
	{	
		//pDC->Draw3dRect(nStartPosX+1,nStartPosY+1,CHESS_WIDTH-2,CHESS_HEIGHT-2,m_tColor_Yellow,m_tColor_Yellow);
		pDC->Draw3dRect(nStartPosX,nStartPosY,CHESS_WIDTH,CHESS_HEIGHT,m_tColor_Black,m_tColor_Black);
		pDC->Draw3dRect(nStartPosX-1,nStartPosY-1,CHESS_WIDTH+2,CHESS_HEIGHT+2,m_tColor_Yellow,m_tColor_Yellow);
		pDC->Draw3dRect(nStartPosX-2,nStartPosY-2,CHESS_WIDTH+4,CHESS_HEIGHT+4,m_tColor_Black,m_tColor_Black);
		//pDC->Draw3dRect(nStartPosX-3,nStartPosY-3,CHESS_WIDTH+6,CHESS_HEIGHT+6,m_tColor_Black,m_tColor_Black);
	}
	else if(nSelMode == SRC_SELECTED)
	{
		memDC.SelectObject(BMP_SRCMOVEFLAG);

		//left->right->top->bottom->center
		const int wh = 10;
		int step = (CHESS_WIDTH - wh)/2;
		pDC->StretchBlt(nStartPosX,nStartPosY+step,wh,wh,&memDC,0,wh*0,wh,wh,SRCCOPY);
		pDC->StretchBlt(nStartPosX+(CHESS_WIDTH-wh),nStartPosY+step,wh,wh,&memDC,0,wh*1,wh,wh,SRCCOPY);
		pDC->StretchBlt(nStartPosX+wh,nStartPosY,wh,wh,&memDC,0,wh*2,wh,wh,SRCCOPY);
		pDC->StretchBlt(nStartPosX+wh,nStartPosY+(CHESS_WIDTH-wh),wh,wh,&memDC,0,wh*3,wh,wh,SRCCOPY);
		pDC->StretchBlt(nStartPosX+wh,nStartPosY+wh,wh,wh,&memDC,0,wh*4,wh,wh,SRCCOPY);
	}
	else if(nSelMode == DEST_SELECTED)	//after moving 
	{		
		pDC->Draw3dRect(nStartPosX+1,nStartPosY+1,CHESS_WIDTH-2,CHESS_HEIGHT-2,m_tColor_Red,m_tColor_Red);
		pDC->Draw3dRect(nStartPosX,nStartPosY,CHESS_WIDTH,CHESS_HEIGHT,m_tColor_Red,m_tColor_Red);
		pDC->Draw3dRect(nStartPosX-1,nStartPosY-1,CHESS_WIDTH+2,CHESS_HEIGHT+2,m_tColor_Red,m_tColor_Red);
		pDC->Draw3dRect(nStartPosX-2,nStartPosY-2,CHESS_WIDTH+4,CHESS_HEIGHT+4,m_tColor_Black,m_tColor_Black);
		pDC->Draw3dRect(nStartPosX-3,nStartPosY-3,CHESS_WIDTH+6,CHESS_HEIGHT+6,m_tColor_Black,m_tColor_Black);
	}
}

void CGameView::DrawUserInfo(CDC *pDC)
{
	int iOneStep = 0;
	int iWidthHeight = 32;
	
	for(int ii=0;ii<4;ii++)
	{	
		int iX = 0;
		int iY = 0;

		CString strUserName = m_userInfo[ii].userName;

		if(ii == 0)
		{
			iX = iX - 4*iOneStep;
			iY = iY + 7*iOneStep;			
		}
		else if(ii == 1)
		{
			iX = iX - 6*iOneStep;
			iY = iY - 4*iOneStep;
		}
		else if(ii == 2)
		{
			iX = iX + 4*iOneStep;
			iY = iY - 7*iOneStep;
		}
		else if(ii == 3)
		{
			iX = iX + 6*iOneStep;
			iY = iY + 3*iOneStep - iWidthHeight;
		}

		
		pDC->SetBkColor(COLOR_BKGND);
		pDC->TextOut(iX,iY,strUserName);
	}
}

void CGameView::DrawOrderIcon(CDC *pDC)
{
	CDC memDC;	
	memDC.CreateCompatibleDC(pDC);
	memDC.SelectObject(BMP_TOKENORDER);
	memDC.SetBkColor(COLOR_BKGND);
	
	int curOrder = 0;
	int myOrder = 2;
	int order = GetRelativePosition(myOrder,curOrder);

	int nStartPosX = m_ptOrderIcon[order].x;
	int nStartPosY = m_ptOrderIcon[order].y;

	int iWidthHeight = 32;
	int textWidthHeight = 24;
	int iIconOrder = m_bTakenOrderOnOff? 0:1;
	pDC->StretchBlt(nStartPosX,nStartPosY,iWidthHeight,iWidthHeight,&memDC,0,iWidthHeight*iIconOrder,iWidthHeight,iWidthHeight,SRCCOPY);
	
	//Draw the Text(Show Left Time)
	if(!m_bOffLine)
	{
		nStartPosX = nStartPosX + iWidthHeight;
		nStartPosY = nStartPosY ; 
		iWidthHeight = textWidthHeight;
		memDC.SelectObject(BMP_LEFTTIME);
		memDC.SetBkColor(COLOR_BKGND);	
		pDC->StretchBlt(nStartPosX,nStartPosY,iWidthHeight,iWidthHeight,&memDC,0,iWidthHeight*(30-m_nLeftTime),iWidthHeight,iWidthHeight,SRCCOPY);
	}
}

void CGameView::InvalidateChessRect(CPoint &point)
{
	int nDistance = CHESS_WIDTH/8;
	int left = point.x - nDistance;
	int top = point.y - nDistance;
	int right = left + CHESS_WIDTH + nDistance * 2;
	int bottom = top + CHESS_HEIGHT + nDistance * 2;
	CRect rect(left,top,right,bottom);
	InvalidateRect(rect,TRUE);
}

void CGameView::InvalidateChessRect(int nChessIndex)
{
	if(nChessIndex == INVALID_INDEX)
	{
		InvalidateGameRect();

		return;
	}
	else
	{
		int nX = m_pChessInfo[nChessIndex].point.x;
		int nY = m_pChessInfo[nChessIndex].point.y;
		CPoint point(nX, nY);
		InvalidateChessRect(point);
	}
}

int CGameView::GetChessIndex(CPoint &point)
{
	int retIndex = INVALID_INDEX;

	if( NULL == m_pChessInfo ) return retIndex;
	
	for(int nIndex = 0; nIndex < TOTAL_POINTS; nIndex++)
	{		
		int left = m_pChessInfo[nIndex].point.x;
		int top = m_pChessInfo[nIndex].point.y;
		int right = left + CHESS_WIDTH;
		int bottom = top + CHESS_HEIGHT;
		CRect ChessRect(left,top,right,bottom);

		if(ChessRect.PtInRect(point))
		{			
			retIndex = nIndex;		

			break;
		}	
	}	

	return retIndex;
}

int CGameView::GetPositionIndex(CPoint &point)
{
	int retIndex = INVALID_INDEX;
	
	for(int index=0;index<TOTAL_POINTS;index++)
	{		
		int posIndex = m_pChessInfo[index].nIndex;

		int left = m_pChessInfo[index].point.x;
		int top = m_pChessInfo[index].point.y;		
		int right = left + CHESS_WIDTH;
		int bottom = top + CHESS_HEIGHT;

		CRect ChessRect(left,top,right,bottom);
		if(ChessRect.PtInRect(point))
		{			
			retIndex = posIndex;	

			break;
		}	
	}	

	return retIndex;
}

BOOL CGameView::GetPositionIndexList(int index, int *posList)
{
	
	return TRUE;
}

void CGameView::FlashChessAction(BOOL bFlashOn)
{
	static HANDLE hThread = NULL;

	if(bFlashOn)
	{
		if(IsInGame() && m_bFlashChessThread) return;

		hThread = ::CreateThread(NULL,1024,
			(LPTHREAD_START_ROUTINE)CGameView::FlashChessThread,
			(LPVOID)this,0,NULL);
		m_bFlashChessThread = (hThread != NULL);
	}
	else
	{
		if(m_bFlashChessThread && hThread != NULL)
		{			
			m_bFlashChessThread = FALSE;
			WaitForSingleObject(hThread,INFINITE);
			hThread = NULL;
		}
	}
}

void CGameView::FlashPositionAction(BOOL bFlashOn)
{
	static HANDLE hThread = NULL;

	if(bFlashOn)
	{
		if(m_bFlashPositionThread) return;
		
		hThread = ::CreateThread(NULL,1024,
			(LPTHREAD_START_ROUTINE)CGameView::FlashPositionThread,
			(LPVOID)this,0,NULL);
		m_bFlashPositionThread = (hThread != NULL);
	}
	else
	{
		if(m_bFlashPositionThread && hThread != NULL)
		{			
			m_bFlashPositionThread = FALSE;
			
			WaitForSingleObject(hThread,INFINITE);
			hThread = NULL;
		}
	}
}

void CGameView::FlashChess(int nChessIndex)
{
	//If it is in war, do not stop the flash thread,
	//else stop it and restart...

	int nFlasingIndex = m_nFlashingIndex;
	int nSrcSelIndex = m_nSrcSelIndex;

	if(nChessIndex != INVALID_INDEX)
	{
		//Stop the flashing Chess action firstly
		if(!IsInGame())
		{
			FlashChessAction(FALSE);
			if(nFlasingIndex != INVALID_INDEX)
			{
				m_pChessInfo[nFlasingIndex].bFlashOn = FALSE;
			}
		}
		
		//The Chess is flashing,do this action again will stop flashing	
		if(nFlasingIndex == nChessIndex)
		{
			if(!IsInGame())
			{
				if(nSrcSelIndex != INVALID_INDEX)
				{
					m_pChessInfo[nSrcSelIndex].nSelMode = NO_SELECTED;
					InvalidateChessRect(nSrcSelIndex);
					m_nSrcSelIndex = INVALID_INDEX;
					m_bSelSrcChess = FALSE;

					m_nLastPreSelIndex = INVALID_INDEX;
				}
			}
		}

		//do the flashing action
		else
		{	
			if(IsInGame())
			{
				if(nFlasingIndex != INVALID_INDEX)
				{
					m_pChessInfo[nFlasingIndex].bFlashOn = FALSE;
					InvalidateChessRect(nFlasingIndex);
				}
			}

			m_nFlashingIndex = nChessIndex;	//Set the flashing chess index
			FlashChessAction(TRUE);
		}			
	}

	//Run the thread...
	else 
	{
		while(m_bFlashChessThread)
		{
			if(nFlasingIndex != INVALID_INDEX)
			{
				BOOL bFlashOn = m_pChessInfo[nFlasingIndex].bFlashOn;
				m_pChessInfo[nFlasingIndex].bFlashOn = !bFlashOn;
				m_pChessInfo[nFlasingIndex].nSelMode = NO_SELECTED;
			}
			else break;

			if(!m_bFlashChessThread) break;
			
			InvalidateChessRect(nFlasingIndex);
			
			for(int nCount = 0; nCount < 15; nCount++)
			{
				if(!m_bFlashChessThread) break;

				Sleep(10);
			}
		}
		
		m_bFlashChessThread = FALSE;

		//stop the flashing
		if(nFlasingIndex != INVALID_INDEX)
		{
			m_pChessInfo[nFlasingIndex].bFlashOn = FALSE;
			m_pChessInfo[nFlasingIndex].nSelMode = NO_SELECTED;
			InvalidateChessRect(nFlasingIndex);
			m_nFlashingIndex = INVALID_INDEX;
		}
	}
}

void CGameView::SetChessState(int nChessIndex,int nState)
{
	if(nChessIndex != INVALID_INDEX)
	{
		m_pChessInfo[nChessIndex].nSelMode = (SELECTED_MODE)nState;

		InvalidateChessRect(nChessIndex);
	}
}

void CGameView::FlashPosition(int nPosIndex)
{
	int nFlashingIndex = m_nFlashingIndex;

	//Start the thread...
	if(nPosIndex != INVALID_INDEX)
	{	
		FlashPositionAction(FALSE);
		if(nFlashingIndex != INVALID_INDEX)
		{
			InvalidateChessRect(nFlashingIndex);
		}

		m_nFlashingIndex = nPosIndex;
		FlashPositionAction(TRUE);		
	}

	//Run the thread...
	else
	{
		BOOL bFlash = TRUE;
		while(m_bFlashPositionThread)
		{
			if(nFlashingIndex == INVALID_INDEX) break;

			if(bFlash)
			{
				bFlash = FALSE;
			}
			else
			{
				bFlash = TRUE;
			}

			if(!m_bFlashPositionThread) break;

			InvalidateChessRect(nFlashingIndex);

			for(int i=0;i<31;i++)
			{
				if(!m_bFlashPositionThread) break;

				Sleep(10);
			}
		}

		m_bFlashPositionThread = FALSE;
				
		if(nFlashingIndex != INVALID_INDEX)
		{			
			InvalidateChessRect(nFlashingIndex);
		}

		if(!IsInGame())
		{
			//Reset the source and the destination flashing position
			int nSrcSelIndex = m_nSrcSelIndex;
			int nDestSelIndex = m_nDestSelIndex;
			if(nSrcSelIndex != INVALID_INDEX)
			{
				m_nLastSrcSelIndex = nSrcSelIndex;
				InvalidateChessRect(nSrcSelIndex);

				m_nSrcSelIndex = INVALID_INDEX;				
			}

			if(nDestSelIndex != INVALID_INDEX)
			{
				m_nLastDestSelIndex = nDestSelIndex;
				InvalidateChessRect(nDestSelIndex);

				m_nDestSelIndex = INVALID_INDEX;
			}
		}
		else
		{
			//continue the flashing
			if(nFlashingIndex != INVALID_INDEX)
			{
				InvalidateChessRect(nFlashingIndex);
			}
		}
	}
}

void CGameView::OnLButtonDown(UINT nChesss, CPoint point) 
{
	if(!m_bCanMoveChess) 
	{
		m_bPreSelChess = FALSE;

		return;
	}

	ProcessLButtonDown(point);

	if( !m_bSelSrcChess )	//If not selected, check selected or not
	{
		ProcessMouseMove(point);
	}
	
	CView::OnLButtonDown(nChesss, point);
}

void CGameView::ProcessLButtonDown(CPoint &point)
{
	int nChessIndex = GetChessIndex(point);

	if(INVALID_INDEX == nChessIndex)
	{
	}
	else
	{
		CHESS_VALUE tValue = m_pChessInfo[nChessIndex].tValue;
		CHESS_COLOR tColor = m_pChessInfo[nChessIndex].tColor;
		if( NO_CHESS != tValue )	//Here is a Chess
		{			
			m_nSrcSelIndex = nChessIndex;
			m_bSelSrcChess = TRUE;

			FlashChess(nChessIndex);

			return;
		}
		else
		{
			CHESS_COLOR tCurColor = (CHESS_COLOR)m_nCurColor;
			m_pChessInfo[nChessIndex].tValue = NORMAL_CHESS;
			m_pChessInfo[nChessIndex].tColor = tCurColor;

			if( RED == (CHESS_COLOR)tCurColor ) m_nCurColor = BLUE;
			else if( BLUE == (CHESS_COLOR)tCurColor ) m_nCurColor = RED;
			else {}

			InvalidateChessRect(nChessIndex);
		}
	}
}

void CGameView::GetChessMovePathInfo(int srcIndex,int destIndex,
										int iPathInfo[],int &iStepCount)
{
}

void CGameView::OnLButtonUp(UINT nChesss, CPoint point) 
{
	return;

	//Has Not connected to server
	if(!m_bConnectToServer)
	{

		return;
	}
	
	CView::OnLButtonUp(nChesss, point);
}

BOOL CGameView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default
	if(m_bPreSelChess)
	{
		SetCursor(m_hHandCursor);

		return TRUE;
	}

	return CView::OnSetCursor(pWnd, nHitTest, message);
}

void CGameView::OnMouseMove(UINT nChesss, CPoint point) 
{
	//CString strMousePos("");
	//strMousePos.Format("三旗游戏 -- Mouse Move: (%d, %d)", point.x, point.y);
	//::SetWindowText(AfxGetMainWnd()->m_hWnd,strMousePos);

	if(!m_bCanMoveChess) 
	{
		m_bPreSelChess = FALSE;

		return;
	}

	ProcessMouseMove(point);	
	
	CView::OnMouseMove(nChesss, point);
}

void CGameView::ProcessMouseMove(CPoint &point)
{
	int nChessIndex = GetChessIndex(point);
	int nLastPreSelIndex = m_nLastPreSelIndex;

	if(INVALID_INDEX == nChessIndex)	//Not Selected
	{
		if(INVALID_INDEX != nLastPreSelIndex)	//Refresh Last Selected
		{
			SetChessState(nLastPreSelIndex, NO_SELECTED);
		}
		
		m_bPreSelChess = FALSE;
	}
	else
	{		
		if( nLastPreSelIndex == nChessIndex )	//The Same Selection, do nothing
		{
			return;
		}

		if(nLastPreSelIndex != nChessIndex)	//The different selection, 
		{									//refresh the last selected
			SetChessState(nLastPreSelIndex, NO_SELECTED);
		}

		if(nLastPreSelIndex == m_nLastSrcSelIndex)
		{
			SetChessState(nLastPreSelIndex, SRC_SELECTED);
		}
		else if(nLastPreSelIndex == m_nLastDestSelIndex)
		{
			SetChessState(nLastPreSelIndex, DEST_SELECTED);
		}
		
		m_bPreSelChess = TRUE;
		SetCursor(m_hHandCursor);
		
		SetChessState(nChessIndex, PRE_SELECTED);		
		InvalidateChessRect(nChessIndex);
	}

	m_nLastPreSelIndex = nChessIndex;	//Set the mouse last selected
}

void CGameView::OnTimer(UINT nIDEvent) 
{
	if( nIDEvent == INIT_CHESSINFO_TIMER )
	{
		KillTimer(nIDEvent);

		InitChessInfo();
	}

	CView::OnTimer(nIDEvent);
}

int CGameView::CheckValidPosition(int nSrcIndex, int nDestIndex)
{
	return 1;
}

int CGameView::GetRelativePosition(int nMyDirection,int nAbsDirection)
{
	if(nAbsDirection < nMyDirection)
	{
		nAbsDirection += MAX_DIRECTION;
	}
	
	return (nAbsDirection - nMyDirection);
}

int CGameView::TranslateChessIndex(int nChessIndex, int nChessColor)
{
	int nRetChessIndex = nChessIndex;
	
	int nMyColor = m_nMyColor;
	
	if(nChessColor == nMyColor)	//It is my side
	{
		nRetChessIndex = nChessIndex;
	}
	else
	{
		nRetChessIndex = (TOTAL_POINTS - 1) - nChessIndex;
	}

	return nRetChessIndex;
}

BOOL CGameView::IsCallSan(int nChessIndex, int nChessColor)
{
	if( (INVALID_INDEX == nChessIndex) || (NO_COLOR == nChessColor) ) return FALSE;

	const int nLinePoints = LINE_POINTS;
	int nColIndex = nChessIndex/nLinePoints;
	int nRowIndex = nChessIndex - (nColIndex * nLinePoints);

	
	return FALSE;
}

BOOL CGameView::Connect(CString strServerName,int intPort)
{
	WSADATA wsaData;	
	
	if(WSAStartup(WINSOCK_VERSION,&wsaData))
	{
		MessageBox("Could not load Windows Sockets DLL.",NULL,MB_OK);

		return FALSE;
	}
	
	CString strIPAddress = strServerName;
	struct hostent *hp = NULL;
	
	if(isalpha( int(strServerName.GetAt(0)) )) {
		// server address is a name 
		hp = gethostbyname(strIPAddress);

		if(hp == NULL)
		{
			ReportWinsockErr("Cannot resolve the Address!!");

			return FALSE;
		}
		else
		{
			struct in_addr *ip = (struct in_addr *) hp->h_addr_list[0];
			strIPAddress.Format("%d.%d.%d.%d",
								ip->S_un.S_un_b.s_b1, 
								ip->S_un.S_un_b.s_b2,
								ip->S_un.S_un_b.s_b3,
								ip->S_un.S_un_b.s_b4);
		}
	}
	/*
	else { 
		// Convert nnn.nnn address to a usable one 
		DWORD dwAddr = inet_addr(strIPAddress);
		hp = gethostbyaddr((char *)&dwAddr,4,AF_INET);
	}
	*/
	

	/*
	SOCKADDR_IN server;
	memset(&server,0,sizeof(server));
	memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
	server.sin_family = hp->h_addrtype;
	server.sin_port = htons(intPort);
	///*/
	SOCKADDR_IN server;
	memset(&server,0,sizeof(server));
	server.sin_addr.s_addr = inet_addr(strIPAddress);
	server.sin_family = AF_INET;
	server.sin_port = htons(intPort);
	//////

	m_hSocket=socket(PF_INET,SOCK_STREAM,0);	
	if(m_hSocket == SOCKET_ERROR)
	{
		ReportWinsockErr("Create Socket error!!");

		return FALSE;
	}

	int nConnect=connect(m_hSocket,(LPSOCKADDR)&server,sizeof(server));
	if(nConnect == SOCKET_ERROR)
	{
		ReportWinsockErr("Connect failed! Maybe the Server does not exist.");

		return FALSE;
	}
	else
	{
		//MessageBox("Successfully connected Server!!",NULL,MB_OK);
	}

	int iErrorCode=WSAAsyncSelect(m_hSocket,m_hWnd,WM_SOCKET_EVENT,FD_READ|FD_CLOSE);
	if(iErrorCode==SOCKET_ERROR)
	{
		MessageBox("WSAAsyncSelect failed on socket",NULL,MB_OK);

		return FALSE;
	}

	return TRUE;
}
void CGameView::ReportWinsockErr(CString strErrorMsg)
{
	CString strTextOut("");
	strTextOut.Format("\nWinsock error %d: %s\n\n", WSAGetLastError(), strErrorMsg);
	MessageBeep(MB_ICONSTOP);
	MessageBox(strTextOut, AfxGetAppName(), MB_OK|MB_ICONSTOP);
	return;
}

BOOL CGameView::Send(CString strMessage)
{
	if(m_hSocket == INVALID_SOCKET)
	{
		CWaitCursor wait;
		if(!Connect(m_strServerName,m_intPort)) return FALSE;
		wait.Restore();
	}

	int nCharSend = send(m_hSocket,strMessage,strMessage.GetLength(),0);
	if(nCharSend==SOCKET_ERROR)
	{
		TRACE("Error occurred during send!!");

		return FALSE;
	}
	TRACE("Send Message ---> %s\n",strMessage);

	return TRUE;
}

//WM_SOCKET_EVENT
LRESULT CGameView::OnSocketEvent(WPARAM wParam,LPARAM lParam)
{
	return 0;	
}

void CGameView::run()
{
	while(m_bRunState)
	{
		Sleep(0);

		if(/**/ m_hRunThread)
		{
			SuspendThread(m_hRunThread);
		}
		if(!m_bRunState) break;

		/////Copy the message from a list...		

		//process the recv msg....
		
		///////
	}
}

void CGameView::OnBtStartGame()
{
	m_strRecordHistory = "";

	BOOL bReadyTo = TRUE;

}

void CGameView::OnBtLoadChessInfo()
{
}

void CGameView::CodeData(CString &strData,int nCode)
{	
	//-1: CONVERT_TXT_TO_MSG
	//1 CONVERT_MSG_TO_TXT
	int nMagicNumber = 32;
	int nKeyNumber = nMagicNumber*nCode;
	
	//Convert User Name
	char *szData = strData.GetBuffer(0);
	strData.ReleaseBuffer();
	int len = strlen(szData);
	for(int i=0; i<len; i++)
	{		
		if(szData[i] != '\n')
		{
			szData[i] = szData[i] + nKeyNumber;
		}
	}		
}

void CGameView::OnBtImpetratePeace()
{
	if(m_bPeaceAction) return;

	///////////////////////////////////////////////
	////////////////////////////////////////////////

	m_bPeaceAction = TRUE;
}

void CGameView::OnBtSurrender()
{
	int result = MessageBox("Do you really want to Do that?","Kill yourself??",MB_YESNO|MB_ICONQUESTION|MB_ICONEXCLAMATION);
	if(result == IDYES)
	{
		///////////////////////////////////////////////
		////////////////////////////////////////////////
	}
}

void CGameView::OnBtOpenFile()
{
	CFileDialog dlg(TRUE,NULL,NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST,
				//"War Files (*.war)|*.war|All Files (*.*)|*.*||");
				"War Files (*.war)|*.war||");
	if(dlg.DoModal() == IDOK)
	{
		CWaitCursor wait;

		CString strPathName = dlg.GetPathName();
		g_strFileName = strPathName;		

		InitChessInfo();

		LoadChessFile(g_strFileName);
		InvalidateGameRect();

		wait.Restore();
	}
}

void CGameView::OnBtPreviousStep()
{
	if(m_nCurStepCount == 0 || m_curStepPosition == NULL)
	{
		m_btGameButtons[1].EnableWindow(m_nCurStepCount != 0);

		return;
	}

	if(m_bOffLineControl)
	{
		m_btGameButtons[1].EnableWindow(m_nCurStepCount != 0);
		m_btGameButtons[2].EnableWindow(TRUE);

		//////////////////////////////////
		m_moveStepPosition = m_curStepPosition;
		POSITION pos = m_moveStepPosition;
		CString strChessMessage("");
		GetNextChessInfo(strChessMessage,pos);

		m_nCurStepCount--;
		if(m_nCurStepCount > 0)
		{
			//Only Get Previous position,will start from the previous positon
			CString strChessInfo= m_strChessInfoList.GetPrev(pos);
			////

			//Get the previous step Chess info...
			strChessInfo = "";
			POSITION oldPos = pos;		
			while(pos != NULL)
			{
				oldPos = pos;
				strChessInfo = m_strChessInfoList.GetPrev(pos);			
				
				//$MoveFromTo:SrcColor-DestColor:srcIndex-srcValue:destIndex-destValue#
				if(strChessInfo.Left(1) == "$")
				{
					break;
				}
			}
			//pos == NULL means that it is the first step, need not flash position
			if(pos != NULL && strChessInfo != "")
			{
			}		
			//////////////////////////////////		
			if(pos != NULL)
			{			
				m_curStepPosition = oldPos;
			}
		}	
			
		SetWindowTitle();

		////			
		InvalidateGameRect();
	}
}

void CGameView::OnBtNextStep()
{
	if(m_nCurStepCount == m_nTotalStepCount || m_curStepPosition == NULL)
	{
		m_btGameButtons[2].EnableWindow(m_nCurStepCount != m_nTotalStepCount);
		return;
	}
	
	if(m_bOffLineControl)
	{
		m_bOffLineControl = FALSE;
		m_btGameButtons[1].EnableWindow(TRUE);
		m_btGameButtons[2].EnableWindow(m_nCurStepCount != m_nTotalStepCount);

		SetTimer(OFFLINE_GETSTEPINFO_TIMER,0,NULL);
	}
}

void CGameView::ProcessBtNextStep(int nIDEvent)
{
	if(nIDEvent == OFFLINE_LOADFILE_TIMER)
	{
		//Init the Chess info
		KillTimer(nIDEvent);

		LoadChessFile(g_strFileName);
	}
	else if(nIDEvent == OFFLINE_GETSTEPINFO_TIMER)
	{
		//Get the every time move Chess info (from src to dest)
		KillTimer(nIDEvent);

		///*
		CString strChessMessage("");
		GetNextChessInfo(strChessMessage,TRUE);		
	}
	else if(nIDEvent == OFFLINE_MOVESTEP_TIMER)
	{
		//Move Chess Step by Step
		KillTimer(nIDEvent);

		if(m_curMoveChessPosition != NULL)
		{			
			CString strMoveChess = m_strMoveChessList.GetNext(m_curMoveChessPosition);			
			
			//Will Move Next Step
			SetTimer(nIDEvent,100,NULL);
			////
		}
		else
		{
			m_bOffLineControl = TRUE;
		}
	}
}

void CGameView::OnBtSaveChessInfo()
{
}

void CGameView::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here	
	ProcessDisconnect();

	m_tGameStatus = OFFLINE;
}

void CGameView::ProcessDisconnect(BOOL bManual /*=TRUE*/,
									  CString strComment /* = ""*/)
{
	if(m_hSocket != INVALID_SOCKET)
	{
		closesocket(m_hSocket);
		WSACleanup();

		m_hSocket = INVALID_SOCKET;
	}

	FreeWavRes();

	FlashChessAction(FALSE);
	FlashPositionAction(FALSE);

	if(m_hRunThread != NULL)
	{
		if(bManual)
		{
			m_bRunState = FALSE;
			ResumeThread(m_hRunThread);
			WaitForSingleObject(m_hRunThread,INFINITE);
			CloseHandle(m_hRunThread);
		}
		else
		{
			TerminateThread(m_hRunThread,0);
		}

		m_hRunThread = NULL;
	}

	if(!bManual)	//Server Shut Down
	{
		MessageBox(strComment,"Warning",MB_OK|MB_ICONSTOP);
	}


	InitControlData();
	m_bConnectToServer = FALSE;

	m_tGameStatus = OFFLINE;
	m_nTableID = 1;
	m_nPosition = INVALID_INDEX;

	InvalidateGameRect();

	ShowButtons(READY);

	//SetWindowText
	CString strText("");	
	strText.Format("[Game3Chess] -- [---]");
	::SetWindowText(AfxGetMainWnd()->m_hWnd,strText);
	//

	CWnd*	pMainWnd	=::AfxGetMainWnd();
	if(NULL != pMainWnd && ::IsWindow(pMainWnd->GetSafeHwnd())) 
	{
		pMainWnd->PostMessage(WM_CLOSE, 0, 0);
	}
}

BOOL CGameView::IsInGame()
{
	//In Game -> TRUE
	BOOL bInGame = ( (m_tGameStatus == PLAYING_PRE) || 
					 (m_tGameStatus == PLAYING_MOVE) );
	bInGame &= (!m_bOffLine);

	return bInGame;
}

////////////////////////////////////////////////////////////
void CGameView::LoadChessFile(CString strChessFile)
{
	BOOL bLoadSuc = TRUE;
	
	if(g_strFileName == "") return;
	strChessFile = g_strFileName;
		
	ifstream ism(strChessFile,ios::in|ios::binary);
	if(ism.is_open())
	{
		m_bOffLine = TRUE;
		m_strChessInfoList.RemoveAll();
		m_curStepPosition = NULL;
		m_moveStepPosition = NULL;
				
		m_nTotalStepCount = 0;
		m_nCurStepCount = 0;

		m_tGameStatus = OFFLINE;
		KillTimer(TOKEN_ORDER_TIMER);
		m_bPreSelChess = FALSE;
		InitControlData();

		const int iDataLen = 256;
		char szDataBuf[iDataLen];
		while(!ism.eof())
		{
			ism.getline(szDataBuf,iDataLen);
			int len = strlen(szDataBuf);

			////
			CString strData = (CString)szDataBuf;
			CodeData(strData,1);
			////

			if(len > 4 && strData.Right(1) == "#")
			{
				m_strChessInfoList.AddTail(strData);

				if(strData.Left(1) == "$") m_nTotalStepCount++;
			}
			else if(strData == "")
			{
				bLoadSuc = TRUE;

				continue;
			}
			else
			{
				bLoadSuc = FALSE;

				break;
			}
		}

		ism.close();
	}
	else
	{	
		bLoadSuc = FALSE;
		MessageBox("The file can not be opened.Maybe the file does not exist!","Warning",MB_OK|MB_ICONSTOP);
		return;
	}	

	if(!bLoadSuc)
	{
		m_bOffLine = FALSE;
		MessageBox("The file can not be loaded.Maybe the file type is not right!","Warning",MB_OK|MB_ICONSTOP);

		return;
	}

	m_curStepPosition = m_strChessInfoList.GetHeadPosition();	
	m_moveStepPosition = m_curStepPosition;
	

	////Init the Chess data(Load Chess data,show user...),
	//and set m_curStepPosition, prepare to do move Chess...
	CString strChessMessage("");
	GetNextChessInfo(strChessMessage,FALSE);
	if(strChessMessage != "")
	{
		m_tGameStatus = PLAYING_MOVE;
		m_bOffLineControl = TRUE;

		InvalidateGameRect();

		SetWindowTitle();

		//Set the Order(flash the order icon)
		m_bTakenOrderOnOff = TRUE;
		SetTimer(TOKEN_ORDER_TIMER,1000,NULL);
		InvalidateGameRect();
		////

		m_btGameButtons[1].EnableWindow(m_nCurStepCount != 0);
		m_btGameButtons[2].EnableWindow(m_nCurStepCount != m_nTotalStepCount);
		m_btGameButtons[3].EnableWindow(TRUE);
	}
	////////
}

void CGameView::GetNextChessInfo(CString &strChessMessage, BOOL bMoveChess)
{
	strChessMessage = "";

	if(m_nCurStepCount != 0 && m_nCurStepCount == m_nTotalStepCount) return;
	
	CString strChessInfo("#");
	
	if(!bMoveChess)
	{
		POSITION oldPos = m_curStepPosition;
	
		//Get the header info,will load Chess info and show user name
		//And Set m_curStepPosition...
		while(strChessInfo.Left(1) != "$" && m_curStepPosition != NULL)
		{
			oldPos = m_curStepPosition;

			strChessInfo = m_strChessInfoList.GetNext(m_curStepPosition);

			if(strChessInfo.Left(1) != "$") 
			{
				strChessMessage += strChessInfo;
			}
		}
		m_curStepPosition = oldPos;
		m_moveStepPosition = m_curStepPosition;
	}
	else
	{
		//Get the next step info...
		m_curStepPosition = m_moveStepPosition;

		POSITION pos = m_curStepPosition;
		POSITION oldPos = pos;
		CString strFirstStepInfo = m_strChessInfoList.GetNext(pos);
		strChessMessage += strFirstStepInfo;

		if(pos != NULL)
		{
			do
			{
				oldPos = pos;
				strChessInfo = m_strChessInfoList.GetNext(pos);
				
				if(strChessInfo.Left(1) != "$") 
				{
					strChessMessage += strChessInfo;
				}
			}while(strChessInfo.Left(1) != "$" && pos != NULL);
		}
		m_moveStepPosition = oldPos;
		////
	}

	//Invalidate format
	int len = strChessMessage.GetLength();
	if(len > MAX_BUFLEN-32 || strChessMessage.FindOneOf("$#:+\r") == -1)
	{
		strChessMessage = "";

		if(!bMoveChess)
		{
			m_strChessInfoList.RemoveAll();
			m_curStepPosition = NULL;			
		}
	}
	////
}

void CGameView::GetNextChessInfo(CString &strChessMessage, POSITION &curPos)
{
	strChessMessage = "";

	//Get the next step info...
	POSITION pos = curPos;	
	CString strChessInfo("#");

	CString strFirstStepInfo = m_strChessInfoList.GetNext(pos);
	strChessMessage += strFirstStepInfo;

	while(strChessInfo.Left(1) != "$" && pos != NULL)
	{
		strChessInfo = m_strChessInfoList.GetNext(pos);

		if(strChessInfo.Left(1) != "$") 
		{
			strChessMessage += strChessInfo;
		}
	}

	//Invalidate format
	int len = strChessMessage.GetLength();
	if(len > MAX_BUFLEN-32 || strChessMessage.FindOneOf("$#:+\r") == -1)
	{
		strChessMessage = "";
	}
	////
}

////////////////////////////////////////////////////////////