Click here to Skip to main content
15,892,797 members
Articles / Desktop Programming / MFC

XTrueColorToolBar - True-color toolbar with support for Office-style color button

Rate me:
Please Sign up or sign in to vote.
4.69/5 (20 votes)
10 Jan 2008CPOL5 min read 72.8K   4.2K   63  
XTrueColorToolBar is an MFC class based on CToolBar that provides support for true-color bitmaps, with optional support for an Office-style color picker button.
// mainfrm.cpp : implementation of the CMainFrame class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "wordpad.h"
#include "mainfrm.h"
#include "wordpdoc.h"
#include "wordpvw.h"
#include "strings.h"
#include "colorlis.h"
#include "XNamedColors.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_WM_SYSCOLORCHANGE()
	ON_WM_SIZE()
	ON_WM_MOVE()
	ON_COMMAND(ID_HELP, OnHelpFinder)
	ON_WM_DROPFILES()
	ON_COMMAND(ID_CHAR_COLOR, OnCharColor)
	ON_COMMAND(ID_PEN_TOGGLE, OnPenToggle)
	ON_WM_FONTCHANGE()
	ON_WM_QUERYNEWPALETTE()
	ON_WM_PALETTECHANGED()
	ON_WM_DEVMODECHANGE()
	ON_COMMAND(ID_HELP_INDEX, OnHelpFinder)
	//}}AFX_MSG_MAP
	// Global help commands
//  ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
	ON_COMMAND(ID_DEFAULT_HELP, OnHelpFinder)
	ON_UPDATE_COMMAND_UI(ID_VIEW_FORMATBAR, OnUpdateControlBarMenu)
	ON_UPDATE_COMMAND_UI(ID_VIEW_RULER, OnUpdateControlBarMenu)
	ON_MESSAGE(WPM_BARSTATE, OnBarState)
	ON_REGISTERED_MESSAGE(CWordPadApp::m_nOpenMsg, OnOpenMsg)
	ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
	ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
	ON_COMMAND_EX(ID_VIEW_FORMATBAR, OnBarCheck)
	ON_COMMAND_EX(ID_VIEW_RULER, OnBarCheck)
	ON_COMMAND(ID_SET_TEXT_COLOR, OnTextColor)
	ON_NOTIFY(TBN_DROPDOWN, ID_VIEW_FORMATBAR, OnColorDropDown)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// arrays of IDs used to initialize control bars

// toolbar buttons - IDs are command buttons
static UINT BASED_CODE toolbar[] =
{
	// same order as in the bitmap 'toolbar.bmp'
	// (int nBitmap, int nCommand, BYTE byteState, BYTE byteStyle, DWORD dw, int nString)
	ID_FILE_NEW,
	ID_FILE_OPEN,
	ID_FILE_SAVE,
ID_SEPARATOR,
	ID_FILE_PRINT_DIRECT,
	ID_FILE_PRINT_PREVIEW,
ID_SEPARATOR,
	ID_EDIT_FIND,
ID_SEPARATOR,
	ID_EDIT_CUT,
	ID_EDIT_COPY,
	ID_EDIT_PASTE,
	ID_EDIT_UNDO,
ID_SEPARATOR,
	ID_INSERT_DATE_TIME,
ID_SEPARATOR,
	ID_PEN_TOGGLE,
	ID_PEN_PERIOD,
	ID_PEN_SPACE,
	ID_PEN_BACKSPACE,
	ID_PEN_NEWLINE,
	ID_PEN_LENS
};

#define NUM_PEN_ITEMS 7
#define NUM_PEN_TOGGLE 5

static UINT BASED_CODE format[] =
{
	// same order as in the bitmap 'format.bmp'
		ID_SEPARATOR, // font name combo box
		ID_SEPARATOR,
		ID_SEPARATOR, // font size combo box
		ID_SEPARATOR,
	ID_CHAR_BOLD,
	ID_CHAR_ITALIC,
	ID_CHAR_UNDERLINE,
	//ID_CHAR_COLOR,
	ID_SET_TEXT_COLOR,
		ID_SEPARATOR,
	ID_PARA_LEFT,
	ID_PARA_CENTER,
	ID_PARA_RIGHT,
		ID_SEPARATOR,
	ID_INSERT_BULLET,
};

static const UINT TEXT_COLOR_TEMPLATE_INDEX = 8;

static UINT BASED_CODE indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
	m_hIconDoc = theApp.LoadIcon(IDI_ICON_DOC);
	m_hIconText = theApp.LoadIcon(IDI_ICON_TEXT);
	m_hIconWrite = theApp.LoadIcon(IDI_ICON_WRITE);
}

CMainFrame::~CMainFrame()
{
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	WNDCLASS wndcls;

	BOOL bRes = CFrameWnd::PreCreateWindow(cs);
	HINSTANCE hInst = AfxGetInstanceHandle();

	// see if the class already exists
	if (!::GetClassInfo(hInst, szWordPadClass, &wndcls))
	{
		// get default stuff
		::GetClassInfo(hInst, cs.lpszClass, &wndcls);
		wndcls.style &= ~(CS_HREDRAW|CS_VREDRAW);
		// register a new class
		wndcls.lpszClassName = szWordPadClass;
		wndcls.hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
		ASSERT(wndcls.hIcon != NULL);
		if (!AfxRegisterClass(&wndcls))
			AfxThrowResourceException();
	}
	cs.lpszClass = szWordPadClass;
	CRect rect = theApp.m_rectInitialFrame;
	if (rect.Width() > 0 && rect.Height() > 0)
	{
		// make sure window will be visible
		CDisplayIC dc;
		CRect rectDisplay(0, 0, dc.GetDeviceCaps(HORZRES),
			dc.GetDeviceCaps(VERTRES));
		if (rectDisplay.PtInRect(rect.TopLeft()) &&
			rectDisplay.PtInRect(rect.BottomRight()))
		{
			cs.x = rect.left;
			cs.y = rect.top;
			cs.cx = rect.Width();
			cs.cy = rect.Height();
		}
	}
	return bRes;
}

//=============================================================================
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
//=============================================================================
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!CreateToolBar())
		return -1;

	if (!CreateFormatBar())
		return -1;

	if (!CreateStatusBar())
		return -1;

	///////////////////////////////////////////////////////////////////////////

	// set up true-color image buttons
	m_wndFormatBar.AttachToolbarImages(IDB_FORMATBAR,
									   8,	// no. of images in bitmap
									   0);	// 0 = normal, 1 = disabled, 2 = hot

	// create template for color button
	m_wndFormatBar.CreateTemplate(RGB(255,0,1));
	
	// init toolbar for drop-down color button and set initial color
	m_wndFormatBar.InitColorButton(ID_SET_TEXT_COLOR, RGB(0,0,0));

	///////////////////////////////////////////////////////////////////////////

	EnableDocking(CBRS_ALIGN_ANY);

	if (!CreateRulerBar())
		return -1;

	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	m_wndFormatBar.EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);
	DockControlBar(&m_wndToolBar);
	DockControlBar(&m_wndFormatBar);

	CWnd* pView = GetDlgItem(AFX_IDW_PANE_FIRST);
	if (pView != NULL)
	{
		pView->SetWindowPos(&wndBottom, 0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
	}

	return 0;
}

BOOL CMainFrame::CreateToolBar()
{
	int nPen = GetSystemMetrics(SM_PENWINDOWS) ? NUM_PEN_TOGGLE :
		NUM_PEN_ITEMS;
	UINT nID = theApp.m_bLargeIcons ? IDR_MAINFRAME1_BIG :
		IDR_MAINFRAME1;

	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadBitmap(nID) ||
		!m_wndToolBar.SetButtons(toolbar, sizeof(toolbar)/sizeof(UINT) - nPen))
	{
		TRACE(_T("Failed to create toolbar\n"));
		return FALSE;      // fail to create
	}
	if (theApp.m_bLargeIcons)
		m_wndToolBar.SetSizes(CSize(31,30), CSize(24,24));
	else
		m_wndToolBar.SetSizes(CSize(23,22), CSize(16,16));
	CString str;
	str.LoadString(IDS_TITLE_TOOLBAR);
	m_wndToolBar.SetWindowText(str);
	return TRUE;
}

//=============================================================================
BOOL CMainFrame::CreateFormatBar()
//=============================================================================
{
	UINT nID = theApp.m_bLargeIcons ? IDB_FORMATBAR_BIG : IDB_FORMATBAR;

	DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | 
					CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_HIDE_INPLACE | 
					CBRS_SIZE_DYNAMIC;

	if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, dwStyle,
		CRect(0,0,0,0), ID_VIEW_FORMATBAR) ||
		!m_wndFormatBar.LoadBitmap(nID) ||
		!m_wndFormatBar.SetButtons(format, sizeof(format)/sizeof(UINT)))
	{
		TRACE(_T("Failed to create FormatBar\n"));
		ASSERT(FALSE);
		return FALSE;      // fail to create
	}

	if (theApp.m_bLargeIcons)
		m_wndFormatBar.SetSizes(CSize(31,30), CSize(24,24));
	else
		m_wndFormatBar.SetSizes(CSize(23,22), CSize(16,16));

	CString str;
	str.LoadString(IDS_TITLE_FORMATBAR);
	m_wndFormatBar.SetWindowText(str);
	m_wndFormatBar.PositionCombos();

	return TRUE;
}

BOOL CMainFrame::CreateRulerBar()
{
	if (!m_wndRulerBar.Create(this,
		WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_HIDE_INPLACE, ID_VIEW_RULER))
	{
		TRACE(_T("Failed to create ruler\n"));
		return FALSE;      // fail to create
	}
	return TRUE;
}

BOOL CMainFrame::CreateStatusBar()
{
	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE(_T("Failed to create status bar\n"));
		return FALSE;      // fail to create
	}
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame Operations

HICON CMainFrame::GetIcon(int nDocType)
{
	switch (nDocType)
	{
		case RD_WINWORD6:
		case RD_WORDPAD:
		case RD_EMBEDDED:
		case RD_RICHTEXT:
			return m_hIconDoc;
		case RD_TEXT:
		case RD_OEMTEXT:
			return m_hIconText;
		case RD_WRITE:
			return m_hIconWrite;
	}
	return m_hIconDoc;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

void CMainFrame::OnFontChange()
{
	m_wndFormatBar.SendMessage(CWordPadApp::m_nPrinterChangedMsg);
}

void CMainFrame::OnDevModeChange(LPTSTR lpDeviceName)
{
	theApp.NotifyPrinterChanged();
	CFrameWnd::OnDevModeChange(lpDeviceName); //sends message to descendants
}

void CMainFrame::OnSysColorChange()
{
	CFrameWnd::OnSysColorChange();
	m_wndRulerBar.SendMessage(WM_SYSCOLORCHANGE);
}

void CMainFrame::ActivateFrame(int nCmdShow)
{
	CFrameWnd::ActivateFrame(nCmdShow);
	// make sure and display the toolbar, ruler, etc while loading a document.
	OnIdleUpdateCmdUI();
	UpdateWindow();
}

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
	CFrameWnd::OnSize(nType, cx, cy);
	theApp.m_bMaximized = (nType == SIZE_MAXIMIZED);
	if (nType == SIZE_RESTORED)
		GetWindowRect(theApp.m_rectInitialFrame);
}

LONG CMainFrame::OnBarState(UINT wParam, LONG lParam)
{
	if (lParam == -1)
		return 0L;
	ASSERT(lParam != RD_EMBEDDED);
	if (wParam == 0)
	{
		CDockState& ds = theApp.GetDockState(lParam);
		ds.Clear(); // empty out the dock state
		GetDockState(ds);
	}
	else
	{
		if (IsTextType(lParam))
		{
			// in text mode hide the ruler and format bar so that it is the default
			CControlBar* pBar = GetControlBar(ID_VIEW_FORMATBAR);
			if (pBar != NULL)
				pBar->ShowWindow(SW_HIDE);
			pBar = GetControlBar(ID_VIEW_RULER);
			if (pBar != NULL)
				pBar->ShowWindow(SW_HIDE);
		}
		HICON hIcon = GetIcon((int)lParam);
		SendMessage(WM_SETICON, TRUE, (LPARAM)hIcon);
		SetDockState(theApp.GetDockState(lParam));
	}
	return 0L;
}

void CMainFrame::OnMove(int x, int y)
{
	CFrameWnd::OnMove(x, y);
	WINDOWPLACEMENT wp;
	wp.length = sizeof(wp);
	GetWindowPlacement(&wp);
	theApp.m_rectInitialFrame = wp.rcNormalPosition;
	CView* pView = GetActiveView();
	if (pView != NULL)
		pView->SendMessage(WM_MOVE);
}

LONG CMainFrame::OnOpenMsg(UINT, LONG lParam)
{
	TCHAR szAtomName[256];
	szAtomName[0] = NULL;
	GlobalGetAtomName((ATOM)lParam, szAtomName, 256);
	CWordPadDoc* pDoc = (CWordPadDoc*)GetActiveDocument();
	if (szAtomName[0] != NULL && pDoc != NULL)
	{
		if (lstrcmpi(szAtomName, pDoc->GetPathName()) == 0)
			return TRUE;
	}
	return FALSE;
}

void CMainFrame::OnHelpFinder()
{
	theApp.WinHelp(0, HELP_FINDER);
}

void CMainFrame::OnDropFiles(HDROP hDropInfo)
{
	TCHAR szFileName[_MAX_PATH];
	::DragQueryFile(hDropInfo, 0, szFileName, _MAX_PATH);
	::DragFinish(hDropInfo);
	theApp.OpenDocumentFile(szFileName);
}

void CMainFrame::OnCharColor()
{
	CColorMenu colorMenu;
	CRect rc;
	int index = m_wndFormatBar.CommandToIndex(ID_CHAR_COLOR);
	m_wndFormatBar.GetItemRect(index, &rc);
	m_wndFormatBar.ClientToScreen(rc);
	colorMenu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,rc.left,rc.bottom, this);
}

void CMainFrame::OnPenToggle()
{
	static int nPen = 0;
	m_wndToolBar.SetButtons(toolbar, sizeof(toolbar)/sizeof(UINT) - nPen);
	nPen = (nPen == 0) ? NUM_PEN_TOGGLE : 0;
	m_wndToolBar.Invalidate();
	m_wndToolBar.GetParentFrame()->RecalcLayout();
}

BOOL CMainFrame::OnQueryNewPalette()
{
	CView* pView = GetActiveView();
	if (pView != NULL)
		return pView->SendMessage(WM_QUERYNEWPALETTE);
	return FALSE;
}

void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd)
{
	CView* pView = GetActiveView();
	if (pView != NULL)
		pView->SendMessage(WM_PALETTECHANGED, (WPARAM)pFocusWnd->GetSafeHwnd());
}

//=============================================================================
void CMainFrame::OnTextColor()
//=============================================================================
{
	TRACE(_T("OnTextColor - click on color button left side\n"));

	// get color of color button (bar under letter A)
	COLORREF rgb = m_wndFormatBar.GetColorButton();

	CWordPadView * pView = (CWordPadView *) GetActiveView();

	// set new text color in current view
	if (pView)
		pView->SetColor(rgb);
}

//=============================================================================
void CMainFrame::OnColorDropDown(NMHDR *pNMHDR, LRESULT * /*pResult*/)
//=============================================================================
{
	NMTOOLBAR *pNMTOOLBAR = (NMTOOLBAR *) pNMHDR;

	if (pNMTOOLBAR && (pNMTOOLBAR->iItem == ID_SET_TEXT_COLOR))
	{
		TRACE(_T("OnColorDropDown - click on color button drop-down arrow\n"));
		
		// get color of color button (bar under letter A)
		COLORREF rgb = m_wndFormatBar.GetColorButton();

		CColorDialog dlg(rgb);

		// display color picker dialog
		if (dlg.DoModal() == IDOK)
		{
			rgb = dlg.GetColor();

			// update color of color button (bar under letter A)
			m_wndFormatBar.SetColorButton(ID_SET_TEXT_COLOR, rgb);
		}
	}
}

//=============================================================================
BOOL CMainFrame::OnToolTipText(UINT nID, NMHDR *pNMHDR, LRESULT *pResult)
//=============================================================================
{
	ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
	
	TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
	TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
	
	CString strTipText = _T("");
	CString strMessage = _T("");

	if (GetToolText(pNMHDR->idFrom, strTipText, strMessage))
	{
		//----------------------------------------------------------------
		// we got a text string so lets give it to Windows to display
		// as our custom tool tip
		//----------------------------------------------------------------
#ifndef _UNICODE
		if (pNMHDR->code == TTN_NEEDTEXTA)
			lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText));
		else
			_mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText));
#else
		if (pNMHDR->code == TTN_NEEDTEXTA)
			_wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText));
		else
			lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText));
#endif
		
		//-----------------------------------------------------------------
		// this sets the status bar message to our custom message string
		//-----------------------------------------------------------------
		SetMessageText(strMessage);
		return TRUE;
	} 

	//----------------------------------------------------------------
	// we DID NOT get our own string so pass this notification on to
	// to the base class for processing
	//----------------------------------------------------------------
	return CFrameWnd::OnToolTipText(nID, pNMHDR, pResult);
}

//=============================================================================
BOOL CMainFrame::GetToolText(UINT nID, CString& strTipText, CString& strMessage)
//=============================================================================
{
	BOOL rc = FALSE;

	switch (nID)
	{
		case ID_SET_TEXT_COLOR:
			{
				// get color of color button (bar under letter A)
				COLORREF rgb = m_wndFormatBar.GetColorButton();

				CXNamedColors nc(rgb);
				TCHAR szColor[100];

				// get color name
				nc.GetName(szColor, sizeof(szColor)/sizeof(TCHAR)-1);
				if (szColor[0] == _T('\0'))
				{
					// color does not have name - display RGB value
					nc.GetRGBString(szColor, sizeof(szColor)/sizeof(TCHAR)-1);
					strTipText.Format(_T("Font Color (RGB(%s))"), szColor);
				}
				else
				{
					// display color name
					strTipText.Format(_T("Font Color (%s)"), szColor);
				}

				// set status message same as tip
				strMessage = strTipText;

				rc = TRUE;		// this was color button
			}
			break;

		default:
			break;
	}

	return rc;
}

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)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions