• Windows下编程--模拟时钟的实现


    windows下编程--模拟时钟的实现:

    主要可以分为几个步骤:

    (1)   编写按键事件处理(启动和停止时钟)

    (2)   编写时钟事件处理,调用显示时钟函数

    (3)   编写显示时钟函数,要调用显示数字时钟函数、画出钟面函数和画出指针函数

    (4)   编写显示数字时钟函数。注意要自己用矩形填充(FillRect)擦除背景。

    (5)   编写画出钟面函数

    (6)   编写画出指针函数

    (7)   增加WM_PAINT消息处理:调用显示时钟函数,防止在停止时钟后从窗口最小化恢复会不显示内容。

    最后结果类似于这种形式---一个模拟时钟,数字时钟+画面时钟

    每一步的说明:

    (1)编写按键事件处理(启动和停止时钟)

    (2)   编写时钟事件处理,调用显示时钟函数

    (3)   编写显示时钟函数,要调用显示数字时钟函数、画出钟面函数和画出指针函数

    (4)   编写显示数字时钟函数。注意要自己用矩形填充(FillRect)擦除背景。

    (5) 编写画出钟面函数

    (6)   编写画出指针函数(注意好时针分针秒针的角度关系计算方法就行了)

    (7)   增加WM_PAINT消息处理:调用显示时钟函数,防止在停止时钟后从窗口最小化恢复会不显示内容。

    基本上只是考察了基本的windows编程,掌握好时钟事件和按钮的编程。

    最后附上长长的代码...

      1 /*------------------------------------------------------------
      2    HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
      3                  (c) Charles Petzold, 1998
      4   ------------------------------------------------------------*/
      5 
      6 #include <windows.h>
      7 #include <stdio.h>
      8 #include <math.h>
      9 
     10 #define PI        3.14159265358979323846
     11 #define TIMER_SEC   1
     12 #define TIMER_MIN   2
     13 #define BUTTON1     3
     14 #define BUTTON2     4
     15 
     16 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
     17 
     18 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
     19                     PSTR szCmdLine, int iCmdShow)
     20 {
     21      static TCHAR szAppName[] = TEXT ("HelloWin") ;
     22      HWND         hwnd,hwndButton1,hwndButton2;
     23      MSG          msg ;
     24      WNDCLASS     wndclass ;
     25 
     26      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     27      wndclass.lpfnWndProc   = WndProc ;
     28      wndclass.cbClsExtra    = 0 ;
     29      wndclass.cbWndExtra    = 0 ;
     30      wndclass.hInstance     = hInstance ;
     31      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     32      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     33      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     34      wndclass.lpszMenuName  = NULL ;
     35      wndclass.lpszClassName = szAppName ;
     36 
     37      if (!RegisterClass (&wndclass))
     38      {
     39           MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
     40                       szAppName, MB_ICONERROR) ;
     41           return 0 ;
     42      }
     43      
     44      hwnd = CreateWindow (szAppName,                  // window class name
     45                           TEXT ("Analog Clock"), // window caption
     46                           WS_OVERLAPPEDWINDOW,        // window style
     47                           CW_USEDEFAULT,              // initial x position
     48                           CW_USEDEFAULT,              // initial y position
     49                           560,              // initial x size
     50                           360,              // initial y size
     51                           NULL,                       // parent window handle
     52                           NULL,                       // window menu handle
     53                           hInstance,                  // program instance handle
     54                           NULL) ;                     // creation parameters
     55      
     56      ShowWindow (hwnd, iCmdShow) ;
     57      UpdateWindow (hwnd) ;
     58 
     59      hwndButton1 = CreateWindow(TEXT("button"),                       // 窗口类名(系统内部定义了该窗口类)
     60          TEXT("StartTimer"),                               // 标题
     61          WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,        // 样式
     62          100, 250,                                      // 左上角位置x,y
     63          120, 40,                                         // 宽度,高度
     64          hwnd,                                        // 父窗口句柄
     65          (HMENU)BUTTON1,                                // 控件ID
     66          hInstance,                                     // 实例句柄
     67          NULL);                                        // 自定义参数
     68 
     69      hwndButton2 = CreateWindow(TEXT("button"),                       // 窗口类名
     70          TEXT("StopTimer"),                               // 标题
     71          WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,        // 样式
     72          300, 250,                                      // 左上角位置x,y
     73          120, 40,                                         // 宽度,高度
     74          hwnd,                                        // 父窗口句柄
     75          (HMENU)BUTTON2,                                // 控件ID
     76          hInstance,                                     // 实例句柄
     77          NULL);
     78 
     79      while (GetMessage (&msg, NULL, 0, 0))
     80      {
     81           TranslateMessage (&msg) ;
     82           DispatchMessage (&msg) ;
     83      }
     84      return msg.wParam ;
     85 }
     86 
     87 // 画出钟面(不包括指针)
     88 void DrawClockFace(HDC hdc){
     89 //    PAINTSTRUCT ps;
     90     RECT        rect;
     91     HPEN hPen;
     92     HPEN oldPen;
     93     hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));                    // 创建画笔(线形,线宽,颜色)
     94     oldPen = (HPEN)SelectObject(hdc, hPen);        // 选择画笔,并保留原画笔
     95     Ellipse(hdc, 180, 20, 340, 180);   // 时钟--半径 80  作出时钟原始图像
     96     Rectangle(hdc, 220, 205, 295, 230);
     97     double xStart1, yStart1, xEnd1, yEnd1;
     98     for (int i = 0; i <= 11; i++){
     99         if (i <= 3){
    100             xEnd1 = 260 + 80 * sin(i* PI / 6);
    101             xStart1 = 260 + (80 - 10) * sin(i* PI / 6);
    102             yEnd1 = 100 - 80 * cos(i* PI / 6);
    103             yStart1 = 100 - (80 - 10) * cos(i* PI / 6);
    104         }
    105         if (i > 3 && i <= 6){
    106             xEnd1 = 260 + 80 * sin(i* PI / 6);
    107             xStart1 = 260 + (80 - 10) * sin(i* PI / 6);
    108             yStart1 = 100 + (80 - 10) * cos(PI - i* PI / 6);
    109             yEnd1 = 100 + 80 * cos(PI - i* PI / 6);
    110         }
    111         if (i > 6 && i <= 9)
    112         {
    113             xEnd1 = 260 - 80 * cos(1.5*PI - i* PI / 6);
    114             xStart1 = 260 - (80 - 10) * cos(1.5*PI - i* PI / 6);
    115             yStart1 = 100 + (80 - 10) * sin(1.5*PI - i* PI / 6);
    116             yEnd1 = 100 + 80 * sin(1.5*PI - i* PI / 6);
    117         }
    118         if (i > 9){
    119             xEnd1 = 260 - 80 * sin(2 * PI - i* PI / 6);
    120             xStart1 = 260 - (80 - 10) * sin(2 * PI - i* PI / 6);
    121             yEnd1 = 100 - 80 * cos(2 * PI - i* PI / 6);
    122             yStart1 = 100 - (80 - 10) * cos(2 * PI - i* PI / 6);
    123         }
    124         MoveToEx(hdc, xStart1, yStart1, NULL);
    125         LineTo(hdc, xEnd1, yEnd1);
    126     }
    127     DeleteObject(hPen);
    128     // 钟面相应数字 --- 12
    129     rect.left = 250;
    130     rect.top = 5;
    131     rect.right = 270;
    132     rect.bottom = 18;
    133     DrawText(hdc, TEXT("12"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    134     // 钟面相应数字 --- 11
    135     rect.left = 210;
    136     rect.top = 15;
    137     rect.right = 220;
    138     rect.bottom = 30;
    139     DrawText(hdc, TEXT("11"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    140     // 钟面相应数字 --- 10
    141     rect.left = 175;
    142     rect.top = 50;
    143     rect.right = 190;
    144     rect.bottom = 60;
    145     DrawText(hdc, TEXT("10"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    146     // 钟面相应数字 --- 9
    147     rect.left = 165;
    148     rect.top = 95;
    149     rect.right = 175;
    150     rect.bottom = 105;
    151     DrawText(hdc, TEXT("9"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    152     // 钟面相应数字 --- 8
    153     rect.left = 175;
    154     rect.top = 135;
    155     rect.right = 190;
    156     rect.bottom = 145;
    157     DrawText(hdc, TEXT("8"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    158     // 钟面相应数字 --- 7
    159     rect.left = 208;
    160     rect.top = 167;
    161     rect.right = 215;
    162     rect.bottom = 185;
    163     DrawText(hdc, TEXT("7"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    164     // 钟面相应数字 --- 6
    165     rect.left = 250;
    166     rect.top = 182;
    167     rect.right = 270;
    168     rect.bottom = 192;
    169     DrawText(hdc, TEXT("6"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    170     // 钟面相应数字 --- 5
    171     rect.left = 295;
    172     rect.top = 170;
    173     rect.right = 310;
    174     rect.bottom = 180;
    175     DrawText(hdc, TEXT("5"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    176     // 钟面相应数字 --- 4
    177     rect.left = 335;
    178     rect.top = 135;
    179     rect.right = 345;
    180     rect.bottom = 145;
    181     DrawText(hdc, TEXT("4"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    182     // 钟面相应数字 --- 3
    183     rect.left = 345;
    184     rect.top = 95;
    185     rect.right = 355;
    186     rect.bottom = 105;
    187     DrawText(hdc, TEXT("3"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    188     // 钟面相应数字 --- 2
    189     rect.left = 335;
    190     rect.top = 48;
    191     rect.right = 345;
    192     rect.bottom = 60;
    193     DrawText(hdc, TEXT("2"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    194     // 钟面相应数字 --- 1
    195     rect.left = 300;
    196     rect.top = 20;
    197     rect.right = 310;
    198     rect.bottom = 30;
    199     DrawText(hdc, TEXT("1"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    200     return;
    201 }
    202 
    203 // 画出时钟指针
    204 void DrawClockHands(HDC hdc,int hour,int min,int sec){
    205     PAINTSTRUCT ps;
    206     RECT        rect;
    207     HPEN hPen;
    208     HPEN oldPen;
    209     double xStart1, yStart1, xEnd1, yEnd1;
    210     hour = (hour >= 12 ? hour - 12 : hour);
    211     hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 0));                    // 创建画笔(线形,线宽,颜色)
    212     oldPen = (HPEN)SelectObject(hdc, hPen);        // 选择画笔,并保留原画笔
    213                                            // 显示时针
    214     xStart1 = 260;
    215     yStart1 = 100;
    216     xEnd1 = 260 + (80 - 50) * sin(hour*PI / 6 + ((min * 60 + sec) * PI / (1800*12)));
    217     yEnd1 = 100 - (80 - 50) * cos(hour*PI / 6 + ((min * 60 + sec) * PI / (1800*12)));
    218     MoveToEx(hdc, xStart1, yStart1, NULL);
    219     LineTo(hdc, xEnd1, yEnd1);
    220     DeleteObject(hPen);
    221 
    222     hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 0));                    // 创建画笔(线形,线宽,颜色)
    223     oldPen = (HPEN)SelectObject(hdc, hPen);        // 选择画笔,并保留原画笔
    224                                          // 显示分针
    225     xStart1 = 260;
    226     yStart1 = 100;
    227     xEnd1 = 260 + (80 - 35) * sin(min*PI / 30 + (sec * PI / 1800));
    228     yEnd1 = 100 - (80 - 35) * cos(min*PI / 30 + (sec * PI / 1800));
    229     MoveToEx(hdc, xStart1, yStart1, NULL);
    230     LineTo(hdc, xEnd1, yEnd1);
    231     DeleteObject(hPen);
    232 
    233     hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));                    // 创建画笔(线形,线宽,颜色)
    234     oldPen = (HPEN)SelectObject(hdc, hPen);        // 选择画笔,并保留原画笔
    235                                           // 显示秒针
    236     xStart1 = 260;
    237     yStart1 = 100;
    238     xEnd1 = 260 + (80 - 15) * sin(sec * PI / 30);
    239     yEnd1 = 100 - (80 - 15) * cos(sec * PI / 30);
    240     MoveToEx(hdc, xStart1, yStart1, NULL);
    241     LineTo(hdc, xEnd1, yEnd1);
    242     DeleteObject(hPen);
    243 
    244     return;
    245 }
    246 /*////////////////////////////////////////////////////
    247 void ShowTime1(HDC hdc){          // use for debug
    248     HPEN hPen, oldPen;
    249     hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));    // 创建画笔(线形,线宽,颜色)
    250     oldPen = (HPEN)SelectObject(hdc, hPen);        // 选择画笔,并保留原画笔
    251     MoveToEx(hdc, 5, 5, NULL);
    252     LineTo(hdc, 10, 10);
    253 }
    254 *////////////////////////////////////////////////////
    255 
    256 // 显示数字时钟,注意用函数FillRect擦除背景
    257 void ShowTime(HDC hdc,int hour,int min,int sec){
    258     PAINTSTRUCT ps;
    259     RECT       rect;
    260     LOGBRUSH    logbrush;
    261     HBRUSH        hBrush, oldBrush;
    262     HRGN        hRgn;        // 区域用于区域填充、剪切、合并、反转、画边框或设无效区 
    263 
    264     HDC hdc1;
    265     HPEN hPen, oldPen;
    266     hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));                    // 创建画笔(线形,线宽,颜色)
    267     oldPen = (HPEN)SelectObject(hdc1, hPen);        // 选择画笔,并保留原画笔
    268     MoveToEx(hdc1, 5, 5, NULL);
    269     LineTo(hdc1, 10, 10);
    270 
    271 //    logbrush.lbColor = RGB(255, 255, 255);
    272 //    logbrush.lbHatch = HS_BDIAGONAL;                    // 阴影样式:HS_BDIAGONAL 对角线,HS_DIAGCROSS 对角交叉线
    273 //    logbrush.lbStyle = BS_HATCHED;                        // 画刷样式:BS_SOLID 实心,BS_HATCHED 阴影
    274 //    hBrush = (HBRUSH)CreateBrushIndirect(&logbrush);
    275     hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
    276     oldBrush = (HBRUSH)SelectObject(hdc, hBrush);        // 选择画刷,并保留原画刷
    277     SelectObject(hdc, hBrush);
    278     hRgn = CreateEllipticRgn(195, 35, 325, 165);        // 定义区域 
    279     FillRgn(hdc, hRgn, hBrush);                            // 填充区域
    280     DeleteObject(hBrush);                            // 删除画刷
    281     SelectObject(hdc, oldBrush);                    // 恢复原画刷
    282 
    283     DrawClockHands(hdc, hour, min, sec);
    284     return;
    285 }
    286 
    287 // 显示时钟函数,
    288 void ShowClock(HWND hwnd){
    289     int x,y,r;
    290     HDC hdc = GetDC(hwnd);
    291     RECT rect;
    292     TCHAR buf[100];
    293     SYSTEMTIME     st;
    294 
    295     //GetClientRect(hwnd,&rect);
    296     rect.left = 230;
    297     rect.top = 210;
    298     rect.right = rect.left + 100;
    299     rect.bottom = rect.top + 30;
    300     GetLocalTime(&st);
    301     wsprintf(buf, TEXT("%d:%d:%d"), st.wHour, st.wMinute, st.wSecond);
    302     DrawText(hdc, buf, -1, &rect,
    303         DT_SINGLELINE | DT_LEFT | DT_TOP);
    304 
    305     ReleaseDC(hwnd, hdc);
    306     return;
    307 }
    308 
    309 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    310 {
    311      HDC         hdc ;
    312      PAINTSTRUCT ps ;
    313      HPEN hPen;
    314      HPEN oldPen;
    315      SYSTEMTIME     st;
    316      switch (message)
    317      {
    318      case WM_CREATE:
    319           PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
    320           return 0 ;
    321           
    322      case WM_PAINT:
    323           hdc = BeginPaint (hwnd, &ps) ;
    324           DrawClockFace(hdc);   // 画钟
    325           GetLocalTime(&st);    //画时针分针秒针
    326          DrawClockHands(hdc ,st.wHour, st.wMinute, st.wSecond);
    327           ShowClock(hwnd);// 当窗口重刷时显示时间,否则停止时钟时可能空白
    328         //  EndPaint(hwnd, &ps) ;
    329           return 0 ;
    330      
    331      case WM_COMMAND:
    332          // LOWORD (wParam) 子窗口ID, HIWORD (wParam)     按钮通知码, lParam    子窗口句柄
    333 
    334          switch (LOWORD(wParam))  //子窗口ID
    335          {
    336          case BUTTON1:
    337              SetTimer(hwnd, TIMER_SEC, 1000, NULL); // 启动定时器(1000毫秒一次),TIMER_SEC为自定义索引号
    338              break;
    339          case BUTTON2:
    340              KillTimer(hwnd, TIMER_SEC);            // 删除定时器
    341              break;
    342          }
    343          return 0;
    344 
    345      case WM_TIMER:
    346          switch (wParam)
    347          {
    348          case TIMER_SEC:
    349              ShowClock(hwnd);//每秒一次的处理
    350              InvalidateRgn(hwnd, NULL, 1);     // 使区域无效
    351             // ShowTime1(hdc);
    352              ShowTime(hdc, st.wHour, st.wMinute, st.wSecond);
    353 
    354              break;
    355          case TIMER_MIN:        //每分钟一次的处理
    356              break;
    357          }
    358          return 0;
    359      case WM_DESTROY:
    360           PostQuitMessage (0) ;
    361           return 0 ;
    362      }
    363      return DefWindowProc (hwnd, message, wParam, lParam) ;
    364 }
    View Code
  • 相关阅读:
    JS 给li标签下所有a标签添加点击事件并添加和删除样式
    Linux简介及常用命令
    简易计算器
    登陆窗口小项目
    时间工具类
    String类的常用方法(附带练习)
    java-自定义异常
    Java小练习
    Java-接口练习1
    动态加载js
  • 原文地址:https://www.cnblogs.com/imwtr/p/4105236.html
Copyright © 2020-2023  润新知