|
Posted by Lisa Pearlson on July 18, 2005, 3:50 am
Please log in for more thread options
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;
}
|
|
Posted by riki on July 18, 2005, 3:33 pm
Please log in for more thread options
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
|
|
Posted by Lisa Pearlson on July 18, 2005, 5:40 am
Please log in for more thread options 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?
> 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
|
|
Posted by riki on July 18, 2005, 3:54 pm
Please log in for more thread options 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
|
|
Posted by Lisa Pearlson on July 18, 2005, 6:26 am
Please log in for more thread options >> 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
|
| Similar Threads | Posted | | Class not registered | May 14, 2008, 5:05 am |
| FileSystemWatcher class for NetFramework2 | August 11, 2005, 12:52 am |
| Can’t override BACK key with Class Specified | March 1, 2006, 7:32 pm |
| Class: method or internal procedure ??? | May 17, 2007, 11:43 am |
| Re: Why does this Backlight turn on/off class not work on my device | March 29, 2007, 7:57 am |
| Activate previous instance and delay/dialog class name | December 13, 2005, 7:48 am |
| Using AlternateView class works for Windows Mobile but not Blackbe | October 12, 2007, 3:46 pm |
| Custom Setup.dll | July 6, 2005, 9:26 pm |
| launch custom.cpl.xml | February 14, 2007, 4:13 pm |
| Custom ring tone | June 5, 2005, 10:50 pm |
|