Flat Toolbar (requires IE3+)

. The toolbar class discussed in this article works with the standard MFC CToolBar.

NOTE: You must also have new the COMCTL32.DLL (version 4.7 or later). This is installed with Internet Explorer 3 and will come standard with the new Windows 98. So if you are using VC++ 5 then you probably already have this DLL.

Here is a toolbar enhancement that gives you DevStudio-like toolbars.

These have a flat look with a "gripper" on the left hand side and separator lines between groups. As the mouse moves over the toolbar, the tools get a button created around them.

There are a number of issues that needed to be addressed here.

MFC uses the style bits that control the flat look for its own purposes. So you cannot set this style when creating the toolbar, but must modify the style afterwards. To do this, I have added a SetFlatLookStyle() function.

Flat look toolbars are painted transparently. Unfortunately, MFC has not been written with transparent toolbars in mind, so one needs to repaint the background. This is done on size and move messages, for example when draggin a docked toolbar. They are also done when the tool button's style changes. For example, when a button changes from pushed to released, the background needs to be repainted.

The toolbar control does not draw the separators between groups of toolbar buttons, but instead leaves a gap. The class intecepts the WM_PAINT method and adds separators at the correct position.

The toolbar control also does not support the gripper at the left or top end of the toolbar. The class adjusts the client area and draws the gripper approriately.

To use this class, simply change your use of CToolBar to CFlatToolBar and call the SetFlatLookStyle() function after creating the toolbar itself (ie. after toolbar bitmaps are loaded).



//***************************************************************
// FlatToolBar.h
// (c) 1997, Roger Onslow

#if !defined(__FLATTOOLBAR_H__)
#define __FLATTOOLBAR_H__

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

class CFlatToolBar : public CToolBar 
{
	DECLARE_DYNAMIC(CFlatToolBar);
public:
	void SetFlatLookStyle();
	void RepaintBackground();
	void DrawSeparators();
	void DrawSeparators(CClientDC* pDC);
	void EraseNonClient();
	void DrawGripper(CWindowDC *pDC, CRect& rectWindow);
protected:
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CFlatToolBar)
	virtual void OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler);
	//}}AFX_VIRTUAL
	// Message Handlers
protected:
	//{{AFX_MSG(CFlatToolBar)
	afx_msg void OnWindowPosChanging(LPWINDOWPOS lpWndPos);
	afx_msg void OnPaint();
	afx_msg void OnNcPaint();
	afx_msg void OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS*	lpncsp );
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP();
};

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

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(__FLATTOOLBAR_H__)

//***************************************************************
// FlatToolBar.cpp
// (c) 1997, Roger Onslow

#include "stdafx.h"
#include "FlatToolBar.h"

#ifdef _DEBUG
#undef THIS_FILE
#define new DEBUG_NEW

static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

BEGIN_MESSAGE_MAP(CFlatToolBar, CToolBar)
	//{{AFX_MSG_MAP(CFlatToolBar)
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_PAINT()
	ON_WM_NCPAINT()
	ON_WM_NCCALCSIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(CFlatToolBar,CToolBar)

// Must set after creation, as MFC wipes out extra style bits
void CFlatToolBar::SetFlatLookStyle()
{
	// Set flat style (transparent)
	ModifyStyle(0,TBSTYLE_FLAT);
	// others are...
	// #define TBSTYLE_TOOLTIPS        0x0100
	// #define TBSTYLE_WRAPABLE        0x0200
	// #define TBSTYLE_ALTDRAG         0x0400
	// #define TBSTYLE_FLAT            0x0800
	// #define TBSTYLE_LIST            0x1000
}

// Because buttons are transparent, we need to repaint the background
void CFlatToolBar::RepaintBackground()
{
	// get parent window (there should be one)
	CWnd* pParent = GetParent();
	if (pParent) {
		// get rect for this toolbar
		CRect rw; GetWindowRect(&rw);
		// convert rect to parent coords
		CRect rc = rw; pParent->ScreenToClient(&rc);
		// invalidate this part of parent
		pParent->InvalidateRect(&rc);
		// now do all the other toolbars (etc) that belong to the parent
		for (
			CWnd* pSibling = pParent->GetWindow(GW_CHILD);
		pSibling;
		pSibling = pSibling->GetNextWindow(GW_HWNDNEXT)
			) {
			// but do not draw ourselves
			if (pSibling == this) continue;
			// convert rect to siblings coords
			CRect rc = rw; pSibling->ScreenToClient(&rc);
			// invalidate this part of sibling
			pSibling->InvalidateRect(&rc);
		}
	}
}

// Draw the separators in the client area
void CFlatToolBar::DrawSeparators()
{
	// get a dc for the client area
	CClientDC dc(this);
	// draw the separators on it
	DrawSeparators(&dc);
}

// Draw the separators
void CFlatToolBar::DrawSeparators(CClientDC* pDC)
{
	// horizontal vs vertical
	bool ishorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
	// get number of buttons
	int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
	int nIndex;
	
	// try each button
	for (nIndex = 0; nIndex < nIndexMax; nIndex++)
	{
		UINT dwStyle=GetButtonStyle(nIndex);
		UINT wStyle=LOWORD(dwStyle);
		
		// if it is a separator
		if (wStyle == TBBS_SEPARATOR)
		{
			// get it's rectangle and width
			CRect rect;
			GetItemRect(nIndex,rect);
			
			// if small enough to be a true separator
			int w=rect.Width();
			if (w <= 8)
			{
				if (ishorz)
				{
					// draw the separator bar in the middle
					CRect rectbar=rect;
					int x=(rectbar.left+rectbar.right)/2;
					rectbar.left=x-1;
					rectbar.right=x+1;
					pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
				}
				else
				{
					// draw the separator bar in the middle
					CRect rectbar = rect;
					rectbar.left = rectbar.left - m_sizeButton.cx;
					rectbar.right = rectbar.left + m_sizeButton.cx;
					rectbar.top = rectbar.bottom+1;
					rectbar.bottom = rectbar.top+3;
					int y = (rectbar.top+rectbar.bottom)/2;
					rectbar.top = y-1;
					rectbar.bottom = y+1;
					pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
					
				}
			}
		}
	}
}

// Draw the gripper at left or top
void CFlatToolBar::DrawGripper(CWindowDC *pDC, CRect& rectWindow)
{
	// get the gripper rect (1 pixel smaller than toolbar)
	CRect gripper = rectWindow;
	gripper.DeflateRect(1,1);
	if (m_dwStyle & CBRS_FLOATING) {
		// no grippers
	} else if (m_dwStyle & CBRS_ORIENT_HORZ) {
		// gripper at left
		gripper.right = gripper.left+3;
		pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
		gripper.OffsetRect(+4,0);
		pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
		rectWindow.left += 8;
	} else {
		// gripper at top
		gripper.bottom = gripper.top+3;
		pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
		gripper.OffsetRect(0,+4);
		pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
		rectWindow.top += 8;
	}
}

// Erase the non-client area (borders) - copied from MFC implementation
void CFlatToolBar::EraseNonClient()
{
	// get window DC that is clipped to the non-client area
	CWindowDC dc(this);
	CRect rectClient;
	GetClientRect(rectClient);
	CRect rectWindow;
	GetWindowRect(rectWindow);
	ScreenToClient(rectWindow);
	rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
	dc.ExcludeClipRect(rectClient);
	
	// draw borders in non-client area
	rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
	DrawBorders(&dc, rectWindow);
	
	// erase parts not drawn
	dc.IntersectClipRect(rectWindow);
	SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
	
	DrawGripper(&dc, rectWindow); // 
} 

// Because buttons are transparaent, we need to repaint background if style changes 
void CFlatToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
    static CUIntArray styles; // get the number of buttons
    int nIndexMax=(int)DefWindowProc(TB_BUTTONCOUNT, 0, 0); 
	
    int nIndex; // save styles 
    for (nIndex=0; nIndex < nIndexMax; nIndex++)
    {
        UINT dwStyle=GetButtonStyle(nIndex);
        styles.SetAtGrow(nIndex,dwStyle); 
    } 
    
    // do base class processing 
    CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler); 
	
    // make checked button appear pushed in 
    for (nIndex=0; nIndex < nIndexMax; nIndex++) 
    { 
        UINT dwStyle=GetButtonStyle(nIndex);
        if (dwStyle & TBBS_DISABLED) 
        { 
            // don't touch if disabled (avoids flicker) 
        } 
        else if (dwStyle & TBBS_CHECKBOX) 
        {
            UINT dwStyleWas=dwStyle; // if checked, make it pressed, else not pressed 
            if (dwStyle & TBBS_CHECKED) 
            { 
                dwStyle |=TBBS_PRESSED;
            }
            else if (!(styles[nIndex]&TBBS_CHECKED) && (styles[nIndex]&TBBS_PRESSED)) 
            {
                dwStyle |=TBBS_PRESSED; 
            } 
            else
            {
                dwStyle &=~TBBS_PRESSED;
            }
            // set new style if changed 
            if (dwStyleWas !=dwStyle) SetButtonStyle(nIndex,dwStyle); 
        } 
    }
    // check for changes to style (buttons presssed/released)
    for (nIndex=0; nIndex < nIndexMax; nIndex++) 
    { 
        UINT dwStyle=GetButtonStyle(nIndex);
        if (styles[nIndex] !=dwStyle) {
            // repaint whole toolbar (not just this button) 
            Invalidate(); 
            // no need to check any more 
            break; 
        }
    }
} 

// Because buttons are transparent, we need to repaint background on size or move 
void CFlatToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp) 
{ 
    // default processing 
    CToolBar::OnWindowPosChanging(lpwp); 
    RepaintBackground(); 
}

// Paint the toolbar 
void CFlatToolBar::OnPaint() 
{
    // standard tolbar 
    CToolBar::OnPaint(); 
    
    // erase the background 
    EraseNonClient(); 
	
    // plus separators 
    DrawSeparators(); 
}

// Paint the non-client area copied from MFC implementatios 
void CFlatToolBar::OnNcPaint() 
{ 
    // EraseNonClient(); don't do it here 
}

// Calculate the non-client area adjusting for grippers 
void CFlatToolBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) 
{
    CToolBar::OnNcCalcSize(bCalcValidRects,lpncsp); 
    
    // adjust non-client area for gripper at left or top 
    if (m_dwStyle & CBRS_FLOATING) 
    {
        // no grippers 
    } 
    else if (m_dwStyle & CBRS_ORIENT_HORZ) 
    {
        // move 2 pixels right to make room 
        lpncsp->rgrc[0].left += 2;
        lpncsp->rgrc[0].right += 2;
    }
    else 
    {
        // move 4 pixels downto make room
        lpncsp->rgrc[0].top += 4;
        lpncsp->rgrc[0].bottom += 4;
    }
}



Comments

  • Boutique en ligne pas cher GHD

    Posted by ddfjub249 on 07/16/2013 06:34am

    D'autres variétés ou une série de redresseurs GHD comprennent GHD violet et GHD précieux Ensemble-cadeau qui peut faire un excellent cadeau pour quelqu'un spécial Saint-Valentin, ou comme cadeau d'anniversaire. Il suffit de la même manière que vous voulez faire des emplettes pour d'autres articles sur Internet pour obtenir la meilleure affaire, vous pouvez aussi magasiner en ligne pour obtenir pas cher straighteners.Whether cheveux GHD vous soyez un particulier ou propriétaire d'un salon, ce produit capillaire spécial a excellent outil à avoir. En tant que propriétaire de saloon, vous pouvez aller pour le GHD IV Salon Styler et autre série spéciale pour le salon. Mais vous obtenez rien de moins qu'un véritable lisseur GHD. Si vous êtes offert un lisseur GHD à un taux étonnamment bas que vous attendez, vous devez réfléchir à deux fois, car cela pourrait être un drapeau rouge pour faux produit. [url=http://ghdpascherfer.webgarden.es/]lisseur ghd pas cher[/url] Le ressort de la boutique, il est beaucoup Cheap GHD Norge.Our lisseur ghd pas seulement pas cher mais la qualité est Veldig soutien-gorge, est la meilleure product.These ghd pas cher du monde a Flot différent versjoner av ghd stylers cheveux y hjelpe skjønnhet bevisst en y Öppna son Utseende de rêve . Ils sont conçus pour y do coiffure oppleve un grand, avec des résultats étonnants merkbart. Nous consacrons-nous ici å servir chaque client avec lisseur ghd produit beste et Best service.and ces ghd droit Rod Price mer tiltrekke you.We pense que vous nageoire vos lisseur ghd pas cher de favoris. [url=http://bbeatsinorge.cabanova.com/]ghd lisseur[/url] GHD rettang 7 brosse avec des ions actifs est une innovation révolutionnaire dans les soins capillaires, et est conçu pour permettre aux femmes de toujours être en mesure de regarder leur meilleur out.You pouvez définir ce réglage de chaleur particulier après que vos cheveux sont fins, normaux ou épais, tandis que le plaque souple minimise trop de pression. Le résultat est beau, coiffures élégantes avec décoloration minime.

    Reply
  • clarisonic coupled with in pink blossom style is truly appealing

    Posted by iouwanzi on 06/05/2013 11:42pm

    [url=http://www.miaclarisonicaustralia.org/clarisonic-pro]clarisonic pro[/url] Nous n’avons jamais perdu pour protéger mes propres cheveux sauvage à l’aide d’un jet clean. Je veux partager avec vous une autre section de mon propre régime cheveux (traitement).Avec mon vieux métal bon personnel, nous requise pour élever la température à 100 °, conçu pour la chevelure lisse, bien que je ne savais jamais même la présence de squirt résistant à la chaleur en ! Cela va sans la nécessité d’énoncer dans lequel mes cheveux sauvage était une bonne affaire cassé ! [url=http://www.miaclarisonicaustralia.org/]clarisonic mia 2[/url] Les producteurs primaires suivantes commencé pour sa bonne qualité merveilleuse de votre sèche-cheveux et fer à lisser est aujourd’hui célèbre également la distinction entre les femmes qui parfois vous avez besoin pour redresser votre chevelure afin d’éliminer ces types de problèmes ghd fer luxe Violet, à son tour, n’est pas un peu ne serait tout simplement pas seulement en possession du logiciel. un temps très long sur les compétences à l’aide de modèle MK4 GHD coiffer les cheveux bouclés, qui habituellement aurait certainement visiteurs parfaites un partage vraiment Thru la douceur, verrouille par exemple signifiait redresser ce n’est, en général, les lois de tension semi-automatique ou entièrement automatique et les règlements, vous pouvez acheter un bon cheveu sauvage style avec vous partout dans le monde grâce à une Botheration vitale tout autour. meilleurs d’entre eux à travers un endroit spécifique pour redresser redresseur GHD MK4 cheveux bouclés pourraient l’être. problème en effet, le fait qui se produit à l’aide d’un opérateur capable dvd, plus de points, le type choisi des méthodes simples pour vous aider à contrôler l’application correcte et [url=http://www.miaclarisonicaustralia.org/clarisonic-classic]clarisonic classic[/url] et en plus vous savez quoi ? Cette approche n’est pas presque tous. Est normalement photographié, à peu près chaque période unique, juste par le photographe professionnel populaire particulière ? Certes, le logiciel n’est pas tout un plus petit montant connu Katy.concernant pour lequel vous consacrez une bonne période de 7 jours. Juste pour une partie, Document mis au point plusieurs évolutions dont je parle avant longtemps. Bien sûr, le logiciel peut-être promi ! Toujours juste avant tout cela, Document allait donner à ma propre volonté.

    Reply
  • Asegure el pelo más cercano al principal dentro de los alisadores de pelo.

    Posted by hanmeihm on 05/30/2013 09:46am

    [url=http://www.ghd-baratas.manifo.com/]Ghd Baratas[/url] Tengo la ghd color blanco real y tambin precio $ 270. me gusta esto! dese qi antes, sin embargo, que uno va a ser taaan mucho mejor! la nica cosa que me altero bsicamente reordenar podra llegar a ser en el plazo de oscuridad desde los laterales asociados con la acumulaci®n porquera de tu cabello y puede convertir este tono extremadamente esmeralda. la ghd real, simplemente deja bloquea taaan amable, adems de suavizar adems de que no se tire a los hairas para que nhd.i no han hecho jams encontrado que (sin embargo la ghd, por lo que poseen una garanta que asegura que una persona que es workbuy ll en el caso de que el uso de su sitio web o incluso con un aprobado en la dealersalon internet .., as como asegurarse de que el uso de la companyoh as como los sitios de subastas en Internet no es una buena manera de comprar la ghd real, porque hay muchas imitaciones ! mejor de la suerte). [url=http://www.planchasghdbaratasonline.com/]ghd España[/url] Los propietarios pasan por concluy que soplan generalmente principal secar el cabello antes con un Gran da del pelo de semana straigntener pelo que enderezar las unidades formularios requeridos pelo bonito en un prximo perodo de tiempo una oportunidad viene de afliccin alta temperatura. Los efectos es uno de los m¢s puesta en marcha con m¢s h²medo en el camino a sin agua GHD jefe de straignteners pelo. Tener un empapado para que se seque a cabo normalmente stylers GHD no va a quitar temperaturas dao sin embargo significa que usted puede mantenerse al margen de la componente ambiental significativo de brushing el pelo. Todas estas complemento RRS la mejor distribucin de los ejemplos de la estancia perfecta hidratado para que seca la cabeza GHD straignteners de pelo disponibles en estos das. [url=http://www.planchasghdbaratasonline.com/]planchas ghd[/url] El set de regalo magnfico ofrece el oro ghd Styler V clsico en un completo finish.Suitable rico rub metlico para todo tipo de cabello, este cepillo tiene las mismas caractersticas que el normal ghd Gold Classic styler V, incluyendo el modo de reposo automtico, voltaje universal y un extra largo cable giratorio para permitir una total libertad mientras modela. Un estuche negro acolchado que tambin inteligentemente incorpora un prctico resistente al calor estera, completa este conjunto elegante

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds