Click here to Skip to main content
15,891,033 members
Articles / Desktop Programming / ATL

Template class for 'Property Browser'- like property pages for ATL ActiveX Controls

Rate me:
Please Sign up or sign in to vote.
4.89/5 (5 votes)
26 Nov 19992 min read 83.3K   2K   45  
Allows you to easily create property pages for ActiveX controls
// PBDib.cpp: implementation of the PBDib class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PBDib.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

PBDib::PBDib()
	{
	m_hPalette = NULL;
	m_hDIB = NULL;
	}

PBDib::~PBDib()
	{
	Free();
	}

void PBDib::Free()
	{
	if(m_hDIB)
		{
		::GlobalFree(m_hDIB);
		m_hDIB = NULL;
		}
	if(m_hPalette)
		{
		::GlobalFree(m_hPalette);
		m_hPalette = NULL;
		}
	}

BOOL PBDib::ReadDIBFile(LPCTSTR szFile)
	{
	BITMAPFILEHEADER bmfHeader;
	DWORD dwBitsSize;
	LPSTR pDIB;
	HANDLE hFile;

	Free();
	hFile = ::CreateFile(szFile,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
	if(hFile == INVALID_HANDLE_VALUE)
		return FALSE;

	/*
	* get length of DIB in bytes for use when reading
	*/
	dwBitsSize = ::GetFileSize(hFile,NULL);
	
	/*
	* Go read the DIB file header and check if it's valid.
	*/
	DWORD dwRead;
	if(!ReadFile(hFile,&bmfHeader, sizeof(bmfHeader),&dwRead,NULL))
		{
		::CloseHandle(hFile);
		return FALSE;
		}
	if ( dwRead != sizeof(bmfHeader))
		{
		::CloseHandle(hFile);
		return FALSE;
		}
	
	if (bmfHeader.bfType != DIB_HEADER_MARKER)
		{
		::CloseHandle(hFile);
		return FALSE;
		}
	
		/* Allocate memory for DIB*/

	m_hDIB = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
	if (m_hDIB == 0)
		{
		::CloseHandle(hFile);
		return FALSE;
		}
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
	
	/*
	* Go read the bits.
	*/
	if(!ReadFile(hFile,pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER),&dwRead,NULL))
		{
		::CloseHandle(hFile);
		::GlobalUnlock((HGLOBAL) m_hDIB);
		::GlobalFree((HGLOBAL) m_hDIB);
		return FALSE;
		}

	if (dwRead != dwBitsSize - sizeof(BITMAPFILEHEADER) )
		{
		::CloseHandle(hFile);
		::GlobalUnlock((HGLOBAL) m_hDIB);
		::GlobalFree((HGLOBAL) m_hDIB);
		return FALSE;
		}
	::GlobalUnlock((HGLOBAL) m_hDIB);
	::CloseHandle(hFile);
	BOOL bLoadPalette = CreatePalette();
	if(!bLoadPalette)
		Free();
	return bLoadPalette;
	}

BOOL PBDib::CreatePalette()
	{
	LPLOGPALETTE lpPal;      // pointer to a logical palette
	HANDLE hLogPal;          // handle to a logical palette
	int i;                   // loop index
	WORD wNumColors;         // number of colors in color table
	LPSTR lpbi;              // pointer to packed-DIB
	LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
	LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
	BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
	BOOL bResult = FALSE;
	
	/* if handle to DIB is invalid, return FALSE */
	
	if (m_hDIB == NULL)
		return FALSE;
	
	lpbi = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
	
	/* get pointer to BITMAPINFO (Win 3.0) */
	lpbmi = (LPBITMAPINFO)lpbi;
	
	/* get pointer to BITMAPCOREINFO (old 1.x) */
	lpbmc = (LPBITMAPCOREINFO)lpbi;
	
	/* get the number of colors in the DIB */
	wNumColors = GetNumColors(lpbi);
	
	if (wNumColors != 0)
		{
		/* allocate memory block for logical palette */
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
			+ sizeof(PALETTEENTRY)
			* wNumColors);
		
		/* if not enough memory, clean up and return NULL */
		if (hLogPal == 0)
			{
			::GlobalUnlock((HGLOBAL) m_hDIB);
			return FALSE;
			}
		
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
		
		/* set version and number of palette entries */
		lpPal->palVersion = PALVERSION;
		lpPal->palNumEntries = (WORD)wNumColors;
		
		/* is this a Win 3.0 DIB? */
		bWinStyleDIB = IS_WIN30_DIB(lpbi);
		for (i = 0; i < (int)wNumColors; i++)
			{
			if (bWinStyleDIB)
				{
				lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
				lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
				lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
				lpPal->palPalEntry[i].peFlags = 0;
				}
			else
				{
				lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
				lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
				lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
				lpPal->palPalEntry[i].peFlags = 0;
				}
			}
		
		/* create the palette and get handle to it */
		m_hPalette = ::CreatePalette(lpPal);
		::GlobalUnlock((HGLOBAL) hLogPal);
		::GlobalFree((HGLOBAL) hLogPal);
		}
	
	::GlobalUnlock((HGLOBAL) m_hDIB);
	return (m_hPalette != NULL) ? TRUE : FALSE;
	}

WORD PBDib::GetNumColors(LPSTR lpbi)
	{
	WORD wBitCount;  // DIB bit count
	
	/*  If this is a Windows-style DIB, the number of colors in the
	 *  color table can be less than the number of bits per pixel
	 *  allows for (i.e. lpbi->biClrUsed can be set to some value).
	 *  If this is the case, return the appropriate value.
	 */
	
	if (IS_WIN30_DIB(lpbi))
		{
		DWORD dwClrUsed;
	
		dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
		if (dwClrUsed != 0)
			return (WORD)dwClrUsed;
		}
	
		/*  Calculate the number of colors in the color table based on
		*  the number of bits per pixel for the DIB.
	*/
	if (IS_WIN30_DIB(lpbi))
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
	else
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
	
	/* return number of colors based on bits per pixel */
	switch (wBitCount)
		{
		case 1:
			return 2;
			
		case 4:
			return 16;
			
		case 8:
			return 256;
			
		default:
			return 0;
		}
	}

int PBDib::GetHeight()
	{
	if(!m_hDIB)
		return 0;
	LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
	LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
	int nHeight = 0;
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);

	
	lpbmi = (LPBITMAPINFOHEADER)lpDIB;
	lpbmc = (LPBITMAPCOREHEADER)lpDIB;

	/* point to the header (whether old or Win 3.0 */

	lpbmi = (LPBITMAPINFOHEADER)lpDIB;
	lpbmc = (LPBITMAPCOREHEADER)lpDIB;
	/* return the DIB height if it is a Win 3.0 DIB */
	if (IS_WIN30_DIB(lpDIB))
		nHeight = lpbmi->biHeight;
	else  /* it is an other-style DIB, so return its height */
		nHeight = lpbmc->bcHeight;
	::GlobalUnlock(m_hDIB);
	return nHeight;
	}

int PBDib::GetWidth()
	{
	if(!m_hDIB)
		return 0;
	LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
	LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
	int nWidth = 0;
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
	
	
	lpbmi = (LPBITMAPINFOHEADER)lpDIB;
	lpbmc = (LPBITMAPCOREHEADER)lpDIB;
	
	/* point to the header (whether old or Win 3.0 */
	
	lpbmi = (LPBITMAPINFOHEADER)lpDIB;
	lpbmc = (LPBITMAPCOREHEADER)lpDIB;
	/* return the DIB height if it is a Win 3.0 DIB */
	if (IS_WIN30_DIB(lpDIB))
		nWidth = lpbmi->biWidth;
	else  /* it is an other-style DIB, so return its height */
		nWidth = lpbmc->bcWidth;
	::GlobalUnlock(m_hDIB);
	return nWidth;
	
	}

HBITMAP PBDib::CreateBitmap()
	{
    LPBITMAPINFOHEADER  lpbi;
    HDC                 hdc;
    HBITMAP             hbm;
	HPALETTE hpalT;
	
    if (!m_hDIB)
        return NULL;
	
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(m_hDIB);
	
    if (!lpbi)
        return NULL;
	
    hdc = GetDC(NULL);
	
    if (m_hPalette)
		{
        hpalT = SelectPalette(hdc,m_hPalette,FALSE);
        RealizePalette(hdc);     // GDI Bug...????
		}
	
    hbm = CreateDIBitmap(hdc,
		(LPBITMAPINFOHEADER)lpbi,
		(LONG)CBM_INIT,
		(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
		(LPBITMAPINFO)lpbi,
		DIB_RGB_COLORS );
	
    if (m_hPalette)
        SelectPalette(hdc,hpalT,FALSE);
	
    ReleaseDC(NULL,hdc);
    GlobalUnlock(m_hDIB);
    return hbm;
	}

int PBDib::PaletteSize(VOID FAR * pv)
	{
    LPBITMAPINFOHEADER lpbi;
    WORD               NumColors;
	
    lpbi      = (LPBITMAPINFOHEADER)pv;
    NumColors = GetNumColors((LPSTR)lpbi);
	
    if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
        return (NumColors * sizeof(RGBTRIPLE));
    else
        return (NumColors * sizeof(RGBQUAD));
	
	}

HPALETTE PBDib::ClonePalette()
	{
	LPLOGPALETTE lpPal;      // pointer to a logical palette
	HANDLE hLogPal;          // handle to a logical palette
	int i;                   // loop index
	WORD wNumColors;         // number of colors in color table
	LPSTR lpbi;              // pointer to packed-DIB
	LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
	LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
	BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
	HPALETTE hPal;
	/* if handle to DIB is invalid, return FALSE */
	
	if (m_hDIB == NULL)
		return NULL;
	
	lpbi = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
	
	/* get pointer to BITMAPINFO (Win 3.0) */
	lpbmi = (LPBITMAPINFO)lpbi;
	
	/* get pointer to BITMAPCOREINFO (old 1.x) */
	lpbmc = (LPBITMAPCOREINFO)lpbi;
	
	/* get the number of colors in the DIB */
	wNumColors = GetNumColors(lpbi);
	
	if (wNumColors != 0)
		{
		/* allocate memory block for logical palette */
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
			+ sizeof(PALETTEENTRY)
			* wNumColors);
		
		/* if not enough memory, clean up and return NULL */
		if (hLogPal == 0)
			{
			::GlobalUnlock((HGLOBAL) m_hDIB);
			return NULL;
			}
		
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
		
		/* set version and number of palette entries */
		lpPal->palVersion = PALVERSION;
		lpPal->palNumEntries = (WORD)wNumColors;
		
		/* is this a Win 3.0 DIB? */
		bWinStyleDIB = IS_WIN30_DIB(lpbi);
		for (i = 0; i < (int)wNumColors; i++)
			{
			if (bWinStyleDIB)
				{
				lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
				lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
				lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
				lpPal->palPalEntry[i].peFlags = 0;
				}
			else
				{
				lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
				lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
				lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
				lpPal->palPalEntry[i].peFlags = 0;
				}
			}
		
		/* create the palette and get handle to it */
		hPal = ::CreatePalette(lpPal);
		::GlobalUnlock((HGLOBAL) hLogPal);
		::GlobalFree((HGLOBAL) hLogPal);
		}
	
	::GlobalUnlock((HGLOBAL) m_hDIB);
	return hPal;
	}

HBITMAP PBDib::CreateBitmapXY(SIZE szBmp)
	{

    LPBITMAPINFOHEADER  lpbi;
    HDC                 hdc;
    HBITMAP             hbm;
	HPALETTE hpalT;
 	if(szBmp.cx == 0 || szBmp.cy == 0)
		return NULL;
   if (!m_hDIB)
        return NULL;
	int h = GetHeight();
	int w = GetWidth();
     lpbi = (LPBITMAPINFOHEADER)GlobalLock(m_hDIB);
   hdc = CreateCompatibleDC(NULL);
	hbm = ::CreateCompatibleBitmap(hdc,szBmp.cx,szBmp.cy);
	HBITMAP hOldBmp = (HBITMAP)::SelectObject(hdc,hbm);
    if (m_hPalette)
		{
        hpalT = SelectPalette(hdc,m_hPalette,FALSE);
        RealizePalette(hdc);     // GDI Bug...????
		}
	StretchDIBits(hdc, 0,0, szBmp.cx,szBmp.cy,
		0,0,w,h,
		(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
		(LPBITMAPINFO)lpbi,
		DIB_RGB_COLORS,
		SRCCOPY);
    if (m_hPalette)
        SelectPalette(hdc,hpalT,FALSE);
	SelectObject(hdc,hOldBmp);	
    ReleaseDC(NULL,hdc);
    GlobalUnlock(m_hDIB);
    return hbm;
	}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions