Back Buffer class ~ part 1

Introduction

I assume that you know what a back buffer is (also known as a double or offscreen buffer). If not see wikipedia – Double Buffering. In brief, it’s a byte array used to prepare graphics off-screen to prevent flicker. Once the desired image is complete, it is copied to screen.

Here is a first stab at back buffer class. It is deliberately simple and meant to be a starting point only, functionality will be added.

This is the header file…

CBackBuffer.h
  1. // BackBuffer class definition
  2. // Carl Bateman based on snippets by Geoff Howland
  3. // October 2005
  4.  
  5. #include <windows.h>
  6.  
  7. class CBackBuffer{
  8. public:
  9.   // own user defined functions	
  10.   CBackBuffer() {};  // over ride default constructor
  11.   ~CBackBuffer() {}; // over ride default destructor
  12. 	void Create();
  13. 	void Destroy();
  14. 	void Display();
  15.   // simple accessors
  16.   int Height(void) const
  17.   { return m_iHeight; };
  18.   int Width(void) const
  19.   { return m_iWidth; };
  20.   BYTE* BackData(void)
  21.   { return m_bmpBackData; };
  22.  
  23. protected:
  24. 	// generic back buffer info
  25. 	BYTE* m_bmpBackData;
  26. 	int m_iHeight;
  27.   int m_iWidth;
  28.  
  29.   // MS Windows specific data
  30.   BITMAP m_bitmap;            // The BITMAP structure defines the type, width, height, color format, and bit values of a bitmap
  31. 	BITMAPINFO m_BitmapInfo;    // The BITMAPINFO structure defines the dimensions and color information for a Win32 DIB
  32. 	HBITMAP m_hBitmap;
  33. 	HDC m_hdcSource;
  34. 	HDC m_hdcDestination;
  35. };

This is the implementation file…

CBackBuffer.cpp
  1. // BackBuffer class implementation
  2. // Carl Bateman based on snippets by Geoff Howland
  3. // October 2005
  4.  
  5. #include "CBackBuffer.h"
  6.  
  7. void CBackBuffer::Create () {
  8. 	HWND hwndActive = GetActiveWindow();
  9. 	if(hwndActive == NULL)
  10. 		return;
  11. 	RECT lpRect;
  12. 	GetClientRect(hwndActive, &lpRect);
  13. 	m_iWidth = lpRect.right ;
  14. 	m_iHeight = lpRect.bottom ;
  15. 	// Set up BitmapInfoHeader
  16. 	m_BitmapInfo.bmiHeader.biBitCount = 24;
  17. 	m_BitmapInfo.bmiHeader.biClrImportant = 0;
  18. 	m_BitmapInfo.bmiHeader.biClrUsed = 0;
  19. 	m_BitmapInfo.bmiHeader.biCompression = BI_RGB;
  20. 	m_BitmapInfo.bmiHeader.biHeight = -m_iHeight;
  21. 	m_BitmapInfo.bmiHeader.biPlanes = 1;
  22. 	m_BitmapInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  23. 	m_BitmapInfo.bmiHeader.biSizeImage = m_iWidth * m_iHeight * (m_BitmapInfo.bmiHeader.biBitCount / 8);
  24. 	m_BitmapInfo.bmiHeader.biWidth = m_iWidth;
  25. 	m_BitmapInfo.bmiHeader.biXPelsPerMeter = 0;
  26. 	m_BitmapInfo.bmiHeader.biYPelsPerMeter = 0;
  27.  
  28. 	m_BitmapInfo.bmiColors[0].rgbRed = 0;
  29. 	m_BitmapInfo.bmiColors[0].rgbGreen = 0;
  30. 	m_BitmapInfo.bmiColors[0].rgbBlue = 0;
  31. 	m_BitmapInfo.bmiColors[0].rgbReserved = 0;
  32.  
  33. 	// Create the DIB section with CreateDIBSection
  34. 	m_hdcDestination = GetDC(hwndActive);
  35. 	m_hdcSource      = CreateCompatibleDC(m_hdcDestination); 
  36. 	m_hBitmap        = CreateDIBSection (m_hdcSource, (BITMAPINFO *) &m_BitmapInfo, 0, (void **) &m_bmpBackData, NULL, 0);
  37. 	GetObject (m_hBitmap, sizeof (BITMAP), &m_bitmap);
  38. 	m_bmpBackData    = (BYTE*) m_bitmap.bmBits;
  39. 	SelectObject (m_hdcSource, m_hBitmap);
  40. }
  41.  
  42. void CBackBuffer::Destroy () {
  43. 	// if we have a bitmap destroy
  44. 	if (m_hBitmap != NULL) {
  45. 		DeleteObject (m_hBitmap);
  46. 		m_hBitmap = NULL;
  47. 		DeleteDC (m_hdcSource);
  48. 		DeleteDC (m_hdcDestination);
  49. 	}
  50. }
  51.  
  52. void CBackBuffer::Display() {
  53. 	// Display from CreateDIBSection creation
  54. 	BitBlt (m_hdcDestination, 0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight, m_hdcSource, 0, 0, SRCCOPY);
  55. }

And this is the test file… and frankly it’s a mess, I’m still messing around with the code to make it as clear as possible.

winmain.cpp
  1. // winmain.cpp
  2. // Back Buffer test app
  3.  
  4. // -- INCLUDES --
  5. #define WIN32_LEAN_AND_MEAN  // just say no to MFC - set as project option
  6. #include <windows.h>         // include important windows stuff
  7. #include "CBackBuffer.h"
  8.  
  9. // defines for windows 
  10. #define WINDOW_CLASS_NAME "WINCLASS1"
  11. HWND      hwnd;              // track main window
  12. HINSTANCE hinstance;         // track hinstance
  13. HDC       hdc;               // graphics device context
  14. RECT      rcClient;          // client rectangle area
  15. CBackBuffer* pBackBuffer;
  16. int cxWindow=640, cyWindow=480;
  17. int cxClient=0, cyClient=0;  //int cxWindow=1000, cyWindow=500;
  18.  
  19. // -------------
  20. // -- WINPROC --
  21. // -------------
  22. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
  23. 	// this is the main message handler of the system
  24. 	PAINTSTRUCT		ps;		// used in WM_PAINT
  25. 	static HMENU hMenu;
  26.  
  27. 	// what is the message 
  28. 	switch(msg) {	
  29. 		case WM_CREATE : 
  30.       // if buffer created here window has no width or height, must use default values
  31. 			return(0);
  32. 		case WM_ACTIVATE : 
  33.       // if buffer created here window may be activated many times
  34.       if(pBackBuffer==NULL)	{
  35.         hdc=hdc;
  36.         pBackBuffer = new CBackBuffer;
  37. 			  pBackBuffer->Create();
  38.       };
  39. 			return(0);
  40. 		case WM_PAINT : 
  41. 			hdc = BeginPaint(hwnd,&ps);	 
  42. 			pBackBuffer->Display();
  43. 			EndPaint(hwnd,&ps);
  44. 			return(0);
  45. 		case WM_SIZING : 
  46.       // change back buffer size on the fly here if so desired
  47. 			return(0);
  48. 		case WM_SIZE : 
  49.       // change back buffer size after sizing finished here
  50. 			return(0);
  51. 		case WM_DESTROY : 
  52. 			pBackBuffer->Destroy();
  53. 			PostQuitMessage(0);
  54. 			return(0);
  55. 		default:break;
  56. 	} // end switch
  57.  
  58. 	// process any messages that we didn't take care of 
  59. 	return (DefWindowProc(hwnd, msg, wparam, lparam));
  60. } // end WinProc
  61.  
  62. // -------------
  63. // -- WINMAIN --
  64. // -------------
  65. int WINAPI WinMain(	HINSTANCE hinstance, HINSTANCE hprevinstance,
  66. 					          LPSTR lpcmdline,     int ncmdshow)
  67. {
  68. 	WNDCLASSEX winclass; // this will hold the class we create
  69. 	MSG				 msg;		   // generic message
  70.  
  71. 	// first fill in the window class stucture
  72. 	winclass.cbSize         = sizeof(WNDCLASSEX);
  73. 	winclass.style					= NULL;
  74. 	winclass.lpfnWndProc		= WindowProc;
  75. 	winclass.cbClsExtra			= 0;
  76. 	winclass.cbWndExtra			= 0;
  77. 	winclass.hInstance			= hinstance;
  78. 	winclass.hIcon					= LoadIcon(NULL, IDI_APPLICATION);
  79. 	winclass.hCursor				= LoadCursor(NULL, IDC_ARROW); 
  80. 	winclass.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
  81. 	winclass.lpszMenuName		= NULL;
  82. 	winclass.lpszClassName	= WINDOW_CLASS_NAME; 
  83. 	winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
  84.  
  85. 	// register the window class
  86. 	if (!RegisterClassEx(&winclass))
  87. 		return(0);
  88.  
  89. 	// create the window
  90. 	if (!(hwnd = CreateWindowEx(
  91. 							 NULL,														// extended style
  92. 							 WINDOW_CLASS_NAME,						    // class
  93. 							 "BackBuffer - Part1",            // title
  94. 							 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  95. 					 		 CW_USEDEFAULT, CW_USEDEFAULT,	  // initial top left, right
  96. 							 cxWindow, cyWindow,              // initial width,height
  97. 							 NULL,	                          // handle to parent  
  98. 							 NULL,	                          // handle to menu
  99. 							 hinstance,                       // handle to instance of this application
  100. 							 NULL)))	                        // extra creation parms
  101. 	return(0);
  102.  
  103. 	// enter main event loop
  104.   while(TRUE)	{ // test if there is a message in queue, if so get it
  105. 		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { 
  106.       if (msg.message == WM_QUIT)	 // test if this is a quit
  107.         {	break; }
  108. 			TranslateMessage(&msg);	// translate any accelerator keys		
  109. 			DispatchMessage(&msg);	// send the message to the window proc
  110. 		}    
  111. 	} 
  112. 	ReleaseDC(hwnd, hdc);
  113. 	return(msg.wParam);	// return to Windows like this
  114. } // end WinMain

This is pretty much the simplest Windows program I could come up with, I’ve included the WM_ messages I think may be useful.

All being well, it should look like this (after resizing the window).
BackBuffer running

Bit dull, I know, but early days yet. Next up I’ll implement line and triangle drawing.

house insurance
online comparison
buytolet mortgage
uk mortgage