mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
535 lines
11 KiB
535 lines
11 KiB
|
|
/*************************************************
|
|
* blockvw.cpp *
|
|
* *
|
|
* Copyright (C) 1995-1999 Microsoft Inc. *
|
|
* *
|
|
*************************************************/
|
|
|
|
// blockview.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "cblocks.h"
|
|
#include "dib.h"
|
|
#include "dibpal.h"
|
|
#include "spriteno.h"
|
|
#include "sprite.h"
|
|
#include "phsprite.h"
|
|
#include "myblock.h"
|
|
#include "splstno.h"
|
|
#include "spritlst.h"
|
|
#include "osbview.h"
|
|
#include "slot.h"
|
|
#include "about.h"
|
|
#include "blockvw.h"
|
|
#include "blockdoc.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBlockView
|
|
|
|
IMPLEMENT_DYNCREATE(CBlockView, COSBView)
|
|
|
|
|
|
int GSpeed=SPEED_SLOW;
|
|
BOOL m_bTimer2;
|
|
BOOL m_bShowTip;
|
|
|
|
CString GHint="";
|
|
CBlockView::CBlockView()
|
|
{
|
|
m_bMouseCaptured = FALSE;
|
|
m_pCapturedSprite = NULL;
|
|
m_uiTimer = 0;
|
|
m_iSpeed = 0;
|
|
m_bStart = FALSE;
|
|
m_bSuspend = FALSE;
|
|
m_bShowTip = FALSE;
|
|
m_bFocusWnd = TRUE;
|
|
|
|
}
|
|
|
|
CBlockView::~CBlockView()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CBlockView, COSBView)
|
|
//{{AFX_MSG_MAP(CBlockView)
|
|
ON_WM_CREATE()
|
|
ON_WM_DESTROY()
|
|
ON_WM_TIMER()
|
|
ON_COMMAND(ID_ACTION_FAST, OnActionFast)
|
|
ON_COMMAND(ID_ACTION_SLOW, OnActionSlow)
|
|
ON_COMMAND(ID_ACTION_STOP, OnActionStop)
|
|
ON_COMMAND(ID_FILE_START, OnFileStart)
|
|
ON_COMMAND(ID_FILE_SUSPEND, OnFileSuspend)
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_SUSPEND, OnUpdateFileSuspend)
|
|
ON_WM_CHAR()
|
|
ON_UPDATE_COMMAND_UI(ID_ACTION_FAST, OnUpdateActionFast)
|
|
ON_UPDATE_COMMAND_UI(ID_ACTION_SLOW, OnUpdateActionSlow)
|
|
ON_COMMAND(ID_ACTION_NORMAL, OnActionNormal)
|
|
ON_UPDATE_COMMAND_UI(ID_ACTION_NORMAL, OnUpdateActionNormal)
|
|
ON_COMMAND(ID_ACTION_NORMALFAST, OnActionNormalfast)
|
|
ON_UPDATE_COMMAND_UI(ID_ACTION_NORMALFAST, OnUpdateActionNormalfast)
|
|
ON_UPDATE_COMMAND_UI(ID_ACTION_NORMALSLOW, OnUpdateActionNormalslow)
|
|
ON_COMMAND(ID_ACTION_NORMALSLOW, OnActionNormalslow)
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MENUSELECT()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_SETFOCUS()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBlockView drawing
|
|
|
|
void CBlockView::OnInitialUpdate()
|
|
{
|
|
COSBView::OnInitialUpdate();
|
|
|
|
m_bStart = FALSE;
|
|
m_bSuspend = FALSE;
|
|
|
|
|
|
}
|
|
|
|
void CBlockView::OnDraw(CDC* pDC)
|
|
{
|
|
COSBView::OnDraw(pDC);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBlockView message handlers
|
|
|
|
// Create a new buffer and palette to match a new
|
|
// background DIB
|
|
BOOL CBlockView::NewBackground(CDIB* pDIB)
|
|
{
|
|
// Create a new buffer and palette
|
|
if (!Create(pDIB)) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Map the colors of the background DIB to
|
|
// the identity palette we just created for the background
|
|
pDIB->MapColorsToPalette(GetPalette());
|
|
|
|
// Resize the main frame window to fit the background image
|
|
GetParentFrame()->RecalcLayout();
|
|
if ((GetVersion() & 0x80000000) == 0)
|
|
{
|
|
ResizeParentToFit(FALSE); // Try shrinking first
|
|
ResizeParentToFit(TRUE); // Let's be daring
|
|
}
|
|
else
|
|
{
|
|
|
|
Resize(FALSE); // Try shrinking first
|
|
Resize(TRUE); // Let's be daring
|
|
}
|
|
// Render the entire scene to the off-screen buffer
|
|
Render();
|
|
|
|
// Paint the off-screen buffer to the window
|
|
Draw();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Render the scene to the off-screen buffer
|
|
// pClipRect defaults to NULL
|
|
void CBlockView::Render(CRect* pClipRect)
|
|
{
|
|
CBlockDoc* pDoc = GetDocument();
|
|
CRect rcDraw;
|
|
|
|
// get the background DIB and render it
|
|
CDIB* pDIB = pDoc->GetBackground();
|
|
if (pDIB) {
|
|
pDIB->GetRect(&rcDraw);
|
|
// If a clip rect was supplied use it
|
|
if (pClipRect) {
|
|
rcDraw.IntersectRect(pClipRect, &rcDraw);
|
|
}
|
|
|
|
// draw the image of the DIB to the os buffer
|
|
ASSERT(m_pDIB);
|
|
pDIB->CopyBits(m_pDIB,
|
|
rcDraw.left,
|
|
rcDraw.top,
|
|
rcDraw.right - rcDraw.left,
|
|
rcDraw.bottom - rcDraw.top,
|
|
rcDraw.left,
|
|
rcDraw.top);
|
|
}
|
|
|
|
// Render the sprite list from the bottom of the list to the top
|
|
// Note that we always clip to the background DIB
|
|
CSpriteList* pList = pDoc->GetSpriteList();
|
|
POSITION pos = pList->GetTailPosition();
|
|
CSprite *pSprite;
|
|
while (pos) {
|
|
pSprite = pList->GetPrev(pos);
|
|
pSprite->Render(m_pDIB, &rcDraw);
|
|
}
|
|
}
|
|
|
|
// A new sprite has been added to the document
|
|
void CBlockView::NewSprite(CSprite* pSprite)
|
|
{
|
|
// map the colors in the sprite DIB to the
|
|
// palette in the off-screen buffered view
|
|
if (m_pPal) {
|
|
pSprite->MapColorsToPalette(m_pPal);
|
|
}
|
|
|
|
// Render the scene
|
|
// Render();
|
|
|
|
// Draw the new scene to the screen
|
|
// Draw();
|
|
}
|
|
|
|
|
|
int CBlockView::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (COSBView::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
void CBlockView::OnDestroy()
|
|
{
|
|
if (m_uiTimer) {
|
|
KillTimer(1);
|
|
m_uiTimer = 0;
|
|
}
|
|
if (m_bTimer2)
|
|
{
|
|
VERIFY(KillTimer(2));
|
|
m_bTimer2 = 0;
|
|
}
|
|
|
|
COSBView::OnDestroy();
|
|
}
|
|
|
|
void CBlockView::OnActionStop()
|
|
{
|
|
SetSpeed(0);
|
|
}
|
|
|
|
void CBlockView::SetSpeed(int iSpeed)
|
|
{
|
|
// Stop the current timer
|
|
if (m_uiTimer) {
|
|
KillTimer(1);
|
|
m_uiTimer = 0;
|
|
}
|
|
// Stop idle loop mode
|
|
CBlockApp* pApp = (CBlockApp*) AfxGetApp();
|
|
pApp->SetIdleEvent(NULL);
|
|
m_iSpeed = iSpeed;
|
|
if (iSpeed == 0) return;
|
|
if (iSpeed > 0) {
|
|
m_uiTimer = (UINT)SetTimer(1, iSpeed, NULL);
|
|
return;
|
|
}
|
|
// Set up idle loop mode
|
|
//pApp->SetIdleEvent(this);
|
|
}
|
|
|
|
|
|
void CBlockView::OnFileStart()
|
|
{
|
|
AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND,ID_FILE_NEW);
|
|
SetSpeed(GSpeed);
|
|
m_bStart = TRUE;
|
|
}
|
|
|
|
void CBlockView::GameOver(BOOL bHighScore)
|
|
{
|
|
SetSpeed(0);
|
|
m_bStart = FALSE;
|
|
if (bHighScore)
|
|
{
|
|
CString szMsg1,szMsg2;
|
|
szMsg1.LoadString(IDS_SUPERMAN);
|
|
szMsg2.LoadString(IDS_BLOCK);
|
|
MessageBox(szMsg1,szMsg2,MB_OK);
|
|
}
|
|
}
|
|
|
|
void CBlockView::OnUpdateFileSuspend(CCmdUI* pCmdUI)
|
|
{
|
|
CString szMsg;
|
|
/*
|
|
if (m_bSuspend)
|
|
szMsg.LoadString(IDS_RESUME);
|
|
else
|
|
szMsg.LoadString(IDS_SUSPEND);
|
|
|
|
pCmdUI->SetText((const char *) szMsg);
|
|
*/
|
|
pCmdUI->Enable(m_bStart);
|
|
pCmdUI->SetCheck(m_bSuspend);
|
|
}
|
|
|
|
void CBlockView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
static BYTE wCode[2];
|
|
static BOOL bGetNext = FALSE;
|
|
|
|
if (m_bStart)
|
|
{
|
|
if (bGetNext)
|
|
{
|
|
wCode[1] = (BYTE) nChar;
|
|
bGetNext = FALSE;
|
|
GetDocument()->Hit(MAKEWORD(wCode[1],wCode[0]));
|
|
}
|
|
else if (IsDBCSLeadByte((BYTE)nChar))
|
|
{
|
|
wCode[0] = (BYTE) nChar;
|
|
bGetNext = TRUE;
|
|
}
|
|
}
|
|
COSBView::OnChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CBlockView::OnActionFast()
|
|
{
|
|
GSpeed = SPEED_FAST;
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
}
|
|
|
|
void CBlockView::OnActionNormalfast()
|
|
{
|
|
GSpeed = SPEED_NORMALFAST;
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
|
|
}
|
|
void CBlockView::OnActionNormal()
|
|
{
|
|
GSpeed = SPEED_NORMAL;
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
|
|
}
|
|
|
|
void CBlockView::OnActionNormalslow()
|
|
{
|
|
GSpeed = SPEED_NORMALSLOW;
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
}
|
|
|
|
void CBlockView::OnActionSlow()
|
|
{
|
|
GSpeed = SPEED_SLOW;
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
}
|
|
|
|
void CBlockView::OnUpdateActionFast(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(GSpeed == SPEED_FAST ? 1 : 0);
|
|
}
|
|
|
|
void CBlockView::OnUpdateActionNormalfast(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(GSpeed == SPEED_NORMALFAST ? 1 : 0);
|
|
}
|
|
|
|
void CBlockView::OnUpdateActionNormal(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(GSpeed == SPEED_NORMAL ? 1 : 0);
|
|
|
|
|
|
}
|
|
|
|
void CBlockView::OnUpdateActionNormalslow(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(GSpeed == SPEED_NORMALSLOW ? 1 : 0);
|
|
|
|
}
|
|
|
|
void CBlockView::OnUpdateActionSlow(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(GSpeed == SPEED_SLOW ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
void CBlockView::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
COSBView::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CBlockView::OnMenuSelect( UINT nItemID, UINT nFlag, HMENU hMenu )
|
|
{
|
|
if ((nFlag == 0xFFFF) && (hMenu == NULL))
|
|
{
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
}
|
|
else
|
|
{
|
|
if (GSpeed != 0)
|
|
SetSpeed(0);
|
|
}
|
|
UNREFERENCED_PARAMETER(nItemID);
|
|
}
|
|
|
|
CPoint m_ptLoc;
|
|
int m_nCount=0;
|
|
|
|
|
|
void CBlockView::OnFileSuspend()
|
|
{
|
|
LONG_PTR hOldCur=0;
|
|
m_bSuspend = !m_bSuspend;
|
|
if (m_bSuspend)
|
|
{
|
|
SetSpeed(0);
|
|
m_nCount = 0;
|
|
VERIFY(m_bTimer2 = (INT)SetTimer(2, 300, NULL));
|
|
hOldCur = (LONG_PTR)GetClassLongPtr(GetSafeHwnd(),GCLP_HCURSOR);
|
|
SetClassLongPtr(GetSafeHwnd(),GCLP_HCURSOR,(LONG_PTR)AfxGetApp()->LoadCursor(IDC_HAND_CBLOCK));
|
|
}
|
|
else
|
|
{
|
|
SetSpeed(GSpeed);
|
|
VERIFY(KillTimer(2));
|
|
m_bTimer2 = 0;
|
|
SetClassLongPtr(GetSafeHwnd(),GCLP_HCURSOR,(LONG_PTR)hOldCur);
|
|
}
|
|
}
|
|
|
|
void CBlockView::OnTimer(UINT nIDEvent)
|
|
{
|
|
|
|
switch (nIDEvent)
|
|
{
|
|
case 1:
|
|
{
|
|
if (! m_bFocusWnd)
|
|
GetDocument()->UpdateAllViews(NULL);
|
|
GetDocument()->Tick();
|
|
int i = 0;
|
|
POSITION pos;
|
|
CBlock *pBlock;
|
|
CBlockDoc* pDoc = GetDocument();
|
|
CSpriteList* pspList = pDoc->GetSpriteList();
|
|
if (pspList->IsEmpty()) return; // no sprites
|
|
// update the position of each sprite
|
|
for (pos = pspList->GetHeadPosition(); pos != NULL;)
|
|
{
|
|
pBlock = (CBlock *)pspList->GetNext(pos);
|
|
ASSERT(pBlock->IsKindOf(RUNTIME_CLASS(CBlock)));
|
|
i += pBlock->UpdatePosition(pDoc);
|
|
GetDocument()->Land();
|
|
}
|
|
if (i) {
|
|
// draw the changes
|
|
RenderAndDrawDirtyList();
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
if (! m_bSuspend)
|
|
break;
|
|
m_nCount++;
|
|
if (m_nCount >= 2)
|
|
{
|
|
if (!m_bShowTip)
|
|
{
|
|
WORD wCode = GetDocument()->GetFocusChar(m_ptLoc);
|
|
if (wCode)
|
|
{
|
|
if (! GetDocument()->GetKeyStroke(wCode))
|
|
{
|
|
char szBuf[6];
|
|
wsprintf(szBuf,"%X",wCode);
|
|
GHint = CString(szBuf);
|
|
}
|
|
m_bShowTip = TRUE;
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_bShowTip)
|
|
{
|
|
GHint = "";
|
|
m_bShowTip = FALSE;
|
|
AfxGetApp()->OnIdle(RANK_USER);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
UNREFERENCED_PARAMETER(nIDEvent);
|
|
}
|
|
|
|
|
|
void CBlockView::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bSuspend)
|
|
{
|
|
if (m_ptLoc != point)
|
|
{
|
|
m_ptLoc = point;
|
|
m_nCount = 0;
|
|
}
|
|
}
|
|
COSBView::OnMouseMove(nFlags,point);
|
|
UNREFERENCED_PARAMETER(nFlags);
|
|
}
|
|
|
|
void CBlockView::OnAppAbout()
|
|
{
|
|
CString szAppName;
|
|
szAppName.LoadString(IDS_BLOCK);
|
|
ShellAbout(GetSafeHwnd(),szAppName,TEXT(""), AfxGetApp()->LoadIcon(IDR_MAINFRAME));
|
|
if (m_bStart && !m_bSuspend)
|
|
SetSpeed(GSpeed);
|
|
|
|
}
|
|
|
|
void CBlockView::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
COSBView::OnKillFocus(pNewWnd);
|
|
m_bFocusWnd = FALSE;
|
|
}
|
|
|
|
void CBlockView::OnSetFocus(CWnd* pOldWnd)
|
|
{
|
|
COSBView::OnSetFocus(pOldWnd);
|
|
// because there is a gap between next time tick,
|
|
// so force update veiw first.
|
|
GetDocument()->UpdateAllViews(NULL);
|
|
m_bFocusWnd = TRUE;
|
|
}
|
|
|
|
void CBlockView::ForceSpeed(int nSpeed)
|
|
{
|
|
if (m_bSuspend || !m_bStart)
|
|
return;
|
|
SetSpeed(nSpeed);
|
|
}
|