This node is in response to a question wharfinger asked me in the chatterbox. Here is the solution to his question. It is being left here as a general tutorial on how to do this, if anyone else is ever interested. If no one cares after wharfinger gets to it, then I'll take it down.

Instructions: Put in a blank VS 6.0 project and hit build. End of story.

/*  For Wharfinger, this should solve your problem hopefully

What this program does is create a fully functional 30 x 30 bitmap onto a black brushed window.

  There are no menus and no window commands, although it will shutdown properly.

	You cannot put RGBQUADs into a bitmap, that is how you describe a palette, I think. 
	If you already have a program , you can use the function below to translate them into 
	an appropirate 32-bit DWORD.

	You must::

	CreateCompatibleBitmap
	CreateCompatibleDC
	SelectObject
	BitBlt (or your other transfer mechanism of your choice).
	
	The asserts are in there to see if anything fails due to memory, and to help me try to track
	down a really dumb bug I had.

	Any questions? email me jay@manifestresearch.com

	By default this program creates a red bitmap, although you can change the values by playing
	with the default in the items below.  The procedure applies to any well-behaved array or
	DWORDS containing bitmap data.

  */
#include <windows.h>
#include <assert.h>

LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
DWORD* dwArray;
BITMAPINFO bmInfo;
HBITMAP myBitmap;
HDC myCompatibleDC;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

	WNDCLASS wc;
	HWND hwnd;
	MSG msg;


	ZeroMemory(&wc, sizeof(WNDCLASS));

	wc.hInstance = hInstance;
	wc.lpfnWndProc = MyWndProc;
	wc.lpszClassName = "MYWNDCLASSNAME";
	wc.hbrBackground = (HBRUSH) BLACK_BRUSH + 1 ;
	
	RegisterClass(&wc);
	hwnd = CreateWindow("MYWNDCLASSNAME", "This is just a test for wharfinger", 
WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, 
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInstance, NULL);

	while(GetMessage(&msg, hwnd, 0,0))
	{
		DispatchMessage(&msg);
	}

	return 0;
}

DWORD MakeDwordColor(int r, int g, int b)
{
	DWORD dwStuff = ((r << 16) | (g << 8) | (b));

	return dwStuff;
}

LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	PAINTSTRUCT ps;
	int i;
	int nResult;

	switch(msg)
	{
	case WM_CREATE:

			dwArray = (DWORD*) malloc(30*30*sizeof(DWORD));

			assert(dwArray);

			for(i=0; i<30*30; i++)
				dwArray[i] = MakeDwordColor(0xff, 0x00, 0x00);  
//Change this color here to change the bmp color

			ZeroMemory(&bmInfo, sizeof(BITMAPINFO));
			bmInfo.bmiHeader.biBitCount = 32;
			bmInfo.bmiHeader.biHeight = 30;
			bmInfo.bmiHeader.biPlanes = 1;
			bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			bmInfo.bmiHeader.biWidth = 30;
			bmInfo.bmiHeader.biCompression = BI_RGB;


			myBitmap = CreateCompatibleBitmap(GetDC(hwnd), 30, 30);
			assert(myBitmap);

			myCompatibleDC = CreateCompatibleDC(GetDC(hwnd));
			assert(myCompatibleDC);

			SelectObject(myCompatibleDC, myBitmap);

			nResult = SetDIBits(myCompatibleDC, myBitmap, 0, 30, dwArray, &bmInfo, 0);

			assert(nResult != 0);

		break;

	case WM_PAINT:
		BeginPaint(hwnd, &ps);

			nResult = BitBlt(ps.hdc, 0, 0, 30, 30, myCompatibleDC, 0, 0, SRCCOPY);
			assert(nResult != NULL);

		EndPaint(hwnd, &ps);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		exit(0);
		break;

	default:
		return DefWindowProc(hwnd, msg, wparam, lparam);

	}

	return lparam;
}

I remember this being very difficult to figure out at first (because you can't just use CreateCompatibleBitmap on your shiny new compatible device context) but I'm using a lot of memory-based bitmaps at the moment for screen buffers.

I don't know what the original question was, but here's a general solution. (I'll skip a wrapper prog.)

HBITMAP hbmImage;
HWND hWnd;

void CreateBitmap(void) {
   HDC wDC = GetDC(hWnd);
   // create a bitmap compatible to the screen
   hbmImage = CreateCompatibleBitmap(wDC,30,30);
   ReleaseDC(hWnd,wDC);
}

void DrawBitmap(int x,int y) {
   HDC wDC = GetDC(hWnd);
   HDC bdc = CreateCompatibleDC(wDC);

   // select the bitmap into the bitmap's dc
   HBITMAP bOld = (HBITMAP)SelectObject(bdc,hbmImage);

   // write into the window's dc
   BitBlt(wDC,x,y,30,30,bdc,0,0,SRCCOPY);

   // select the bitmap out of the bitmap dc
   // so you can destroy the bitmap dc
   SelectObject(bdc, bOld);

   DeleteDC(bdc);
   ReleaseDC(wDC);
}

void FillBitmapWithRed(void) {
   HDC wDC = GetDC(hWnd);
   HDC bDC = CreateCompatibleDC(wDC);
   HBITMAP bOld = (HBITMAP)SelectObject(bDc,hbmImage);
   HBRUSH brush = CreateSolidBrush(RGB(255,0,0));
   RECT r = { 0,0,30,30 };

   FillRect(bDC,&r,brush);

   DeleteObject(brush);
   SelectObject(bDC, bOld);
   DeleteDC(bDC);
   ReleaseDC(wDC);
}

void DestroyBitmap(void) {
   DeleteObject(hbmImage);
}

I don't know what happens if you don't release/destroy/delete everything when you're done with it, but according to documentation it's a good idea.

Log in or register to write something here or to contact authors.