Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

CButtonST v3.9 (MFC Flat buttons)

, 28 Mar 2003
A fully featured owner-draw button class - it's got the lot!
cbuttonst-beta.zip
cbuttonst26_demo.zip
CButtonST_demo.clw
CButtonST_demo.dsp
CButtonST_demo.dsw
FILE_ID.DIZ
res
32x32x16_About.ico
32x32x16_Cancel.ico
32x32x16_CancelBor.ico
32x32x16_Exit.ico
32x32x16_Explore.ico
32x32x16_Info.ico
32x32x16_Left.ico
32x32x16_Ok.ico
32x32x16_OkBor.ico
32x32x16_Question.ico
32x32x16_Right.ico
32x32x16_Screw.ico
32x32x16_Text.ico
32x32x16_View.ico
32x32x256_Baloon.ico
32x32x256_Cancel.ico
32x32x256_CDGold.ico
32x32x256_Hand.ico
32x32x256_Lamp.ico
32x32x256_Ok.ico
32x32x256_Zip.ico
32x32x256_ZipSmall.ico
32x32x2_CancelBor.ico
32x32x2_Lamp.ico
32x32x2_OkBor.ico
CButtonST_demo.ico
hand.cur
Release
TransparentCButtonST_demo.exe
CButtonST_demo.exe
cbuttonst26_src.zip
cbuttonst31_demo.zip
CButtonST_Demo.aps
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.ncb
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Cancel1_32x32x16.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Eagle.bmp
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
Lamp2.ico
LedOff.ico
LedOn.ico
Left2_32x32x16.ico
LogOff.ico
Ok1_32x32x16.ico
Ok4_32x32x2.ico
Open.ico
Palette.bmp
Right2_32x32x16.ico
Run.ico
Search1.ico
Search2.ico
Sky.bmp
Sound.ico
STLogo_Small.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Winzip2.ico
Workgroup.ico
cbuttonst31_src.zip
CButtonST31_src
cbuttonst32_demo.zip
CButtonST_Demo.aps
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Cancel1_32x32x16.ico
Cancel3_32x32x256.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Eagle.bmp
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
Help2_32x32x256.ico
IEDocument_48x48x256.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
Lamp2.ico
LedOff.ico
LedOn.ico
Left2_32x32x16.ico
LogOff.ico
Ok1_32x32x16.ico
Ok3_32x32x256.ico
Ok4_32x32x2.ico
Open.ico
Palette.bmp
Razor_32x32x256.ico
Right2_32x32x16.ico
Run.ico
Search1.ico
Search2.ico
Sky.bmp
Sound.ico
STLogo_Small.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Winzip2.ico
Workgroup.ico
cbuttonst32_src.zip
cbuttonst_demo.zip
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Butterfly.ico
Button.bmp
Cancel1_32x32x16.ico
Cancel3_32x32x256.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Classes1_32x32x16.ico
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
Help2_32x32x256.ico
Hover.wav
IEDocument_48x48x256.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
LedOff.ico
LedOn.ico
Left6_32x32x256.ico
LogOff.ico
No3_32x32x256.ico
Ok3_32x32x256.ico
Open.ico
Razor_32x32x256.ico
Right6_32x32x256.ico
Run.ico
Search1.ico
Sky.bmp
Sound.ico
Start.wav
STLogo_Small.bmp
toolbar.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Workgroup.ico
cbuttonst_src.zip
#include "stdafx.h"
#include "BkDialogST.h"

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

#ifndef WM_NCLBUTTONDOWN
#define WM_NCLBUTTONDOWN                0x00A1
#define	BKDLGST_DEFINES
#endif

CBkDialogST::CBkDialogST(CWnd* pParent /*=NULL*/)
{
	//{{AFX_DATA_INIT(CBkDialogST)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT

	Init();
}

CBkDialogST::CBkDialogST(UINT uResourceID, CWnd* pParent)
	: CDialog(uResourceID, pParent)
{
	Init();
}


CBkDialogST::CBkDialogST(LPCTSTR pszResourceID, CWnd* pParent)
	: CDialog(pszResourceID, pParent)
{
	Init();
}

CBkDialogST::~CBkDialogST()
{
	FreeResources();
}

void CBkDialogST::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CBkDialogST)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CBkDialogST, CDialog)
	//{{AFX_MSG_MAP(CBkDialogST)
	ON_WM_ERASEBKGND()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

void CBkDialogST::Init()
{
	FreeResources(FALSE);

	// Default drawing bitmap mode
	m_byMode = BKDLGST_MODE_TILE;

	// No EasyMove mode
	m_bEasyMoveMode = FALSE;
} // End of Init

void CBkDialogST::FreeResources(BOOL bCheckForNULL)
{
	if (bCheckForNULL == TRUE)
	{
		// Destroy bitmap
		if (m_hBitmap)	::DeleteObject(m_hBitmap);
#ifndef UNDER_CE
		// Destroy region
		if (m_hRegion)
		{
			::SetWindowRgn(m_hWnd, NULL, FALSE);
			::DeleteObject(m_hRegion);
		} // if
#endif
	} // if

	m_hBitmap = NULL;
#ifndef UNDER_CE
	m_hRegion = NULL;
#endif
	m_dwWidth = 0;
	m_dwHeight = 0;
} // End of FreeResources

void CBkDialogST::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// EasyMove mode
	if (m_bEasyMoveMode == TRUE)
		PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
	
	CDialog::OnLButtonDown(nFlags, point);
} // End of OnLButtonDown

void CBkDialogST::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	// If there is a bitmap loaded
	if (m_hBitmap != NULL)
	{
		Invalidate();
	} // if
} // End of OnSize

BOOL CBkDialogST::OnEraseBkgnd(CDC* pDC) 
{
	CRect		rWnd;
	int			nX			= 0;
	int			nY			= 0;

	BOOL	bRetValue = CDialog::OnEraseBkgnd(pDC);

	// If there is a bitmap loaded
	if (m_hBitmap)
	{
		GetClientRect(rWnd);

		CDC			dcMemoryDC;
		CBitmap		bmpMemoryBitmap;
		CBitmap*	pbmpOldMemoryBitmap = NULL;

		dcMemoryDC.CreateCompatibleDC(pDC);
		bmpMemoryBitmap.CreateCompatibleBitmap(pDC, rWnd.Width(), rWnd.Height());
		pbmpOldMemoryBitmap = (CBitmap*)dcMemoryDC.SelectObject(&bmpMemoryBitmap);

		// Fill background 
		dcMemoryDC.FillSolidRect(rWnd, pDC->GetBkColor());

		CDC			dcTempDC;
		HBITMAP		hbmpOldTempBitmap = NULL;

		dcTempDC.CreateCompatibleDC(pDC);
		hbmpOldTempBitmap = (HBITMAP)::SelectObject(dcTempDC.m_hDC, m_hBitmap);

		switch (m_byMode)
		{
			case BKDLGST_MODE_TILE:
				// Tile the bitmap
				while (nY < rWnd.Height()) 
				{
					while(nX < rWnd.Width()) 
					{
						dcMemoryDC.BitBlt(nX, nY, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
						nX += m_dwWidth;
					} // while
					nX = 0;
					nY += m_dwHeight;
				} // while
				break;
			case BKDLGST_MODE_CENTER:
				nX = ((rWnd.Width() - m_dwWidth)/2);
				nY = ((rWnd.Height() - m_dwHeight)/2);
				dcMemoryDC.BitBlt(nX, nY, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_STRETCH:
				// Stretch the bitmap
				dcMemoryDC.StretchBlt(0, 0, rWnd.Width(), rWnd.Height(), &dcTempDC, 0, 0, m_dwWidth, m_dwHeight, SRCCOPY);
				break;
			case BKDLGST_MODE_TILETOP:
				while(nX < rWnd.Width()) 
				{
					dcMemoryDC.BitBlt(nX, 0, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
					nX += m_dwWidth;
				} // while
				break;
			case BKDLGST_MODE_TILEBOTTOM:
				while(nX < rWnd.Width()) 
				{
					dcMemoryDC.BitBlt(nX, rWnd.bottom - m_dwHeight, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
					nX += m_dwWidth;
				} // while
				break;
			case BKDLGST_MODE_TILELEFT:
				while (nY < rWnd.Height()) 
				{
					dcMemoryDC.BitBlt(0, nY, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
					nY += m_dwHeight;
				} // while
				break;
			case BKDLGST_MODE_TILERIGHT:
				while (nY < rWnd.Height()) 
				{
					dcMemoryDC.BitBlt(rWnd.right - m_dwWidth, nY, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
					nY += m_dwHeight;
				} // while
				break;
			case BKDLGST_MODE_TOPLEFT:
				dcMemoryDC.BitBlt(0, 0, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_TOPRIGHT:
				dcMemoryDC.BitBlt(rWnd.right - m_dwWidth, 0, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_TOPCENTER:
				nX = ((rWnd.Width() - m_dwWidth)/2);
				dcMemoryDC.BitBlt(nX, 0, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_BOTTOMLEFT:
				dcMemoryDC.BitBlt(0, rWnd.bottom - m_dwHeight, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_BOTTOMRIGHT:
				dcMemoryDC.BitBlt(rWnd.right - m_dwWidth, rWnd.bottom - m_dwHeight, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
			case BKDLGST_MODE_BOTTOMCENTER:
				nX = ((rWnd.Width() - m_dwWidth)/2);
				dcMemoryDC.BitBlt(nX, rWnd.bottom - m_dwHeight, m_dwWidth, m_dwHeight, &dcTempDC, 0, 0, SRCCOPY);
				break;
		} // switch

		pDC->BitBlt(0, 0, rWnd.Width(), rWnd.Height(), &dcMemoryDC, 0, 0, SRCCOPY);

		OnPostEraseBkgnd(&dcMemoryDC);

		::SelectObject(dcTempDC.m_hDC, hbmpOldTempBitmap);
		dcMemoryDC.SelectObject(pbmpOldMemoryBitmap);
	} // if

	return bRetValue;
} // End of OnEraseBkgnd

void CBkDialogST::OnPostEraseBkgnd(CDC* pDC)
{
} // End of OnPostEraseBkgnd

// -------------------------------------------------------------------------------------
// Scan a bitmap and return a perfect fit region.
// The caller must release the memory...
// (this method starts with a full region and excludes inside the loop)
// -------------------------------------------------------------------------------------
// Credits for this function go to Vander Nunes
//
#ifndef UNDER_CE
HRGN CBkDialogST::ScanRegion(HBITMAP hBitmap, BYTE byTransR, BYTE byTransG, BYTE byTransB)
{
	// bitmap width and height
	DWORD dwBmpWidth = 0, dwBmpHeight = 0;

	// the final region and a temporary region
	HRGN hRgn = NULL, hTmpRgn = NULL;

	// 24bit pixels from the bitmap
	LPBYTE lpbyPixels = Get24BitPixels(hBitmap, &dwBmpWidth, &dwBmpHeight);
	if (!lpbyPixels) return NULL;

	// create our working region
	hRgn = ::CreateRectRgn(0, 0, dwBmpWidth, dwBmpHeight);
	if (!hRgn) 
	{ 
		delete lpbyPixels; 
		return NULL; 
	} // if

	// ---------------------------------------------------------
	// scan the bitmap
	// ---------------------------------------------------------
	DWORD p=0;
	for (DWORD y=0; y<dwBmpHeight; y++)
	{
		for (DWORD x=0; x<dwBmpWidth; x++)
		{
			BYTE jRed   = lpbyPixels[p+2];
			BYTE jGreen = lpbyPixels[p+1];
			BYTE jBlue  = lpbyPixels[p+0];

			if (jRed == byTransR && jGreen == byTransG && jBlue == byTransB)
			{
				// remove transparent color from region
				hTmpRgn = ::CreateRectRgn(x,y,x+1,y+1);
				::CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);
				::DeleteObject(hTmpRgn);
			} // if

			// next pixel
			p+=3;
		} // for
	} // for

	// release pixels
	delete lpbyPixels;

	// return the region
	return hRgn;
} // End of ScanRegion
#endif

// -------------------------------------------------------------------------------------
// Return bitmap pixels in 24bits format.
// The caller must release the memory...
// -------------------------------------------------------------------------------------
// Credits for this function go to Vander Nunes
//
#ifndef UNDER_CE
LPBYTE CBkDialogST::Get24BitPixels(HBITMAP hBitmap, LPDWORD lpdwWidth, LPDWORD lpdwHeight)
{
	// a bitmap object just to get bitmap width and height
	BITMAP bmpBmp;

	// pointer to original bitmap info
	LPBITMAPINFO pbmiInfo;

	// bitmap info will hold the new 24bit bitmap info
	BITMAPINFO bmiInfo;

	// width and height of the bitmap
	DWORD dwBmpWidth = 0, dwBmpHeight = 0;

	// ---------------------------------------------------------
	// get some info from the bitmap
	// ---------------------------------------------------------
	::GetObject(hBitmap, sizeof(bmpBmp),&bmpBmp);
	pbmiInfo   = (LPBITMAPINFO)&bmpBmp;

	// get width and height
	dwBmpWidth  = (DWORD)pbmiInfo->bmiHeader.biWidth;
	dwBmpWidth -= (dwBmpWidth%4);                       // width is 4 byte boundary aligned.
	dwBmpHeight = (DWORD)pbmiInfo->bmiHeader.biHeight;

	// copy to caller width and height parms
	*lpdwWidth  = dwBmpWidth;
	*lpdwHeight = dwBmpHeight;
	// ---------------------------------------------------------

	// allocate width * height * 24bits pixels
	LPBYTE lpbyPixels = new BYTE[dwBmpWidth * dwBmpHeight * 3];
	if (!lpbyPixels) return NULL;

	// get user desktop device context to get pixels from
	HDC hDC = ::GetWindowDC(NULL);

	// fill desired structure
	bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmiInfo.bmiHeader.biWidth = dwBmpWidth;
	bmiInfo.bmiHeader.biHeight = 0 - (int)dwBmpHeight;
	bmiInfo.bmiHeader.biPlanes = 1;
	bmiInfo.bmiHeader.biBitCount = 24;
	bmiInfo.bmiHeader.biCompression = BI_RGB;
	bmiInfo.bmiHeader.biSizeImage = dwBmpWidth * dwBmpHeight * 3;
	bmiInfo.bmiHeader.biXPelsPerMeter = 0;
	bmiInfo.bmiHeader.biYPelsPerMeter = 0;
	bmiInfo.bmiHeader.biClrUsed = 0;
	bmiInfo.bmiHeader.biClrImportant = 0;

	// get pixels from the original bitmap converted to 24bits
	int iRes = ::GetDIBits(hDC,hBitmap, 0, dwBmpHeight, (LPVOID)lpbyPixels, &bmiInfo, DIB_RGB_COLORS);

	// release the device context
	::ReleaseDC(NULL,hDC);

	// if failed, cancel the operation.
	if (!iRes)
	{
		delete lpbyPixels;
		return NULL;
	} // if

	// return the pixel array
	return lpbyPixels;
} // End of Get24BitPixels
#endif

//
// Parameters:
//		[IN]	bActivate
//				TRUE if EasyMove mode must be activated.
//
// Return value:
//		BKDLGST_OK
//			Function executed successfully.
//
DWORD CBkDialogST::ActivateEasyMoveMode(BOOL bActivate)
{
	m_bEasyMoveMode = bActivate;

	return BKDLGST_OK;
} // End of ActivateEasyMoveMode

//
// Parameters:
//		[IN]	nBitmap
//				Resource ID of the bitmap to use as background.
//		[IN]	crTransColor
//				A COLORREF value indicating the color to "remove" from the
//				bitmap. When crTransColor is specified (different from -1L)
//				a region will be created using the supplied bitmap and applied
//				to the window.
//
// Return value:
//		BKDLGST_OK
//			Function executed successfully.
//		BKDLGST_INVALIDRESOURCE
//			The resource specified cannot be found or loaded.
//		BKDLGST_FAILEDREGION
//			Failed creating region
//
DWORD CBkDialogST::SetBitmap(int nBitmap, COLORREF crTransColor)
{
	HBITMAP		hBitmap			= NULL;
	HINSTANCE	hInstResource	= NULL;

	// Find correct resource handle
	hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nBitmap), RT_BITMAP);

	// Load bitmap In
	hBitmap = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmap), IMAGE_BITMAP, 0, 0, 0);

	return SetBitmap(hBitmap, crTransColor);
} // End of SetBitmap

//
// Parameters:
//		[IN]	hBitmap
//				Handle to the bitmap to use as background.
//		[IN]	crTransColor
//				A COLORREF value indicating the color to "remove" from the
//				bitmap. When crTransColor is specified (different from -1L)
//				a region will be created using the supplied bitmap and applied
//				to the window.
//
// Return value:
//		BKDLGST_OK
//			Function executed successfully.
//		BKDLGST_INVALIDRESOURCE
//			The resource specified cannot be found or loaded.
//		BKDLGST_FAILEDREGION
//			Failed creating region
//
DWORD CBkDialogST::SetBitmap(HBITMAP hBitmap, COLORREF crTransColor)
{
	int		nRetValue;
	BITMAP	csBitmapSize;

	// Free any loaded resource
	FreeResources();

	if (hBitmap)
	{
		m_hBitmap = hBitmap;

		// Get bitmap size
		nRetValue = ::GetObject(hBitmap, sizeof(csBitmapSize), &csBitmapSize);
		if (nRetValue == 0)
		{
			FreeResources();
			return BKDLGST_INVALIDRESOURCE;
		} // if
		m_dwWidth = (DWORD)csBitmapSize.bmWidth;
		m_dwHeight = (DWORD)csBitmapSize.bmHeight;

#ifndef UNDER_CE
		// Create region ?
		if (crTransColor != -1L)
		{
			m_hRegion = ScanRegion(m_hBitmap, GetRValue(crTransColor), GetGValue(crTransColor), GetBValue(crTransColor));
			if (m_hRegion == NULL)
			{
				FreeResources();
				return BKDLGST_FAILEDREGION;
			} // if

			::SetWindowRgn(m_hWnd, m_hRegion, FALSE);
		} // if
#endif
	} // if

	Invalidate();

	return BKDLGST_OK;
} // End of SetBitmap

//
// Parameters:
//		[IN]	byMode
//				Specifies how the bitmap will be placed in the dialog background.
//		[IN]	bRepaint
//				If TRUE the dialog will be repainted.
//
// Return value:
//		BKDLGST_OK
//			Function executed successfully.
//		BKDLGST_INVALIDMODE
//			Invalid mode.
//
DWORD CBkDialogST::SetMode(BYTE byMode, BOOL bRepaint)
{
	if (byMode >= BKDLGST_MAX_MODES)	return BKDLGST_INVALIDMODE;

	// Set new mode
	m_byMode = byMode;

	if (bRepaint == TRUE)	Invalidate();

	return BKDLGST_OK;
} // End of SetMode

#ifndef UNDER_CE
DWORD CBkDialogST::ShrinkToFit(BOOL bRepaint)
{
	CRect	rWnd;
	CRect	rClient;
	DWORD	dwDiffCX;
	DWORD	dwDiffCY;

	GetWindowRect(&rWnd);
	GetClientRect(&rClient);

	dwDiffCX = rWnd.Width() - rClient.Width();
	dwDiffCY = rWnd.Height() - rClient.Height();

	m_byMode = BKDLGST_MODE_CENTER;

	MoveWindow(rWnd.left, rWnd.top, dwDiffCX + m_dwWidth, dwDiffCY + m_dwHeight, bRepaint);

	return BKDLGST_OK;
} // End of ShrinkToFit
#endif

#ifdef	BKDLGST_DEFINES
#undef	BKDLGST_DEFINES
#undef	WM_NCLBUTTONDOWN
#endif

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

Share

About the Author

Davide Calabro
Web Developer
Italy Italy
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 29 Mar 2003
Article Copyright 1999 by Davide Calabro
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid