位图(Bitmap)类背后的思路是,提供一种从文件或者资源加载位图并将位图绘制到一个设备环境的方法。通过将这些功能结合到一个类中,我们就能够在游戏中创建极易使用的Bitmap对象,并且可以隐藏处理位图的各种繁杂工作。Bitmap类有以下需求:
1.从文件中加载位图
2.从资源中加载位图
3.创建纯色的空白位图
4.将位图绘制到设备环境
5.获得位图的宽度和高度
代码清单:
//----------------------------------------------------------------- // Bitmap Object // C++ Header - Bitmap.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include //----------------------------------------------------------------- // Bitmap Class //----------------------------------------------------------------- class Bitmap { protected: // Member Variables HBITMAP m_hBitmap; int m_iWidth, m_iHeight; // Helper Methods void Free(); public: // Constructor(s)/Destructor Bitmap(); Bitmap(HDC hDC, LPTSTR szFileName); Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance); Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor = RGB(0, 0, 0)); virtual ~Bitmap(); // General Methods BOOL Create(HDC hDC, LPTSTR szFileName); BOOL Create(HDC hDC, UINT uiResID, HINSTANCE hInstance); BOOL Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor); void Draw(HDC hDC, int x, int y); int GetWidth() { return m_iWidth; }; int GetHeight() { return m_iHeight; }; };
//----------------------------------------------------------------- // Bitmap Object // C++ Source - Bitmap.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Bitmap.h" //----------------------------------------------------------------- // Bitmap Constructor(s)/Destructor //----------------------------------------------------------------- Bitmap::Bitmap() : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0) { } // Create a bitmap from a file Bitmap::Bitmap(HDC hDC, LPTSTR szFileName) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0) { Create(hDC, szFileName); } // Create a bitmap from a resource Bitmap::Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0) { Create(hDC, uiResID, hInstance); } // Create a blank bitmap from scratch Bitmap::Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0) { Create(hDC, iWidth, iHeight, crColor); } Bitmap::~Bitmap() { Free(); } //----------------------------------------------------------------- // Bitmap Helper Methods //----------------------------------------------------------------- void Bitmap::Free() { // Delete the bitmap graphics object if (m_hBitmap != NULL) { DeleteObject(m_hBitmap); m_hBitmap = NULL; } } //----------------------------------------------------------------- // Bitmap General Methods //----------------------------------------------------------------- BOOL Bitmap::Create(HDC hDC, LPTSTR szFileName) { // Free any previous bitmap info Free(); // Open the bitmap file HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; // Read the bitmap file header BITMAPFILEHEADER bmfHeader; DWORD dwBytesRead; BOOL bOK = ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); if ((!bOK) || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmfHeader.bfType != 0x4D42))//0x4D42 代表 "BM",为bmp文件的标志 { CloseHandle(hFile); return FALSE; } BITMAPINFO* pBitmapInfo = (new BITMAPINFO); if (pBitmapInfo != NULL) { // Read the bitmap info header bOK = ReadFile(hFile, pBitmapInfo, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL); if ((!bOK) || (dwBytesRead != sizeof(BITMAPINFOHEADER))) { CloseHandle(hFile); //Free(); return FALSE; } // Store the width and height of the bitmap m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth; m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight; // Get a handle to the bitmap and copy the image bits PBYTE pBitmapBits; m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0); if ((m_hBitmap != NULL) && (pBitmapBits != NULL)) { SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN);//更改文件指针 bOK = ReadFile(hFile, pBitmapBits, pBitmapInfo->bmiHeader.biSizeImage, &dwBytesRead, NULL); if (bOK) return TRUE; } } // Something went wrong, so cleanup everything Free(); return FALSE; } BOOL Bitmap::Create(HDC hDC, UINT uiResID, HINSTANCE hInstance) { // Free any previous DIB info Free(); // Find the bitmap resource HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(uiResID), RT_BITMAP); if (hResInfo == NULL) return FALSE; // Load the bitmap resource HGLOBAL hMemBitmap = LoadResource(hInstance, hResInfo); if (hMemBitmap == NULL) return FALSE; // Lock the resource and access the entire bitmap image PBYTE pBitmapImage = (BYTE*)LockResource(hMemBitmap); if (pBitmapImage == NULL) { FreeResource(hMemBitmap); return FALSE; } // Store the width and height of the bitmap BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage; m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth; m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight; // Get a handle to the bitmap and copy the image bits PBYTE pBitmapBits; m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0); if ((m_hBitmap != NULL) && (pBitmapBits != NULL)) { const PBYTE pTempBits = pBitmapImage + pBitmapInfo->bmiHeader.biSize + pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD); //从图像数据区开始copy CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage); // Unlock and free the bitmap graphics object UnlockResource(hMemBitmap); FreeResource(hMemBitmap); return TRUE; } // Something went wrong, so cleanup everything UnlockResource(hMemBitmap); FreeResource(hMemBitmap); Free(); return FALSE; } BOOL Bitmap::Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor) { // Create a blank bitmap m_hBitmap = CreateCompatibleBitmap(hDC, iWidth, iHeight); if (m_hBitmap == NULL) return FALSE; // Set the width and height m_iWidth = iWidth; m_iHeight = iHeight; // Create a memory device context to draw on the bitmap HDC hMemDC = CreateCompatibleDC(hDC); //为什么要用兼容的hdc? // Create a solid brush to fill the bitmap HBRUSH hBrush = CreateSolidBrush(crColor); // Select the bitmap into the device context HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap); // Fill the bitmap with a solid color RECT rcBitmap = { 0, 0, m_iWidth, m_iHeight }; FillRect(hMemDC, &rcBitmap, hBrush); // Cleanup SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); DeleteObject(hBrush); return TRUE; } void Bitmap::Draw(HDC hDC, int x, int y) { if (m_hBitmap != NULL) { // Create a memory device context for the bitmap HDC hMemDC = CreateCompatibleDC(hDC); // Select the bitmap into the device context HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap); // Draw the bitmap to the destination device context BitBlt(hDC, x, y, GetWidth(), GetHeight(), hMemDC, 0, 0, SRCCOPY); // Restore and delete the memory device context SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); } }
以下给出一个程序实例,应用Bitmap类。程序的效果是在窗口中定时循环显示一组幻灯片。
//----------------------------------------------------------------- // Slideshow Application // C++ Header - Slideshow.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include #include "Resource.h" #include "GameEngine.h" #include "Bitmap.h" //----------------------------------------------------------------- // Global Variables //----------------------------------------------------------------- HINSTANCE g_hInstance; GameEngine* g_pGame; const int g_iNUMSLIDES = 6; //幻灯片数量 Bitmap* g_pSlides[g_iNUMSLIDES]; int g_iCurSlide;
//----------------------------------------------------------------- // Slideshow Application // C++ Source - Slideshow.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Slideshow.h" //----------------------------------------------------------------- // Game Engine Functions //----------------------------------------------------------------- BOOL GameInitialize(HINSTANCE hInstance) { // Create the game engine g_pGame = new GameEngine(hInstance, TEXT("Slideshow"), TEXT("Slideshow"), IDI_SLIDESHOW, IDI_SLIDESHOW_SM); if (g_pGame == NULL) return FALSE; // Set the frame rate g_pGame->SetFrameRate(1); // Store the instance handle g_hInstance = hInstance; return TRUE; } void GameStart(HWND hWindow) { // Create and load the slide bitmaps HDC hDC = GetDC(hWindow); g_pSlides[0] = new Bitmap(hDC, TEXT("Image1.bmp")); g_pSlides[1] = new Bitmap(hDC, TEXT("Image2.bmp")); g_pSlides[2] = new Bitmap(hDC, TEXT("Image3.bmp")); g_pSlides[3] = new Bitmap(hDC, IDB_IMAGE4, g_hInstance); g_pSlides[4] = new Bitmap(hDC, IDB_IMAGE5, g_hInstance); g_pSlides[5] = new Bitmap(hDC, 640, 480, RGB(0, 0, 0)); // Set the first slide g_iCurSlide = 0; } void GameEnd() { // Cleanup the slide bitmaps for (int i = 0; i < g_iNUMSLIDES; i++) delete g_pSlides[i]; // Cleanup the game engine delete g_pGame; } void GameActivate(HWND hWindow) { } void GameDeactivate(HWND hWindow) { } void GamePaint(HDC hDC) { // Draw the current slide bitmap g_pSlides[g_iCurSlide]->Draw(hDC, 0, 0); } void GameCycle() { static int iDelay = 0; // Establish a 3-second delay before moving to the next slide if (++iDelay > 3) { // Restore the delay counter iDelay = 0; // Move to the next slide if (++g_iCurSlide == g_iNUMSLIDES) g_iCurSlide = 0; // Force a repaint to draw the next slide InvalidateRect(g_pGame->GetWindow(), NULL, FALSE); } }
//----------------------------------------------------------------- // Slideshow Resource Identifiers // C++ Header - Resource.h //----------------------------------------------------------------- //----------------------------------------------------------------- // Icons Range : 1000 - 1999 //----------------------------------------------------------------- #define IDI_SLIDESHOW 1000 #define IDI_SLIDESHOW_SM 1001 //----------------------------------------------------------------- // Bitmaps Range : 2000 - 2999 //----------------------------------------------------------------- #define IDB_IMAGE1 2000 #define IDB_IMAGE2 2001 #define IDB_IMAGE3 2002 #define IDB_IMAGE4 2003 #define IDB_IMAGE5 2004
//----------------------------------------------------------------- // Slideshow Resources // RC Source - Slideshow.rc //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Resource.h" //----------------------------------------------------------------- // Icons //----------------------------------------------------------------- IDI_SLIDESHOW ICON "Res//Slideshow.ico" IDI_SLIDESHOW_SM ICON "Res//Slideshow_sm.ico" //----------------------------------------------------------------- // Bitmaps //----------------------------------------------------------------- IDB_IMAGE1 BITMAP "Res//Image1.bmp" IDB_IMAGE2 BITMAP "Res//Image2.bmp" IDB_IMAGE3 BITMAP "Res//Image3.bmp" IDB_IMAGE4 BITMAP "Res//Image4.bmp" IDB_IMAGE5 BITMAP "Res//Image5.bmp"