• 《windows程序设计》学习_4.1:计时器(可用于扫雷)


    欢迎来我的个人网站:http://www.rxwcv.cn

        

      为了做一个逼真的扫雷,我的扫雷程序的位图都是从windowsXP下面的扫雷里来的。具体是怎么获取位图的呢?win8.1不给力,习惯了vc++6.0,所以虚拟机里装上了xp,用vc++6.0加载扫雷程序,就可以获得xp原版的位图了。

          这次要做的是一个计时器,扫雷的的计时器不是时、分、秒;类型的,而是百秒、十秒、秒类型的。看过雷区翻盖的朋友,也该都能明白,计时器显示时间的变化其实也是在画图,不停的换0~9这几个数字的图。那么现在只需要一个时钟消息,让他来触发画图就可以了。而windows中,恰好有这个消息:WM_TIMER。这个消息是如何使用的呢?

          当你要触发计时器时,先要设置计时器(SetTimer);当时钟到来以后,在WM_TIMER写响应程序;在不需要计时器的时候,注销计时器 (KillTimer)。这也是我的程序的大体思路:当WM_CREATE消息到来时,先把时钟画出来,画在右上角,值全为0;当单击鼠标左键时开始计 时,时钟到来的时候,发送自定义消息;在自定义消息下画图(显示出时钟跳动),当WM_DESTROY消息到来时,注销掉时钟。

          程序中定义的宏是用来表示计时器用的,因为我们完全可以设置多个计时器,每个计时器时钟间隔不同来完成扫雷中计时器功能。但我并不是这样做的,而是 设置了一个一秒跳动一下的计时器,并且设置了一个整型变量sec记录秒数。sec%10表明了是多少秒;(sec%100)/10表示的是几十秒(这里主 要是因为直接整除10会出现错误的结果,所以先把百位去掉了);sec/100表明的是几百秒。

    #include <windows.h>
    #include "resource.h"
    
    #define ID_TIMER_1   1
    
    
    //自定义消息
    #define WM_MYMSG (WM_USER + 100) 
    
    LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance,        //当前实例句柄
                       HINSTANCE hPrevInstance, //先前实例句柄
                       LPSTR lpCmdLine,            //命令行
                       int nCmdShow)            //显示状态,全屏,最小化或一般
    {
        static TCHAR szAppName[] = TEXT("计时器");
        //窗口句柄
        HWND hwnd;
        //消息
        MSG msg;
        //窗口类
        WNDCLASS wndclass;
        //窗口风格:当移动窗口或者改变大小时重绘窗口
        wndclass.style           =  CS_HREDRAW | CS_VREDRAW;
        //指明回调函数
        wndclass.lpfnWndProc   = WndProc;
        //额外的比特用来确认下一个窗口类的位置,暂时不用
        wndclass.cbClsExtra    = 0;
        //额外的比特用来确认下一个窗口实例的位置,暂时不用
        wndclass.cbWndExtra    = 0;
        //实例句柄
        wndclass.hInstance     = hInstance;
        //装载图标
        wndclass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
        //装载光标
        wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
        
        wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
        //菜单:暂时无
        wndclass.lpszMenuName  = NULL;
        //窗口类名
        wndclass.lpszClassName = szAppName;
    
        //注册窗口
        if(!RegisterClass(&wndclass))
        {
            return -1;
        }
    
        //创建窗口
        hwnd = CreateWindow(szAppName,                
                            TEXT("计时器"),            
                            WS_OVERLAPPEDWINDOW,    
                            CW_USEDEFAULT,            
                            CW_USEDEFAULT,            
                            CW_USEDEFAULT,            
                            CW_USEDEFAULT,            
                            NULL,                    
                            NULL,                    
                            hInstance,                
                            NULL);                    
    
        //显示窗口
        ShowWindow(hwnd,SW_SHOWNA);
    
        //更新窗口
        UpdateWindow(hwnd);
    
        //消息循环
        while(GetMessage(&msg,NULL,0,0))
        {
            
            TranslateMessage(&msg);
            //将消息给窗口
            DispatchMessage(&msg);
    
        }
    
        return msg.wParam;
    
    }
    //回调函数:本程序的主要功能是设计一个计时器
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        //位图句柄
        static HBITMAP hBitmap_clc;
        //客户区大小
        static int cxClient,cyClient;
        //资源大小
        static int cxSource_clc,cySource_clc;
        //位图结构信息
        BITMAP bitmap_clc;
        //设备描述表句柄
        HDC hdc,hdcMem;
        //实例句柄
        HINSTANCE hInstance;
        //绘图结构信息
        PAINTSTRUCT ps;
        //计时用的变量
        static int sec = 0; 
    
        switch(message)
        {
        //创建消息:装载位图,获取位图信息
        case WM_CREATE:
            //获得实例句柄
            hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
            //装载位图
            hBitmap_clc = LoadBitmap(hInstance, MAKEINTRESOURCE  (IDB_BITMAP1));
            //获取位图的信息,放到bitmap_clc里
            GetObject(hBitmap_clc,sizeof(BITMAP),&bitmap_clc);
            //每个数字的长和宽
            cxSource_clc = bitmap_clc.bmWidth;
            cySource_clc = bitmap_clc.bmHeight/12;
            return 0;
    
        //当前客户区大小
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
    
        //绘图消息:设置默认的贴图
        case WM_PAINT:
            hdc = BeginPaint (hwnd, &ps);
            //给指定的设备创建兼容的内存设备内容
            hdcMem = CreateCompatibleDC(hdc);
            //把对象选到设备内容中:参数为设备内容句柄,对象句柄
            SelectObject(hdcMem,hBitmap_clc);
            //开始画图
            //贴图位置:最右边是1秒,中间10秒,左边100秒        
            BitBlt(hdc, cxClient-cxSource_clc,   0, cxSource_clc, cySource_clc,hdcMem, 0, cySource_clc*11, SRCCOPY);
            BitBlt(hdc, cxClient-cxSource_clc*2, 0, cxSource_clc, cySource_clc,hdcMem, 0, cySource_clc*11, SRCCOPY);
            BitBlt(hdc, cxClient-cxSource_clc*3, 0, cxSource_clc, cySource_clc,hdcMem, 0, cySource_clc*11, SRCCOPY);
            DeleteDC(hdcMem);
            EndPaint (hwnd, &ps); 
            return 0;
    
        //鼠标左键点击:开始计时
        case WM_LBUTTONDOWN:
            SetTimer(hwnd,ID_TIMER_1,1000,NULL);
            return 0;
    
        //时钟到来:发出声音,发送自定义消息
        case WM_TIMER:
            //MessageBeep(MB_ICONASTERISK);
            PlaySound(TEXT("123.wav"), NULL, SND_FILENAME | SND_ASYNC);   //自定义声音
            sec++;
            //发送自定义消息
            SendMessage(hwnd,WM_MYMSG,wParam,lParam); 
            return 0;
        //自定义消息,开始画图改变时钟的值
        case WM_MYMSG:
            hdc = GetDC(hwnd);
            hdcMem =  CreateCompatibleDC(hdc);
            SelectObject(hdcMem,hBitmap_clc);
            //开始画图
            //数字的位置:0是第12个,位置为cySource_clc*11,1?是第11个,位置为cySource_clc*10,依次类推
            BitBlt(hdc, cxClient-cxSource_clc,   0, cxSource_clc, cySource_clc, hdcMem, 0, cySource_clc*(11-sec%10), SRCCOPY);
            BitBlt(hdc, cxClient-cxSource_clc*2, 0, cxSource_clc, cySource_clc, hdcMem, 0, cySource_clc*(11-(sec%100)/10), SRCCOPY);
            BitBlt(hdc, cxClient-cxSource_clc*3, 0, cxSource_clc, cySource_clc, hdcMem, 0, cySource_clc*(11-sec/100), SRCCOPY);
            DeleteDC(hdcMem);
            ReleaseDC(hwnd,hdc);
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            KillTimer(hwnd,ID_TIMER_1);
            return 0;
        }
        //缺省处理
        return DefWindowProc (hwnd, message, wParam, lParam);
    }

    欢迎来我的个人网站:http://www.rxwcv.cn
  • 相关阅读:
    编译器小知识
    C++ 文件大小格式化
    如何利用开盘半小时预测当天走势
    判断股票跌到位及买进时机的简单原则
    六招炒股绝技 牛市熊市都赚钱
    细分行业龙头
    股市新手入门口诀
    关于量价十八则的口诀
    如何确认底部的条件及操作原则
    每日一招:散户巧寻主力筹码的方法
  • 原文地址:https://www.cnblogs.com/Hewie/p/3423267.html
Copyright © 2020-2023  润新知