zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/imwtr/p/4105236.html
Copyright © 2011-2022 走看看