HBITMAP to Window

Started by
11 comments, last by b1gjo3 15 years, 11 months ago
hello, im trying to get an HBITMAP to display on my window. I have loaded the image from file and im trying to display it with this..

PAINTSTRUCT Ps;
myDC = BeginPaint(myHwnd, &Ps);
MemDC = CreateCompatibleDC(myDC);
SelectObject(MemDC, myBitmap);
BitBlt(myDC, 0, 0, iWidth, iHeight, MemDC, 0, 0, SRCCOPY);
DeleteDC(MemDC);
EndPaint(myHwnd, &Ps);

before, i had read all the RGB values from the HBITMAP and displayed them all using SetPixel(). It was way to slow and im trying to speed up the process. im not sure where to go from here. can someone give me some guidance. thanks
Advertisement
From Game Programming Genesis Part III:

int ShowBitmapResource(HDC hDestDC, int xDest, int yDest, int nResID){  HDC hSrcDC;           // source DC - memory device context  HBITMAP hbitmap;      // handle to the bitmap resource  BITMAP bmp;           // structure for bitmap info  int nHeight, nWidth;  // bitmap dimensions  // first load the bitmap resource  if ((hbitmap = (HBITMAP)LoadImage(hinstance, MAKEINTRESOURCE(nResID),                                    IMAGE_BITMAP, 0, 0,                                    LR_CREATEDIBSECTION)) == NULL)    return(FALSE);  // create a DC for the bitmap to use  if ((hSrcDC = CreateCompatibleDC(NULL)) == NULL)    return(FALSE);  // select the bitmap into the DC  if (SelectObject(hSrcDC, hbitmap) == NULL)    return(FALSE);  // get image dimensions  if (GetObject(hbitmap, sizeof(BITMAP), &bmp) == 0)    return(FALSE);  nWidth = bmp.bmWidth;  nHeight = bmp.bmHeight;  // copy image from one DC to the other  if (BitBlt(hDestDC, xDest, yDest, nWidth, nHeight, hSrcDC, 0, 0,             SRCCOPY) == NULL)    return(FALSE);  // kill the memory DC  DeleteDC(hSrcDC);  // return success!  return(TRUE);}


Also an alternative to this is to create a PictureBox control as a child of your window, and then give the control your bitmap (the control handles drawing it for you). This is handy for sticking one or two pictures in a dialog box, for instance.
how come i the call to SelectObject fails? what could be going wrong?

thank you!
Are you sure the bitmap is not already selected into a different DC?
im pretty sure its not selected, but if it is already selected, is that why its failing?
A bitmap can only be selected into one context at a time. Other reasons that the call could fail include myBitmap not actually being a valid bitmap or the DC not being a valid DC.

What does your current code look like?
these are functions for loading an image, and also getting rgb values from an HBITMAP
#ifndef IMAGE_H#define IMAGE_H#include <windows.h>#include <olectl.h> #include <ole2.h>#include "Color.h"HBITMAP LoadAnImage(const char*);ColorRGB* GetImageInfo(HBITMAP bmp, int* w, int* h){	//variables	BITMAP bm;	COLORREF Color;	int width, height;	int R, G, B;	int pixelCount, count = 0;	//load image	HDC dc = ::GetDC(0);	HDC MemDC = ::CreateCompatibleDC(dc);	HANDLE hBMP = bmp;	HBITMAP hOldBmp = (HBITMAP)::SelectObject(MemDC,hBMP);		//get width height	GetObject(hBMP, sizeof(BITMAP), (LPVOID)&bm);	width = bm.bmWidth;	height = bm.bmHeight;	pixelCount = width*height;	ColorRGB* imgRgbTable = new ColorRGB[pixelCount];	for (int i = 0; i < height; i++)	{		for (int y = 0; y < width; y++)		{			Color = ::GetPixel(MemDC,y,i); // X,Y			R = GetRValue(Color);			G = GetGValue(Color);			B = GetBValue(Color);			imgRgbTable[count].SetRGB(R,G,B);			count++;		}	}	::SelectObject(MemDC,hOldBmp);	::DeleteObject(hBMP);	::DeleteDC(MemDC);	::ReleaseDC(0,dc);	/*debug	for (int i = 0; i < pixelCount; i++)		cout << "R: " << imgRgbTable.R << " - G: " << imgRgbTable.G << " - B: " << imgRgbTable.B << endl;	*/	*w = width;	*h = height;	return imgRgbTable;}HBITMAP LoadAnImage(const char* FileName){	// Use IPicture stuff to use JPG / GIF files	IPicture* p;	IStream* s = NULL;	IPersistStream* ps = NULL;	HGLOBAL hG;	void* pp;	FILE* fp;	// Read file in memory	fopen_s(&fp, FileName,"rb");	if (!fp)		return NULL;	fseek(fp,0,SEEK_END);	int fs = ftell(fp);	fseek(fp,0,SEEK_SET);	hG = GlobalAlloc(GPTR,fs);	if (!hG)	{		fclose(fp);		return NULL;	}	pp = (void*)hG;	fread(pp,1,fs,fp);	fclose(fp);	// Create an IStream so IPicture can	CreateStreamOnHGlobal(hG,false,&s);		if (!s)    {		GlobalFree(hG);		return NULL;    }	OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);	if (!p)    {		s->Release();		GlobalFree(hG);		return NULL;	}	s->Release();	GlobalFree(hG);	HBITMAP hB = 0;	p->get_Handle((unsigned int*)&hB);	// Copy the image. Necessary, because upon p's release,	// the handle is destroyed.	HBITMAP hBB = (HBITMAP)CopyImage(hB,IMAGE_BITMAP,0,0,                                    LR_COPYRETURNORG);	p->Release();	return hBB;}


this is my winmain
int APIENTRY _tWinMain(){	myBitmap = LoadAnImage("C:\\Users\\BigJoe\\Desktop\\test.bmp");	myRgb = GetImageInfo(myBitmap, &iWidth, &iHeight);	//setup window gui and create root folder	myGui = new ScanGUI("Image Scanner", iWidth, iHeight);	myGui->InitWindow();	MSG msg = {0};	while (WM_QUIT != msg.message)	{		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)		{			TranslateMessage(&msg);			DispatchMessage(&msg);		}	}	return 0;}


heres a portion of my WndProc
		case WM_PAINT:			  HDC hSrcDC;           // source DC - memory device context			  // create a DC for the bitmap to use			  if ((hSrcDC = CreateCompatibleDC(myDC)) == NULL)				return(FALSE);			  // select the bitmap into the DC			  if (SelectObject(hSrcDC, myBitmap) == NULL)				return(FALSE);			  // copy image from one DC to the other			  if (BitBlt(myDC, 0, 0, iWidth, iHeight, hSrcDC, 0, 0, SRCCOPY) == NULL)				return(FALSE);			  // kill the memory DC			  DeleteDC(hSrcDC);


iWidth, iHeight, myBitmap are globals atm
Some comments:

LoadAnImage() - why not just use LoadImage()?
GetImageInfo() - the bmBits members of the BITMAP struct has the RGB information

As for the problem:
Your WM_PAINT handler is incorrect. You should get dcSrc from BeginPaint() and let EndPaint() do what it wants to it. Create a compatible memory DC and select myBitmap into that - remembering of course to store the returned HBITMAP. Use BitBlt() from the memory DC to dcSrc. The select the stored HBITMAP back into the memory DC so that your bitmap is no longer in it and delete the memory DC.
LoadImage can't load JPEG and GIF files.

Quote:
// Use IPicture stuff to use JPG / GIF files


My quess as Colin suggests (but I'll put a finer point on it) is that this code works ONCE on the first draw but it gets redrawn so fast that the bug you have in your code isn't obvious.

When you SelectObject(MemDc, myBitmap) you need to store the returned HBITMAP. Then after you are done with BitBlt() SelectObject(MemDc, oldBitmap) back in. If you don't you destroy the DC but your HBITMAP still thinks it is selected and so can't be selected into a new DC on the next draw. Thus your SelectObject fails.

...HBITMAP oldBitmap; // Somewhere to store the old HBITMAP...oldBitmap = (HBITMAP)SelectObject(MemDC, myBitmap); // Store the old HBITMAPBitBlt(myDC, 0, 0, iWidth, iHeight, MemDC, 0, 0, SRCCOPY);SelectObject(MemDc, oldBitmap); // Restore the old HBITMAP and free myBitmap...
"Being Irish he had an abiding sense of tragedy that sustainted him through the temporary periods of joy." -- W.B. Yeats
ok so this is what i have now

	HDC MemDC = NULL;	HBITMAP oldBitmap = NULL;	PAINTSTRUCT Ps;	//check any available messages from the queue	switch (message)	{		case WM_PAINT:			myDC = BeginPaint(myHwnd, &Ps);			MemDC = CreateCompatibleDC(myDC);			oldBitmap = (HBITMAP)SelectObject(MemDC, myBitmap);			BitBlt(myDC, 0, 0, iWidth, iHeight, MemDC, 0, 0, SRCCOPY);			SelectObject(MemDC, oldBitmap);			DeleteDC(MemDC);			EndPaint(myHwnd, &Ps);			break;


(myDC is a member variable of my Window class. i get myDC in the next source code, dont know if this will help my problem)
	//create the Window from the class above    myHwnd = CreateWindowEx(myWinExStyle, myWndClass.lpszClassName, myWndClass.lpszClassName,				myWinStyle, (cen.right - myWidth) / 2, (cen.bottom - myHeight) / 2,                rect.right - rect.left, rect.bottom - rect.top,                NULL, NULL, this->myInst, this);                     if (!myHwnd)       return false;	myDC = GetDC(myHwnd);


thank you everyone for showing interest in my problem

This topic is closed to new replies.

Advertisement