小时钟(改)



#include "stdafx.h"
#include "小时钟.h"
#include <math.h>
#include <time.h>




#define MAX_LOADSTRING 100


// 全局变量: 
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名


// 此代码模块中包含的函数的前向声明: 
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);


int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);


  // TODO:  在此放置代码。
MSG msg;
HACCEL hAccelTable;


// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);


// 执行应用程序初始化: 
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}


hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));


// 主消息循环: 
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


return (int) msg.wParam;
}






//
//  函数:  MyRegisterClass()
//
//  目的:  注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;


wcex.cbSize = sizeof(WNDCLASSEX);


wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));


return RegisterClassEx(&wcex);
}


//
//   函数:  InitInstance(HINSTANCE, int)
//
//   目的:  保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;


   hInst = hInstance; // 将实例句柄存储在全局变量中


   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);


   if (!hWnd)
   {
      return FALSE;
   }


   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);


   return TRUE;
}




#define IDT_CLOCK 1
const int IDM_HELP = 100;
const int IDM_TOPMOST = 101;


// 实现函数
void SetIsotropic(HDC hdc, int cxClient, int cyClient);
void DrawClockFace(HDC hdc);
void DrawHand(HDC hdc, int nLength, int nWidth, int nDegrees, COLORREF clrColor);


// 上一次Windows通知时的时间
static int s_nPreHour;        // 小时    
static int s_nPreMinute;    // 分钟
static int s_nPreSecond;    // 秒
// 窗口客户区的大小
static int s_cxClient;
static int s_cyClient;
// 是否位于最顶层
static BOOL s_bTopMost;


LRESULT __stdcall WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch (nMsg)
{
case WM_CREATE:
{
 // 向系统菜单中添加自定义的项
 HMENU hSysMenu;
 hSysMenu = ::GetSystemMenu(hWnd, FALSE);
 ::AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL); //分界线
 ::AppendMenu(hSysMenu, MF_STRING, IDM_TOPMOST, "总在最前");
 ::AppendMenu(hSysMenu, MF_STRING, IDM_HELP, "帮助");


 // 设置时间
 SYSTEMTIME time;
 ::GetLocalTime(&time);
 s_nPreHour = time.wHour % 12;
 s_nPreMinute = time.wMinute;
 s_nPreSecond = time.wSecond;


 // 创建定时器
 ::SetTimer(hWnd, IDT_CLOCK, 1000, NULL);
 return 0;
}
case WM_SIZE:
{
s_cxClient = LOWORD(lParam);
s_cyClient = HIWORD(lParam);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = ::BeginPaint(hWnd, &ps);


// 设置坐标系
TextOut(hdc, 10, 10, "许振辉是天才", strlen("许振辉是天才"));
SetIsotropic(hdc, s_cxClient, s_cyClient);


// 绘制时钟外观
DrawClockFace(hdc);


// 绘制指针


// 经过1个小时时针走30度(360/12),经过1分钟时针走0.5度(30/60)
DrawHand(hdc, 200, 8, s_nPreHour * 30 + s_nPreMinute / 2, RGB(0, 0, 0));
// 经过1分钟分针走6度(360/60)
DrawHand(hdc, 400, 6, s_nPreMinute * 6, RGB(0, 0, 0));
// 经过1秒钟秒针走6度(360/60)
DrawHand(hdc, 400, 1, s_nPreSecond * 6, RGB(0, 0, 0));
 
::EndPaint(hWnd, &ps);
return 0;
}
case WM_TIMER:
{
// 如果窗口处于最小化状态就什么也不做
if (::IsIconic(hWnd))    // IsIconic函数用来判断窗口是否处于最小化状态
return 0;


// 取得系统时间
SYSTEMTIME time;
::GetLocalTime(&time);


// 建立坐标系
HDC hdc = ::GetDC(hWnd);
SetIsotropic(hdc, s_cxClient, s_cyClient);


// 以COLOR_3DFACE为背景色就可以擦除指针了(因为窗口的背景色也是COLOR_3DFACE)
COLORREF crfColor = ::GetSysColor(COLOR_3DFACE);


// 如果分钟改变的话就擦除时针和分针
if (time.wMinute != s_nPreMinute)
{
// 擦除时针和分针
DrawHand(hdc, 200, 8, s_nPreHour * 30 + s_nPreMinute / 2, crfColor);
DrawHand(hdc, 400, 6, s_nPreMinute * 6, crfColor);
s_nPreHour = time.wHour;
s_nPreMinute = time.wMinute;
}


// 如果秒改变的话就擦除秒针,然后重画所有指针
if (time.wSecond != s_nPreSecond)
{
// 擦除秒针
DrawHand(hdc, 400, 1, s_nPreSecond * 6, crfColor);


// 重画所有指针
DrawHand(hdc, 400, 1, time.wSecond * 6, RGB(0, 0, 0));
DrawHand(hdc, 200, 8, time.wHour * 30 + time.wMinute / 2, RGB(0, 0, 0));
DrawHand(hdc, 400, 6, time.wMinute * 6, RGB(0, 0, 0));
s_nPreSecond = time.wSecond;
}
return 0;
}
case WM_CONTEXTMENU:
POINT pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam);
{
// 取得系统菜单的句柄
HMENU hSysMenu = ::GetSystemMenu(hWnd, FALSE);


// 弹出系统菜单
int nID = ::TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_RETURNCMD,
pt.x, pt.y, 0, hWnd, NULL);
if (nID > 0)
::SendMessage(hWnd, WM_SYSCOMMAND, nID, 0);
return 0;
}
case WM_CLOSE:
{
::KillTimer(hWnd, IDT_CLOCK);
::DestroyWindow(hWnd);
return 0;
}
case WM_DESTROY:
{
  ::PostQuitMessage(0);
  return 0;
}
case WM_NCHITTEST:
{
UINT nHitTest;
nHitTest = ::DefWindowProc(hWnd, WM_NCHITTEST, wParam, lParam);
if (nHitTest == HTCLIENT &&
::GetAsyncKeyState(MK_LBUTTON) < 0) // 如果鼠标左键按下,GetAsyncKeyState函数的返回值小于0
nHitTest = HTCAPTION;
return nHitTest;
}
case WM_SYSCOMMAND:
int nID = wParam;
{
if (nID == IDM_HELP)
{
::MessageBox(hWnd, "一个时钟的例子", "时钟", 0);
}
else if (nID == IDM_TOPMOST)
{
HMENU hSysMenu = ::GetSystemMenu(hWnd, FALSE);
if (s_bTopMost)
{
::CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
s_bTopMost = FALSE;
}
else
{
::CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_CHECKED);
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
s_bTopMost = TRUE;
}
}
return ::DefWindowProc(hWnd, WM_SYSCOMMAND, nID, 0);
}
}


return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}








void SetIsotropic(HDC hdc, int cx, int cy)
{
::SetMapMode(hdc, MM_ISOTROPIC);
::SetWindowExtEx(hdc, 1000, 1000, NULL);
::SetViewportExtEx(hdc, cx, -cy, NULL);
::SetViewportOrgEx(hdc, cx / 2, cy / 2, NULL);
}


// 绘制时钟的外观
void DrawClockFace(HDC hdc)
{
const int SQUARESIZE = 20;
static POINT pt[] =
{
0, 450,        // 12点
225, 390,    // 1点
390, 225,    // 2点
450, 0,        // 3点
390, -225,    // 下面的坐标是上面的点的对称点(以X轴、Y轴或原点对称)
225, -390,
0, -450,
-225, -390,
-390, -225,
-450, 0,
-390, 225,
-225, 390
};


// 选择一个黑色的画刷
::SelectObject(hdc, ::GetStockObject(BLACK_BRUSH));


// 画12个圆
for (int i = 0; i < 12; i++)
{
::Ellipse(hdc, pt[i].x - SQUARESIZE, pt[i].y + SQUARESIZE,
pt[i].x + SQUARESIZE, pt[i].y - SQUARESIZE);
}
}






// 指针的长度、宽度、相对于0点偏移的角度、颜色分别由参数nLength、nWidth、nDegrees、clrColor指定
void DrawHand(HDC hdc, int nLength, int nWidth, int nDegrees, COLORREF clrColor)
{
// 将角度nDegrees转化成弧度 .    2*3.1415926/360 == 0.0174533
double nRadians = (double)nDegrees*0.0174533;


// 计算坐标
POINT pt[2];
pt[0].x = (int)(nLength*sin(nRadians));
pt[0].y = (int)(nLength*cos(nRadians));
pt[1].x = -pt[0].x / 5;
pt[1].y = -pt[0].y / 5;


// 创建画笔,并选如DC结构中
HPEN hPen = ::CreatePen(PS_SOLID, nWidth, clrColor);
HPEN hOldPen = (HPEN)::SelectObject(hdc, hPen);


// 画线
::MoveToEx(hdc, pt[0].x, pt[0].y, NULL);
::LineTo(hdc, pt[1].x, pt[1].y);


::SelectObject(hdc, hOldPen);
::DeleteObject(hPen);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值