www.pudn.com > mmxswarm.zip > ChildView.cpp
// ChildView.cpp : implementation of the CChildView class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
//
#include "stdafx.h"
#include "MMXSwarm.h"
#include "ChildView.h"
#include "MMXSurface.h"
#include "SSE2Surface.h"
#include "Swarm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChildView
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_SETCURSOR()
ON_WM_TIMER()
ON_WM_SIZE()
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
ON_COMMAND(ID_VIEW_PAUSE_BLUR, OnViewPauseBlur)
ON_COMMAND(ID_VIEW_PAUSE_SWARM, OnViewPauseSwarm)
ON_COMMAND(ID_VIEW_PAUSE_BLIT, OnViewPauseBlit)
ON_UPDATE_COMMAND_UI(ID_VIEW_PAUSE_BLUR, OnUpdatePauseBlur)
ON_UPDATE_COMMAND_UI(ID_VIEW_PAUSE_SWARM, OnUpdatePauseSwarm)
ON_UPDATE_COMMAND_UI(ID_VIEW_PAUSE_BLIT, OnUpdatePauseBlit)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAUSE_BLUR, OnUpdatePauseBlur)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAUSE_SWARM, OnUpdatePauseSwarm)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAUSE_BLIT, OnUpdatePauseBlit)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_FPS, OnUpdateFPS)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_RESOLUTION, OnUpdateResolution)
ON_COMMAND_RANGE(IDD_16BIT_MMXINTRINSICS, IDD_32BIT_GENERICCBLUR, OnImageFormats)
ON_UPDATE_COMMAND_UI_RANGE(IDD_16BIT_MMXINTRINSICS, IDD_32BIT_GENERICCBLUR, OnUpdateImageFormats)
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
END_MESSAGE_MAP()
CChildView::CChildView()
{
m_pSurface = NULL;
m_dwTickStart = ::GetTickCount();
m_nFrameCounter = 0;
m_nFilterLoad = 0;
m_nFilterSave = 0;
m_bSizeChanged = false;
m_bPauseBlur = false;
m_bPauseSwarm = false;
m_bPauseBlit = false;
m_bTimerPopped = false;
m_eSurf = eNone;
}
CChildView::~CChildView()
{
delete m_pSurface;
}
/////////////////////////////////////////////////////////////////////////////
// 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::OnFileOpen()
{
CImage image;
CString strFilter;
CString strAllFilePrompt;
CSimpleArray aguidFileTypes;
HRESULT hResult;
INT_PTR nResult;
if (m_pSurface == NULL)
return;
VERIFY(strAllFilePrompt.LoadString(IDS_ALL_IMAGES));
hResult = image.GetImporterFilterString(strFilter, aguidFileTypes, strAllFilePrompt);
if(FAILED(hResult)) {
CString fmt;
fmt.Format(IDS_ERROR_GETEXPORTERFILTER, hResult, _com_error(hResult).ErrorMessage());
::AfxMessageBox(fmt);
return;
}
CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
dlg.m_ofn.nFilterIndex = m_nFilterLoad;
nResult = dlg.DoModal();
if(nResult != IDOK) {
return;
}
m_nFilterLoad = dlg.m_ofn.nFilterIndex;
hResult = image.Load(dlg.GetFileName());
ASSERT(SUCCEEDED(hResult));
if (SUCCEEDED(hResult)) {
m_pSurface->Import(image);
// Stop the weird effects
m_bPauseBlur = true;
m_bPauseSwarm = true;
}
}
void CChildView::OnFileSave()
{
CString strFilter;
CSimpleArray aguidFileTypes;
CImage *pImage;
CString fmt;
HRESULT hResult;
INT_PTR nResult;
pImage = m_pSurface->GetImage();
ASSERT(pImage != NULL);
hResult = pImage->GetExporterFilterString( strFilter, aguidFileTypes );
if(FAILED(hResult)) {
fmt.Format(IDS_ERROR_GETEXPORTERFILTER, hResult, _com_error(hResult).ErrorMessage());
::AfxMessageBox(fmt);
return;
}
CFileDialog dlg(FALSE, NULL, NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
dlg.m_ofn.nFilterIndex = m_nFilterSave;
nResult = dlg.DoModal();
if( nResult != IDOK ) {
return;
}
m_nFilterSave = dlg.m_ofn.nFilterIndex;
GUID guid = m_nFilterSave > 0 ? aguidFileTypes[m_nFilterSave-1] : GUID(GUID_NULL);
CString strFileName = dlg.GetPathName();
if (dlg.GetFileExt().IsEmpty()) {
if (strFileName[strFileName.GetLength()-1] == '.') {
strFileName = strFileName.Left(strFileName.GetLength()-1);
}
CString strExt;
if (m_nFilterSave == 0) {
strExt = _T(".jpg"); // default to JPEG
}
else {
// Look up the first extension in the filters
int nCount = (m_nFilterSave*2)-1;
int nLeft = 0;
while (nCount) {
if (strFilter[nLeft++] == '|') {
nCount--;
}
}
ASSERT(nLeft < strFilter.GetLength());
strExt = strFilter.Tokenize(_T(";|"), nLeft).MakeLower();
strExt = ::PathFindExtension(strExt);
}
strFileName += strExt;
}
hResult = pImage->Save(strFileName, guid);
if(FAILED(hResult)) {
fmt.Format(IDS_ERROR_SAVE, hResult, _com_error(hResult).ErrorMessage());
::AfxMessageBox(fmt);
}
}
void CChildView::OnImageFormats(UINT nID)
{
ASSERT((nID >= IDD_16BIT_MMXINTRINSICS) && (nID <= IDD_32BIT_GENERICCBLUR));
m_eSurf = ESurface(nID);
CreateSurface();
}
void CChildView::OnViewPauseBlur()
{
m_bPauseBlur = !m_bPauseBlur;
}
void CChildView::OnViewPauseSwarm()
{
m_bPauseSwarm = !m_bPauseSwarm;
}
void CChildView::OnViewPauseBlit()
{
m_bPauseBlit = !m_bPauseBlit;
}
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Do not call CWnd::OnPaint() for painting messages
if (m_pSurface != NULL)
m_pSurface->BlitBits();
}
BOOL CChildView::OnIdle(LONG /*lCount*/)
{
BOOL bContinue = FALSE;
if (m_pSurface == NULL)
return(FALSE);
// Debugging helper for blur
// m_pSurface->Line(CPoint(160, 120), CPoint(160, 0), RGB(255, 128, 128));
// m_pSurface->Line(CPoint(80, 60), CPoint(240, 60), RGB(128, 128, 255));
if (::GetAsyncKeyState(VK_SHIFT) & 0x8000) {
m_pSurface->RandomLine((int)Random() << 15 | Random());
bContinue = TRUE;
}
if (::GetAsyncKeyState(VK_DELETE) & 0x8000) {
m_pSurface->ClearBits();
bContinue = TRUE;
}
if (::GetAsyncKeyState(VK_SPACE) & 0x8000) {
m_pSurface->RandomBits();
bContinue = TRUE;
}
if (::GetAsyncKeyState(VK_UP) & 0x8000) {
m_pSurface->ShiftBits();
bContinue = TRUE;
}
// The guts...
if (!m_bPauseBlur) {
m_pSurface->BlurBits();
bContinue = TRUE;
}
if (!m_bPauseSwarm) {
m_swarm.Tick();
bContinue = TRUE;
}
if (bContinue) {
m_nFrameCounter++;
if (!m_bPauseBlit) {
m_pSurface->BlitBits();
}
}
::GdiFlush();
return(bContinue);
}
BOOL CChildView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// Add your message handler code here and/or call default
if (nHitTest == HTCLIENT) {
SetCursor(LoadCursor(NULL, IDC_CROSS));
return(TRUE);
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
void CChildView::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (m_hWnd && cx && cy) {
TRACE("OnSize: width == %d, height == %d\n", cx, cy);
// Initialize screen format
// First time init with an hwnd
if (m_eSurf == eNone) {
CClientDC dc(this);
int pixels;
bool bWarnDepth = false;
bool bWarnDebug = false;
SetTimer(m_kTimerID, m_kTimerDelay, NULL);
pixels = dc.GetDeviceCaps(BITSPIXEL) * dc.GetDeviceCaps(PLANES);
switch (pixels) {
case 16:
m_eSurf = IsSSE2() ? e16BitSSE2Intrin :
IsMMX() ? e16BitMMXIntrin : e16BitGeneric;
break;
case 24:
m_eSurf = IsSSE2() ? e24BitSSE2Intrin :
IsMMX() ? e24BitMMXIntrin : e24BitGeneric;
break;
case 32:
m_eSurf = IsSSE2() ? e32BitSSE2Intrin :
IsMMX() ? e32BitMMXIntrin : e32BitGeneric;
break;
default:
bWarnDepth = true;
m_eSurf = IsSSE2() ? e32BitSSE2Intrin :
IsMMX() ? e32BitMMXIntrin : e32BitGeneric;
break;
}
#ifdef _DEBUG
bWarnDebug = true;
#endif
if (bWarnDepth || bWarnDebug) {
CString fmt;
if (bWarnDepth) {
fmt.LoadString(IDS_WARNING_BITDEPTH);
}
if (bWarnDepth && bWarnDebug) {
fmt += "\n";
}
if (bWarnDebug) {
CString temp;
temp.LoadString(IDS_WARNING_DEBUG);
fmt += temp;
}
::AfxMessageBox(fmt, MB_ICONINFORMATION);
}
}
m_bSizeChanged = true;
CreateSurface();
}
}
void CChildView::CreateSurface()
{
int nBits = 0;
delete m_pSurface;
m_pSurface = NULL;
switch (m_eSurf) {
case e16BitSSE2Intrin:
nBits = 16;
m_pSurface = new CSSE2Surface16Intrinsic();
break;
case e16BitMMXIntrin:
nBits = 16;
m_pSurface = new CMMXSurface16Intrinsic();
break;
case e16BitGeneric:
nBits = 16;
m_pSurface = new CSurface();
break;
case e24BitSSE2Intrin:
nBits = 24;
m_pSurface = new CSSE2Surface24Intrinsic();
break;
case e24BitMMXIntrin:
nBits = 24;
m_pSurface = new CMMXSurface24Intrinsic();
break;
case e24BitGeneric:
nBits = 24;
m_pSurface = new CSurface();
break;
case e32BitSSE2Intrin:
nBits = 32;
m_pSurface = new CSSE2Surface32Intrinsic();
break;
case e32BitMMXIntrin:
nBits = 32;
m_pSurface = new CMMXSurface32Intrinsic();
break;
case e32BitGeneric:
nBits = 32;
m_pSurface = new CSurface();
break;
default:
ASSERT(FALSE);
break;
}
ASSERT(m_pSurface != NULL);
m_pSurface->Create(this, nBits);
m_pSurface->ClearBits();
CRect cRect;
GetClientRect(&cRect);
int numLeaders = max(2, (cRect.Width()*cRect.Height())>>16);
int numLlamas = numLeaders*35;
m_swarm.Initialize(m_pSurface, numLeaders, numLlamas, cRect.Size());
}
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
nIDEvent;
ASSERT(nIDEvent == m_kTimerID);
// This only exists to kick the UI handler for fps.
m_bTimerPopped = true;
}
void CChildView::OnUpdateFPS(CCmdUI* pCmdUI)
{
if (!m_bTimerPopped) // Only update on regular intervals
return;
DWORD dwStop = max(m_dwTickStart+1, ::GetTickCount());
CString fmt;
fmt.Format(_T("%d fps"), (m_nFrameCounter*1000L)/(dwStop-m_dwTickStart));
m_nFrameCounter = 0;
m_bTimerPopped = false;
m_dwTickStart = dwStop;
pCmdUI->SetText(fmt);
pCmdUI->Enable(TRUE);
}
void CChildView::OnUpdatePauseBlur(CCmdUI* pCmdUI)
{
if (pCmdUI->m_nID == ID_INDICATOR_PAUSE_BLUR) {
pCmdUI->Enable(m_bPauseBlur ? FALSE : TRUE);
}
else {
ASSERT(pCmdUI->m_nID == ID_VIEW_PAUSE_BLUR);
pCmdUI->SetCheck(m_bPauseBlur ? 1 : 0);
pCmdUI->Enable(TRUE);
}
}
void CChildView::OnUpdatePauseSwarm(CCmdUI* pCmdUI)
{
if (pCmdUI->m_nID == ID_INDICATOR_PAUSE_SWARM) {
pCmdUI->Enable(m_bPauseSwarm ? FALSE : TRUE);
}
else {
ASSERT(pCmdUI->m_nID == ID_VIEW_PAUSE_SWARM);
pCmdUI->SetCheck(m_bPauseSwarm ? 1 : 0);
pCmdUI->Enable(TRUE);
}
}
void CChildView::OnUpdatePauseBlit(CCmdUI* pCmdUI)
{
if (pCmdUI->m_nID == ID_INDICATOR_PAUSE_BLIT) {
pCmdUI->Enable(m_bPauseBlit ? FALSE : TRUE);
}
else {
ASSERT(pCmdUI->m_nID == ID_VIEW_PAUSE_BLIT);
pCmdUI->SetCheck(m_bPauseBlit ? 1 : 0);
pCmdUI->Enable(TRUE);
}
}
void CChildView::OnUpdateResolution(CCmdUI* pCmdUI)
{
if (m_bSizeChanged) {
CString str;
str.Format(_T("%dx%d"), m_pSurface->GetVisibleWidth(), m_pSurface->GetVisibleHeight());
pCmdUI->SetText(str);
m_bSizeChanged = false;
}
pCmdUI->Enable(TRUE);
}
void CChildView::OnUpdateImageFormats(CCmdUI* pCmdUI)
{
BOOL bEnable = TRUE;
switch (pCmdUI->m_nID) {
case IDD_16BIT_MMXINTRINSICS:
case IDD_24BIT_MMXINTRINSICS:
case IDD_32BIT_MMXINTRINSICS:
bEnable = IsMMX();
break;
case IDD_16BIT_SSE2INTRINSICS:
case IDD_24BIT_SSE2INTRINSICS:
case IDD_32BIT_SSE2INTRINSICS:
bEnable = IsSSE2();
break;
default:
break;
}
if (ESurface(pCmdUI->m_nID) == m_eSurf)
pCmdUI->SetCheck(1);
else
pCmdUI->SetCheck(0);
pCmdUI->Enable(bEnable);
}
BOOL CChildView::OnEraseBkgnd(CDC* /*pDC*/)
{
return(TRUE);
}
void CChildView::OnDestroy(void)
{
CWnd::OnDestroy();
KillTimer(m_kTimerID);
}