本文由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:
[cpp] view plain copy print ?
- GetLocalTime(LPSYSTEMTIME)
GetLocalTime(LPSYSTEMTIME)//传递一个SYSTEMTIME类型的指针 就是系统时间
(4)时间的处理
我就仅仅介绍我的做法:
[cpp] view plain copy print ?
- int x, y, cxBitmap, cyBitmap;
int x, y, cxBitmap, cyBitmap;
[cpp] view plain copy print ?
-
//x、y表示位图贴在窗口客户区的坐标,cxBitmap、cyBitmap表示位图的长宽。为了方便起见,以上四个全是全局变量
时间处理代码:
[cpp] view plain copy print ?
- VOID DrawTime(HDC hdc, WORD time, BOOL isSecond)
- {
- HDC hdcMem;
- int decade, uint;
-
- hdcMem = CreateCompatibleDC(hdc);
- SelectObject(hdcMem, hBitmap);
-
-
- 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 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)设定一个时间计时器,每隔一秒调用一次(这个不是本次的重点,以后会讲到的,其实很简单^_^)
下面直接上完整的源代码:(有注释)
[cpp] view plain copy print ?
-
- #include<windows.h>
- #include"resource.h"
-
-
- #define WS_NORESIZEWINDOW (WS_OVERLAPPED | \
- WS_CAPTION | \
- WS_SYSMENU | \
- WS_MINIMIZEBOX)
-
- #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);
- SelectObject(hdcMem, hBitmap);
-
-
- 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);
- }
//数字时钟
#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);
}
好了到此为止,数字时钟算是完成了,下面来看看运行效果:

怎么样,是不是和电子表的显示很相似呢?呵呵……
点击下载数字时钟