65,186
社区成员




#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <math.h>
#include <time.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(linker, "/SUBSYSTEM:Windows")
//说白了就是极坐标转普通坐标,不过x,y和数学里面的反一反,反正LZ你知道是通过角度和长度,得到相应x,y就行了
void GetPos(double degree, int len, int* x, int* y)
{
*x = len * sin(degree);
*y = len * cos(degree);
}
//画钟
void DrawClock(HWND hw, HDC h, int hour, int minute, int second)
{
HDC bufdc = CreateCompatibleDC(h); //设备,图就画在这东西上面
HBITMAP buf = CreateCompatibleBitmap(bufdc, 200, 200); //位图
RECT cr; //框
HBRUSH bBg = CreateSolidBrush(RGB(255, 255, 255)); //背景画刷,纯白的
GetClientRect(hw, &cr); //取得client area的框,或者说范围
SelectObject(bufdc, bBg); //为你的设备选择一个画刷,这里用来画背景
SelectObject(bufdc, buf); //为你的设备选择一个位图
FillRect(bufdc, &cr, bBg); //现在背景画刷填充整个client area,这就算把背景弄成白的了
{
int sx, sy, ex, ey;
int i;
for(i = 0; i < 12; ++i) { //开始画时钟十二个时刻的刻度
GetPos(2*3.14159/12*i, 85, &sx, &sy); //第一个参数是角度,用的是弧度制,其实就是2*Pi/i,第二个是长度,这里长度是85,所以是刻度的起始点
GetPos(2*3.14159/12*i, 95, &ex, &ey); //同上,这里长度90,所以是刻度的终点
MoveToEx(bufdc, 100+sx, 100-sy, 0); //设置起点,注意之前的起点终点是相对于圆心(0,0)的,但这里设置圆心为(100,100)
LineTo(bufdc, 100+ex, 100-ey); //同上,从起点到终点画条线,这就算刻度了
}
}
//这里开始画时钟的指针
{
int hx, hy, mx, my, sx, sy; //显然这些分别是时钟的时针,分针,秒针的终点,相对于圆心(0,0)的
GetPos(2*3.14159 / 12 * (hour + (double)minute / 60 + (double)second / 3600), 50, &hx, &hy); //这里除以12说明时针走12下绕一圈,反正第一个参数就是根据当前时刻算角度啦,反正最后得到时针的坐标
GetPos(2*3.14159 / 60 * (minute + (double)second / 60), 65, &mx, &my); //这里是分针的坐标
GetPos(2*3.14159 / 60 * second, 80, &sx, &sy); //这里是秒针的坐标
MoveToEx(bufdc, 100, 100, NULL); //和上面刻度一样,以(100,100)为圆心,转换坐标后画线,这是起点
LineTo(bufdc, 100+hx, 100-hy); //终点
MoveToEx(bufdc, 100, 100, NULL); //同上
LineTo(bufdc, 100+mx, 100-my); //同上
MoveToEx(bufdc, 100, 100, NULL); //同上
LineTo(bufdc, 100+sx, 100-sy); //同上
}
BitBlt(h, 0, 0, 200, 200, bufdc, 0, 0, SRCCOPY); 刚刚画的东西都在bufdc上,其实都还在内存里,并没真的画出来,这里正式将它贴到设备上,这里贴的是个宽200,长200,左上角坐标是(0,0)的正方形区域。
DeleteDC(bufdc); //既然贴完了,这个自然就木有用了,删之
DeleteObject(bBg); //同上
DeleteObject(buf); //同上
}
LRESULT CALLBACK WndProc(HWND h, UINT m, WPARAM w, LPARAM l)
{
switch(m) {
case WM_CREATE: //启动时
SetTimer(h, 1, 1000, 0); //设置定时器
return 0;
case WM_ERASEBKGND:
return 1;
case WM_TIMER: //触发定时器
InvalidateRect(h, 0, FALSE); //强制重画
return 0;
case WM_PAINT: { //这里开始重画
PAINTSTRUCT ps;
HDC dc = BeginPaint(h, &ps); //开始画鸟
{
time_t t;
struct tm* pst;
time(&t); //得到当前世界
pst = localtime(&t);
DrawClock(h, dc, pst->tm_hour, pst->tm_min, pst->tm_sec); //画钟
}
EndPaint(h, &ps); //画完收工
return 0;
}
case WM_DESTROY: //窗口销毁时
KillTimer(h, 1); //删除定时器
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(h, m, w, l);
}
}
//这东西是要windows编程都一样就不注释了
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmd, INT nShow)
{
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpszClassName = TEXT("MYCLOCK");
if (RegisterClass(&wc) != 0) {
MSG m;
HWND hw = CreateWindow(TEXT("MYCLOCK"), TEXT("Clock"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, 0);
if (hw != NULL) {
RECT r;
GetWindowRect(hw, &r);
r.right = r.left + 200;
r.bottom = r.top + 200;
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow(hw, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE);
ShowWindow(hw, SW_SHOWNORMAL);
UpdateWindow(hw);
while( GetMessage(&m, 0, 0, 0) > 0) {
TranslateMessage(&m);
DispatchMessage(&m);
}
return 0;
}
return 1;
} else
return 1;
}
我觉得我注释得够详细了,lz快给分吧~