Click here to Skip to main content
15,886,873 members
Articles / Desktop Programming / MFC

A color picker dialog with a color dropper like Photoshop and Frontpage 2000

Rate me:
Please Sign up or sign in to vote.
4.83/5 (10 votes)
23 Jan 20022 min read 94.9K   4.3K   29  
A color picker and dropper that extends the standard Windows dialogs to behave like Photoshop or Frontpage 2000
// Copyright UCanCode Software Technology Inc, All Rights Reserved
// You can contact us.
// Support@UCanCode.net
// http://www.ucancode.net
/********************************************************************/
#include "stdafx.h"
#include "FOColorCellObj.h"
#include "afxpriv.h"
#include "math.h"

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

#define FORMMIN(X,Y)				(((X) < (Y)) ? (X) : (Y))
#define FORMMAX(X,Y)				(((X) > (Y)) ? (X) : (Y))

FO_GLOBAL gfxData;

FO_GLOBAL::FO_GLOBAL()
{
	OnUpdateMetrics();
	OnSysColorChange();
	
	OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	
	::GetVersionEx (&osvi);
	bNT4 = ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
		(osvi.dwMajorVersion < 5));
}

FO_GLOBAL::~FO_GLOBAL()
{
}

void FO_GLOBAL::OnSysColorChange()
{
	m_crBtnFace = GetSysColor(COLOR_BTNFACE);
	m_crBtnShadow = GetSysColor(COLOR_BTNSHADOW);
	m_crBtnDkShadow = GetSysColor(COLOR_3DDKSHADOW);
	m_crBtnLight = GetSysColor(COLOR_3DLIGHT);
	m_crBtnHilite = GetSysColor(COLOR_BTNHIGHLIGHT);
	m_crBtnText = GetSysColor(COLOR_BTNTEXT);
	m_crTextGrayed = GetSysColor (COLOR_GRAYTEXT);
	m_crWindowFrame = GetSysColor(COLOR_WINDOWFRAME);
	
	m_crHilite = GetSysColor(COLOR_HIGHLIGHT);
	m_crTextHilite = GetSysColor(COLOR_HIGHLIGHTTEXT);
	m_crWindowText = GetSysColor(COLOR_WINDOWTEXT);
	m_crBtn3dShadow = GetSysColor(COLOR_3DSHADOW);
	m_crBtn3dHiLight = GetSysColor(COLOR_3DHILIGHT);
	m_crAcCaption = GetSysColor(COLOR_ACTIVECAPTION);
	m_crInAcCaption = GetSysColor(COLOR_INACTIVECAPTION);
	m_crInAcCaptionText = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
	m_crDesktop = GetSysColor(COLOR_DESKTOP);
	
	m_cr3dFace = gfxData.m_cr3dFace;
#ifdef COLOR_HOTLIGHT
	
	OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	
	::GetVersionEx (&osvi);
	if (osvi.dwMajorVersion >= 5)
	{
		m_crTextHot = GetSysColor (COLOR_HOTLIGHT);
	}
	else
#endif
	{
		m_crTextHot = RGB (0, 0, 255);	// Light blue
	}
	
	CWindowDC dc (NULL);
	m_nBitsPerPixel = dc.GetDeviceCaps (BITSPIXEL);
	
}

CSize FO_GLOBAL::GetScreenDimensions()
{
	OnUpdateMetrics();
	return CSize(m_cxScreen, m_cyScreen);
}

void FO_GLOBAL::OnUpdateMetrics()
{
	m_cxEdge = ::GetSystemMetrics(SM_CXEDGE);
	m_cyEdge = ::GetSystemMetrics(SM_CYEDGE);
	m_cxBorder = ::GetSystemMetrics(SM_CXBORDER);
	m_cxScreen = ::GetSystemMetrics(SM_CXSCREEN);
	m_cyScreen = ::GetSystemMetrics(SM_CYSCREEN);
	m_cxVScroll = ::GetSystemMetrics(SM_CXVSCROLL);
	m_cxFrame = ::GetSystemMetrics(SM_CXFRAME);
	m_cyFrame = ::GetSystemMetrics(SM_CYFRAME);
	m_cxFixedFrame = ::GetSystemMetrics(SM_CXFIXEDFRAME);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL(CFOColorCellObj, CObject, 0)
CFOColorCellObj::CFOColorCellObj()
{
	m_rcPosition = CRect(0,0,0,0);
	m_crCell = RGB(255,255,255);
	m_pBrushCell = NULL;
	nCellBorderSize = 1;
	m_bAtFirstType = TRUE;
}

CFOColorCellObj::~CFOColorCellObj()
{
	RelaseBrushObject();
}

CRect CFOColorCellObj::GetRect() const
{
	if(!m_bAtFirstType)
	{
		return m_rcPosition;
	}
	CRect rcBounds;
	
	rcBounds.left = rcBounds.right  = m_Points[0].x;
	rcBounds.top  = rcBounds.bottom = m_Points[0].y;
	
	for (int i=1; i<6; i++)
	{
		rcBounds.left   = FORMMIN(rcBounds.left,   m_Points[i].x);
		rcBounds.top    = FORMMIN(rcBounds.top,    m_Points[i].y);
		rcBounds.right  = FORMMAX(rcBounds.right,  m_Points[i].x);
		rcBounds.bottom = FORMMAX(rcBounds.bottom, m_Points[i].y);
	}
	
	return rcBounds;
}

void CFOColorCellObj::Serialize(CArchive& ar)
{
	if(ar.IsStoring())
	{
	}
	else
	{
	}
}

void CFOColorCellObj::SetCellColor(const COLORREF &cr) 
{ 
	RelaseBrushObject();
	m_crCell = cr; 
}

CBrush* CFOColorCellObj::CreateBrush(CDC* pDC)
{
	pDC;
	CBrush* pBrush = new CBrush();
	pBrush->CreateSolidBrush(m_crCell);
	return pBrush;
}


CBrush* CFOColorCellObj::GetBrush(CDC* pDC)
{
	if (m_pBrushCell == NULL)
		m_pBrushCell = CreateBrush(pDC);
	return m_pBrushCell;
}

void CFOColorCellObj::RelaseBrushObject()
{
	if(m_pBrushCell != NULL)
	{
		delete m_pBrushCell;
	}
	m_pBrushCell = NULL;
}

void CFOColorCellObj::PrepareDC(CDC* pDC)
{
	pDC->SaveDC();
	pDC->SetBkMode(TRANSPARENT);
	CBrush* pBrush = GetBrush(pDC);
	pDC->SelectObject(pBrush);
	pDC->SelectStockObject(NULL_PEN);
}

void CFOColorCellObj::OnDraw(CDC *pDC)
{
	PrepareDC(pDC);
	ASSERT_VALID (pDC);
	pDC->FillSolidRect(m_rcPosition,gfxData.m_crBtnFace);
	CRect rcPos;
	rcPos = m_rcPosition;
	rcPos.DeflateRect(nCellBorderSize,nCellBorderSize,nCellBorderSize,nCellBorderSize);
	
	if(!m_bAtFirstType)
	{
		pDC->Rectangle(rcPos);
		pDC->Draw3dRect(rcPos,gfxData.m_crBtn3dShadow,gfxData.m_crBtn3dShadow);
	}
	else
	{
		pDC->Polygon (m_Points, 6);
	}

	ClearDC(pDC);
}

void CFOColorCellObj::OnDrawSelect(CDC *pDC)
{
	ASSERT_VALID (pDC);
	CBrush* pBrWhite = CBrush::FromHandle ((HBRUSH) ::GetStockObject (WHITE_BRUSH));
	ASSERT_VALID (pBrWhite);
	
	CBrush* pBrBlack = CBrush::FromHandle ((HBRUSH) ::GetStockObject (BLACK_BRUSH));
	ASSERT_VALID (pBrBlack);
	if(m_bAtFirstType)
	{
		if(m_crCell == RGB(255,255,255))
		{
			CRgn rgnOne;
			rgnOne.CreatePolygonRgn(m_Points, 6, ALTERNATE);
			pDC->FrameRgn(&rgnOne, pBrWhite, 3, 3);

			pDC->FrameRgn(&rgnOne, pBrBlack, 2, 2);
		}
		else
		{
			CRgn rgnOne;
			rgnOne.CreatePolygonRgn(m_Points, 6, ALTERNATE);
			pDC->FrameRgn(&rgnOne, pBrWhite, 3, 3);

			pDC->FrameRgn(&rgnOne, pBrBlack, 1, 1);
		}
	}
	else
	{
		CRgn rgnOne, rgnTwo, rgnThree;
		
		CRect rcPos;
		rcPos = m_rcPosition;
		rcPos.DeflateRect(1,1,1,1);
		
		rgnTwo.CreateRectRgnIndirect(&rcPos);
		pDC->FrameRgn(&rgnTwo, pBrWhite, 2, 2);
		rcPos.InflateRect(2,2,2,2);
		
		rgnThree.CreateRectRgnIndirect(&rcPos);
		pDC->FrameRgn(&rgnThree, pBrBlack, 1, 1);
	}
}

void CFOColorCellObj::ClearDC(CDC* pDC)
{
	pDC->RestoreDC(-1);
}

int CFOColorCellObj::MoreNear(float fNear)
{
	int nRound = (int)fabs(fNear);
	nRound = (fabs(fNear) - (float)nRound >= 0.5) ? nRound+1 : nRound;
	return (fNear < 0) ? -nRound : nRound;
}

void CFOColorCellObj::AdjustCellPosition(int x, int y, int nWidth)
{
	float nSideLength = (float)((float)nWidth * 0.57735026918962F);
	m_Points[0] = CPoint(MoreNear(x - (float)(nWidth / 2)),MoreNear(y - (float)(nSideLength/2)));
	m_Points[1] = CPoint(MoreNear((float)x),MoreNear(y - (float)(nWidth / 2)));
	m_Points[2] = CPoint(MoreNear(x + (float)(nWidth / 2)),MoreNear(y - (float)(nSideLength/2)));
	m_Points[3] = CPoint(MoreNear(x + (float)(nWidth / 2)),MoreNear(y + (float)(nSideLength/2))+1);
	m_Points[4] = CPoint(MoreNear((float)x),MoreNear(y + (float)(nWidth / 2))+1);
	m_Points[5] = CPoint(MoreNear(x - (float)(nWidth / 2)),MoreNear(y + (float)(nSideLength/2))+1);
}

BOOL CFOColorCellObj::HitTest(CPoint point)
{
	if(m_bAtFirstType)
	{
		CRgn rgn;
		rgn.CreatePolygonRgn(m_Points, 6, ALTERNATE);
		return rgn.PtInRegion (point);
	}
	else
	{
		CRgn rgn;
		rgn.CreateRectRgn(m_rcPosition.left,m_rcPosition.top,m_rcPosition.right,m_rcPosition.bottom);
		return rgn.PtInRegion (point);
	}
}

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
jack Mesic is the president of UCanCode Software Technology,Inc..

Comments and Discussions