本文由BlueCoder编写 转载请说明出处:
http://blog.csdn.net/crocodile__/article/details/9448103
我的邮箱:bluecoder@yeah.net 欢迎大家和我交流编程心得
我的微博:BlueCoder_黎小华 欢迎光临^_^
学习编程离不开实战演练——用所掌握的技术来实现相应的功能,今天来玩一玩Win32的位图Bitmap,写一个数字时钟
我们先来看看这个数字时钟的需求:
(1)可以用ASCII码的数字,但是不太美观,因此需要做一个位图,完美模拟电子表的数字(我亲自做了一个,待会儿上传)
(2)如何将位图贴到我们的程序中
a)先将位图加载到内存中
我们先来看看msdn:
HBITMAP LoadBitmap( HINSTANCE hInstance, // handle to application instance LPCTSTR lpBitmapName // name of bitmap resource );因此不难知道使用方法,用法我没必要多少,我只想提一点:
我们的位图是保存在硬盘(ROM)中的,程序是在内存(RAM)中的,因此首先需将位图加载到内存中,我们的程序才能直接使用。LoadBitmap函数就是其这样一个作用
类似的函数还有:LoadIcon、LoadCursor等等
b)将位图贴到我们的程序中
这个需要用到很常用的、也是很有用的函数:
BOOL BitBlt( HDC hdcDest, // handle to destination DC int nXDest, // x-coord of destination upper-left corner int nYDest, // y-coord of destination upper-left corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle HDC hdcSrc, // handle to source DC int nXSrc, // x-coordinate of source upper-left corner int nYSrc, // y-coordinate of source upper-left corner DWORD dwRop // raster operation code );这个函数有一个很强大的功能:
我们可以按照自己的需要截取位图的一部分,这就意味着有时我们的程序只需要那么几张、或是仅仅一张位图,就能达到使用更多张位图的效果
它的具体用法可以参见给出的完整代码
(3)获取系统时间
这个就没什么多说的了,直接使用以下函数就ok:
GetLocalTime(LPSYSTEMTIME)//传递一个SYSTEMTIME类型的指针 就是系统时间
(4)时间的处理
我就仅仅介绍我的做法:
int x, y, cxBitmap, cyBitmap;
//x、y表示位图贴在窗口客户区的坐标,cxBitmap、cyBitmap表示位图的长宽。为了方便起见,以上四个全是全局变量
时间处理代码:
VOID DrawTime(HDC hdc, WORD time, BOOL isSecond) { HDC hdcMem; int decade, uint;//十位和个位 hdcMem = CreateCompatibleDC(hdc); //兼容DC SelectObject(hdcMem, hBitmap); //选中位图 //判断当前时间是否小于10 ,如果小于10 , 就要用0来填十位 if(time < 10) { decade = 0; uint = time; } else { decade = time / 10; uint = time % 10; } //绘制十位 x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, (11 - decade) * (cyBitmap / 12), SRCCOPY); //绘制个位 x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, (11 - uint) * (cyBitmap / 12), SRCCOPY); //如果不是秒 , 那么个位后面加一个冒号 if(!isSecond) { x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, cyBitmap / 12, SRCCOPY); } DeleteDC(hdcMem); }
(5)设定一个时间计时器,每隔一秒调用一次(这个不是本次的重点,以后会讲到的,其实很简单^_^)
下面直接上完整的源代码:(有注释)
//数字时钟 #include<windows.h> #include"resource.h" //重新定义窗口风格(不可改变大小) #define WS_NORESIZEWINDOW (WS_OVERLAPPED | \ WS_CAPTION | \ WS_SYSMENU | \ WS_MINIMIZEBOX) //设定计时器ID #define ID_TIMER 1 HBITMAP hBitmap; int x, y, cxBitmap, cyBitmap; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("NumClock"); 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)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("NumClock Demo"), WS_NORESIZEWINDOW, (1366 - 200) / 2, (768 - 150) / 2, 200, 150, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } VOID DrawTime(HDC hdc, WORD time, BOOL isSecond) { HDC hdcMem; int decade, uint;//十位和个位 hdcMem = CreateCompatibleDC(hdc); //兼容DC SelectObject(hdcMem, hBitmap); //选中位图 //判断当前时间是否小于10 ,如果小于10 , 就要用0来填十位 if(time < 10) { decade = 0; uint = time; } else { decade = time / 10; uint = time % 10; } //绘制十位 x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, (11 - decade) * (cyBitmap / 12), SRCCOPY); //绘制个位 x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, (11 - uint) * (cyBitmap / 12), SRCCOPY); //如果不是秒 , 那么个位后面加一个冒号 if(!isSecond) { x += cxBitmap; BitBlt(hdc, x, y, cxBitmap, cyBitmap / 12, hdcMem, 0, cyBitmap / 12, SRCCOPY); } DeleteDC(hdcMem); } //计时器回调函数 VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) { HDC hdc; SYSTEMTIME st; GetLocalTime(&st);//获取本地系统时间 hdc = GetDC(hwnd); x = 33; y = 51; DrawTime(hdc, st.wHour, FALSE); //绘制小时数字 DrawTime(hdc, st.wMinute, FALSE); //绘制分钟数字 DrawTime(hdc, st.wSecond, TRUE); //绘制秒钟数字 ReleaseDC(hwnd, hdc); } //窗口回调函数 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { //初始化参数 case WM_CREATE: { HINSTANCE hInstance; BITMAP bitmap; hInstance = ((LPCREATESTRUCT)lParam)->hInstance;//获取窗口的实例句柄 hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); GetObject(hBitmap, sizeof(BITMAP), &bitmap); cxBitmap = bitmap.bmWidth; cyBitmap = bitmap.bmHeight; SetTimer(hwnd, ID_TIMER, 1000, TimerProc);//计时器开始 } return 0 ; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
好了到此为止,数字时钟算是完成了,下面来看看运行效果:
怎么样,是不是和电子表的显示很相似呢?呵呵……
点击下载位图资源