8c 利用定时器实现时钟

利用定时器来实现一个数字时钟    思路清晰 就是API太多 还有映射方式有点复杂   常见的集中映射方式是个要了解的地方


#include<Windows.h>

#define ID_TIMER 1


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT ("DigClock") ;
	HWND  hwnd ;
	MSG  msg ;
	WNDCLASS  wndclass ;
	wndclass.style  = CS_HREDRAW | CS_VREDRAW ;
	wndclass.lpfnWndProc  = WndProc ;
	wndclass.cbClsExtra  = 0 ;
	wndclass.cbWndExtra  = 0 ;
	wndclass.hInstance  = hInstance ;
	wndclass.hIcon  = LoadIcon (NULL,
		IDI_APPLICATION) ;
	wndclass.hCursor  = LoadCursor (NULL, IDC_ARROW) ;
	wndclass.hbrBackground  = (HBRUSH) GetStockObject
		(WHITE_BRUSH) ;
	wndclass.lpszMenuName  = NULL ;
	wndclass.lpszClassName  = szAppName ;
	if (!RegisterClass (&wndclass))
	{
		MessageBox ( NULL, TEXT ("Program requires Windows NT!") , 
			szAppName,
			MB_ICONERROR) ;
		return 0 ;
	}
	hwnd = CreateWindow ( szAppName, TEXT ("Digital Clock"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL) ;
	ShowWindow (hwnd, iCmdShow) ;
	UpdateWindow (hwnd) ;
	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return msg.wParam ;
}


void DisplayDigit (HDC hdc, int iNumber)
{
	static BOOL fSevenSegment [10][7] = {//顺序是由上到下 由左到右、/、此处不是数码管顺序 orz  害我纳闷好久
		1, 1, 1, 0, 1, 1, 1,  // 0
		0, 0, 1, 0, 0, 1, 0,  // 1
		1, 0, 1, 1, 1, 0, 1,  // 2
		1, 0, 1, 1, 0, 1, 1,  // 3
		0, 1, 1, 1, 0, 1, 0,  // 4
		1, 1, 0, 1, 0, 1, 1,  // 5
		1, 1, 0, 1, 1, 1, 1,  // 6
		1, 0, 1, 0, 0, 1, 0,  // 7
		1, 1, 1, 1, 1, 1, 1,  // 8
		1, 1, 1, 1, 0, 1, 1 } ; // 9
	/*
	typedef struct tagPOINT
	{
	LONG  x;
	LONG  y;
	} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
	*/
	static POINT ptSegment [7][6] = {//ptSegment 阵列是一个 POINT 结构的阵列, 指出了 7 个段中每个点的图形座标。 每个数字由下列程式码画出:
		7,6,   11, 2,   31,  2,		35,  6,		31, 10,		11, 10,
		6,7,   10, 11,  10, 31,		6,  35,		2,  31,		2,  11,
		36,7,  40, 11,  40, 31,		36,  35,	32, 31,		32, 11,
		7,36,  11, 32,  31, 32,		35,  36,	31, 40,		11, 40,
		6,37,  10, 41,  10, 61,		6,  65,		2,  61,		2,  41,
		36,37, 40, 41,  40, 61,		36,  65,	32, 61,		32, 41,
		7,66,  11, 62,  31, 62,		35,  66,	31, 70,		11, 70 
	} ;
	int iSeg ;
	for (iSeg = 0 ; iSeg < 7 ; iSeg++)
		if (fSevenSegment [iNumber][iSeg])
			Polygon (hdc, ptSegment [iSeg], 6) ;
}


void DisplayTwoDigits (HDC hdc, int iNumber, BOOL fSuppress)
{
	if (!fSuppress || (iNumber / 10 != 0))
		DisplayDigit (hdc, iNumber / 10) ;

	OffsetWindowOrgEx (hdc, -42, 0, NULL) ;
	//该函数用指定的水平位移和垂直位移改变设备环境的窗口原点。

	DisplayDigit (hdc, iNumber % 10) ;

	OffsetWindowOrgEx (hdc, -42, 0, NULL) ;
}
void DisplayColon (HDC hdc)//画冒号
{
	POINT ptColon [2][4] = { 
		2, 21,  6, 17,  10, 21,  6,25, 
		2, 51,  6, 47,  10, 51,  6, 55
	} ;
	Polygon (hdc, ptColon [0], 4) ;
	Polygon (hdc, ptColon [1], 4) ;
	OffsetWindowOrgEx (hdc, -12, 0, NULL) ;
	/*
	nXOffset:指定以逻辑单位为单位的水平位移。移动方向取决于当前设置的窗口坐标方向,如果为正表示向窗口水平轴坐标的负方向移动,如果为负表示向窗口水平轴坐标的正方向移动。
	nYOffset:指定以逻辑单位为单位的垂直位移。 移动方向取决于当前设置的窗口坐标方向,如果为正表示向窗口垂直轴坐标的负方向移动,如果为负表示向窗口垂直轴坐标的正方向移动。
	*/
}
void DisplayTime (HDC hdc, BOOL f24Hour, BOOL fSuppress)
{
	SYSTEMTIME st ;
	GetLocalTime (&st) ;//取得当前时间
	/*
	typedef struct _SYSTEMTIME
	{
	WORD wYear ;
	WORD wMonth ;
	WORD wDayOfWeek ;
	WORD wDay ;
	WORD wHour ;
	WORD wMinute ;
	WORD wSecond ;
	WORD wMilliseconds ;
	} 
	SYSTEMTIME, * PSYSTEMTIME ;
	*/
	//时
	if (f24Hour)
		DisplayTwoDigits (hdc, st.wHour, fSuppress) ;
	else//如果是12小时制
		DisplayTwoDigits (hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress) ; ?

	DisplayColon (hdc) ;//输出冒号
	DisplayTwoDigits (hdc, st.wMinute, FALSE) ;//分
	DisplayColon (hdc) ;//输出冒号
	DisplayTwoDigits (hdc, st.wSecond, FALSE) ;//秒
}


LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
	static BOOL f24Hour, fSuppress ;
	static HBRUSH hBrushRed ;
	static int  cxClient, cyClient ;
	HDC  hdc ;
	PAINTSTRUCT ps ;
	TCHAR  szBuffer [2] ;

	switch (message)
	{
	case WM_CREATE:
		hBrushRed = CreateSolidBrush (RGB (255, 0, 0)) ;
		SetTimer (hwnd, ID_TIMER, 1000, NULL) ;// fall through

		///
	case WM_SETTINGCHANGE://change
		GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2) ;
		/*
		int GetLocaleInfo(
		LCID Locale, // locale identifier
		LCTYPE LCType, // information type
		LPTSTR lpLCData, // information buffer
		int cchData // size of buffer
		);
		*/
		f24Hour = (szBuffer[0] == '1') ;
		/*
		LOCALE_ITIME
		0	AM/PM 12-hour format
		1	24-hour format
		*/

		GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2) ;
		/*根据我的渣渣英语推断是前导0是否存在的问题 就是 显示9 还是09
		LOCALE_ITLZERO
		Specifier for leading zeros in time fields. It is preferred for your application to use the LOCALE_STIMEFORMAT constant instead of LOCALE_ITLZERO.
		Value	Meaning
		0	No leading zeros for hours
		1	Leading zeros for hours*/
		fSuppress = (szBuffer[0] == '0') ;
		InvalidateRect (hwnd, NULL, TRUE) ;
		return 0 ;

	case WM_SIZE:
		cxClient = LOWORD (lParam) ;
		cyClient = HIWORD (lParam) ;
		return 0 ;
	case WM_TIMER:
		InvalidateRect (hwnd, NULL, TRUE) ;
		return 0 ;

		//
	case WM_PAINT:
		hdc = BeginPaint (hwnd, &ps) ;

		SetMapMode (hdc, MM_ISOTROPIC) ;
		/*函数功能描述:该函数设置指定设备环境的映射方式,映射方式定义了将逻辑单位转换为设备单位的度量单位,并定义了设备的X、Y轴的方向。*/
		//MM_ISOTROPIC:逻辑单位转换成具有均等比例轴的任意单位,即沿X轴的一个单位等于沿Y轴的一个单位,

		SetWindowExtEx (hdc, 276, 72, NULL) ;//276 42*6=252 12*2=24  252+24=276
		/*如SetWindowExtEx(hDC,600,400,NULL); //设置窗口区域,逻辑坐标 把窗口大小设置为宽(X坐标方向)600 (Y坐标方向)高400 是程序把图像
		映像成实物时采用的坐标 是逻辑上的*/

		SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;
		/*SetViewportExtEx(hDC,300,200,NULL); //设置视图区域,物理坐标 把输出时(程序运行时)看到的界面区域的坐标为宽(X坐标方向)
		300 高(Y坐标方向)200 是实实在在的300 和200*/

		SetWindowOrgEx (hdc, 138, 36, NULL) ;
		//该函数用指定的坐标设置设备环境的窗口原点。
		/*X:指定新窗口原点的逻辑X坐标。
		Y:指定新窗口原点的逻辑Y坐标。*/

		SetViewportOrgEx (hdc, cxClient/2, cyClient / 2, NULL) ;
		//SetViewportOrgEx说明哪个设备点映射到窗口原点(0,0)
		/*X:[输入]新的viewport原点的设备单位的x坐标
		Y:[输入]新的viewport原点的设备单位的y坐标
		*/

		SelectObject (hdc, GetStockObject (NULL_PEN)) ;
		SelectObject (hdc, hBrushRed) ;

		DisplayTime (hdc, f24Hour, fSuppress) ;//环境已经设置好 开始显示时间

		EndPaint (hwnd, &ps) ;
		//映射逻辑点 (0,0) 到设备点 (xViewOrg, yViewOrg)
		//画线采用的是逻辑坐标

		return 0 ;


	case WM_DESTROY:
		KillTimer (hwnd, ID_TIMER) ;
		DeleteObject (hBrushRed) ;
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值