首先看下程序吧
一个数字时钟,如何实现呢?
首先,这样的数字可以分为7个部分
111111
2 3
2 3
444444
5 6
5 6
777777
这样,可以定义一个二维数组,如果对应的位置存在,就令其为1,比如数字3:
#######
#
#
#######
#
#
#######
应该为{1,0,1,1,0,1,1};
//用于画数字时判断各个部分是否画出的二维数组
static BOOL fSevenSegment[10][7] = {//10个数字,每个数字都是由7部分组成
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
};
然后,应该指出7个部分的坐标,先看其中一个:
再定义一个数组:
static POINT ptSegment[7][6] = {//组成数字的7个部分的多边形坐标,每个部分6个点
// /\ 这里三个点
// ||
// ||
// \/ 下面三个点
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
//剩下的部分坐标就不一一说明了
};
至此,可以试着输出一些数字:
# include<windows.h>
LRESULT CALLBACK WndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
void DisplayDigit(HDC hdc, int iNumber)
{
//segment分割;段;部分;
//===================数字的显示=====================
// 111111
// 2 3
// 2 3
// 444444
// 5 6
// 5 6
// 777777
//================================================
static BOOL fSevenSegment[10][7] = {//10个数字,每个数字都是由7部分组成
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
};
static POINT ptSegment[7][6] = {//组成数字的7个部分的多边形坐标,每个部分6个点
// /\ 这里三个点
// ||
// ||
// \/ 下面三个点
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); //绘制数字iNumber(一位数的)
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int iCmdShow
)
{
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//这里用NULL表示使用微软提供的图标
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //同上
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszClassName = "类名";
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndclass);//注册窗口类
HWND hwnd;
hwnd = CreateWindow("类名", "窗口名", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);//在窗口风格用或语句就可以加上滚动条了
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
int i = 0;
PAINTSTRUCT ps;
HDC hdc;
switch (uMsg)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0;i < 10;i++)
{
DisplayDigit(hdc, i);
OffsetWindowOrgEx(hdc, -42, 0, NULL);
//这么理解,默认“窗口“原点(0,0)对应"视口"原点(0,0)(客户区左
//上角),并且向右x递增,向下y递增,默认是WM_TEXT模式,
//将窗口原点左移42个像素,比如原来(x0,y0)对应(x1,y1),左移
//后(x0-42,y0-42)对应(x1,y1)
//这样做就不用改变之前点的坐标了,比较方便
}
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
//DestroyWindow(hwnd);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
程序运行结果:
以下是完整程序:
# include<windows.h>
# define ID_TIMER 1
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR lpCmdLine,
int iCmdShow
)
{
TCHAR szAppName[] = TEXT("DigClock");
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//这里用NULL表示使用微软提供的图标
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //同上
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wndclass))//注册窗口类
{
MessageBox(NULL, "Program requires windows NT!", szAppName, MB_ICONERROR);
return 0;
}
HWND hwnd;
hwnd = CreateWindow(szAppName, TEXT("Digital Clock"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInstance, NULL);//在窗口风格用或语句就可以加上滚动条了
//cw_usedefault表示采用系统默认的值
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
//画数字
void DisplayDigit(HDC hdc, int iNumber)
{
//segment分割;段;部分;
//===================数字的显示=====================
// 111111
// 2 3
// 2 3
// 444444
// 5 6
// 5 6
// 777777
//================================================
static BOOL fSevenSegment[10][7] = {//10个数字,每个数字都是由7部分组成
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
};
static POINT ptSegment[7][6] = {//组成数字的7个部分的多边形坐标,每个部分6个点
// /\ 这里三个点
// ||
// ||
// \/ 下面三个点
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); //绘制数字iNumber(一位数的)
}
}
//bool表示是否去掉前面的0,,比如1,如果为true,就不显示0,否则显示(如01)
void DisplayTwoDigits(HDC hdc, int iNumber, BOOL fSuppress)
{
if (!fSuppress || (iNumber / 10 != 0))
DisplayDigit(hdc, iNumber / 10);
//将窗口原点左移42个像素,比如原来(x0,y0)对应(x1,y1),左移后(x0-42,y0-42)对应(x1,y1)
//这样做就不用改变之前点的坐标了,比较方便
OffsetWindowOrgEx(hdc, -42, 0, NULL);
DisplayDigit(hdc, iNumber % 10);
OffsetWindowOrgEx(hdc, -42, 0, NULL);//绘制数字iNumber(两位数的)
}
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);
}
void DisplayTime(HDC hdc, BOOL f24Hour, BOOL fSuppress)
{
SYSTEMTIME st;
GetLocalTime(&st);
if (f24Hour)//画时
DisplayTwoDigits(hdc, st.wHour, fSuppress);
else
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 uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static BOOL f24Hour, fSuppress;
static HBRUSH hBrushRed;
static int cxClient, cyClient;
HDC hdc;
PAINTSTRUCT ps;
TCHAR szBuffer[2];
switch (uMsg)
{
case WM_CREATE:
hBrushRed = CreateSolidBrush(RGB( 255,0, 0));
SetTimer(hwnd, ID_TIMER, 1000, NULL);
//fall through
case WM_SETTINGCHANGE://如果用户更改了任何系统设置,WM_SETTINGCHA
//NGE消息就会被传给所有的应用程序,可以去"控制面板"
//“区域设置”中实验一下
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2);
//LOCALE_ITIME标识符确定使用的是12小时制还是24小时制,
f24Hour = (szBuffer[0] == '1');
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2);
//然后使用LOCALE_ITLZERO标志符(在小时显示中禁止前面显示0)
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);
SetWindowExtEx(hdc, 276, 72, NULL);
SetViewportExtEx(hdc, cxClient, cyClient, NULL);
SetWindowOrgEx(hdc, 138, 36, NULL);
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
SelectObject(hdc, GetStockObject(NULL_PEN));
SelectObject(hdc, hBrushRed);
DisplayTime(hdc, f24Hour, fSuppress);
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE:
KillTimer(hwnd, ID_TIMER);
DeleteObject(hBrushRed);
PostQuitMessage(0);
//DestroyWindow(hwnd);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
上面的程序都是windwos程序设计第五版上面的,不是太好理解,所以写博客记录下来,长时间容易忘…….