aclockview.cpp

来自「《Visual C/C++图形图像与游戏编程典型实例解析》配套源代码」· C++ 代码 · 共 378 行

CPP
378
字号
// AClockView.cpp : CAClockView 类的实现
//

#include "stdafx.h"
#include "AClock.h"

#include "AClockDoc.h"
#include "AClockView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAClockView

IMPLEMENT_DYNCREATE(CAClockView, CView)

BEGIN_MESSAGE_MAP(CAClockView, CView)
	ON_COMMAND(ID_130, On130)
	ON_WM_TIMER()
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_DESTROY()
END_MESSAGE_MAP()

// CAClockView 构造/销毁

CAClockView::CAClockView()
{
	// TODO: 在此处添加构造代码

}

CAClockView::~CAClockView()
{
}

BOOL CAClockView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或
	// 样式

	return CView::PreCreateWindow(cs);
}

// CAClockView 绘制

void CAClockView::OnDraw(CDC* /*pDC*/)
{
	CAClockDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// TODO: 在此处为本机数据添加绘制代码
}


// CAClockView 诊断

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

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

CAClockDoc* CAClockView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAClockDoc)));
	return (CAClockDoc*)m_pDocument;
}
#endif //_DEBUG

// CAClockView 消息处理程序

void CAClockView::On130()
{	//时钟
	// TODO: 在此添加命令处理程序代码
	int w,h,m;

	GetParam(w,h,m);
	InitContext(w,h);
	SetTimer(0x901,100,0);
	PulseEvent(m_hClockEvent);
	KillTimer(0x101);
}

void CAClockView::GetParam(int& w,int& h,int& m)
{
	RECT rect;

	GetClientRect(&rect);
	w=rect.right-rect.left;
	h=rect.bottom-rect.top;
	m=(((w>h)?h:w)-2)/2;
}

DWORD WINAPI DrawClockProc(LPVOID lpParameter)
{
	CAClockView* pMainView=(CAClockView*)lpParameter;
	DWORD EventID;
	int w,h,m;

	for(;;)
	{
		EventID=WaitForSingleObject(pMainView->m_hClockEvent,INFINITE);
		if(WAIT_OBJECT_0==EventID)
		{
			pMainView->GetParam(w,h,m);
			pMainView->DrawBackFrame(w,h,m);
		}
	}

	return(0);
}

void CAClockView::InitContext(int w,int h)
{
	BITMAPINFOHEADER BmpInfoHdr;
	DWORD ThreadID;
	CClientDC cdc(this);

	ZeroMemory(&BmpInfoHdr,sizeof(BITMAPINFOHEADER));
	BmpInfoHdr.biSize=sizeof(BITMAPINFOHEADER);
	BmpInfoHdr.biWidth=w;
	BmpInfoHdr.biHeight=h;
	BmpInfoHdr.biPlanes=1;
	BmpInfoHdr.biBitCount=24;
	BmpInfoHdr.biCompression=BI_RGB;
	BmpInfoHdr.biXPelsPerMeter=11811;
	BmpInfoHdr.biYPelsPerMeter=11811;

	m_hBmp1=CreateDIBSection(cdc.m_hDC,(BITMAPINFO*)&BmpInfoHdr,
		DIB_RGB_COLORS,(void**)&m_pData1,0,0);
	FillMemory(m_pData1,w*h*3,0xff);

	m_hMemDC=CreateCompatibleDC(cdc.m_hDC);
	m_hBmp2=CreateDIBSection(m_hMemDC,(BITMAPINFO*)&BmpInfoHdr,
		DIB_RGB_COLORS,(void**)&m_pData2,0,0);
	FillMemory(m_pData2,w*h*3,0xff);

	m_hClockThread=CreateThread(0,0,DrawClockProc,this,CREATE_SUSPENDED,&ThreadID);
	m_hClockEvent=CreateEvent(0,0,0,0);
	ResumeThread(m_hClockThread);

//	DeleteObject(m_hBmp1);
//	DeleteObject(m_hBmp2);
}

void CAClockView::DrawPanel(HDC hDC,int w,int h,int m)
{
	Graphics graph(hDC);
    Matrix mat1,mat2,mat3;
	GraphicsState state;
	INT i,j,cw,ch;
	REAL ang;

	Image img(L"combra.jpg");
	cw=img.GetWidth();
	ch=img.GetHeight();
	mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f,h/2.0f);
	graph.SetTransform(&mat1);
	cw=(cw>h)?2*h/3:cw;
	ch=(ch>h)?2*h/3:ch;
	graph.DrawImage(&img,-cw/2,-ch/2,cw,ch);

	mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f,h/2.0f);
	mat2.SetElements(cosf(PI/2.0f),-sinf(PI/2.0f),sinf(PI/2.0f),cosf(PI/2.0f),0,0);
	mat2.Multiply(&mat1,MatrixOrderAppend);
	graph.SetTransform(&mat2);

	Pen pen(Color(255,255,0,0),3.0f);
	pen.SetStartCap(LineCapSquare);
	pen.SetEndCap(LineCapArrowAnchor);
//	graph.DrawLine(&pen,-m,0,m,0); //X轴
//	graph.DrawLine(&pen,0,-m,0,m); //Y轴

	for(i=0;i<360;i+=6)
	{
		//画表盘
		ang=i*PI/180.0f;
		state=graph.Save();
		mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f,h/2.0f);
		mat2.SetElements(cosf(PI/2.0f),-sinf(PI/2.0f),sinf(PI/2.0f),cosf(PI/2.0f),0,0);
		mat3.SetElements(cosf(ang),sinf(ang),-sinf(ang),cosf(ang),0,0);
		mat3.Multiply(&mat2,MatrixOrderAppend);
		mat3.Multiply(&mat1,MatrixOrderAppend);
		graph.SetTransform(&mat3);
		if(0==i%30) 
		{
			pen.SetWidth(6.0f);
			pen.SetColor(Color(255,0,255,0));
			graph.DrawLine(&pen,m-10,0,m-5,0);
		}
		else if(0==i%6) 
		{
			pen.SetWidth(3.0f);
			pen.SetColor(Color(255,0,0,0));
			graph.DrawLine(&pen,m-10,0,m-5,0);
		}
		graph.Restore(state);

		//画数字
		mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f-10,h/2.0f-12);
		graph.SetTransform(&mat1);
		
		SolidBrush brush(Color(255,128,128,64));
		FontFamily family(L"Times New Roman");
		Font font(&family,24,FontStyleRegular,UnitPixel);
		PointF pointF((m-25)*cosf(i*PI/180.0f),(m-25)*sinf(i*PI/180.0f));
		TCHAR num[20];

		USES_CONVERSION;

		if(0==i%30)
		{
			j=i+90;
			j=(j>360)?j%360/30:j/30;
			sprintf(num,"%d",j);
			graph.DrawString(T2W(num),-1,&font,pointF,&brush);
		}
	}
}

void CAClockView::DrawPins(HDC hDC,SYSTEMTIME& tm,int w,int h,int m,float c)
{
	REAL secAng,minAng,hourAng;
	Pen pen(Color(255,0,0,0),c); 
	pen.SetStartCap(LineCapSquare);
	pen.SetEndCap(LineCapArrowAnchor);

	secAng=(6.0f*tm.wSecond+6.0f*tm.wMilliseconds/1000.0f)*PI/180.0f;
	minAng=(6.0f*tm.wMinute+tm.wSecond/10.0f+tm.wMilliseconds/10000.0f)*PI/180.0f;
	hourAng=(30.0f*(tm.wHour%12)+tm.wMinute/2.0f+tm.wSecond/120.0f+tm.wMilliseconds/120000.0f)*PI/180.0f;

	pen.SetWidth(c+6.0f);
	pen.SetColor(Color(255,255,0,255));
	DrawSinglePin(hDC,pen,w,h,hourAng,m-60);
	pen.SetWidth(c+2.0f);
	pen.SetColor(Color(255,0,0,255));
	DrawSinglePin(hDC,pen,w,h,minAng,m-20);
	pen.SetWidth(c);
	pen.SetColor(Color(255,0,255,0));
	DrawSinglePin(hDC,pen,w,h,secAng,m-10);

	Matrix mat1;
	Graphics graph(hDC);
	mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f-8,h/2.0f-8);
	graph.SetTransform(&mat1);
	SolidBrush brush(Color(255,0,0,0));
	graph.FillEllipse(&brush,0,0,16,16);
}

void CAClockView::DrawSinglePin(HDC hDC,Pen& pen,int w,int h,float ang,int len)
{
	Graphics graph(hDC);
    Matrix mat1,mat2,mat3;
	GraphicsState state;
		
	state=graph.Save();
	mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f,h/2.0f);
	mat2.SetElements(cosf(PI/2.0f),-sinf(PI/2.0f),sinf(PI/2.0f),cosf(PI/2.0f),0,0);
	mat3.SetElements(cosf(ang),sinf(ang),-sinf(ang),cosf(ang),0,0);
	mat3.Multiply(&mat2,MatrixOrderAppend);
	mat3.Multiply(&mat1,MatrixOrderAppend);
	graph.SetTransform(&mat3);
	graph.DrawLine(&pen,-20,0,len,0);
	graph.Restore(state);
}

void CAClockView::DrawDigital(HDC hDC,SYSTEMTIME& tm,int w,int h,int m)
{
	Graphics graph(hDC);
	SolidBrush brush(Color(255,0,0,255));
	FontFamily family(L"Times New Roman");
	Font font(&family,24,FontStyleRegular,UnitPixel);
	PointF pt(REAL(m-10),-REAL(m));
	TCHAR time[80];
	Matrix mat1;
	
	USES_CONVERSION;

	mat1.SetElements(1.0f,0.0f,0.0f,1.0f,w/2.0f,h/2.0f);
	graph.SetTransform(&mat1);
	wsprintf(time,"%02d:%02d:%02d.%01d",tm.wHour,tm.wMinute,tm.wSecond,tm.wMilliseconds/100);
	graph.DrawString(T2W(time),-1,&font,pt,&brush);
}

void CAClockView::DrawCurrFrame(int w,int h)
{
	CClientDC cdc(this);
	Graphics graph(cdc.m_hDC);
	Bitmap bmp(m_hBmp1,0);
	graph.DrawImage(&bmp,0,0,w,h);
}

void CAClockView::DrawBackFrame(int w,int h,int m)
{
	SYSTEMTIME tm;
		
	m_hOldBmp=(HBITMAP)SelectObject(m_hMemDC,m_hBmp2);
	
	FillMemory(m_pData2,w*h*3,0xff);
	DrawPanel(m_hMemDC,w,h,m);
	GetLocalTime(&tm);
	DrawPins(m_hMemDC,tm,w,h,m,3.0f);
	DrawDigital(m_hMemDC,tm,w,h,m);
	
	SelectObject(m_hMemDC,m_hOldBmp);
}

void CAClockView::OnTimer(UINT nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(0x901==nIDEvent)
	{
		int w,h,m;

		GetParam(w,h,m);
		CopyMemory(m_pData1,m_pData2,w*h*3);
		PulseEvent(m_hClockEvent);
		DrawCurrFrame(w,h);
	}

	CView::OnTimer(nIDEvent);
}

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

	// TODO:  在此添加您专用的创建代码
	m_hClockThread=m_hClockEvent=0;
	m_pData1=m_pData2=0;
	m_hBmp1=m_hBmp2=0;

	return 0;
}

void CAClockView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此添加消息处理程序代码
	if(m_hBmp1&&m_hBmp2)
	{
		ClearContext();
		InitContext(cx,cy);
		SetTimer(0x901,100,0);
	}
}

void CAClockView::ClearContext()
{
	DWORD ExitCode;
	BOOL br;

	KillTimer(0x901);
	br=GetExitCodeThread(m_hClockThread,&ExitCode);
	TerminateThread(m_hClockThread,ExitCode);
	CloseHandle(m_hClockEvent);
	DeleteObject(m_hBmp1);
	DeleteObject(m_hBmp2);
}

void CAClockView::OnDestroy()
{
	CView::OnDestroy();

	// TODO: 在此添加消息处理程序代码
	ClearContext();
}

⌨️ 快捷键说明

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