The class of self-built operation BMP bitmap file in VC

zhaozj2021-02-11  189

Programmers with programming experience know: To make the application's appearance is beautiful and inevitable to use a large number of bitmaps. Nowadays, the popular visual programming tools provide good support for the use of bitmaps, known as the three major visual development tools VB, VC, Delphi provides a good support for bitmaps by package bitmap objects: VB provides Two functions are very strong: PictureBox and Image, which is very easy to display bitmaps by using them, loaded. A bitmap object is also provided in Delphi: TIMAGE, its functionality is similar to the image in VB. The operation of the bitmap is performed by using the device-related class CDC with GDI object class cbitmap by using the device-related class CDC class CBITMAP.

However, using the CBITMAP class in the VC must load the BMP bitmap into the resource, then use it through the member function of class CBITmap, operate it in a member function via the CDC class. This has two short defects: putting the bitmap is put into resources, which is not conducive to software issuance; only limited bitmaps in resources can be used, and other bitmaps cannot be selected. Moreover, the BMP bitmap file is saved in a DIB (device-free bitmap), and the BMP bitmap is converted to DDB (device-related bitmap) after the BMP bitmap is loaded, and the class CBITMAP is packaged on a series of DDB operations. It is not as limited to the platform characteristics that use it.

To make up for two shortcomings of using the resource bitmap, you must use the BMP bitmap file directly. A method of reading and displaying a BMP bitmap file is provided in an example of the VC, but it is quite troubles. First use the API function GLOBALLOC allocate memory and create HDIB bitmap handles, all operations can only be read directly to write memory, and then displayed on the screen via STRECHDIBITS and SETDIBSTODEVICE functions, and it is time to operate.

Therefore, the author uses a new function provided in Win32 by studying CBitmap, using new functions provided in Win32, and fully simulating the implementation of CBITMAP: from class cgdiobject derived, all interfaces of the new class The partial interface of CBITMAP is exactly the same. This is nothing about the use of the programmer who is used to using the CBITMAP interface usage.

First, let's briefly introduce the structure of DIB. The DIB bitmap can exist both in memory or in the file form (BMP file). All DIBs contain two parties: BitmapInfo, including bitmap information headers and color tables; bitmap data. For the two parts described above for the memory, add a bitmap file header for the DIB file. The two structures are shown in the figure:

DIB DIB file

Second, Win32 provides a new function createDibSection, which can create a memory area that stores the DIB bit, can perform the corresponding GDI operation, but also directly through the pointer orientation DIB bit area of ​​the DIB bit area. This is a very useful function, through which we can use DIB to replace DDB.

After understanding the corresponding knowledge, we can derive a class: cbitmapfile. CGDIOBJECT.

There are two points worth noting when writing classes:

Define class cBitmapFile in the bitmapfile.h file, first of all, you must declare that class CBITMAPFile is from the publicly born from class CGDIObject. Then use macro declare_dynamic (cbitmapfile) in the class to indicate that the highest parent class of the new class is COBJECT, which is a library specification that complies with MFC. The macro Declare_Dynamic is the declaration of the static function fromHandle, which must be placed at the foresight definition of the class. Plus Implement_Dynamic (CBitmapFile, CGDiObject) before the member function of the class in BitmapFile.cpp file; indicates that class cBitmapFile is directly derived from class CGDiobject. There are three functions in CBITMAPFile, and the definitions in class cbitmap are slightly different:

The parameters of the Loadbitmap function in class cbitmapfile are LPCTSTR, saved is the file name of the BMP file. There is less parameter NPLANES in the parameters of the CreateBitmap function in class cbitmapfile, which is default to 1 in the function. The parameters of the CreateBitmapIndirect function in class cbitmapfile are multiple parameter lpbits, which point to the memory area of ​​the specified bitmap DIB bit.

The most important thing in the member function is the function cretemapindirect and functions loadbitmap:

The function CreateBitMapSection is used to create a compatible DC-based HBitmap handle and use the function attach inheritance from the class CGDiobject to associate it with the clause M_HObject of the class CGDIObject. The DIB bitmap data of the norture graph is then copied to the memory area of ​​the DIB bit created by the function createDibSection. Read the data block in the file from the specified file name in the function loadbitmap, then determine whether the file is the BMP bitmap file by the file header flag, and then saved by BitmapFileHeader and the real file size and file real The size comparison file is damaged, and then the bitmapfileHeader is subtracted to calculate the size of the bitmap information head and color table in the BitmapFileHeader structure size. Dynamically apply for a space to save bitmap information head and color table information, and then BFSIZE in BitmapfileHeader The size of the DIB bitmap data is subtracted to the bfoffbits, and the dynamically applied a piece of space to save the DIB bitmap data, and finally call the member function createBitMapIndirect to create a DIB bitmap.

The method of drawing the DIB bitmap in an onPaint () event of the application is identical to the method of drawing bitmaps when using class CBitmap, but it is important to note because the CDC class does not provide the new CBITMAPFILE pointer type will be DIB bit. The diagram is selected into the SELECTOBJECT function of the memory, so the return type is forced to convert to the cbitmapfile * type when using SelectObject.

At this point, there are so many questions about some of the points in the new class CBitmapFile writing, some should pay more attention to the problem.

Addition file

//

// File Description: Define class cBitmapFile, this class is used to read BMP files, involving reading,

// Establish and a range of commonly used operations.

// File name: BitmapFile.h

// 时间: 1999-2-11

// Author: Jia Tun

// #ifndef _CBITMAPFILE_H_ #define _CBITMAPFILE_H_ class CBitmapFile: public CGdiObject {DECLARE_DYNAMIC (CBitmapFile) public: static CBitmapFile * PASCAL FromHandle (HBITMAP hBitmap); // Constructors CBitmapFile (); BOOL LoadBitmap (LPCTSTR lpszFileName); BOOL CreateBitmap (int nWidth, int nHeight, UINT nBitCount, const void * lpBits); BOOL CreateBitmapIndirect (lPBITMAPINFO lpBitmapInfo, const void * lpBits); // Attributes operator HBITMAP () const; int GetBitmap (BITMAP * pBitMap); protected: // Attributes int GetColorNumber (WORD wBitCount); public: // Operations DWORD SetBitmapBits (DWORD dwCount, const void * lpBits); DWORD GetBitmapBits (DWORD dwCount, LPVOID lpBits); // Implementation public: virtual ~ CBitmapFile ();}; #endif //// file Description: Implementation of member functions within class cbitmapfile

// File name: BitmapFile.cpp

// 时间: 1999-2-11

// Author: Jia Tun

// #include "BitmapFile.h" #include IMPLEMENT_DYNAMIC (CBitmapFile, CGdiObject); CBitmapFile * PASCAL CBitmapFile :: FromHandle (HBITMAP hBitmap) {return (CBitmapFile *) CGdiObject :: FromHandle (hBitmap);} CBitmapFile :: CBitmapFile () {} BOOL CBitmapFile :: LoadBitmap (LPCTSTR lpszFileName) {CFile file; (! file.Open (lpszFileName, CFile :: modeRead | CFile :: shareDenyWrite)) if {MessageBox (NULL, "BMP file open error ! "," warning ", mb_ok); return false;} BitmapfileHeader Bfhheader; File.Read (& BFHHEADER); if (BFHHEADER.BFTYPE! = ((Word) ('M' << 8) | ' B ')) {MessageBox (NULL, "The File is Not a Bmp File!", "Warning", MB_OK; RETURN FALSE;} IF (bfhheader.bfsize! = File.getlength ()) {MessageBox (null, " ! The BMP file header error "," warning ", MB_OK); return FALSE;} UINT uBmpInfoLen = (UINT) bfhHeader.bfOffBits-sizeof (BITMAPFILEHEADER); LPBITMAPINFO lpBitmap = (LPBITMAPINFO) new BYTE [uBmpInfoLen]; file.Read ( (Lpvoid) lpbitmap, ubmpinfolen; if ((* (lpbitmap))! = Sizeof (bitmapInfoheader)) {MessageBox (NULL, "The BMP is not Windows 3.0 format!", "Warning", MB_OK); return FALSE;} DWORD dwBitlen = bfhHeader.bfSize - bfhHeader.bfOffBits; LPVOID lpBits = new BYTE [dwBitlen]; file.ReadHuge (lpBits, dwBitlen); file.Close (); BOOL bSuccess = CreateBitmapIndirect (lpBitmap, lpBits); delete lpBitmap; delete lpBits; if (bSuccess!) return FALSE; return TRUE;} BOOL CBitmapFile :: CreateBitmap (int nWidth, int NHEIGHT, UINT Nbitcount, Const Void * LPSRCBITS) {assert (nbitcount == 1 || nbitcount == 4 || nbitcount == 8 || nbitcount == 16 || nbitcount == 24 || nbitcount == 32);

LPBITMAPINFO lpBitmap; lpBitmap = (BITMAPINFO *) new BYTE [sizeof (BITMAPINFOHEADER) GetColorNumber (nBitCount) * sizeof (RGBQUAD)]; lpBitmap-> bmiHeader.biSize = sizeof (BITMAPINFOHEADER); lpBitmap-> bmiHeader.biWidth = nWidth; lpBitmap -> bmiHeader.biHeight = nHeight; lpBitmap-> bmiHeader.biBitCount = nBitCount; lpBitmap-> bmiHeader.biPlanes = 1; lpBitmap-> bmiHeader.biCompression = BI_RGB; lpBitmap-> bmiHeader.biSizeImage = 0; lpBitmap-> bmiHeader.biClrUsed = 0; BOOL bSuccess = CreateBitmapIndirect (lpBitmap, lpSrcBits); delete lpBitmap; if return FALSE (bSuccess!); return TRUE;} BOOL CBitmapFile :: CreateBitmapIndirect (lPBITMAPINFO lpBitmapInfo, const void * lpSrcBits) {DeleteObject (); LPVOID lpBits; CDC * dc = new CDC; dc-> CreateCompatibleDC (NULL); HBITMAP hBitmap = :: CreateDIBSection (dc-> m_hDC, lpBitmapInfo, DIB_RGB_COLORS, & lpBits, NULL, 0); ASSERT (hBitmap = NULL!); delete dc; Attach (HBitMap); Bitmap BMP; GetBitmap (& BMP); DWORD DWCOUNT = (DWORD) bmp.bmwidthbytes * bmp.bmHeight; IF (setBitMapbits (dwcount, lpsrcbits)! = dwcount) { Messagebox (Null, "Dib Build Error!", "Warning", MB_OK; RETURN FALSE;} Return true;} cBitmapFile :: Operator hbitmap () const {return (hbitmap) (this == null? Null: m_hobject); } int CBitmapFile :: GetBitmap (BITMAP * pBitMap) {ASSERT (m_hObject = NULL!); return :: GetObject (m_hObject, sizeof (BITMAP), pBitMap);} int CBitmapFile :: GetColorNumber (WORD wBitCount) {ASSERT (wBitCount = = 1 || wbitcount == 4 || wbitcount == 8 || wbitcount == 16 || wbitcount == 24 || wbitcount == 32); switch (wbitcount) {case 1: return 2; case 4: return 16 Case 8: Return 256; Default: return 0;

}} DWORD CBITMAPFILE :: SetBitMapBits (DWORD DWCOUNT, Const Void * Lpbits) {IF (lpbits! = Null) {Bitmap BMP;

GetBitmap (& BMP);

Memcpy (bmp.bmbits, lpbits, dwcount);

Return dwcount;

}

Else

return 0;} DWORD CBitmapFile :: GetBitmapBits (DWORD dwCount, LPVOID lpBits) {if (lpBits = NULL!) {BITMAP bmp; GetBitmap (& bmp); memcpy (lpBits, bmp.bmBits, dwCount); return dwCount;} else return 0;} cbitmapfile :: ~ cgdiobject :: deleteObject ();}