mtspirographview.cpp

来自「Visual_C++[1].NET_Bible1 Visual_C++宝典书中」· C++ 代码 · 共 228 行

CPP
228
字号
// MTSpirographView.cpp : implementation of the CMTSpirographView class
//

#include "stdafx.h"
#include "MTSpirograph.h"

#include "MTSpirographDoc.h"
#include "MTSpirographView.h"

#include <math.h>

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

/////////////////////////////////////////////////////////////////////////////
// CMTSpirographView

IMPLEMENT_DYNCREATE(CMTSpirographView, CView)

BEGIN_MESSAGE_MAP(CMTSpirographView, CView)
	//{{AFX_MSG_MAP(CMTSpirographView)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

UINT ThreadProc( LPVOID lpParam )
{
	// Get a THREAD_INFO pointer from the
	// parameter that was passed in.
	THREAD_INFO *lpThreadInfo =
		(THREAD_INFO *) lpParam;

	// The next six variables represent
	// values used to draw the spirograph;
	unsigned char Red, Green, Blue;
	int nFixedRadius = 80;
	int nMovingRadius = 10;
	int nMovingOffset = 70;

	// Begin colors based on the system time. This
	// makes the color somewhat random.
	Red = (unsigned char)
		( GetTickCount() & 0x000000ff );
	Green = (unsigned char)
		( ( GetTickCount() & 0x00000ff0 ) >> 4 );
	Blue = (unsigned char)
		( ( GetTickCount() & 0x0000ff00 ) >> 8 );

	while( *lpThreadInfo->lpKillThread == FALSE ){

		// Get a DC for the window.
		HDC hdc = ::GetDC( lpThreadInfo->hWnd );

		// Get the client rect so we can
		// calculate the center point.
		RECT Rect;
		::GetClientRect( lpThreadInfo->hWnd, &Rect );
		int nMidx = Rect.right / 2;
		int nMidy = Rect.bottom / 2;

		// Clear the window.
		::InvalidateRect( lpThreadInfo->hWnd, NULL, TRUE );
		::UpdateWindow( lpThreadInfo->hWnd );

		// Create a pen based on the color. Select it
		// into the DC and remember the old pen so
		// we can select it back in later.
		HPEN hPen, hOldPen;
		hPen =
			::CreatePen( PS_SOLID, 1, RGB( Red, Green, Blue ) );
		hOldPen = (HPEN) ::SelectObject( hdc, hPen );

		// Iterate through a bunch of times and
		// draw the spirograph.
		int prevx, prevy, x = 0, y = 0;
		for( int i=0; i<=500; i++ ){

			// Remember x and y.
			prevx = x;
			prevy = y;

			// Calculate the new x and y.
			x = (int) ( ( nFixedRadius + nMovingRadius ) *
				cos( (double) i ) -
				( nMovingRadius + nMovingOffset ) *
				cos((double)(( ( nFixedRadius + nMovingRadius ) /
				nMovingRadius ) * i ) ) );
			y = (int) ( ( nFixedRadius + nMovingRadius ) *
				sin( (double) i ) -
				( nMovingRadius + nMovingOffset ) *
				sin((double)(( ( nFixedRadius + nMovingRadius ) /
				nMovingRadius ) * i ) ) );

			// Draw the line (or move to the first
			// point if this is the first time through).
			if( i > 0 )
				::LineTo( hdc, x + nMidx, y + nMidy );
			else
				::MoveToEx( hdc, x + nMidx, y + nMidy, NULL );

			}

		// Increment the color variables so
		// that the colors move around.
		Red += 6;
		Green += 5;
		Blue += 4;

		// Increase the fixed radius and
		// limit it to a max of 150.
		nFixedRadius++;
		if( nFixedRadius > 170 )
			nFixedRadius = 90;
		// Increase the moving radius and
		// limit it to a max of 120.
		nMovingRadius++;
		if( nMovingRadius > 40 )
			nMovingRadius = 10;

		// Increase the moving offset and
		// limit it to a max of 90.
		nMovingOffset++;
		if( nMovingOffset > 100 )
			nMovingOffset = 70;

		// Select the old pen into the DC,
		// delete the pen we created, and
		// release the DC we got.
		::SelectObject( hdc, hOldPen );
		::DeleteObject( hPen );
		::ReleaseDC( lpThreadInfo->hWnd, hdc );

		// Sleep so we don't chew up too
		// much CPU time.
		Sleep( 200 );
		}

	return( 0 );

}

/////////////////////////////////////////////////////////////////////////////
// CMTSpirographView construction/destruction

CMTSpirographView::CMTSpirographView()
{

	// This is the flag that tells the
	// thread to quit.
	m_bKillThread = FALSE;

	// NULL the pointer to the thread so
	// we know it hasn't been created.
	m_pThread = NULL;

}

CMTSpirographView::~CMTSpirographView()
{
	// Get the thread handle into local space since
	// the thread will delete itself.
	HANDLE hThread = m_pThread->m_hThread;

	// Set the flag to kill the thread to TRUE;
	m_bKillThread = TRUE;

	// Wait for the thread to end.
	::WaitForSingleObject( hThread, 5000 );

}

BOOL CMTSpirographView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMTSpirographView drawing

void CMTSpirographView::OnDraw(CDC* pDC)
{
 CMTSpirographDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (pDoc)
 {
  // If the m_pThread is NULL, we need to kick
  // off the thread.
  if (NULL == m_pThread)
  {
   // Store the window handle and the Kill flag.
   m_ThreadInfo.hWnd = m_hWnd;
   m_ThreadInfo.lpKillThread = &m_bKillThread;

    // Start the thread.
   m_pThread = AfxBeginThread(ThreadProc,
                              (LPVOID)&m_ThreadInfo);
  }
 }
}


/////////////////////////////////////////////////////////////////////////////
// CMTSpirographView diagnostics

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

void CMTSpirographView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMTSpirographDoc* CMTSpirographView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMTSpirographDoc)));
	return (CMTSpirographDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMTSpirographView message handlers

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?