Bitmap位圖應用1 ------ Win32的數字時鐘

本文由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);
}


 


 

 

好了到此爲止,數字時鐘算是完成了,下面來看看運行效果:

 

怎麼樣,是不是和電子錶的顯示很相似呢?呵呵……

 

 

點擊下載位圖資源

發佈了39 篇原創文章 · 獲贊 29 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章