MFC画时钟

程序最终运行界面:



实现步骤:

1.打开VC++6.0创建一个单文档,命名为Clock

2.通过类向导在视图类CClockView中添加WM_TIMER和WM_CREATE两个消息响应。

3.在视图类CClockView的OnDraw函数中添加如下代码:(记得添加一个头文件:#include <math.h>)

void CClockView::OnDraw(CDC* pDC)
{
	CClockDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	
	CRect rect;
	GetClientRect(&rect);//获取客户区
	//计算椭圆中心位置
	int CenterX = rect.right/2;
	int CenterY = rect.bottom/2;
	//取当前时间
	CTime Time = CTime::GetCurrentTime();
	CString strTime;
	int i,x,y;
	CSize size;
	//创建一只黄色的笔用来画椭圆
	CPen pen(PS_SOLID,5,RGB(255,255,0));
	//设置当前画笔并记下以前的画笔
	CPen *pOldPen = pDC->SelectObject(&pen);
	//绘制钟面椭圆
	pDC->Ellipse(5,5,rect.right-5,rect.bottom-5);
	double Radians;
	//设置字体颜色为红色
	pDC->SetTextColor(RGB(255,0,0));
	for (i = 1; i <= 12; ++i)
	{
		strTime.Format("%d",i);//格式化钟点值
		size = pDC->GetTextExtent(strTime,strTime.GetLength());
		Radians = (double)i*2*3.14/12.0;//2π:计算弧度
		//计算钟点放置位置
		x = CenterX - (size.cx/2) + (int)((double)(CenterX - 20) * sin(Radians));
		y = CenterY - (size.cy/2) - (int)((double)(CenterY - 20) * cos(Radians));
		//绘制钟点
		pDC->TextOut(x,y,strTime);
	}

	//计算时钟指针夹角
	Radians = (double)Time.GetHour() + (double)Time.GetMinute()/60.0 +(double)Time.GetSecond()/3600.0;
	Radians *= (2*3.14/12.0);//计算弧度
	//创建时钟画笔
	CPen HourPen(PS_SOLID,5,RGB(0,0,0));
	pDC->SelectObject(&HourPen);
	//绘制时钟指针
	pDC->MoveTo(CenterX,CenterY);
	pDC->LineTo(CenterX + (int)((double)(CenterX/3)*sin(Radians)),\
		CenterY - (int)((double)(CenterY/3)*cos(Radians)));
	/*******************************/
	//计算分钟指针夹角
	Radians = (double)Time.GetMinute() +(double)Time.GetSecond()/60.0;
	Radians *= (2*3.14/60.0);//计算弧度
	//创建分钟画笔
	CPen MinutePen(PS_SOLID,3,RGB(0,0,255));
	pDC->SelectObject(&MinutePen);
	//绘制分钟指针
	pDC->MoveTo(CenterX,CenterY);
	pDC->LineTo(CenterX + (int)((double)(CenterX*1/2)*sin(Radians)),\
		CenterY - (int)((double)(CenterY*1/2)*cos(Radians)));
	/*******************************/
	//计算秒钟指针夹角
	Radians = (double)Time.GetSecond();
	Radians *= (2*3.14/60.0);//计算弧度
	//创建秒钟画笔
	CPen SecondPen(PS_SOLID,2,RGB(255,0,0));
	pDC->SelectObject(&SecondPen);
	//绘制秒钟指针
	pDC->MoveTo(CenterX,CenterY);
	pDC->LineTo(CenterX + (int)((double)(CenterX*7/8)*sin(Radians)),\
		CenterY - (int)((double)(CenterY*7/8)*cos(Radians)));
	/*****************************/
	pDC->SelectObject(pOldPen);
}

4.在刚才响应的那两个消息中添加如下代码:

int CClockView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	//设置定时器,1秒发送一次消息
	SetTimer(1,1000,NULL);
	
	return 0;
}

void CClockView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	InvalidateRect(NULL,TRUE);
	UpdateWindow();//刷新窗口
	CView::OnTimer(nIDEvent);
}
5.如果你还想美化一下界面:

1)看下面写注释哪行代码,设置窗口名字

BOOL CClockApp::InitInstance()
{
	AfxEnableControlContainer();

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	// Change the registry key under which our settings are stored.
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	LoadStdProfileSettings();  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CClockDoc),
		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
		RUNTIME_CLASS(CClockView));
	AddDocTemplate(pDocTemplate);

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Dispatch commands specified on the command line
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	// The one and only window has been initialized, so show and update it.
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();

	m_pMainWnd->SetWindowText("指针式时钟 V1.0");//标题栏命名
	return TRUE;
}

2)看写注释的那两行代码,设置窗口宽度和高度

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	cs.cx = 800;//界面宽度
	cs.cy = 600;//界面高度
	return TRUE;
}
3)看写注释的那3行代码,菜单、状态栏、工具条
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}

	// TODO: Delete these three lines if you don't want the toolbar to
	//  be dockable
	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);
	
	SetMenu(NULL);//隐藏菜单
	ShowControlBar(&m_wndToolBar,FALSE,FALSE);//隐藏工具条
	ShowControlBar(&m_wndStatusBar,FALSE,FALSE);//隐藏状态栏
	return 0;
}

6.然后,打开工程目录下面的res文件夹,将里面的Clock.ico图片用自己准备好的Logo替换掉。


附录:

中心位于点 (h,k) 的主轴平行于 x 轴的椭圆由如下方程指定

\frac{(x-h)^{2}}{a^{2}} + \frac{(y-k)^{2}}{b^{2}} = 1 .

这个椭圆可以参数化表达为

x = h+a\,\cos t,\,\!
y = k+b\,\sin t\,\!

这里的 t 可以限制于区间 -\pi\leq t \leq \pi\,\!



全部代码下载地址:链接:http://pan.baidu.com/s/1hqt9K4s 密码: ux71


转载请保留原文地址:http://blog.csdn.net/nonknown/article/details/17677723

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值