本文由BlueCoder編寫 轉載請說明出處:
http://blog.csdn.net/crocodile__/article/details/9448103
我的郵箱:[email protected] 歡迎大家和我交流編程心得
我的微博: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);
}
好了到此爲止,數字時鐘算是完成了,下面來看看運行效果:
怎麼樣,是不是和電子錶的顯示很相似呢?呵呵……