// IssuerView.h : interface of the CIssuerView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(GDIUTIL_H_2003_08_14_INCLUDED_)
#define GDIUTIL_H_2003_08_14_INCLUDED_

class LockStockObject
{
public:
	LockStockObject( CDC* dc, int index )
		:_dc( NULL ),
		_index( 0 ),
		_old( NULL)
	{
		Attach( dc, index );
	}

	~LockStockObject( )
	{
		Restore( );
	}

	void Restore( )
	{
		if( _old && _dc )
			_dc->SelectObject( _old );
		_old = NULL;
		_dc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach( CDC *dc, int index )
	{
		Detach( );
		_dc = dc;
		_index = index;

		if( _dc && _index )
		{
			_old = _dc->SelectStockObject( _index );
		}
	}

protected:
	CDC* _dc;
	CGdiObject *_old;
	int _index;
};


class LocalHGDI
{
public:
	LocalHGDI( HDC dc, HGDIOBJ obj )
		:_dc( NULL ),
		_object(NULL ),
		_old( NULL)
	{
		Attach( dc, obj );
	}

	~LocalHGDI( )
	{
		Restore( );
	}

	void Restore( )
	{
		if( _old && _dc )
			::SelectObject( _dc, _old );
		_old = NULL;
		_dc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach( HDC dc, HGDIOBJ obj )
	{
		Detach( );
		_dc = dc;
		_object = obj;

		if( _dc && _object )
		{
			_old = SelectObject( _dc, _object );
		}
	}

protected:
	HDC _dc;
	HGDIOBJ _old;
	HGDIOBJ _object;
};

class LocalHPalette
{
public:
	LocalHPalette( HDC dc, HPALETTE obj )
		:_dc( NULL ),
		_object(NULL ),
		_old( NULL)
	{
		Attach( dc, obj );
	}

	~LocalHPalette( )
	{
		Restore( );
	}

	void Restore( )
	{
		if( _old && _dc )
			::SelectPalette( _dc, _old, FALSE );
		_old = NULL;
		_dc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach( HDC dc, HPALETTE obj )
	{
		Detach( );
		_dc = dc;
		_object = obj;

		if( _dc && _object )
		{
			_old = ::SelectPalette( _dc, _object, FALSE );
		}
	}

protected:
	HDC _dc;
	HPALETTE _old;
	HPALETTE _object;
};


class LocalGDI
{
public:
	LocalGDI( CDC *dc, CGdiObject * obj )
		:_dc( NULL ),
		_object(NULL ),
		_old( NULL)
	{
		Attach( dc, obj );
	}

	~LocalGDI( )
	{
		Restore( );
	}

	void Restore( )
	{
		if( _old && _dc )
			_dc->SelectObject( _old );
		_old = NULL;
		_dc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach( CDC *dc, CGdiObject * obj )
	{
		Detach( );
		_dc = dc;
		_object = obj;

		if( _dc && _object )
		{
			_old = _dc->SelectObject( obj );
		}
	}

protected:
	CDC *_dc;
	CGdiObject *_old;
	CGdiObject *_object;
};

class LocalPalette
{
public:
	LocalPalette( CDC *dc, CPalette *obj )
		:_dc( NULL ),
		_object(NULL ),
		_old( NULL)
	{
		Attach( dc, obj );
	}

	~LocalPalette( )
	{
		Restore( );
	}

	void Restore( )
	{
		if( _old && _dc )
			_dc->SelectPalette( _old, FALSE );
		_old = NULL;
		_dc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach( CDC *dc, CPalette* obj )
	{
		Detach( );
		_dc = dc;
		_object = obj;

		if( _dc && _object )
		{
			_old = _dc->SelectPalette( obj, FALSE );
		}
	}

protected:
	CDC *_dc;
	CPalette *_old;
	CPalette *_object;
};


class GLock
{
public:
	GLock( HANDLE handle )
		:_handle( NULL ),
		_ptr( NULL )
	{
		Attach( handle );
	}

	~GLock( )
	{
		Release( );
	}

	void Release( )
	{
		if( _ptr )
			GlobalUnlock( _handle );
		_ptr = NULL;
		_handle = NULL;
	}

	void Detach( )
	{
		Release( );
	}

	void Attach( HANDLE handle )
	{
		Detach( );
		_handle = handle;
		if( _handle )
			_ptr = GlobalLock( _handle );
	}

	operator LPVOID ( ) { return _ptr; }

protected:
	LPVOID _ptr;
	HANDLE _handle;
};

class GHandle
{
public:
	GHandle( HANDLE handle = NULL )
		:_handle( handle )
	{
	}

	~GHandle( )
	{
		Release( );	
	}

	void Release( )
	{
		if( _handle )
			GlobalFree( _handle );
		_handle = NULL;
	}

	void SetHandle( HANDLE handle )
	{
		Release( );
		_handle = handle;
	}

	HANDLE Detach( ) 
	{ 
		HANDLE handle = _handle; 
		_handle = NULL;
		return handle;
	}


	void Attach( HANDLE handle )
	{
		SetHandle( handle );
	}

	HANDLE GetHandle( ) { return _handle; }
	operator HANDLE( ) { return _handle; }

	BOOL ReAlloc( DWORD dwLen, UINT flags )
	{
		HANDLE handle = GlobalReAlloc( _handle, dwLen, flags );
		if( handle )
		{
			_handle = handle;
			return TRUE;
		}
		return FALSE;
	}


protected:
	//Use it at your dangerous
	GHandle & operator = ( const GHandle &other );
	/*
	{
		SIZE_T size = 0;
		LPVOID other_ptr = NULL;

		if( other._handle != NULL )
		{
			other_ptr = GlobalLock( other._handle );
			if( other_ptr == NULL )
				size = 0;
			else
			{
				size = GlobalSize( other._handle );
			}
		}

		SIZE_T my_size = 0;
		LPVOID my_ptr = NULL;
		if( _handle != NULL )
		{
			my_ptr = GlobalLock( _handle );
			if( my_ptr == NULL )
				my_size = 0;
			else
			{
				my_size = GlobalSize( _handle );
			}
		}
		if( my_size >= size )
		{
			if( my_ptr && other_ptr )
				memcpy( my_ptr, other_ptr, size );
		}
		else
		{
			if( my_ptr )
				GlobalUnlock( _handle );
			my_ptr = NULL;
			Release( );
			_handle = GlobalAlloc( GMEM_MOVEABLE, size );
			if( _handle )
				my_ptr = GlobalLock( _handle );
			if( my_ptr && other_ptr )
				memcpy( my_ptr, other_ptr, size );
		}

		if( my_ptr )
			GlobalUnlock( _handle );

		if( other_ptr )
			GlobalUnlock( other._handle );
		return *this;
	}*/

protected:
	HANDLE _handle;
};

class CSaveDC 
{
public:
	CSaveDC(CDC& dc)
		:_sdc( NULL ),
		_saved( 0 )
	{ 
		Attach( &dc );
	}

	CSaveDC(CDC *dc) 
		:_sdc( NULL ),
		_saved( 0 )
	{ 
		Attach( dc );
	}

	~CSaveDC() 
	{ 
		Restore( );
	}

	void Restore( )
	{
		if( _saved && _sdc )
			_sdc->RestoreDC( _saved );
		_saved = 0;
		_sdc = NULL;
	}

	void Detach( )
	{
		Restore( );
	}

	void Attach(CDC *dc )
	{
		Restore( );
		if( dc )
		{
			_sdc = dc; 
			_saved = dc->SaveDC();
		}
	}

protected:
	CDC* _sdc;
	int _saved;
};

class GDIUtil
{
public:
	static HANDLE DDBToDIB( HBITMAP hbmp, DWORD dwCompression = BI_RGB, HPALETTE hpal = NULL );
	static HANDLE GrabDIB( CDC* pDC, CRect &rect );
};

#endif //GDIUTIL_H_2003_08_14_INCLUDED_