In an effort to make it easier for me to work with bitmaps, without MFC or
ATL, I created this class.
Nothing spectacular, but I'm wondering if this leaks memory or needs
improvement.

The thing I find most ugly in writing classes to use with native code, is
the HINSTANCE required for many functions.. getting this HINSTANCE seems to
be done by storing this in a global variable and refencing it.
I store it in

HINSTANCE g_hInst;

This isn't very portable, because my classes then need to reference to this
by defining

extern HINSTANCE g_hInst;

Shouldn't there be a way to get the instance handle through some API's
instead ?

Anyway, most important is to make sure this class is usable and doesn't leak
any memory.

Lisa



// Bitmap.h: interface for the CBitmap class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_BITMAP_H__14C7E26D_7024_4B10_A80A_CB4789F4F6E0__INCLUDED_)
#define AFX_BITMAP_H__14C7E26D_7024_4B10_A80A_CB4789F4F6E0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CBitmap
{
public:
HBITMAP GetBitmapHandle();
BITMAP* GetBitmapPtr();
BOOL DrawBitmap(int x, int y);
BOOL LoadImageResource(UINT nResourceId);
void Detach();
BOOL Attach(HDC hDC);
CBitmap();
virtual ~CBitmap();

protected:
BITMAP m_Bitmap;
HDC m_hMemDC;
HDC m_hDC;
HBITMAP m_hBitmap;
};

#endif //
!defined(AFX_BITMAP_H__14C7E26D_7024_4B10_A80A_CB4789F4F6E0__INCLUDED_)



// Bitmap.cpp: implementation of the CBitmap class.
//
//////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <windowsx.h>
#include <aygshell.h>
#include "Bitmap.h"

extern HINSTANCE g_hInst;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CBitmap::CBitmap()
: m_hBitmap(NULL), m_hMemDC(NULL)
{

}

CBitmap::~CBitmap()
{
if (m_hMemDC)
Detach();
}

BOOL CBitmap::Attach(HDC hDC)
{
if (m_hMemDC)
Detach();
m_hDC = hDC;
m_hMemDC = ::CreateCompatibleDC(hDC);
return (BOOL) m_hMemDC;
}

void CBitmap::Detach()
{
::DeleteObject(m_hMemDC);
m_hMemDC = NULL;
}

BOOL CBitmap::LoadImageResource(UINT nResourceId)
{
if (m_hBitmap)
::DeleteObject(m_hBitmap);
m_hBitmap = ::SHLoadImageResource(g_hInst, nResourceId);
::GetObject(m_hBitmap, sizeof(BITMAP), &m_Bitmap);
return (BOOL) m_hBitmap;
}

BOOL CBitmap::DrawBitmap(int x, int y)
{
if (!m_hMemDC || !m_hBitmap)
return FALSE;
HGDIOBJ hOld = ::SelectObject(m_hMemDC, m_hBitmap);
::BitBlt(m_hDC, x, y, m_Bitmap.bmWidth, m_Bitmap.bmHeight,
m_hMemDC, 0, 0, SRCCOPY);
::SelectObject(m_hMemDC, hOld);
return TRUE;
}

BITMAP* CBitmap::GetBitmapPtr()
{
return &m_Bitmap;
}

HBITMAP CBitmap::GetBitmapHandle()
{
return m_hBitmap;
}

Re: custom CBitmap class by riki

riki
Sun Jul 17 22:33:41 CDT 2005

Lisa Pearlson wrote:
> Shouldn't there be a way to get the instance handle through some API's
> instead ?
GetModuleHandle(NULL);
works if the code is in the .exe, if it's in a dll, you need to pass in
the dll name, which is icky.

> CBitmap::CBitmap()
> : m_hBitmap(NULL), m_hMemDC(NULL)
why not:
: m_hBitmap(NULL), m_hMemDC(NULL), hDC(NULL)

> CBitmap::~CBitmap()
> {
> if (m_hMemDC)
> Detach();
> }
why not:
if (m_hBitmap) {
DeleteObject(m_hBitmap);
m_hBitmap =0;
}
I assume the bitmap lives longer than this class? Personally i like to
have the class that creates a resource, destroy/clean it up too.
Does m_Bitmap need to be cleaned up? i can't remember and don't have a
good reference on my desk.

> BOOL CBitmap::Attach(HDC hDC)
> {
> if (m_hMemDC)
> Detach();
> m_hDC = hDC;
> m_hMemDC = ::CreateCompatibleDC(hDC);
> return (BOOL) m_hMemDC;
> }
>
> void CBitmap::Detach()
> {
> ::DeleteObject(m_hMemDC);
shouldn't this be DeleteDC()

> m_hMemDC = NULL;
> }

riki



Small minds discuss people,Average minds discuss events,Great minds
discuss ideas.
By Night:
ThemeChanger for Smartphone : http://homepages.inspire.net.nz/~gambit/
AbstractStart for Smartphone :
http://homepages.inspire.net.nz/~gambit/AbstractStart/
By Day: http://www.EmbeddedFusion.com

Re: custom CBitmap class by Lisa

Lisa
Sun Jul 17 22:40:57 CDT 2005

I don't think the bitmap is supposed to live beyond that class.. the bitmap
lives in the resource. The CBitmap loads the image from resource, so I think
that this class should also be responsible for unloading (destroying) all
that is related to loading it.

I don't think BITMAP needs to be cleaned up.. I think it's just a struct
that gets filled in, pointing to the bitmap data somewhere in memory, to
which HBITMAP points to.. The BITMAP structure doesn't contain any data that
needs deletion. It has a pointer to the bitmap bits, but doesn't copy these
bits. All the data gets deleted when the bitmap handle is deleted, I think..

I don't know about the DeleteObject versus DeleteDC on the DC.
When I run my project in debug mode, and close the application, shouldn't
the IDE report memory leaks? Or are GDI resources tricky?



"riki" <see_my_home@page> wrote in message
news:Oq9qai0iFHA.1460@tk2msftngp13.phx.gbl...
> Lisa Pearlson wrote:
>> Shouldn't there be a way to get the instance handle through some API's
>> instead ?
> GetModuleHandle(NULL);
> works if the code is in the .exe, if it's in a dll, you need to pass in
> the dll name, which is icky.
>
>> CBitmap::CBitmap()
>> : m_hBitmap(NULL), m_hMemDC(NULL)
> why not:
> : m_hBitmap(NULL), m_hMemDC(NULL), hDC(NULL)
>
>> CBitmap::~CBitmap()
>> {
>> if (m_hMemDC)
>> Detach();
>> }
> why not:
> if (m_hBitmap) {
> DeleteObject(m_hBitmap);
> m_hBitmap =0;
> }
> I assume the bitmap lives longer than this class? Personally i like to
> have the class that creates a resource, destroy/clean it up too.
> Does m_Bitmap need to be cleaned up? i can't remember and don't have a
> good reference on my desk.
>
>> BOOL CBitmap::Attach(HDC hDC)
>> {
>> if (m_hMemDC)
>> Detach();
>> m_hDC = hDC;
>> m_hMemDC = ::CreateCompatibleDC(hDC);
>> return (BOOL) m_hMemDC;
>> }
>>
>> void CBitmap::Detach()
>> {
>> ::DeleteObject(m_hMemDC);
> shouldn't this be DeleteDC()
>
>> m_hMemDC = NULL;
>> }
>
> riki
>
>
>
> Small minds discuss people,Average minds discuss events,Great minds
> discuss ideas.
> By Night:
> ThemeChanger for Smartphone : http://homepages.inspire.net.nz/~gambit/
> AbstractStart for Smartphone :
> http://homepages.inspire.net.nz/~gambit/AbstractStart/
> By Day: http://www.EmbeddedFusion.com



Re: custom CBitmap class by riki

riki
Sun Jul 17 22:54:44 CDT 2005

Lisa Pearlson wrote:
> I don't think BITMAP needs to be cleaned up.. I think it's just a struct
> that gets filled in, pointing to the bitmap data somewhere in memory, to
> which HBITMAP points to.. The BITMAP structure doesn't contain any data that
> needs deletion. It has a pointer to the bitmap bits, but doesn't copy these
> bits. All the data gets deleted when the bitmap handle is deleted, I think..
yeah, thats whats in my mind too.

> I don't know about the DeleteObject versus DeleteDC on the DC.
> When I run my project in debug mode, and close the application, shouldn't
> the IDE report memory leaks? Or are GDI resources tricky?

if only it was that easy! you need to use entrek to track that kinda
stuff. for a simple test see if DeleteObject is returning an error, but
i believe you need to use DeleteDC()

riki



"Sweater, n.: A garment worn by a child when its mother feels chilly."
By Night:
ThemeChanger for Smartphone : http://homepages.inspire.net.nz/~gambit/
AbstractStart for Smartphone :
http://homepages.inspire.net.nz/~gambit/AbstractStart/
By Day: http://www.EmbeddedFusion.com

Re: custom CBitmap class by Lisa

Lisa
Sun Jul 17 23:26:50 CDT 2005

>> I don't know about the DeleteObject versus DeleteDC on the DC.
>> When I run my project in debug mode, and close the application, shouldn't
>> the IDE report memory leaks? Or are GDI resources tricky?
>
> if only it was that easy! you need to use entrek to track that kinda
> stuff. for a simple test see if DeleteObject is returning an error, but i
> believe you need to use DeleteDC()
>
> riki


You're right, I need to call DeleteDC.
I think a "GetDC" must be followed with "ReleaseDC", a "SelectObject" with a
"DeleteObject" and a "CreateDC" with a "DeleteDC"

As for memory leaks.. it used to be that if I created objects with "new"
operator and didn't delete them, that the debugger would dump memory leaks..
Perhaps I am mistaken with Visual C++ 6 for desktop development, but I
thought eVC 3 had it too, and so I'm sure eVC 4 does also. Doesn't detect
everything, but some things it did.

"Memory leak detected! Dumping object -> " or something would it say.
Uh well.

Thanks for your help :)
Lisa



Re: custom CBitmap class by Doug

Doug
Mon Jul 18 23:09:39 CDT 2005

Hi Lisa,

> "Memory leak detected! Dumping object -> " or something would it say.

No not for either eVC products unfortunately, you are thinking of VS6. Its
easy to tell if you are leaking something as large as a bitmap though by
just test calling your method repeatedly and watching if memory usage
continues climbing

Cheers
Doug Forster



RE: custom CBitmap class by hansw77041

hansw77041
Thu Oct 06 14:06:48 CDT 2005

Just a thought:
I you do GIF image files, this works... GIF files can be very small compared
to bmp, so there may be a space saving when using it as a resource in the exe
Best regards
Hans Wedemeyer

// from file. does not require the g_hInst
DoBitmap( your hdc, SHLoadImageFile ( LPCTSTR pszPathAndFileName ));

// from Resource
In the project.rc
IDG_MYIMAGE_GIF GIF DISCARDABLE "YourGifFileName.gif"

DoBitmap( your hdc, SHLoadImageResource ( HINSTANCE hinst, UINT uIdGif );

//////////////////////////////////////////////////////////////
void DoBitmap( HDC hdc, HBITMAP hbm )
{
HBITMAP hbmOld;
HDC hdcS = ::CreateCompatibleDC(hdcDst);
BITMAP bm;

GetObject(hbm, sizeof(bm),&bm);

hbmOld = (HBITMAP)::SelectObject(hdcS, hbm);

::BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcS, 0, 0, SRCCOPY);

::SelectObject(hdcS, hbmOld);
::DeleteDC(hdcS);
}

--


"Lisa Pearlson" wrote:

> In an effort to make it easier for me to work with bitmaps, without MFC or
> ATL, I created this class.
> Nothing spectacular, but I'm wondering if this leaks memory or needs
> improvement.