Click here to Skip to main content
14,022,546 members
Click here to Skip to main content

Stats

297.9K views
78.9K downloads
226 bookmarked
Posted 30 Dec 2005
Licenced CPOL

Form Designer

, 1 Aug 2009
Component for adding scriptable forms capabilities to an application.
MFCDemo.exe
CSDemo
App.ico
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
CSDemo.suo
DaeDoe.bmp
MFCDemo
MFCDemo.dsp
MFCDemo.odl
MFCDemo.reg
res
DaeDoe.bmp
MFCDemo.ico
MFCDemoDoc.ico
Toolbar1.bmp
Toolbar2.bmp
Toolbar3.bmp
Wand.bmp
VBDemo
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
DaeDoe.bmp
VBDemo.vbp
DDForms.chm
DDForms
Archive
FormEditorItems.rgs
vssver.scc
Constants.scr
DaeDoe.bmp
DDForms.def
DDForms.vcproj
DDForms.vcproj.vspscc
EventSinkPassThrough.rgs
FormEditor.bmp
FormEditor.rgs
FormEditorItemCollection.rgs
FormEditorItemDetails.rgs
FormViewer.bmp
FormViewer.rgs
FormViewerItemCollection.rgs
FormViewerItemDetails.rgs
mssccprj.scc
PropPageExtended.rgs
PropPageFormEditor.rgs
PropPageFormViewer.rgs
PropPageSimpleScriptEditor.rgs
SimpleScriptEditor.bmp
SimpleScriptEditor.rgs
vssver.scc
DDFormsTools
CodeMaxDriver
CodeMaxDriver.rgs
CodeMaxDriver.vcproj
CodeMaxDriver.vcproj.vspscc
CodeMaxDriverps.def
CodeMaxDriverPS.vcproj
CodeMaxDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
CodeSenseDriver
CodeSenseDriver.rgs
CodeSenseDriver.vcproj
CodeSenseDriver.vcproj.vspscc
CodeSenseDriverps.def
CodeSenseDriverPS.vcproj
CodeSenseDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
DDPropPageAll
DDPropPageAll.def
DDPropPageAll.vcproj
DDPropPageAll.vcproj.vspscc
mssccprj.scc
PropPageAll.rgs
vssver.scc
DDUnlock
DDUnlock.vcproj
DDUnlock.vcproj.vspscc
mssccprj.scc
vssver.scc
DDControlPack
DDButton.bmp
DDCheckBox.bmp
DDComboBox.bmp
DDControlPack.rgs
DDControlPack.vcproj
DDControlPack.vcproj.vspscc
DDHorzScrollBar.bmp
DDLabel.bmp
DDListBox.bmp
DDPicture.bmp
DDRadioButton.bmp
DDTextBox.bmp
DDVertScrollBar.bmp
mssccprj.scc
vssver.scc
Redistributables
Ansi
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
Unicode
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
// ColorPicker.cpp: implementation of the CColorPicker class.
//
// Author : David Shepherd
//			Copyright (c) 2002, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ColorPicker.h"

// number of palette cell rows and columns
#define PALETTE_CELL_ROWS		8
#define PALETTE_CELL_COLS		8

// horizontal and vertical palette cell spacing
#define PALETTE_CELL_HSPACING	2
#define PALETTE_CELL_VSPACING	2

// index of the first custom color palette cell
#define PALETTE_CELL_CUSTOM_IX	(6*PALETTE_CELL_COLS)

// system color tab index
#define SYSTEM_COLOR_TAB_IX		1
// palette color tab index
#define PALETTE_COLOR_TAB_IX	0

/////////////////////////////////////////////////////////////////////////////
// CSystemColor

CSystemColor::CSystemColor()
{
	// initialise everything
	m_Color=RGB(0,0,0);
}

CSystemColor::~CSystemColor()
{
	// clean up
}

/////////////////////////////////////////////////////////////////////////////
// CPaletteColor

CPaletteColor::CPaletteColor()
{
	// initialise everything
	m_Color=RGB(0,0,0);
}

CPaletteColor::~CPaletteColor()
{
	// clean up
}

/////////////////////////////////////////////////////////////////////////////
// CColorPicker

CColorPicker::CColorPicker() :
	m_TabCtrl(this,CP_MSG_MAP_TAB_CONTROL),
	m_SystemColorPicker(this,CP_MSG_MAP_SYSTEM_COLOR_PICKER),
	m_PaletteColorPicker(this,CP_MSG_MAP_PALETTE_COLOR_PICKER)
{
	// initialise everything
	m_PaletteCellWidth=0;
	m_PaletteCellHeight=0;
	m_SelectedPaletteCellIndex=-1;
	m_RunMessageLoop=TRUE;
	m_Color=RGB(0,0,0);

	// load system colors
	LoadSystemColors();
	// load palette colors
	LoadPaletteColors();
}

CColorPicker::~CColorPicker()
{
	// clean up
}

CFontHandle CColorPicker::GetFont()
{
	// return the color picker font
	CFontHandle hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
	if(hFont==NULL)
	{
		throw std::exception();
	}
	return hFont;
}

void CColorPicker::LoadSystemColors()
{
	// system colors
	struct tagSystemColor
	{
		// name
		WCHAR *pName;
		// index
		DWORD Ix;

	} SystemColors[]={
		{	L"Scroll Bars",				COLOR_SCROLLBAR				},
		{	L"Desktop",					COLOR_BACKGROUND			},
		{	L"Active Title Bar",		COLOR_ACTIVECAPTION			},
		{	L"Inactive Title Bar",		COLOR_INACTIVECAPTION		},
		{	L"Menu Bar",				COLOR_MENU					},
		{	L"Window Background",		COLOR_WINDOW				},
		{	L"Window Frame",			COLOR_WINDOWFRAME			},
		{	L"Menu Text",				COLOR_MENUTEXT				},
		{	L"Window Text",				COLOR_WINDOWTEXT			},
		{	L"Active Title Bar Text",	COLOR_CAPTIONTEXT			},
		{	L"Active Border",			COLOR_ACTIVEBORDER			},
		{	L"Inactive Border",			COLOR_INACTIVEBORDER		},
		{	L"Application Workspace",	COLOR_APPWORKSPACE			},
		{	L"Highlight",				COLOR_HIGHLIGHT				},
		{	L"Highlight Text",			COLOR_HIGHLIGHTTEXT			},
		{	L"Button Face",				COLOR_BTNFACE				},
		{	L"Button Shadow",			COLOR_BTNSHADOW				},
		{	L"Disabled Text",			COLOR_GRAYTEXT				},
		{	L"Button Text",				COLOR_BTNTEXT				},
		{	L"Inactive Title Bar Text",	COLOR_INACTIVECAPTIONTEXT	},
		{	L"Button Highlight",		COLOR_BTNHIGHLIGHT			},
		{	L"Button Dark Shadow",		COLOR_3DDKSHADOW			},
		{	L"Button Light Shadow",		COLOR_3DLIGHT				},
		{	L"ToolTip Text",			COLOR_INFOTEXT				},
		{	L"ToolTip",					COLOR_INFOBK				}};
	// load system colors
	for(long l=0; l<NUM_ELEMENTS(SystemColors,tagSystemColor); l++)
	{
		// create the system color
		CSystemColor SystemColor;
		SystemColor.m_Name=SystemColors[l].pName;
		SystemColor.m_Color=MAKE_OLE_COLOR(SystemColors[l].Ix);
		// update the vector
		m_SystemColors.push_back(SystemColor);
	}
}

void CColorPicker::LoadPaletteColors()
{
	// palette colors
	struct tagPaletteColor
	{
		// color
		OLE_COLOR Color;

	} PaletteColors[]={
		// standard colors
		0x00FFFFFF,0x00C0C0ff,0x00C0E0ff,0x00C0FFFF,
		0x00C0FFC0,0x00FFFFC0,0x00FFC0C0,0x00FFC0FF,
		0x00E0E0E0,0x008080FF,0x0080C0FF,0x0080FFFF,
		0x0080FF80,0x00FFFF80,0x00FF8080,0x00FF80FF,
		0x00C0C0C0,0x000000FF,0x000080FF,0x0000FFFF,
		0x0000FF00,0x00FFFF00,0x00FF0000,0x00FF00FF,
		0x00808080,0x000000C0,0x000040C0,0x0000C0C0,
		0x0000C000,0x00C0C000,0x00C00000,0x00C000C0,
		0x00404040,0x00000080,0x00004080,0x00008080,
		0x00008000,0x00808000,0x00800000,0x00800080,
		0x00000000,0x00000040,0x00404080,0x00004040,
		0x00004000,0x00404000,0x00400000,0x00400040,
		// custom colors
		0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,
		0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,
		0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,
		0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF
		};
	// check the element count
	ATLASSERT(NUM_ELEMENTS(PaletteColors,tagPaletteColor)==
		PALETTE_CELL_ROWS*PALETTE_CELL_COLS);
	// load palette colors
	for(long l=0; l<NUM_ELEMENTS(PaletteColors,tagPaletteColor); l++)
	{
		// create the palette color
		CPaletteColor PaletteColor;
		PaletteColor.m_Color=PaletteColors[l].Color;
		// update the vector
		m_PaletteColors.push_back(PaletteColor);
	}
}

void CColorPicker::SetSizeAndPosition(const CPoint &TopRight)
{
	USES_CONVERSION;

	// get the client device context
	CClientDC dc(*this);
	if(dc==NULL)
	{
		throw std::exception();
	}
	// save the device context state
	CAutoDCState AutoDCState(dc);
	// set the font
	if(dc.SelectFont(GetFont())==NULL)
	{
		throw std::exception();
	}
	// determine the required width based on the longest system color name
	DWORD Width=0;
	for(long l=0; l<(long)m_SystemColors.size(); l++)
	{
		// prepend a space to the name
		std::wstring Name=L" "+m_SystemColors[l].m_Name;
		// update the width
		CSize Size(0,0);
		if(dc.GetTextExtent(W2CT(Name.c_str()),-1,&Size)==FALSE)
		{
			throw std::exception();
		}
		Width=max(Width,(DWORD)Size.cx);
	}
	// allow room for the color sample
	DWORD ItemHeight=m_SystemColorPicker.GetItemHeight(0);
	if(ItemHeight==LB_ERR)
	{
		throw std::exception();
	}
	Width+=(DWORD)((float)ItemHeight*ASPECT_RATIO(dc));
	// allow room for the scrollbar
	Width+=GetSystemMetrics(SM_CXVSCROLL);

	// the width needs to be adjusted to ensure an exact number of
	// palette cells fit within the available area

	// get the width occupied by palette cell spacing
	DWORD SpacingWidth=PALETTE_CELL_HSPACING*(PALETTE_CELL_COLS+1);
	// get the minimum width
	DWORD MinimumWidth=max(Width,SpacingWidth+PALETTE_CELL_COLS);
	// get the palette cell width
	m_PaletteCellWidth=(MinimumWidth-SpacingWidth)/PALETTE_CELL_COLS;
	// allow for rounding errors
	m_PaletteCellWidth++;
	// adjust the width
	Width=SpacingWidth+(m_PaletteCellWidth*PALETTE_CELL_COLS);
	// allow room for the border
	Width+=2*GetSystemMetrics(SM_CXBORDER);

	// the height can now be determined based on the display aspect
	// ratio and the number of palette cell rows

	// get the height occupied by palette cell spacing
	DWORD SpacingHeight=PALETTE_CELL_VSPACING*(PALETTE_CELL_ROWS+1);
	// get the palette cell height
	m_PaletteCellHeight=max(1,(DWORD)((float)m_PaletteCellWidth/ASPECT_RATIO(dc)));
	// get the height
	DWORD Height=SpacingHeight+(m_PaletteCellHeight*PALETTE_CELL_ROWS);
	// allow room for the border
	Height+=2*GetSystemMetrics(SM_CYBORDER);

	// get the color picker rect
	CRect ColorPickerRect(0,0,Width,Height);
	// allow room for the tab control
	m_TabCtrl.AdjustRect(TRUE,ColorPickerRect);
	// allow room for the dialog frame
	ColorPickerRect.InflateRect(
		GetSystemMetrics(SM_CXDLGFRAME),GetSystemMetrics(SM_CYDLGFRAME));
	// position the top right corner
	ColorPickerRect.OffsetRect(
		TopRight.x-ColorPickerRect.right+1,TopRight.y-ColorPickerRect.top);
	// prevent screen overrun
	CRect ScreenRect(
		0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
	// todo : allow for the task bar
	ColorPickerRect=ForceRectIntoRect(ScreenRect,ColorPickerRect);

	// size and position the color picker
	if(SetWindowPos(NULL,ColorPickerRect,SWP_NOZORDER)==FALSE)
	{
		throw std::exception();
	}
}

void CColorPicker::SelectStartColor()
{
	// look for a matching system color
	for(long l=0; l<(long)m_SystemColors.size(); l++)
	{
		// compare colors
		if(m_SystemColors[l].m_Color!=m_Color)
		{
			continue;
		}
		// select the system color tab
		if(m_TabCtrl.SetCurSel(SYSTEM_COLOR_TAB_IX)==-1)
		{
			throw std::exception();
		}
		// select the system color
		if(m_SystemColorPicker.SetCurSel(l)==LB_ERR)
		{
			throw std::exception();
		}
		// show the system color picker
		(void)m_SystemColorPicker.ShowWindow(SW_SHOW);

		return;	// done
	}
	// select the palette color tab
	if(m_TabCtrl.SetCurSel(PALETTE_COLOR_TAB_IX)==-1)
	{
		throw std::exception();
	}
	// show the palette color picker
	(void)m_PaletteColorPicker.ShowWindow(SW_SHOW);
	// look for a matching palette color
	for(l=0; l<(long)m_PaletteColors.size(); l++)
	{
		// compare colors
		if(m_PaletteColors[l].m_Color!=m_Color)
		{
			continue;
		}
		// select the palette color
		m_SelectedPaletteCellIndex=l;

		return;	// done
	}
	// create a custom palette color
	for(l=PALETTE_CELL_CUSTOM_IX; l<(long)m_PaletteColors.size(); l++)
	{
		// look for an empty slot
		if(m_PaletteColors[l].m_Color!=0x00FFFFFF)
		{
			continue;
		}
		// create the custom palette color
		m_PaletteColors[l].m_Color=m_Color;
		// select the custom palette color
		m_SelectedPaletteCellIndex=l;

		return;	// done
	}
}

void CColorPicker::DrawSystemColorPicker(const DRAWITEMSTRUCT &DrawItemStruct)
{
	USES_CONVERSION;

	// create GDI object wrappers
	// this must be done before the device context state is saved
	CPen Pen;
	CBrush Brush;
	// wrap the device context and save the state
	CDCHandle hDC=DrawItemStruct.hDC;
	CAutoDCState AutoDCState(hDC);
	// get the item rect
	CRect ItemRect=DrawItemStruct.rcItem;
	// determine if the item is selected
	BOOL IsSelected=(DrawItemStruct.itemState & ODS_SELECTED) ? TRUE : FALSE;

	// get the system color
	CSystemColor SystemColor=m_SystemColors[DrawItemStruct.itemData];

	// get the color sample rect
	CRect ColorSampleRect=ItemRect;
	ColorSampleRect.right=
		ColorSampleRect.left+(long)((float)ItemRect.Height()*ASPECT_RATIO(hDC));
	ColorSampleRect.InflateRect(-1,-1);
	// set the pen
	if(Pen.CreatePen(PS_SOLID,0,RGB(0,0,0))==NULL)
	{
		throw std::exception();
	}
	if(hDC.SelectPen(Pen)==NULL)
	{
		throw std::exception();
	}
	// convert the system color to an RGB value
	COLORREF RGBColor=RGB(0,0,0);
	if(!SUCCEEDED(OleTranslateColor(SystemColor.m_Color,NULL,&RGBColor)))
	{
		throw std::exception();
	}
	// set the brush
	if(Brush.CreateSolidBrush(RGBColor)==NULL)
	{
		throw std::exception();
	}
	if(hDC.SelectBrush(Brush)==NULL)
	{
		throw std::exception();
	}
	// draw the color sample
	if(hDC.Rectangle(ColorSampleRect)==FALSE)
	{
		throw std::exception();
	}

	// get the color name rect
	CRect ColorNameRect=ItemRect;
	ColorNameRect.left=ColorSampleRect.right+1;
	// set the font
	if(hDC.SelectFont(GetFont())==NULL)
	{
		throw std::exception();
	}
	// set the background color
	COLORREF BackColor=GetSysColor(
		IsSelected ? COLOR_HIGHLIGHT : COLOR_WINDOW);
	if(hDC.SetBkColor(BackColor)==CLR_INVALID)
	{
		throw std::exception();
	}
	// set the foreground color
	COLORREF ForeColor=GetSysColor(
		IsSelected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT);
	if(hDC.SetTextColor(ForeColor)==CLR_INVALID)
	{
		throw std::exception();
	}
	// fill in the background
	hDC.FillSolidRect(ColorNameRect,BackColor);
	// prepend a space to the color name
	std::wstring Name=L" "+SystemColor.m_Name;
	// draw the color name
	if(hDC.DrawText(W2CT(Name.c_str()),
		-1,ColorNameRect,DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX)==0)
	{
		throw std::exception();
	}
}

void CColorPicker::DrawPaletteColorPicker(const DRAWITEMSTRUCT &DrawItemStruct)
{
	// wrap the device context
	CDCHandle hDC=DrawItemStruct.hDC;
	// draw all palette cells
	for(long l=0; l<PALETTE_CELL_ROWS*PALETTE_CELL_COLS; l++)
	{
		// create GDI object wrappers
		// this must be done before the device context state is saved
		CPen Pen;
		CBrush Brush;
		// save the device context state
		CAutoDCState AutoDCState(hDC);
		// get the palette cell rect
		CRect PaletteCellRect=GetPaletteCellRect(l);
		// determine if the palette cell is selected
		BOOL IsSelected=(l==m_SelectedPaletteCellIndex) ? TRUE : FALSE;
		// set the pen
		COLORREF PenColor=IsSelected ? RGB(255,255,255) : RGB(0,0,0);
		if(Pen.CreatePen(PS_SOLID,0,PenColor)==NULL)
		{
			throw std::exception();
		}
		if(hDC.SelectPen(Pen)==NULL)
		{
			throw std::exception();
		}
		// set the brush
		if(Brush.CreateSolidBrush(m_PaletteColors[l].m_Color)==NULL)
		{
			throw std::exception();
		}
		if(hDC.SelectBrush(Brush)==NULL)
		{
			throw std::exception();
		}
		// draw the palette cell
		if(hDC.Rectangle(PaletteCellRect)==FALSE)
		{
			throw std::exception();
		}
	}
}

CRect CColorPicker::GetPaletteCellRect(DWORD PaletteCellIndex)
{
	// check the palette cell index
	ATLASSERT(PaletteCellIndex >= 0);
	ATLASSERT(PaletteCellIndex < PALETTE_CELL_ROWS*PALETTE_CELL_COLS);

	// get the palette cell row
	DWORD Row=PaletteCellIndex/PALETTE_CELL_COLS;
	// get the palette cell column
	DWORD Col=PaletteCellIndex%PALETTE_CELL_COLS;

	// return the palette cell rectangle
	CRect PaletteCellRect(0,0,m_PaletteCellWidth,m_PaletteCellHeight);
	PaletteCellRect.OffsetRect(
		PALETTE_CELL_HSPACING+(Col*(m_PaletteCellWidth+PALETTE_CELL_HSPACING)),
		PALETTE_CELL_VSPACING+(Row*(m_PaletteCellHeight+PALETTE_CELL_VSPACING)));

	return PaletteCellRect;
}

DWORD CColorPicker::PaletteCellHitTest(const CPoint &Pos)
{
	// determine which palette cell is located at the passed position
	DWORD PaletteCellIndex=-1;
	for(long l=0; l<(long)m_PaletteColors.size() and PaletteCellIndex==-1; l++)
	{
		// get the palette cell rect
		CRect PaletteCellRect=GetPaletteCellRect(l);
		// hit test
		if(PaletteCellRect.PtInRect(Pos))
		{
			PaletteCellIndex=l;	// found it
		}
	}
	return PaletteCellIndex;
}

void CColorPicker::SelectPaletteCellAtPos(const CPoint &Pos)
{
	// determine which palette cell is located at the passed position
	DWORD PaletteCellIndex=PaletteCellHitTest(Pos);
	if(PaletteCellIndex!=-1)
	{
		// invalidate the old selected palette cell
		if(m_SelectedPaletteCellIndex!=-1)
		{
			if(m_PaletteColorPicker.InvalidateRect(
				GetPaletteCellRect(m_SelectedPaletteCellIndex),FALSE)==FALSE)
			{
				throw std::exception();
			}
		}
		// invalidate the new selected palette cell
		if(m_PaletteColorPicker.InvalidateRect(
			GetPaletteCellRect(PaletteCellIndex),FALSE)==FALSE)
		{
			throw std::exception();
		}
		// update the color
		m_Color=m_PaletteColors[PaletteCellIndex].m_Color;
		// update the selected palette cell index
		m_SelectedPaletteCellIndex=PaletteCellIndex;
	}
}

BOOL CColorPicker::PickColor(const CWindow &Parent,const CPoint &TopRight)
{
TRY
	// reinitialise everything to allow object reuse
	m_SelectedPaletteCellIndex=-1;
	m_RunMessageLoop=TRUE;
	// create the color picker window (invisible)
	if(Create(Parent,CRect(0,0,0,0),_T(""),
		WS_POPUP|WS_CLIPCHILDREN,WS_EX_DLGMODALFRAME)==NULL)
	{
		throw std::exception();
	}
	// size and position the color picker
	SetSizeAndPosition(TopRight);
	// select the initial color
	SelectStartColor();
	// show the color picker
	(void)ShowWindow(SW_SHOW);
	// run the message loop
	while(m_RunMessageLoop)
	{
		// get the next message
		// todo : check for the WM_QUIT message
		MSG Message;
		(void)GetMessage(&Message,NULL,0,0);
		// process the message
		(void)TranslateMessage(&Message);
		(void)DispatchMessage(&Message);
	}
CATCH_ALL
	// clean up
	if(IsWindow())
	{
		(void)DestroyWindow();
	}
	return Caught ? FALSE : TRUE;	// return TRUE on success
}

LRESULT CColorPicker::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// create the tab control
	if(m_TabCtrl.Create(*this,CRect(0,0,0,0),_T(""),
		// standard window styles
		WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|
		// tab control styles
		TCS_FOCUSNEVER,
		// extended window styles
		0,
		// id
		CP_IDC_TAB_CONTROL)==NULL)
	{
		throw std::exception();
	}
	// set the tab control font
	m_TabCtrl.SetFont(GetFont());
	// add the system color tab
	TCITEM TCItem;
	ZeroMemory(&TCItem,sizeof(TCITEM));
	TCItem.mask=TCIF_TEXT;
	TCItem.pszText=_T("System");
	if(m_TabCtrl.InsertItem(0,&TCItem)==-1)	// todo : WTL returns BOOL
	{
		throw std::exception();
	}
	// add the palette color tab
	TCItem.pszText=_T("Palette");
	if(m_TabCtrl.InsertItem(0,&TCItem)==-1)	// todo : WTL returns BOOL
	{
		throw std::exception();
	}
	// create the system color picker
	if(m_SystemColorPicker.Create(*this,CRect(0,0,0,0),_T(""),
		// standard window styles
		WS_CHILD|WS_BORDER|WS_VSCROLL|
		// list box styles
		LBS_NOTIFY|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED,
		// extended window styles
		0,
		// id
		CP_IDC_SYSTEM_COLOR_PICKER)==NULL)
	{
		throw std::exception();
	}
	// add all system colors
	for(long l=0; l<(long)m_SystemColors.size(); l++)
	{
		// add by vector index
		LRESULT Result=m_SystemColorPicker.AddString((LPCTSTR)l);
		if(Result==LB_ERR or Result==LB_ERRSPACE)
		{
			throw std::exception();
		}
	}
	// create the palette color picker
	if(m_PaletteColorPicker.Create(*this,CRect(0,0,0,0),_T(""),
		// standard window styles
		WS_CHILD|WS_BORDER|
		// button styles
		BS_OWNERDRAW,
		// extended window styles
		0,
		// id
		CP_IDC_PALETTE_COLOR_PICKER)==NULL)
	{
		throw std::exception();
	}
CATCH_ALL
	return Caught ? -1 : 0;	// fail creation on error
}

LRESULT CColorPicker::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the client rect
	CRect ClientRect(0,0,0,0);
	if(GetClientRect(ClientRect)==FALSE)
	{
		throw std::exception();
	}
	// size the tab control to fill the entire client area
	if(m_TabCtrl.SetWindowPos(NULL,ClientRect,SWP_NOZORDER)==FALSE)
	{
		throw std::exception();
	}
	// get the system color picker and palette color picker rect
	CRect Rect=ClientRect;
	m_TabCtrl.AdjustRect(FALSE,Rect);
	// size the system color picker
	if(m_SystemColorPicker.SetWindowPos(NULL,Rect,SWP_NOZORDER)==FALSE)
	{
		throw std::exception();
	}
	// size the palette color picker
	if(m_PaletteColorPicker.SetWindowPos(NULL,Rect,SWP_NOZORDER)==FALSE)
	{
		throw std::exception();
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// should be for system color picker
	ATLASSERT(wParam==CP_IDC_SYSTEM_COLOR_PICKER);

	// get the measure item struct
	MEASUREITEMSTRUCT *pMeasureItemStruct=(MEASUREITEMSTRUCT *)lParam;
	// initialise the item height to something sensible
	DWORD MinItemHeight=8;
	pMeasureItemStruct->itemHeight=MinItemHeight;
	// create the display information context
	CDC dc=CreateIC(_T("Display"),NULL,NULL,NULL);
	if(dc==NULL)
	{
		throw std::exception();
	}
	// get the font height
	LOGFONT lf;
	if(GetObject(GetFont(),sizeof(LOGFONT),&lf)==0)
	{
		throw std::exception();
	}
	DWORD FontHeight=abs(lf.lfHeight);
	// set the item height
	DWORD ItemHeight=max(MinItemHeight,POINT_SIZE_TO_PIXELS(dc,FontHeight));
	pMeasureItemStruct->itemHeight=ItemHeight;
CATCH_ALL
	return TRUE;
}

LRESULT CColorPicker::OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// should be for the system color picker
	ATLASSERT(wParam==CP_IDC_SYSTEM_COLOR_PICKER or
		// or palette color picker
		wParam==CP_IDC_PALETTE_COLOR_PICKER);

	// get the draw item struct
	DRAWITEMSTRUCT *pDrawItemStruct=(DRAWITEMSTRUCT *)lParam;
	// draw the system color picker
	if(pDrawItemStruct->CtlID==CP_IDC_SYSTEM_COLOR_PICKER)
	{
		DrawSystemColorPicker(*pDrawItemStruct);
	}
	// draw the palette color picker
	if(pDrawItemStruct->CtlID==CP_IDC_PALETTE_COLOR_PICKER)
	{
		DrawPaletteColorPicker(*pDrawItemStruct);
	}
CATCH_ALL
	return TRUE;
}

LRESULT CColorPicker::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// if the window is being deactivated
	if(LOWORD(wParam)==WA_INACTIVE)
	{
		// get the window being activated
		CWindow ActiveWindow=(HWND)lParam;
		// if the color picker is no longer active
		if(ActiveWindow!=*this and IsChild(ActiveWindow)==FALSE)
		{
			// hide the color picker immediately
			(void)ShowWindow(SW_HIDE);
			// shut down
			m_RunMessageLoop=FALSE;
		}
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the window receiving focus
	CWindow FocusWindow=(HWND)wParam;
	// if the color picker no longer has the focus
	if(FocusWindow!=*this and IsChild(FocusWindow)==FALSE)
	{
		// hide the color picker immediately
		(void)ShowWindow(SW_HIDE);
		// shut down
		m_RunMessageLoop=FALSE;
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnSelChangeTabCtrl(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
TRY
	// get the selected tab
	DWORD TabIndex=m_TabCtrl.GetCurSel();
	if(TabIndex==-1)
	{
		throw std::exception();
	}
	if(TabIndex==SYSTEM_COLOR_TAB_IX)	// system color tab
	{
		// hide the palette color picker
		(void)m_PaletteColorPicker.ShowWindow(SW_HIDE);
		// show the system color picker
		(void)m_SystemColorPicker.ShowWindow(SW_SHOW);
	}
	if(TabIndex==PALETTE_COLOR_TAB_IX)	// palette color tab
	{
		// hide the system color picker
		(void)m_SystemColorPicker.ShowWindow(SW_HIDE);
		// show the palette color picker
		(void)m_PaletteColorPicker.ShowWindow(SW_SHOW);
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnSelChangeSystemColorPicker(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
TRY
	// get the selected item
	DWORD ItemIndex=m_SystemColorPicker.GetCurSel();
	if(ItemIndex==LB_ERR)
	{
		throw std::exception();
	}
	// update the color
	m_Color=m_SystemColors[ItemIndex].m_Color;
	// shut down
	m_RunMessageLoop=FALSE;
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the cursor position
	CPoint CursorPos(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));
	// select the palette cell under the cursor
	SelectPaletteCellAtPos(CursorPos);
	// capture the cursor
	(void)m_PaletteColorPicker.SetCapture();
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// release the cursor
	// we need to be careful here since ReleaseCapture() calls
	// OnPaletteColorPickerCaptureChanged() which in turn calls
	// us back just incase the capture was taken from under our feet
	if(GetCapture()==m_PaletteColorPicker)
	{
		(void)ReleaseCapture();
	}
	// shut down
	m_RunMessageLoop=FALSE;
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the cursor position
	CPoint CursorPos(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));
	// if the cursor is being tracked
	if(GetCapture()==m_PaletteColorPicker)
	{
		// select the palette cell under the cursor
		SelectPaletteCellAtPos(CursorPos);
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerRButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// get the cursor position
	CPoint CursorPos(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));
	// get the palette cell under the cursor
	DWORD PaletteCellIndex=PaletteCellHitTest(CursorPos);
	// if a custom color was clicked
	if(PaletteCellIndex!=-1 and PaletteCellIndex >= PALETTE_CELL_CUSTOM_IX)
	{
		// create the custom colors buffer
		const DWORD MaxCustomColors=16;
		COLORREF CustomColors[MaxCustomColors];
		for(long l=0; l<MaxCustomColors; l++)
		{
			CustomColors[l]=m_PaletteColors[PALETTE_CELL_CUSTOM_IX+l].m_Color;
		}
		// show the color picker
		CHOOSECOLOR cc;
		ZeroMemory(&cc,sizeof(CHOOSECOLOR));
		cc.lStructSize=sizeof(CHOOSECOLOR);
		cc.hwndOwner=*this;
		cc.rgbResult=m_PaletteColors[PaletteCellIndex].m_Color;
		cc.lpCustColors=CustomColors;
		cc.Flags=CC_ANYCOLOR|CC_RGBINIT;
		if(ChooseColor(&cc))
		{
			// update the color
			m_Color=cc.rgbResult;
		}
		// update the custom colors
		for(l=0; l<MaxCustomColors; l++)
		{
			m_PaletteColors[PALETTE_CELL_CUSTOM_IX+l].m_Color=CustomColors[l];
		}
	}
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// simulate a left button up message
	BOOL Dummy=FALSE;
	(void)OnPaletteColorPickerLButtonUp(WM_LBUTTONUP,0,0,Dummy);
CATCH_ALL
	return 0;
}

LRESULT CColorPicker::OnPaletteColorPickerEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// wrap the device context
	CDCHandle hDC=(HDC)wParam;
	// get the client rect
	CRect ClientRect(0,0,0,0);
	if(m_PaletteColorPicker.GetClientRect(ClientRect)==FALSE)
	{
		throw std::exception();
	}
	// erase the background
	hDC.FillSolidRect(ClientRect,RGB(128,128,128));
CATCH_ALL
	// the background was erased
	return TRUE;
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

DaveShep
Web Developer
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190417.4 | Last Updated 1 Aug 2009
Article Copyright 2005 by DaveShep
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid