利用定时器来实现一个数字时钟 思路清晰 就是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) ;
}