Click here to Skip to main content
15,886,751 members
Articles / Desktop Programming / WTL

WTL wrappers for WinMain's CodeMax syntax highlighting edit control

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
28 May 2001CPOL6 min read 138K   1.5K   36  
An article on the CodeMax editing control.
// toolbar.hpp: interface for the CToolBarCtrlEx class.
//
/////////////////////////////////////////////////////////////////////////////
// Tool Bar Control Extention 
//
// Version: 1.0
// Created: April 25, 2000
//  Author: BenBurnett
//   Email:	BenBurnett@telusplanet.net
//
// Copyright (C) 2000 Ben Burnett
// All rights reserved.
//
// Thanks to Paul DiLascia for the code to add drop-down 
//  menus to toolbar buttons. (1997 MSJ)
//
// Owner-draw code for menu from, CCommandBarCtrl in the
//  WTL. See AtlCtrlw.h...
//
// The code and information is provided "as-is" without
//  warranty of any kind, either expressed or implied.
//
// Bug fixes and suggestions are welcomed, contact me 
//  at the email above.
/////////////////////////////////////////////////////////////////////////////

#if !defined(_TOOLBARCTRLEX_H_INCLUDED_)
#define _TOOLBARCTRLEX_H_INCLUDED_

#pragma once

#ifndef __cplusplus
	#error toolbar.h requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
	#error toolbar.h requires atlapp.h to be included first
#endif

#ifndef __ATLCTRLS_H__
#pragma message("toolbar.h requires atlctrls.h to be included first.")
#pragma message(" Once you include it you will not get this message.")
#include <atlctrls.h>
#endif

/*
#if (_WIN32_IE < 0x0500)
	#error toolbar.h requires _WIN32_IE >= 0x0500
#endif
*/

/////////////////////////////////////////////////////////////////////////////
// CToolBarCtrlExImpl class

template < class T, class TBase = CToolBarCtrl, class TWinTraits = CControlWinTraits >
class CToolBarCtrlExImpl : public CWindowImpl < T, TBase, TWinTraits >
{
public:
	DECLARE_WND_SUPERCLASS ( NULL, TBase::GetWndClassName () )

/////////////////////////////////////////////////////////////////////////////
// Declarations
//
	struct _ToolBarData		// toolbar resource data
	{ 
		WORD wVersion;
		WORD wWidth;
		WORD wHeight;
		WORD wItemCount;
		//WORD aItems[wItemCount]

		WORD* items()
			{ return (WORD*)(this + 1); }
	};	

	struct _DropDownButton	// One of these for each drop-down button
	{
		_DropDownButton* next;
		UINT uIdButton;
		UINT uIdMenu;
	};
	
/////////////////////////////////////////////////////////////////////////////
// Data members

	CContainedWindow m_wndParent;
	_DropDownButton* m_pDropDownButtons;
	bool m_bAnimate;		
	COLORREF m_clrMask;	

/////////////////////////////////////////////////////////////////////////////
// Constructor/Destructor

	CToolBarCtrlExImpl() : 
		m_wndParent ( this, 1 ),		
		m_pDropDownButtons ( NULL ),
		m_bAnimate ( true ) ,		
		m_clrMask ( RGB ( 192, 192, 192 ) )
	{

#if (WINVER >= 0x0500) // Win2K only
		
		// Check if menu animation is turned on
		::SystemParametersInfo ( SPI_GETMENUANIMATION, 0, &m_bAnimate, 0 );

#endif
	}

	~CToolBarCtrlExImpl()
	{
		if ( m_wndParent.IsWindow () )
			m_wndParent.UnsubclassWindow(); // scary!

		while (m_pDropDownButtons) {
			
			_DropDownButton* pNext = m_pDropDownButtons->next;
			delete m_pDropDownButtons;

			m_pDropDownButtons = pNext;
		}
		
	}

/////////////////////////////////////////////////////////////////////////////
// Attributes

	COLORREF GetImageMaskColor() const
	{
		ATLASSERT(::IsWindow(m_hWnd));
		return m_clrMask;
	}

	COLORREF SetImageMaskColor(COLORREF clrMask)
	{
		ATLASSERT(::IsWindow(m_hWnd));		
		COLORREF clrOld = m_clrMask;
		m_clrMask = clrMask;		
		return clrOld;
	}
	
	bool GetAnimate() const
	{
		ATLASSERT(::IsWindow(m_hWnd));
		return m_bAnimate;
	}

	bool SetAnimate(bool bAnimate = true)
	{
		ATLASSERT(::IsWindow(m_hWnd));		
		bool bOld = m_bAnimate;
		m_bAnimate = bAnimate;
		return bOld;
	}
		

/////////////////////////////////////////////////////////////////////////////
// Methods

	// Load the toolbar resource
	BOOL LoadToolBar ( UINT uResourceID, BOOL bInitialSeparator = FALSE )
	{
		ATLASSERT ( IS_INTRESOURCE ( uResourceID ) );
		
		HINSTANCE hInst = _Module.GetResourceInstance ();		
		HRSRC hRsrc = ::FindResource ( hInst, MAKEINTRESOURCE ( uResourceID ), RT_TOOLBAR );
				
		if ( NULL == hRsrc ) {

			return FALSE;

		}			

		HGLOBAL hGlobal = ::LoadResource ( hInst, hRsrc );
		
		if ( NULL == hGlobal ) {

			return FALSE;

		}		
		
		_ToolBarData* pData = reinterpret_cast < _ToolBarData* > ( ::LockResource ( hGlobal ) );
		
		if ( NULL == pData ) {

			return FALSE;

		}		
		
		ATLASSERT ( 1 == pData->wVersion );

		WORD * pItems = pData->items ();
		int nItems = pData->wItemCount + ( bInitialSeparator ? 1 : 0 );
		TBBUTTON * pTBBtn = new TBBUTTON [ nItems ];

		// set initial separator (half width)
		if ( bInitialSeparator ) {
			
			pTBBtn[0].iBitmap	= 4;
			pTBBtn[0].idCommand = 0;
			pTBBtn[0].fsState	= 0;
			pTBBtn[0].fsStyle	= TBSTYLE_SEP;
			pTBBtn[0].dwData	= 0;
			pTBBtn[0].iString	= 0;
			
		}

		int nBmp = 0;
		for ( int i = 0, j = ( bInitialSeparator ? 1 : 0 ); i < pData->wItemCount; i++, j++ ) {

			if ( 0 != pItems[i] ) {

				// Toolbar item
				pTBBtn[j].iBitmap	= nBmp++;
				pTBBtn[j].idCommand = pItems[i];
				pTBBtn[j].fsState	= TBSTATE_ENABLED;			
				pTBBtn[j].fsStyle	= TBSTYLE_BUTTON;
				pTBBtn[j].dwData	= 0;
				pTBBtn[j].iString	= 128;				

			}
			else {

				// Separator
				pTBBtn[j].iBitmap	= 0;
				pTBBtn[j].idCommand = 0;
				pTBBtn[j].fsState	= 0;
				pTBBtn[j].fsStyle	= TBSTYLE_SEP;
				pTBBtn[j].dwData	= 0;
				pTBBtn[j].iString	= 0;

			}
		}

		// Set default button structure size
		SetButtonStructSize ();
		
		// Add the bitmaps from the resource ID and then add the buttons
		if ( -1 == AddBitmap ( nBmp, uResourceID ) || !AddButtons ( nItems, pTBBtn ) ) {

			delete [] pTBBtn; // Only free this if not used

			return FALSE;
		}		
				
		// Set bitmap and button sizes
		SIZE sizeBitmap, sizeButton;
		sizeBitmap.cx = pData->wWidth;
		sizeBitmap.cy = pData->wHeight;
		sizeButton.cx = sizeBitmap.cx + 7;
		sizeButton.cy = sizeBitmap.cy + 7;

		if ( !SetBitmapSize ( sizeBitmap ) || !SetButtonSize ( sizeButton ) ) {

			return FALSE;

		}			
		
		return TRUE;
	}

	// 1997 Microsoft Systems Journal - Written by Paul DiLascia.
	// call to add drop-down menus to toolbar buttons.
	//
	// Modified so that it will work in WTL
	//
	BOOL AddDropDownButton ( UINT nIDButton, UINT nIDMenu, BOOL bArrow = TRUE )
	{
		ATLASSERT(::IsWindow(m_hWnd));

		_DropDownButton* pb = FindDropDownButton(nIDButton);
		
		if (!pb) {
			
			pb = new _DropDownButton;
			ATLASSERT ( NULL != pb );

			pb->next = m_pDropDownButtons;
			m_pDropDownButtons = pb;
		}

		pb->uIdButton = nIDButton;
		pb->uIdMenu   = nIDMenu;

		int nIndex = CommandToIndex ( nIDButton );
		ATLASSERT ( -1 != nIndex );
		
		// Add drop-down style to the button
		TBBUTTON tbb;		
		GetButton(nIndex, &tbb);
		tbb.fsStyle |= BTNS_DROPDOWN;
		_SetButton(nIndex, &tbb);
		
		return TRUE;
	}	
	
	// 1997 Microsoft Systems Journal - Written by Paul DiLascia.
	// Find buttons structure for given ID
	_DropDownButton* FindDropDownButton ( UINT nID )
	{
		for ( _DropDownButton* pb = m_pDropDownButtons; pb; pb = pb->next ) {
		
			if ( pb->uIdButton == nID ) {

				return pb;

			}	
			
		}

		return NULL;
	}

	// Set new button information
	void _SetButton ( int nIndex, LPTBBUTTON lpButton )
	{
		ATLASSERT ( ::IsWindow ( m_hWnd ) );
		
		// Get original button state
		TBBUTTON button;
		GetButton ( nIndex, &button );

		// Nothing to do if they are the same
		if ( memcmp ( lpButton, &button, sizeof ( TBBUTTON ) ) != 0 )
		{
			// Don't redraw everything while setting the button
			ModifyStyle ( WS_VISIBLE, 0 );
			DeleteButton ( nIndex );
			InsertButton ( nIndex, lpButton );
			ModifyStyle ( 0, WS_VISIBLE );

			// Invalidate appropriate parts
			if ( ( ( lpButton->fsStyle ^ button.fsStyle ) & TBSTYLE_SEP ) ||
				 ( ( lpButton->fsStyle & TBSTYLE_SEP ) && lpButton->iBitmap != button.iBitmap ) )
			{
				// Changing a separator
				Invalidate ();				
			}
			else
			{
				// Invalidate just the button
				RECT rc;
				GetItemRect ( nIndex, &rc );
				InvalidateRect ( &rc );
			}
		}
	}

	
/////////////////////////////////////////////////////////////////////////////
// Virtual Methods

	virtual bool DoDropDownMenu ( UINT uIdMenu, RECT* rc )
	{
		CMenu menu;
		CMenuHandle popupMenu;
		menu.LoadMenu ( uIdMenu );
		popupMenu = menu.GetSubMenu ( 0 );			
			
		UINT uFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN;

#if (_WIN32_WINNT >= 0x0500) 
		
		// Win2K can flag 'no animation'
		uFlags |= ( m_bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION );

#else
		if ( m_bAnimate ) {

			uFlags |= TPM_VERPOSANIMATION;
		}			

#endif
		if ( !popupMenu.TrackPopupMenu ( uFlags, rc->left, rc->bottom, m_hWnd, rc ) ) {

			return false;
			
		}			

		return true;
	}


/////////////////////////////////////////////////////////////////////////////
// Message map and handlers

	BEGIN_MSG_MAP ( CToolBarCtrlExImpl )		

		MESSAGE_HANDLER ( WM_CREATE, OnCreate )
		
	ALT_MSG_MAP ( 1 )		// Parent window messages	

		NOTIFY_CODE_HANDLER ( TBN_DROPDOWN, OnParentDropDown )		

	END_MSG_MAP ()

	LRESULT OnCreate ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & /*bHandled*/ )
	{
		// These styles are required
		ModifyStyle ( 0, TBSTYLE_FLAT );

		// Add drop-down arrows to the toolbar
		DWORD dwExStyle = TBSTYLE_EX_DRAWDDARROWS;
		
#if ( _WIN32_IE >= 0x0501 )

		// Add some cool Win2K styles
		dwExStyle |= TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS;
		
#endif // ( _WIN32_IE >= 0x0501 )

		SetExtendedStyle ( dwExStyle );
		
		// Let the toolbar initialize itself
		LRESULT lRet = DefWindowProc ( uMsg, wParam, lParam );
		
		// Subclass parent window
		CWindow wndParent = GetParent ();
		CWindow wndTopLevelParent = wndParent.GetTopLevelParent ();
		m_wndParent.SubclassWindow ( wndTopLevelParent );		
		
		return lRet;	
	}		

	//
	// Parent window message handlers
	//

	LRESULT OnParentDropDown ( int /*idCtrl*/, LPNMHDR pnmh, BOOL & bHandled )
	{
		LPNMTOOLBAR lpnmtb = reinterpret_cast < LPNMTOOLBAR > ( pnmh );	
		
		// Check if this is from us
		if ( pnmh->hwndFrom != m_hWnd ) {

			bHandled = FALSE;

			return TBDDRET_NODEFAULT;
		}	
		
		_DropDownButton * pDropDownButton = FindDropDownButton ( lpnmtb->iItem );
		
		RECT rc;
		GetRect ( pDropDownButton->uIdButton, &rc );
		ClientToScreen ( &rc );		
		
		if ( pDropDownButton ) {

			if ( DoDropDownMenu ( pDropDownButton->uIdMenu, &rc ) ) {

				return TBDDRET_DEFAULT;

			}
		}

		return TBDDRET_NODEFAULT;
	}
	
};

/////////////////////////////////////////////////////////////////////////////
// CToolBarCtrlEx class

class CToolBarCtrlEx : public CToolBarCtrlExImpl < CToolBarCtrlEx >
{
public:
	DECLARE_WND_SUPERCLASS ( _T ( "BCB_ToolBarEx" ), GetWndClassName () )	
};

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#endif // !defined(_TOOLBARCTRLEX_H_INCLUDED_)

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
Team Leader Farmer's Edge
Canada Canada
Ben was born in New Zealand and grew up in Mexico; however, he has lived in Canada for most of his adult life. He has traveled to a few places in Canada so far: British Columbia, Saskatchewan, Manitoba, Ontario and Nova Scotia, but has only ever lived in Alberta — all over Alberta. From Lethbridge to Calgary to Fort McMurray: he has seen most of what the province has to offer. He has also left the comfort of his—at the time—home country and gone abroad. In recent history he has been in China, New Zealand, the US, Central America and back to Canada (where he now resides).

He completed a degree at the University of Lethbridge, in Computer Science; worked for the University of Wisconsin-Madison in the Computer Sciences Department as a Systems Programmer for the Condor Research Project[^]; and is currently completing another degree at the University of Lethbridge, once again, in Computer Science.

Ben has been known to enjoy reading, watching movies, playing console games, and learning everything he can about computers. And, more importantly, with regards to his character: does not usually speaks about himself in the third person.

Comments and Discussions