c++

7 replies to this topic

### #1Hyper

Valued Member

• Members
• 195 posts

Posted 07 April 2012 - 01:37 AM

Hello.

I have a question, and I believe I already know the answer, but I am going to ask anyway, as I am extremely unfamiliar (still) with the Win32 API.
I will try to format this as best as I can, as it's slightly confusing to reference it...

If you were loading multiple bitmap images (let's say 50), and needed to render them everytime the screen updated (WM_PAINT notification)...
Should you be calling LoadImage() during every iteration, or should you save the HDC? HBITMAP? And simply BitBlit per image per iteration (WM_PAINT)?

“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

### #2Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 07 April 2012 - 02:26 AM

Definitely do LoadImage() once and save the returned HBITMAP.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #3Hyper

Valued Member

• Members
• 195 posts

Posted 07 April 2012 - 03:23 AM

Perhaps you could show me where I went wrong with that assumption then...?

void IMAGE::repaint() {

// "hdc" is set to BeginPaint()'s hdc value right before calling
HDC hdcMem = CreateCompatibleDC(hdc);

// image is an HBITMAP member stored from "HBITMAP image = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);"
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, image);

// This is absolutely valueless... but I used it anyway (I already know the dimensions, considering I created them)
GetObject(image, sizeof(bm), &bm);

// GetLastError() says this always returns 0/the function always returns 0
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

SelectObject(hdcMem, hbmOld);

// Stop memory leaks (GDI object count loves to sky-rocket)
DeleteDC(hdcMem);
DeleteObject(image);

Am I running into yet another magical undocumented wall, that I seem to always find...? Thanks again.
“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

### #4Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 07 April 2012 - 03:29 AM

Well, if you do LoadImage() once then of course you shouldn't do DeleteObject() on that object until you are shutting down your application. That code looks like it's deleting it after the first time it's rendered.

(Also, for efficiency you can also create the memory DC once and save it, rather than creating and deleting it each frame.)
reedbeta.com - developer blog, OpenGL demos, and other projects

### #5Hyper

Valued Member

• Members
• 195 posts

Posted 07 April 2012 - 03:35 AM

By removing the DeleteDC/Object, it creates a massive memory leak:

Whether you use the classes individually defined DC or a locally created one on the stack, it doesn't work.
BitBlt still returns 0, and still fails inevitably without reason or explanation.
“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

### #6Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 07 April 2012 - 03:40 AM

Something else must be going on with your GDI objects, because that makes no sense. LoadImage() creates an object and DeleteObject() deletes it. Just selecting it into a DC doesn't create an object and you're selecting it out again at the end of the paint function, which is correct.

Anyway, the rest of the code you posted looks correct to me. You're not getting anything from GetLastError()?
reedbeta.com - developer blog, OpenGL demos, and other projects

### #7Hyper

Valued Member

• Members
• 195 posts

Posted 07 April 2012 - 03:52 AM

I agree, it makes absolutely no sense. Granted, I believe I just found where/why it is not working the way you'd expect it to;

In the initial function which loads the image, and sets up the values, this is what I originally had:
...
HDC hdcMem = CreateCompatibleDC(hdc);
this->hdcMem = hdcMem;

this->image = image;

Apparently, you cannot copy the values straight over like that. I was under the impression (the debugger showed the same values) it was working fine.
In the initial loadImage() function, I believe what I'm going to do now is absolve all locally defined functions, and simply use the class' innate ones.

In the destructor of the class, I should be (for safety sake, and not relying on the operating system) calling the DeleteObject/DeleteDC, correct?

Thank you again for the help, as always (through-out the years).
“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

### #8Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 07 April 2012 - 03:54 AM

Yeah, if you wrap the GDI objects in classes, it would be appropriate to call DeleteObject/DeleteDC in the destructor.
reedbeta.com - developer blog, OpenGL demos, and other projects

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users