Jump to content
  • Advertisement
Sign in to follow this  
b1gjo3

HBITMAP to Window

This topic is 3690 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
how come i the call to SelectObject fails? what could be going wrong?

thank you!

Share this post


Link to post
Share on other sites
im pretty sure its not selected, but if it is already selected, is that why its failing?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 HBITMAP
BitBlt(myDC, 0, 0, iWidth, iHeight, MemDC, 0, 0, SRCCOPY);
SelectObject(MemDc, oldBitmap); // Restore the old HBITMAP and free myBitmap
...

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!