欢迎来我的个人网站: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