Memory bitmap class CMemBm






4.82/5 (9 votes)
Feb 15, 2001

282800

9295
A simple class to make generic Windows bitmap operations easier.
- Download source files - 9.92 Kb
- Download demo project - 33 Kb
- Download static control demo project - 24 Kb
- Download "load from resource" demo - 36.3 Kb
An example of how to use this class for drawing transparent bitmap in a static control.
Introduction
Recently, I uploaded to CodeProject an article with source code for an MFC extension library that deals with Device-Dependent Bitmaps (DDB) and Device-Independent Bitmaps (DIB). Then, I began refurbishing my old skin frame classes and soon found that some people were not happy with MFC as it causes the size of applications and libraries to grow. Moreover, while working with skins, etc., I reviewed some of the DDB and DIB class concepts, and that gave rise to the CMemBm
class which seamlessly implements several irritating Windows GDI routines, and at the same time is easy to use.
The CMemBm itself
First of all, the class' name is no longer CMemBm, in the year 2005 it became a member of the charting library called MChart, so from now on it will be MChMemBm
:) hope that won't ruin anything. In addition, when it was used as a drawing canvas for charting on desktop, as well as CE devices, there was a need to make it more portable and serializable.
Well, in a nutshell "what's new"... I've found that in some cases, to augment serialization, for instance, the DDB functionality had apparent drawbacks, so MChMemBm
was made DDB\DIB depending on MCH_USE_DDB
. If the latter is defined somewhere above MChMemBm
, for example, in a precompiled header, the class transparently becomes a 32 bpp DIB section wrapper, i.e. the programming interface remains the same, and a few new methods become available.
The new serialization method is:
void GetAsDIB(MByteString& refDIB) const;
where MByteString
is an alias for std::string
, it does not always work correctly in the DDB mode, but it is OK in DIB. It stores the image data as binary chunk exactly as it is in a raw bitmap file. The image filtering feature is available in the DIB mode:
typedef signed short MChFilter[9]; void ApplyFilter( const MChFilter& crefFilter );
It performs simple 3x3 matrix image filtering, like, it may be used to blur the image or find edges or whatever.
The CE GDI functionality is quite limited compared to desktop, so several methods like stretch drawing, transparent drawing, alpha drawing got excluded with another #define: UNDER_CE
.
#if defined(_WIN32_WCE) && !defined(UNDER_CE) #define UNDER_CE _WIN32_WCE #endif
This is a very simple class. Behind the scenes, it contains the memory DC handle and the bitmap handle, the latter being selected into the former. Let's take a closer look at the public
class methods:
/////////////////////construction/destruction, // initialization and cleanup // create memory bitmap from source bitmap. // !REMEMBER! hbmSrc MUST NOT be selected into // any DC before calling this function // or following will just create copy of // hDC contents, not the hbmSrc. bool Create(HDC hDC, HBITMAP hbmSrc, int iLeft, int iTop, int iWidth, int iHeight, DWORD dwRop = SRCCOPY ); // create memory bitmap from explicit data // (default is monochrome bitmap) bool Create( HDC hDC, int iWidth, int iHeight, UINT cPlanes = 1, UINT cBitsPerPel = 1, const void *lpvBits = NULL ); //copy creation bool Create( const MChMemBm& bmSrc, DWORD dwRop = SRCCOPY ); //create from bitmap resource by name bool Create( HINSTANCE hInst, LPCTSTR pszName ); //create from bitmap resource by ID bool Create( HINSTANCE hInst, UINT nID ) { return Create( hInst, MAKEINTRESOURCE(nID) ); }; // default constructor MChMemBm(){ Initialize(); }; // inplace constructor MChMemBm(HDC hDC, HBITMAP hbmSrc, int iLeft, int iTop, int iWidth, int iHeight, DWORD dwRop = SRCCOPY ) { Initialize(); Create(hDC, hbmSrc, iLeft, iTop, iWidth, iHeight, dwRop); }; //copy constructor MChMemBm( const MChMemBm& bmSrc, DWORD dwRop = SRCCOPY ) { Initialize(); Create(bmSrc, dwRop); }; // create memory bitmap from explicit data // (default is monochrome bitmap) MChMemBm( HDC hDC, int iWidth, int iHeight, UINT cPlanes = 1, UINT cBitsPerPel = 1, const void *lpvBits = NULL ) { Initialize(); Create( hDC, iWidth, iHeight, cPlanes, cBitsPerPel, lpvBits ); }; //construct from resource by name MChMemBm( HINSTANCE hInst, LPCTSTR pszName ) { Initialize(); Create(hInst, pszName); }; //construct from resource by ID MChMemBm( HINSTANCE hInst, UINT nID ) { Initialize(); Create(hInst, nID); }; virtual ~MChMemBm(){ Cleanup(); }; public: //cleanup object data void Cleanup(); //get bitmap width int GetWidth() const; //get bitmap height int GetHeight() const; // get bits per pixel for our bitmap int GetBpp() const; // get color planes for our bitmap int GetPlanes() const; //return our memory dc with bitmap selected in it //(Blt operations - ready) operator HDC() const { return m_hdcImg; }; //boolean validation operator ! bool operator !() const { return !m_bCreated; }; //perform pattern fill, adjusting brush //origin if neccessary void Fill( HDC hDC, int iLeft, int iTop, int iWidth, int iHeight, bool bAdjustBrushOrg = false, DWORD dwRop = PATCOPY ); //do 1-to-1 draw void Draw( HDC hDC, int iLeft, int iTop, DWORD dwRop = SRCCOPY ) const; #ifndef UNDER_CE //perform draw (simple or stretched) void Draw( HDC hDC, int iLeft, int iTop, int iWidth, int iHeight, DWORD dwRop = SRCCOPY, int iStretchMode = COLORONCOLOR ) const; //do transparent drawing using WinAPI or //program emulated code void DrawTrans( HDC hDC, int iLeft, int iTop, int iWidth, int iHeight,COLORREF crTransparent ) const; //do alpha blending draw (works only //when _WIN32_WINDOWS > 0x0400 else do nothing) void DrawAlpha( HDC hDC, int iLeft, int iTop, int iWidth, int iHeight, const BLENDFUNCTION& blendFunc ) const; #endif //get as DIB, stuffed into byte array void GetAsDIB(MByteString& refDIB) const; //pixel manipulation COLORREF GetPixel(int iX, int iY) const; void SetPixel( int iX, int iY, COLORREF clPixel ); //special effects support #ifndef MCH_USE_DDB typedef signed short MChFilter[9]; void ApplyFilter( const MChFilter& crefFilter ); #endif
All these methods are straightforward. I need to make a couple of notes on conditional compilation #defines
. DrawAlpha
and DrawTrans
methods wrap the GDI functions TransparentBlt
and AlphaBlend
which reside in msimg32.dll. As far as I know, this DLL is not a part of Win95, it is included in the MS OSs starting from Win98 and WinNT 4.0 (with some service pack, I am not sure which NT4 SP is needed for this). You may want to compile the project with <SPAN CLASS="cpp-preprocessor">#define _WIN32_WINDOWS 0x0410
(I have put this define in stdafx.h in the demo project). It means that msimg32 will be automatically linked to membm.obj. In this case, both DrawAlpha
and DrawTrans
use the Windows API functions. If you find that this library is absent in your system, just #define _WIN32_WINDOWS 0x0400
and DrawTrans
will use the appropriate code to draw the transparent bitmap, while DrawAlpha
will do nothing.
Note: As I said, MChMemBm
is no longer a stand-alone class, and so several additional defines
\typedef
s are required. I have put a part of them into stdafx.h, while the GDI wrapper helpers are provided in a separate header file, as they are in the MChart library. The following stub defines should be placed somewhere if you are planning to re-use the MChMemBm
class functionality without changing the class code:
//define M_ASSERT that way, or make it alias of some existing //ASSERT macro if any #include #ifndef NDEBUG #define M_ASSERT(x) assert(x) #else #define M_ASSERT(x) #endif //place it in percompiled header if you plan to make use of MChMemBm //class CE support #if defined(_WIN32_WCE) && !defined(UNDER_CE) #define UNDER_CE _WIN32_WCE #endif //define this in precompiled header for CE compilation, as follows #ifdef UNDER_CE #if _WIN32_WCE < 0x500 && _MSC_VER > 1220 // only needed for WM2003 builds under VS2005 #pragma comment(lib, "ccrtrtti.lib") #endif #endif //undefine to use DDB functionality instead of DIB section //#define MCH_USE_DDB //the following are the necessary stubs //to make MChMemBm class stand-alone //define stubs for MChart - specific types to compile standalone #define MByteString std::string #define M_NUMBER_OF_ARRAY_ELEMENTS(a) (sizeof(a)/sizeof(a[0])) #define M_L(x) _T(x) //stringer macro #define MCH_TO_STRING_(x) # x #define MCH_TO_STRING(x) MCH_TO_STRING_(x) struct MException { public: MException( LPCTSTR strMsg ) : m_strMsg(strMsg) {} static void Throw( LPCTSTR strMsg ) { throw MException( strMsg ); } LPCTSTR GetMsg() const { return m_strMsg.c_str(); } protected: typedef std::basic_string StdStringT; StdStringT m_strMsg; }; //define this somewhere before including MChGDIWrappers.h class MChNonCopyableConcept { protected: MChNonCopyableConcept() {} ~MChNonCopyableConcept() {} private: MChNonCopyableConcept( const MChNonCopyableConcept& ); const MChNonCopyableConcept& operator=( const MChNonCopyableConcept& ); };
Brief comments on the demo code
The demo sample is just a generic Win32 Windows application. Here is the implementation of the Paint
function:
void CALLBACK Paint( HWND hWnd, HDC hDC ) { //get window application instance HINSTANCE hInst = (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE ); CMemBm bmMem8( hInst, IDB_BMP8 ); //8 bpp bitmap(256 colors) CMemBm bmMem4( hInst, IDB_BMP4 ); //4 bpp bitmap(16 colors) CMemBm bmMem24( hInst, IDB_BMP24 ); //24 bpp bitmap(16M colors) CMemBm bmExplicit( hDC, iXSize, iYSize, 1, 32, abBits ); //explicit creation of 24 bit bitmap CMemBm bmFile( hInst, _T("avatar.bmp"), TRUE ); //bitmap loading from file bmMem8.Draw( hDC, 20, 20 ); bmMem4.Draw( hDC, 20, 70 ); bmMem24.Draw( hDC, 20, 120 ); //draw them transparently (assuming blue color is transparent) bmMem8.DrawTrans( hDC, 140, 20, 60, 30, RGB(0,0,255) ); bmMem16.DrawTrans( hDC, 140, 70, 60, 30, RGB(0,0,255) ); bmMem24.DrawTrans( hDC, 140, 120, 60, 30, RGB(0,0,255) ); //capture part of this window's dc CMemBm bmSnap( hDC, NULL, 40, 40, 80, 80 ); //draw this snapshot bmSnap.Draw( hDC, 20, 200 ); //get screen snapshot, draw red line on it, //and draw it in window's dc //cleanup previous snapshot contents bmSnap.Cleanup(); //capture screen part bmSnap.Create(NULL, NULL, 40, 40, 80, 80 ); //create red pen HPEN hPen = CreatePen( PS_SOLID, 1, RGB(255,0,0) ); //select it on snapshot's dc HANDLE hOldPen = SelectObject(bmSnap, hPen); //draw diagonal line in the snapshot MoveToEx( bmSnap, 0, 0, NULL ); LineTo( bmSnap, 80, 80 ); //restore snapshot's dc pen SelectObject(bmSnap, hOldPen); //cleanup pen DeleteObject(hPen); //draw snapshot on window's dc bmSnap.Draw( hDC, 20, 300 ); //window dc pattern filling with snapshot bmSnap.Fill( hDC, 200, 20, 200, 200, true ); //test alpha blending: AC_SRC_OVER and 0 are mandatory so far, //128 = 50% opacity( 0 - 255), 0 - do not use bitmap's alpha channel BLENDFUNCTION blendFunc = {AC_SRC_OVER, 0, 128, 0}; //do alpha blend drawing bmSnap.DrawAlpha( hDC, 200, 250, 80, 80, blendFunc ); }
That's all. I hope you enjoyed this little class. In addition, in "downloads" section, I've placed a demo project that shows the possible use of this class in a custom-draw static control (inspired by Danny Shimony).
History
- 13th Feb, 2006
- major class update, class renamed (DDB|DIB wrapper made by conditionally compiling with
#define MCH_USE_DDB
, ported to CE), demo projects updated (To VS 2005).
- major class update, class renamed (DDB|DIB wrapper made by conditionally compiling with
- 24th Nov, 2004
- added minor changes allowing the bitmap to be loaded from a file. Updated the demo project and source.
- 1st Sep, 2003
- added demo project that explains how to dynamically load bitmap from a resource to the
CMemBm
class and use it as an image preview or window background.
- added demo project that explains how to dynamically load bitmap from a resource to the
- 13th Jan, 2002
- updated the source code, demo project and the demo EXE based on the recent bug fix.