Source code of Windows XP (NT5)
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

/*************************************************
* 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);
}