Click here to Skip to main content
15,893,381 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 255.9K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ==========================================================================
//					Class Implementation : COX*Skin
// ==========================================================================
// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// Version: 9.3

#include "stdafx.h"
#include "OXSkins.h"
#include "OXCoolToolBar.h"
#include "OXMenuBar.h"

#include "OXSizeDockBar.h"
#include "OXSzMiniDockFrmWnd.h"
#include "OXFrameWndDock.h"
#include "OXTabClientWnd.h"
#include "XStatus4.h"
#include "OXSplitterRect.h"
#include "OXShortcutBar.h"

BOOL IsThemed()
{
	BOOL ret = FALSE;
	OSVERSIONINFO ovi = {0};
	ovi.dwOSVersionInfoSize = sizeof ovi;
	GetVersionEx(&ovi);
	if(ovi.dwMajorVersion==5 && ovi.dwMinorVersion==1)
	{
		//Windows XP detected
		typedef BOOL WINAPI ISAPPTHEMED();
		typedef BOOL WINAPI ISTHEMEACTIVE();
		ISAPPTHEMED* pISAPPTHEMED = NULL;
		ISTHEMEACTIVE* pISTHEMEACTIVE = NULL;
		HMODULE hMod = LoadLibrary(_T("uxtheme.dll"));
		if(hMod)
		{
			pISAPPTHEMED = reinterpret_cast<ISAPPTHEMED*>(GetProcAddress(hMod,"IsAppThemed"));
			pISTHEMEACTIVE = reinterpret_cast<ISTHEMEACTIVE*>(GetProcAddress(hMod,"IsThemeActive"));
			if(pISAPPTHEMED && pISTHEMEACTIVE)
			{
				if(pISAPPTHEMED() && pISTHEMEACTIVE())				
				{				
					typedef HRESULT CALLBACK DLLGETVERSION(DLLVERSIONINFO*);
					DLLGETVERSION* pDLLGETVERSION = NULL;

					HMODULE hModComCtl = LoadLibrary(_T("comctl32.dll"));
					if(hModComCtl)
					{
						pDLLGETVERSION = reinterpret_cast<DLLGETVERSION*>(
							GetProcAddress(hModComCtl,"DllGetVersion"));
						if(pDLLGETVERSION)
						{
							DLLVERSIONINFO dvi = {0};
							dvi.cbSize = sizeof dvi;
							if(pDLLGETVERSION(&dvi) == NOERROR )
							{
								ret = dvi.dwMajorVersion >= 6;
							}
						}
						FreeLibrary(hModComCtl);
					}
				}
			}
			FreeLibrary(hMod);
		}
	}	
	return ret;
}

// COXDockbarSkin
//


// COXDockbarSkinClassic
//

COXDockbarSkinClassic::COXDockbarSkinClassic()
{
	m_fontCaption.CreatePointFont(100, _T("Arial"));
	m_fontCaptionSolid.CreatePointFont(80, _T("Arial"));

	// Init the control bar constants
	m_ControlBarConstants.iButtonGap = 2;
}

COXDockbarSkinClassic::~COXDockbarSkinClassic()
{
}

void COXDockbarSkinClassic::DrawBackground(CDC* pDC, COXSizeDockBar* pSizeDockBar)
{
	CRect rectClient;
	pSizeDockBar->GetClientRect(rectClient);
	pDC->FillSolidRect(rectClient, ::GetSysColor(COLOR_3DFACE));
}

void COXDockbarSkinClassic::DrawGripper(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsGripper() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		return;
	}

	BOOL bHorz=(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ)==0;

	CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect gripper=pSizeControlBar->m_rectGripper;
	gripper.OffsetRect(-rectWindow.left, -rectWindow.top);

	if(pSizeControlBar->IsSolidGripper())
	{
		CBrush brush((pSizeControlBar->IsActive() ? ::GetSysColor(COLOR_ACTIVECAPTION) : 
			::GetSysColor(COLOR_INACTIVECAPTION)));
		pDC->FillRect(gripper,&brush);
	}
	else
	{
		gripper.DeflateRect(2,2);
	}

	CString sBarTitle;
	pSizeControlBar->GetWindowText(sBarTitle);
	CRect rectText=CRect(0,0,0,0);

	//draw text
	if(pSizeControlBar->IsCaption() && !sBarTitle.IsEmpty())
	{
		rectText=gripper;
		if(!bHorz)
		{
			rectText.bottom-=ID_TEXT_OFFSET;
		}
		else
		{
			rectText.left+=ID_TEXT_OFFSET;
		}

		COLORREF oldColor;
		if(pSizeControlBar->IsSolidGripper())
		{
			oldColor=pDC->SetTextColor((pSizeControlBar->IsActive() ? 
				::GetSysColor(COLOR_CAPTIONTEXT) : 
				::GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
		}
		else
		{
			oldColor=pDC->SetTextColor((pSizeControlBar->IsActive() ? 
				::GetSysColor(COLOR_ACTIVECAPTION) : 
				::GetSysColor(COLOR_INACTIVECAPTION)));
		}

		CFont* pOldFont=NULL;
		CFont fontVert;
		if(!bHorz)
		{
			// setup font for vertically oriented mode
			LOGFONT lf;
			if (pSizeControlBar->IsSolidGripper())
				VERIFY(m_fontCaptionSolid.GetLogFont(&lf));
			else
				VERIFY(m_fontCaption.GetLogFont(&lf));
			lf.lfEscapement=900;
			lf.lfOrientation=900;
			VERIFY(fontVert.CreateFontIndirect(&lf));
			pOldFont=pDC->SelectObject(&fontVert);
		}
		else
		{
			if (pSizeControlBar->IsSolidGripper())
				pOldFont=pDC->SelectObject(&m_fontCaptionSolid);
			else
				pOldFont=pDC->SelectObject(&m_fontCaption);
		}

		CRect rectHelper=rectText;
		if(!bHorz)
		{
			// adjust rectangle to display vertical text
			rectText.top=rectHelper.left;
			rectText.bottom=rectHelper.right;
			rectText.left=rectHelper.top;
			rectText.right=rectHelper.bottom;
		}

		// calculate the rect to display text in
		UINT nFormat=DT_LEFT|DT_SINGLELINE;
		pDC->DrawText(sBarTitle,&rectText,nFormat|DT_CALCRECT);
		if(!bHorz)
		{
			if(rectText.Width()>rectHelper.Height())
				rectText.right=rectText.left+rectHelper.Height();
			rectHelper=rectText;

			rectText.top=rectHelper.left;
			rectText.bottom=rectHelper.right;
			rectText.left=rectHelper.top;
			rectText.right=rectHelper.bottom;
			rectHelper=rectText;
		}
		else
		{
			if(rectText.Width()>rectHelper.Width())
				rectText.right=rectText.left+rectHelper.Width();
			rectHelper=rectText;
		}

		// adjust coordinates
		if(!bHorz)
		{
			rectText.left+=(gripper.Width()-rectHelper.Width())/2+
				(gripper.Width()-rectHelper.Width())%2;
			rectText.right=rectText.left+rectHelper.Width();
		}
		else
		{
			rectText.top+=(gripper.Height()-rectHelper.Height())/2+
				(gripper.Height()-rectHelper.Height())%2;
			rectText.bottom=rectText.top+rectHelper.Height();
		}

		if(!bHorz)
		{
			rectText.bottom=gripper.bottom-ID_TEXT_OFFSET;
			rectText.top=rectText.bottom-rectHelper.Height();
		}
		else
		{
			rectText.left=rectText.left;
			rectText.right=rectText.left+rectHelper.Width();
		}

		rectHelper=rectText;
		if(!bHorz)
		{
			rectHelper.bottom+=rectText.Width();
			rectHelper.right+=rectText.Height();
		}

		int nOldBkMode=0;
		if(pSizeControlBar->IsSolidGripper())
		{
			nOldBkMode=pDC->SetBkMode(TRANSPARENT);
		}
		// draw text
		pDC->DrawText(sBarTitle,&rectHelper,
			DT_BOTTOM|DT_LEFT|DT_SINGLELINE|DT_END_ELLIPSIS);
		if(pSizeControlBar->IsSolidGripper())
		{
			pDC->SetBkMode(nOldBkMode);
		}

		pDC->SetTextColor(oldColor);
		if(pOldFont!=NULL)
		{
			pDC->SelectObject(pOldFont);
		}
	}


	if(!pSizeControlBar->IsSolidGripper())
	{
		// paint the gripper
		if(!bHorz) 
		{
			if(!rectText.IsRectEmpty())
			{
				gripper.bottom=rectText.top-ID_TEXTGRIPPER_MARGIN;
			}
			
			// gripper at left
			if(gripper.bottom>gripper.top && gripper.Height()>=ID_GRIPPER_MINSIZE)
			{
				gripper.right = gripper.left + 3;
				pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
					::GetSysColor(COLOR_BTNSHADOW));
				gripper.OffsetRect(4, 0);
				pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
					::GetSysColor(COLOR_BTNSHADOW));
			}
		}
		else 
		{
			if(!rectText.IsRectEmpty())
			{
				gripper.left=rectText.right+ID_TEXTGRIPPER_MARGIN;
			}

			// gripper at top
			if(gripper.right>gripper.left && gripper.Width()>=ID_GRIPPER_MINSIZE)
			{
				gripper.bottom = gripper.top + 3;
				pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
					::GetSysColor(COLOR_BTNSHADOW));
				gripper.OffsetRect(0, 4);
				pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
					::GetSysColor(COLOR_BTNSHADOW));
			}
		}
	}
}

void COXDockbarSkinClassic::DrawCloseButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsCloseBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// draw close button
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rcButton=pSizeControlBar->m_rectCloseBtn;
	rcButton.OffsetRect(-rectWindow.left, -rectWindow.top);

	// Draw to a memory dc to avoid flashing
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap bmpMem;
	CRect rectMem(rcButton);
	rectMem.OffsetRect(-rectMem.left, -rectMem.top);
	bmpMem.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
	CBitmap* pOldBmp = dc.SelectObject(&bmpMem);

	dc.DrawFrameControl(CRect(0, 0, rcButton.Width(), rcButton.Height()), DFC_CAPTION,DFCS_CAPTIONCLOSE|
		(pSizeControlBar->m_pressedBtn==COXSizeControlBar::CLOSEBTN ? DFCS_PUSHED : 0));
	pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
	dc.SelectObject(pOldBmp);
}

void COXDockbarSkinClassic::DrawResizeButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsResizeBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// draw close button
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rcButton=pSizeControlBar->m_rectResizeBtn;
	rcButton.OffsetRect(-rectWindow.left, -rectWindow.top);

	// Draw to a memory dc to avoid flashing
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap bmpMem;
	CRect rectMem(rcButton);
	rectMem.OffsetRect(-rectMem.left, -rectMem.top);
	bmpMem.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
	CBitmap* pOldBmp = dc.SelectObject(&bmpMem);

	dc.DrawFrameControl(CRect(0, 0, rcButton.Width(), rcButton.Height()),DFC_CAPTION,
		(pSizeControlBar->m_bMaximized ? DFCS_CAPTIONMIN : DFCS_CAPTIONMAX)|
		(pSizeControlBar->m_pressedBtn==COXSizeControlBar::RESIZEBTN ? DFCS_PUSHED : 0)|
		(pSizeControlBar->CanResize() ? 0 : DFCS_INACTIVE));
	pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
	dc.SelectObject(pOldBmp);
}

void COXDockbarSkinClassic::DrawNonClientArea(CDC* pDC, LPCRECT lpRect, COXSizeControlBar* pSizeControlBar)
{
	CRect rect(lpRect);
	pSizeControlBar->DrawBorders(pDC, rect);
	pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_BTNFACE));
}

void COXDockbarSkinClassic::DrawSplitter(CDC* pDC, COXSplitterRect* pSplitterRect, COXSizeDockBar* /*pSizeDockBar*/)
{
    CRect rect=pSplitterRect->m_rect;
    switch(pSplitterRect->m_type)
	{
    case SPLITTER_VERT:
		{
			rect.left++;
			pDC->FillSolidRect(rect.left, rect.top, 1, rect.Height(), 
				::GetSysColor(COLOR_BTNFACE));
			rect.left++;
			pDC->FillSolidRect(rect.left, rect.top, 1, rect.Height(), 
				::GetSysColor(COLOR_BTNHILIGHT));
			
			rect.right--;
			pDC->FillSolidRect(rect.right, rect.top, 1, rect.Height(), 
				::GetSysColor(COLOR_WINDOWFRAME));
			rect.right--;
			pDC->FillSolidRect(rect.right, rect.top, 1, rect.Height(), 
				::GetSysColor(COLOR_BTNSHADOW));
		}
		break;
	
    case SPLITTER_HORZ:
		{
			rect.top++;
			pDC->FillSolidRect(rect.left, rect.top, rect.Width(), 1, 
				::GetSysColor(COLOR_BTNFACE));
			rect.top++;
			pDC->FillSolidRect(rect.left, rect.top, rect.Width(), 1, 
				::GetSysColor(COLOR_BTNHILIGHT));
			
			rect.bottom--;
			pDC->FillSolidRect(rect.left, rect.bottom, rect.Width(), 1,
				::GetSysColor(COLOR_WINDOWFRAME));
			rect.bottom--;
			pDC->FillSolidRect(rect.left, rect.bottom, rect.Width(), 1, 
				::GetSysColor(COLOR_BTNSHADOW));

		}
        break;
		
	default:
        ASSERT(FALSE);
        break;
	}
}

COLORREF COXDockbarSkinClassic::GetClientBorderColor()
{
	return ::GetSysColor(COLOR_WINDOWFRAME);
}

void COXDockbarSkinClassic::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp, COXSizeControlBar* pSizeControlBar)
{
	CRect rect=lpncsp->rgrc[0];
	rect.DeflateRect(ID_CONTAINER_GAP, ID_CONTAINER_GAP);

	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ) 
		{
			rect.DeflateRect(ID_CONTAINER_GAP,0,0,0);
			rect.left+=ID_BUTTON_SIDE;
			if(rect.left>rect.right)
			{
				rect.left=rect.right;
			}
		} 
		else 
		{
			rect.DeflateRect(0,ID_CONTAINER_GAP,0,0);
			rect.top+=ID_BUTTON_SIDE;
			if(rect.top>rect.bottom)
			{
				rect.top=rect.bottom;
			}
		}
		pSizeControlBar->m_bDelayRecalcLayout=TRUE;
	}

	lpncsp->rgrc[0]=rect;
}

void COXDockbarSkinClassic::RecalcLayout(COXSizeControlBar* pSizeControlBar)
{
	CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	rectWindow.DeflateRect(ID_CONTAINER_GAP, ID_CONTAINER_GAP);
	pSizeControlBar->m_rectGripper=rectWindow;
    
	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ) 
		{
			pSizeControlBar->m_rectGripper.right=pSizeControlBar->m_rectGripper.left+ID_BUTTON_SIDE;
			
			if(pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.bottom=pSizeControlBar->m_rectCloseBtn.top+ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.top+=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}

			if(pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.bottom=pSizeControlBar->m_rectResizeBtn.top+ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.top+=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}
		} 
		else 
		{
			pSizeControlBar->m_rectGripper.bottom=pSizeControlBar->m_rectGripper.top+ID_BUTTON_SIDE;
			
			if(pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.left=pSizeControlBar->m_rectCloseBtn.right-ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.right-=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}

			if(pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.left=pSizeControlBar->m_rectResizeBtn.right-ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.right-=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}
		}
	}

	pSizeControlBar->m_bDelayRecalcLayout=FALSE;
}


// COXDockbarSkinXP
//

COXDockbarSkinXP::COXDockbarSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
	m_fontCaption.CreatePointFont(85, _T("Tahoma BOLD"));

	// Init the control bar constants
	m_ControlBarConstants.iButtonGap = 3;
}

COXDockbarSkinXP::~COXDockbarSkinXP()
{
}

void COXDockbarSkinXP::DrawBackground(CDC* pDC, COXSizeDockBar* pSizeDockBar)
{
	CRect rectClient;
	pSizeDockBar->GetClientRect(rectClient);
	pDC->FillSolidRect(rectClient, ::GetSysColor(COLOR_3DFACE));
}

void COXDockbarSkinXP::DrawGripper(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsGripper() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		return;
	}

	BOOL bHorz=(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ)==0;

	CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect gripper=pSizeControlBar->m_rectGripper;

	// If this is a solid griper extend it to include the buttons
	if (pSizeControlBar->IsSolidGripper())
	{
		gripper.UnionRect(gripper, pSizeControlBar->m_rectCloseBtn);
		gripper.UnionRect(gripper, pSizeControlBar->m_rectResizeBtn);
	}
	gripper.InflateRect(3, 3);	
	gripper.OffsetRect(-rectWindow.left, -rectWindow.top);

	if(pSizeControlBar->IsSolidGripper())
	{
		CBrush brush(::GetSysColor(COLOR_INACTIVECAPTION));
		CRect rectCaption(gripper);
		if (bHorz)
			rectCaption.DeflateRect(1, 2, 1, 1);
		else
			rectCaption.DeflateRect(2, 2, 1, 1);
		pDC->FillRect(rectCaption, &brush);
	}
	else
	{
		if (bHorz)
			gripper.DeflateRect(4, 2);
		else
			gripper.DeflateRect(2, 0);
	}

	CString sBarTitle;
	pSizeControlBar->GetWindowText(sBarTitle);
	CRect rectText=CRect(0,0,0,0);

	//draw text
	if(pSizeControlBar->IsCaption() && !sBarTitle.IsEmpty())
	{
		rectText=gripper;

		if (pSizeControlBar->IsSolidGripper())
		{
			if(!bHorz)
			{
				rectText.bottom-=4;
			}
			else
			{
				rectText.left+=4;
			}
		}

		COLORREF oldColor;
		if(pSizeControlBar->IsSolidGripper())
		{
			oldColor=pDC->SetTextColor(::GetSysColor(COLOR_CAPTIONTEXT));
		}
		else
		{
			oldColor=pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
		}

		CFont* pOldFont=NULL;
		CFont fontVert;
		if(!bHorz)
		{
			// setup font for vertically oriented mode
			LOGFONT lf;
			VERIFY(m_fontCaption.GetLogFont(&lf));
			lf.lfEscapement=900;
			lf.lfOrientation=900;
			VERIFY(fontVert.CreateFontIndirect(&lf));
			pOldFont=pDC->SelectObject(&fontVert);
		}
		else
		{
			pOldFont=pDC->SelectObject(&m_fontCaption);
		}

		CRect rectHelper=rectText;
		if(!bHorz)
		{
			// adjust rectangle to display vertical text
			rectText.top=rectHelper.left;
			rectText.bottom=rectHelper.right;
			rectText.left=rectHelper.top;
			rectText.right=rectHelper.bottom;
		}

		// calculate the rect to display text in
		UINT nFormat=DT_LEFT|DT_SINGLELINE;
		pDC->DrawText(sBarTitle,&rectText,nFormat|DT_CALCRECT);
		if(!bHorz)
		{
			if(rectText.Width()>rectHelper.Height())
				rectText.right=rectText.left+rectHelper.Height();
			rectHelper=rectText;

			rectText.top=rectHelper.left;
			rectText.bottom=rectHelper.right;
			rectText.left=rectHelper.top;
			rectText.right=rectHelper.bottom;
			rectHelper=rectText;
		}
		else
		{
			if(rectText.Width()>rectHelper.Width())
				rectText.right=rectText.left+rectHelper.Width();
			rectHelper=rectText;
		}

		// adjust coordinates
		if(!bHorz)
		{
			rectText.left+=(gripper.Width()-rectHelper.Width())/2+
				(gripper.Width()-rectHelper.Width())%2;
			rectText.right=rectText.left+rectHelper.Width();
		}
		else
		{
			rectText.top+=(gripper.Height()-rectHelper.Height())/2+
				(gripper.Height()-rectHelper.Height())%2;
			rectText.bottom=rectText.top+rectHelper.Height();
		}

		if(!bHorz)
		{
			rectText.bottom=gripper.bottom-ID_TEXT_OFFSET;
			rectText.top=rectText.bottom-rectHelper.Height();
		}
		else
		{
			rectText.left=rectText.left;
			rectText.right=rectText.left+rectHelper.Width();
		}

		rectHelper=rectText;
		if(!bHorz)
		{
			rectHelper.bottom+=rectText.Width();
			rectHelper.right+=rectText.Height();
		}

		int nOldBkMode=0;
		if(pSizeControlBar->IsSolidGripper())
		{
			nOldBkMode=pDC->SetBkMode(TRANSPARENT);
		}
		// draw text
		pDC->DrawText(sBarTitle,&rectHelper,
			DT_BOTTOM|DT_LEFT|DT_SINGLELINE|DT_END_ELLIPSIS);
		if(pSizeControlBar->IsSolidGripper())
		{
			pDC->SetBkMode(nOldBkMode);
		}

		pDC->SetTextColor(oldColor);
		if(pOldFont!=NULL)
		{
			pDC->SelectObject(pOldFont);
		}
	}


	if(!pSizeControlBar->IsSolidGripper())
	{
		// paint the gripper

		CPen pen;
		pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetGripperColor());
		CPen* pOldPen = pDC->SelectObject(&pen);

		if(!bHorz) 
		{
			if(!rectText.IsRectEmpty())
			{
				gripper.bottom=rectText.top-ID_TEXTGRIPPER_MARGIN;
			}
			
			// gripper at left
			if(gripper.bottom>gripper.top && gripper.Height()>=ID_GRIPPER_MINSIZE)
			{
				gripper.left += 3;
				gripper.bottom -= 1;
				for (int i = 0; i < 4; i++)
				{
					pDC->MoveTo(gripper.left + i * 2, gripper.top);
					pDC->LineTo(gripper.left + i * 2, gripper.bottom);
				}
			}
		}
		else 
		{
			if(!rectText.IsRectEmpty())
			{
				gripper.left=rectText.right+ID_TEXTGRIPPER_MARGIN;
			}

			// gripper at top
			if(gripper.right>gripper.left && gripper.Width()>=ID_GRIPPER_MINSIZE)
			{
				gripper.top += 3;
				gripper.right -= 1;
				for (int i = 0; i < 4; i++)
				{
					pDC->MoveTo(gripper.left, gripper.top + i * 2);
					pDC->LineTo(gripper.right, gripper.top + i * 2);
				}
			}
		}

		pDC->SelectObject(pOldPen);
	}
}

void COXDockbarSkinXP::DrawCloseButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsCloseBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// Determine the button rectangle
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rect = pSizeControlBar->m_rectCloseBtn;
	rect.OffsetRect(-rectWindow.left, -rectWindow.top);
	rect.InflateRect(1, 1, 2, 2);

	if (pSizeControlBar->IsSolidGripper())
		m_pSkinXP->DrawFrameButton(pDC, rect, DFCS_CAPTIONCLOSE, FALSE, TRUE,
			::GetSysColor(COLOR_INACTIVECAPTION), pSizeControlBar);
	else
		m_pSkinXP->DrawFrameButton(pDC, rect, DFCS_CAPTIONCLOSE, FALSE, FALSE,
			::GetSysColor(COLOR_3DFACE), pSizeControlBar);
}

void COXDockbarSkinXP::DrawResizeButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsCloseBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// Determine the button rectangle
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rect = pSizeControlBar->m_rectResizeBtn;
	rect.OffsetRect(-rectWindow.left, -rectWindow.top);
	rect.InflateRect(1, 1, 2, 2);

	// Determine the flags
	UINT nState = pSizeControlBar->m_bMaximized ? DFCS_CAPTIONMIN : DFCS_CAPTIONMAX;
	BOOL bDisabled = !pSizeControlBar->CanResize();

	if (pSizeControlBar->IsSolidGripper())
		m_pSkinXP->DrawFrameButton(pDC, rect, nState, bDisabled, TRUE,
			::GetSysColor(COLOR_INACTIVECAPTION), pSizeControlBar);
	else
		m_pSkinXP->DrawFrameButton(pDC, rect, nState, bDisabled, FALSE,
			::GetSysColor(COLOR_3DFACE), pSizeControlBar);
}

void COXDockbarSkinXP::DrawNonClientArea(CDC* pDC, LPCRECT lpRect, COXSizeControlBar* /*pSizeControlBar*/)
{
	pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_3DFACE));
}

void COXDockbarSkinXP::DrawSplitter(CDC* pDC, COXSplitterRect* pSplitterRect, COXSizeDockBar* /*pSizeDockBar*/)
{
    CRect rect(pSplitterRect->m_rect);

	if (rect.bottom > 8000)
		rect.bottom = 8000;

	pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));
	
	if (pSplitterRect->m_type == SPLITTER_VERT)
	{
		rect.left = pSplitterRect->m_rect.CenterPoint().x;
		rect.right = rect.left + 1;
	}
	else
	{
		rect.top = pSplitterRect->m_rect.CenterPoint().y;
		rect.bottom = rect.top + 1;
	}

	pDC->FillSolidRect(rect, m_pSkinXP->GetSeparatorColor());
}

COLORREF COXDockbarSkinXP::GetClientBorderColor()
{
	return m_pSkinXP->GetBorderColor();
}

void COXDockbarSkinXP::OnNcPaintSizeDockBar(COXSizeDockBar* pSizeDockBar)
{
	CWindowDC dc(pSizeDockBar);
	CRect rectWindow;
	pSizeDockBar->GetWindowRect(rectWindow);
	CPoint ptOffset = rectWindow.TopLeft();
	rectWindow.OffsetRect(-ptOffset.x, -ptOffset.y);

	// Get the client rectangle in window coordionates
	CRect rectClient;
	pSizeDockBar->GetClientRect(rectClient);
	pSizeDockBar->ClientToScreen(rectClient);
	rectClient.OffsetRect(-ptOffset.x, -ptOffset.y);
	dc.ExcludeClipRect(rectClient);

	dc.FillSolidRect(rectWindow, m_pSkinXP->GetDockbarBackgroundColor());
}

void COXDockbarSkinXP::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp, COXSizeControlBar* pSizeControlBar)
{
	CRect rect=lpncsp->rgrc[0];
	rect.DeflateRect(ID_CONTAINER_GAP, ID_CONTAINER_GAP);

	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ) 
		{
			rect.DeflateRect(ID_CONTAINER_GAP,0,0,0);
			rect.left+=ID_BUTTON_SIDE;
			if(rect.left>rect.right)
			{
				rect.left=rect.right;
			}
		} 
		else 
		{
			rect.DeflateRect(0,ID_CONTAINER_GAP,0,0);
			rect.top+=ID_BUTTON_SIDE;
			if(rect.top>rect.bottom)
			{
				rect.top=rect.bottom;
			}
		}
		pSizeControlBar->m_bDelayRecalcLayout=TRUE;
	}

	lpncsp->rgrc[0]=rect;
}

void COXDockbarSkinXP::RecalcLayout(COXSizeControlBar* pSizeControlBar)
{
	CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	rectWindow.DeflateRect(ID_CONTAINER_GAP, ID_CONTAINER_GAP);
	pSizeControlBar->m_rectGripper=rectWindow;
    
	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ) 
		{
			pSizeControlBar->m_rectGripper.right=pSizeControlBar->m_rectGripper.left+ID_BUTTON_SIDE;
			
			if(pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.bottom=pSizeControlBar->m_rectCloseBtn.top+ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.top+=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}

			if(pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.bottom=pSizeControlBar->m_rectResizeBtn.top+ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.top+=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}
		} 
		else 
		{
			pSizeControlBar->m_rectGripper.bottom=pSizeControlBar->m_rectGripper.top+ID_BUTTON_SIDE;
			
			if(pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.left=pSizeControlBar->m_rectCloseBtn.right-ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.right-=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}

			if(pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn=pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.left=pSizeControlBar->m_rectResizeBtn.right-ID_BUTTON_SIDE;
				pSizeControlBar->m_rectGripper.right-=ID_BUTTON_SIDE+GetControlBarConstants().iButtonGap;
			}
		}
	}

	pSizeControlBar->m_bDelayRecalcLayout=FALSE;
}

// COXDockbarSkin2003
//

COXDockbarSkin2003::COXDockbarSkin2003(COXSkin2003* pSkin2003) :
	COXDockbarSkinXP(pSkin2003)
{
}

COXDockbarSkin2003::~COXDockbarSkin2003()
{
}

void COXDockbarSkin2003::DrawBackground(CDC* pDC, COXSizeDockBar* pSizeDockBar)
{
	CRect rectClient;
	pSizeDockBar->GetClientRect(rectClient);

	int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
	if (iWidth < rectClient.Width())
		iWidth = rectClient.Width();
	
	rectClient.right = rectClient.left + iWidth;

	CRect rectSolid(rectClient);
	rectClient.right = rectClient.CenterPoint().x;
	rectSolid.left = rectClient.right;

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pSkin2003->GradientFill(pDC, rectClient,
		pSkin2003->GetDockbarLeftColor(),
		pSkin2003->GetDockbarRightColor(),
		GRADIENT_FILL_RECT_H);
	pDC->FillSolidRect(rectSolid, pSkin2003->GetDockbarRightColor());
}

void COXDockbarSkin2003::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp, COXSizeControlBar* pSizeControlBar)
{
	CRect rect=lpncsp->rgrc[0];
	rect.DeflateRect(ID_CONTAINER_GAP, ID_CONTAINER_GAP);

	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if(pSizeControlBar->m_dwStyle&CBRS_ORIENT_HORZ) 
		{
			rect.DeflateRect(ID_O11_GRIPPER + ID_BUTTON_SIDE,0,0,0);
			if(rect.left>rect.right)
			{
				rect.left=rect.right;
			}
		} 
		else 
		{
			rect.DeflateRect(0,ID_O11_GRIPPER + ID_BUTTON_SIDE,0,0);
			if(rect.top>rect.bottom)
			{
				rect.top=rect.bottom;
			}
		}
		pSizeControlBar->m_bDelayRecalcLayout=TRUE;
	}

	lpncsp->rgrc[0]=rect;
}

void COXDockbarSkin2003::DrawNonClientArea(CDC* pDC, LPCRECT lpRect, COXSizeControlBar* /*pSizeControlBar*/)
{
	pDC->FillSolidRect(lpRect, m_pSkinXP->GetDockbarBackgroundColor());
}

void COXDockbarSkin2003::DrawGripper(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsGripper() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		return;
	}

    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CPoint ptOffset(-rectWindow.left, -rectWindow.top);
	rectWindow.OffsetRect(ptOffset);

	CRect rectGripper;
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	if (pSizeControlBar->m_dwStyle & CBRS_ORIENT_HORZ)
	{
		rectGripper = pSizeControlBar->m_rectGripper;
		rectGripper.OffsetRect(ptOffset);

		if (::GetVersion() >= 0x80000000)
			// Adoid a problem with the ::GradientFill() API in Win98 and ME
			pSkin2003->GradientFillManual(pDC, rectGripper,
				pSkin2003->GetControlBarLightColor(),
				pSkin2003->GetControlBarDarkColor(),
				GRADIENT_FILL_RECT_H);
		else
			pSkin2003->GradientFill(pDC, rectGripper,
				pSkin2003->GetControlBarLightColor(),
				pSkin2003->GetControlBarDarkColor(),
				GRADIENT_FILL_RECT_H);

		// If this is not the leftmost griper gover the top portion of it
		CRect rectThis;
		pSizeControlBar->GetWindowRect(rectThis);
		pSizeControlBar->m_pDockBar->ScreenToClient(&rectThis);
		if (rectThis.left > 0)
		{
			CRect rectSolid(rectGripper);
			rectSolid.right = rectSolid.left + 2;
			pDC->FillSolidRect(rectSolid, pSkin2003->GetDockbarBackgroundColor());
		}

		// Draw the stripes
		CRect rectStripes(rectGripper);
		rectStripes.DeflateRect(5, 5);
		rectStripes.top = rectStripes.bottom - 2;
		pSkin2003->DrawGripperStripes(pDC, rectStripes, FALSE);

		// Draw the text

		// Setup a font for vertically oriented mode
		LOGFONT lf;
		VERIFY(m_fontCaption.GetLogFont(&lf));
		lf.lfEscapement = 900;
		lf.lfOrientation = 900;
		CFont fontVert;
		VERIFY(fontVert.CreateFontIndirect(&lf));
		CFont* pOldFont = pDC->SelectObject(&fontVert);

		CString strBarTitle;
		pSizeControlBar->GetWindowText(strBarTitle);
		CRect rectText(rectGripper);

		rectText.left = 6;
		rectText.top = 0;
		rectText.right = rectGripper.Height();
		rectText.bottom = rectGripper.bottom + 2;

		// Crop the text if there are buttons
		CRect rectButton(0, 0, 0, 0);
		if (pSizeControlBar->IsResizeBtn())
			rectButton = pSizeControlBar->m_rectResizeBtn;
		else if (pSizeControlBar->IsCloseBtn())
			rectButton = pSizeControlBar->m_rectCloseBtn;
		if (!rectButton.IsRectEmpty())
		{
			rectButton.OffsetRect(ptOffset);
			rectText.top = rectButton.bottom + 1;
		}

		int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
		pDC->DrawText(strBarTitle, &rectText,
			DT_LEFT|DT_BOTTOM|DT_SINGLELINE|DT_END_ELLIPSIS);
		pDC->SetBkMode(iOldBkMode);
		pDC->SelectObject(pOldFont);
	}
	else // vertical
	{
		rectGripper = pSizeControlBar->m_rectGripper;
		rectGripper.OffsetRect(ptOffset);

		if (::GetVersion() >= 0x80000000)
			// Adoid a problem with the ::GradientFill() API in Win98 and ME
			pSkin2003->GradientFillManual(pDC, rectGripper,
				pSkin2003->GetControlBarLightColor(),
				pSkin2003->GetControlBarDarkColor(),
				GRADIENT_FILL_RECT_V);
		else
			pSkin2003->GradientFill(pDC, rectGripper,
				pSkin2003->GetControlBarLightColor(),
				pSkin2003->GetControlBarDarkColor(),
				GRADIENT_FILL_RECT_V);

		// If this is not the topmost griper gover the top portion of it
		CRect rectThis;
		pSizeControlBar->GetWindowRect(rectThis);
		pSizeControlBar->m_pDockBar->ScreenToClient(&rectThis);
		if (rectThis.top > 0)
		{
			CRect rectSolid(rectGripper);
			rectSolid.bottom = rectSolid.top + 2;
			pDC->FillSolidRect(rectSolid, pSkin2003->GetDockbarBackgroundColor());
		}

		// Draw the stripes
		CRect rectStripes(rectGripper);
		rectStripes.DeflateRect(3, 6);
		rectStripes.right = rectStripes.left + 2;
		pSkin2003->DrawGripperStripes(pDC, rectStripes, TRUE);

		// Draw the text
		CFont* pOldFont = pDC->SelectObject(&m_fontCaption);
		CString strBarTitle;
		pSizeControlBar->GetWindowText(strBarTitle);
		CRect rectText(rectGripper);
		rectText.OffsetRect(13, 2);

		// Crop the text if there are buttons
		CRect rectButton(0, 0, 0, 0);
		if (pSizeControlBar->IsResizeBtn())
			rectButton = pSizeControlBar->m_rectResizeBtn;
		else if (pSizeControlBar->IsCloseBtn())
			rectButton = pSizeControlBar->m_rectCloseBtn;
		if (!rectButton.IsRectEmpty())
		{
			rectButton.OffsetRect(ptOffset);
			rectText.right = rectButton.left - 1;			
		}

		int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
		pDC->DrawText(strBarTitle, &rectText,
			DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
		pDC->SetBkMode(iOldBkMode);
		pDC->SelectObject(pOldFont);
	}
}

void COXDockbarSkin2003::DrawSplitter(CDC* pDC, COXSplitterRect* pSplitterRect, COXSizeDockBar* pSizeDockBar)
{
    CRect rect(pSplitterRect->m_rect);

	CRect rectDockBar;
	pSizeDockBar->GetClientRect(rectDockBar);

	if (rect.bottom > 8000)
		rect.bottom = 8000;

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pDC->FillSolidRect(rect, pSkin2003->GetDockbarBackgroundColor());

	if (pSplitterRect->m_type == SPLITTER_VERT)
	{
		rect.left = pSplitterRect->m_rect.CenterPoint().x;
		rect.right = rect.left + 1;
	}
	else
	{
		rect.top = pSplitterRect->m_rect.CenterPoint().y;
		rect.bottom = rect.top + 1;
	}

	pDC->FillSolidRect(rect, pSkin2003->GetSplitterLineColor());

}

void COXDockbarSkin2003::DrawCloseButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsCloseBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// Determine the button rectangle
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rect = pSizeControlBar->m_rectCloseBtn;
	rect.OffsetRect(-rectWindow.left, -rectWindow.top);
	rect.InflateRect(1, 1, 2, 2);

	m_pSkinXP->DrawFrameButton(pDC, rect, DFCS_CAPTIONCLOSE, FALSE, FALSE,
		::GetSysColor(COLOR_3DFACE), pSizeControlBar);
}

void COXDockbarSkin2003::DrawResizeButton(CDC* pDC, COXSizeControlBar* pSizeControlBar)
{
    if(!pSizeControlBar->IsCloseBtn() || (pSizeControlBar->m_dwStyle & CBRS_FLOATING))
		return;

	// Determine the button rectangle
    CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	CRect rect = pSizeControlBar->m_rectResizeBtn;
	rect.OffsetRect(-rectWindow.left, -rectWindow.top);
	rect.InflateRect(1, 1, 2, 2);

	// Determine the flags
	UINT nState = pSizeControlBar->m_bMaximized ? DFCS_CAPTIONMIN : DFCS_CAPTIONMAX;
	BOOL bDisabled = !pSizeControlBar->CanResize();

	m_pSkinXP->DrawFrameButton(pDC, rect, nState, bDisabled, FALSE,
		::GetSysColor(COLOR_3DFACE), pSizeControlBar);
}

void COXDockbarSkin2003::RecalcLayout(COXSizeControlBar* pSizeControlBar)
{
	CRect rectWindow;
	pSizeControlBar->GetWindowRect(rectWindow);
	pSizeControlBar->ScreenToClient(rectWindow);
	pSizeControlBar->m_rectGripper = rectWindow;

	if(pSizeControlBar->IsGripper() && !(pSizeControlBar->m_dwStyle & CBRS_FLOATING))
	{
		if (pSizeControlBar->m_dwStyle & CBRS_ORIENT_HORZ) 
		{
			pSizeControlBar->m_rectGripper.DeflateRect(0, 2);

			pSizeControlBar->m_rectGripper.right = 
				pSizeControlBar->m_rectGripper.left + ID_O11_GRIPPER + ID_BUTTON_SIDE;
			
			if(pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn = pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.bottom = pSizeControlBar->m_rectCloseBtn.top + pSizeControlBar->m_rectCloseBtn.Width();
				pSizeControlBar->m_rectCloseBtn.DeflateRect(7, 7, 6, 6);
			}

			if(pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn = pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.bottom = pSizeControlBar->m_rectResizeBtn.top + pSizeControlBar->m_rectResizeBtn.Width();
				pSizeControlBar->m_rectResizeBtn.DeflateRect(7, 7, 6, 6);
				if (pSizeControlBar->IsCloseBtn())
					pSizeControlBar->m_rectResizeBtn.OffsetRect(0, pSizeControlBar->m_rectResizeBtn.Width() + 3);
			}
		} 
		else // vertical
		{
			pSizeControlBar->m_rectGripper.DeflateRect(2, 0);

			pSizeControlBar->m_rectGripper.bottom = 
				pSizeControlBar->m_rectGripper.top + ID_O11_GRIPPER + ID_BUTTON_SIDE;

			if (pSizeControlBar->IsCloseBtn())
			{
				pSizeControlBar->m_rectCloseBtn = pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectCloseBtn.left = pSizeControlBar->m_rectCloseBtn.right - pSizeControlBar->m_rectCloseBtn.Height();
				pSizeControlBar->m_rectCloseBtn.DeflateRect(7, 7, 6, 6);
			}

			if (pSizeControlBar->IsResizeBtn())
			{
				pSizeControlBar->m_rectResizeBtn = pSizeControlBar->m_rectGripper;
				pSizeControlBar->m_rectResizeBtn.left = pSizeControlBar->m_rectResizeBtn.right - pSizeControlBar->m_rectResizeBtn.Height();
				pSizeControlBar->m_rectResizeBtn.DeflateRect(7, 7, 6, 6);
				if (pSizeControlBar->IsCloseBtn())
					pSizeControlBar->m_rectResizeBtn.OffsetRect(-pSizeControlBar->m_rectResizeBtn.Width() - 3, 0);
			}
		}
	}

	pSizeControlBar->m_bDelayRecalcLayout=FALSE;
}

void COXDockbarSkin2003::OnNcPaintSizeDockBar(COXSizeDockBar* pSizeDockBar)
{
	CWindowDC dc(pSizeDockBar);
	CRect rectWindow;
	pSizeDockBar->GetWindowRect(rectWindow);
	CPoint ptOffset = rectWindow.TopLeft();
	rectWindow.OffsetRect(-ptOffset.x, -ptOffset.y);

	// Get the client rectangle in window coordionates
	CRect rectClient;
	pSizeDockBar->GetClientRect(rectClient);
	pSizeDockBar->ClientToScreen(rectClient);
	rectClient.OffsetRect(-ptOffset.x, -ptOffset.y);
	dc.ExcludeClipRect(rectClient);

	CRect rectMain;
	pSizeDockBar->GetParentFrame()->GetWindowRect(rectMain);

	// Get the dockbar screen rectangle
	CRect rectDockbar;
	pSizeDockBar->GetWindowRect(rectDockbar);

	int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
	if (iWidth < rectMain.Width())
		iWidth = rectMain.Width();

	CRect rectGradient;
	rectGradient.left = rectMain.left - rectDockbar.left;
	rectGradient.right = rectGradient.left + iWidth;
	rectGradient.top = 0;
	rectGradient.bottom = rectDockbar.Height();

	if (pSizeDockBar->GetFirstDockedSizeControlBar(NULL) != NULL)
	{
		dc.FillSolidRect(rectGradient, m_pSkinXP->GetDockbarBackgroundColor());
	}
	else
	{
		CRect rectSolid(rectGradient);
		rectGradient.right = rectGradient.CenterPoint().x;
		rectSolid.left = rectGradient.right;

		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		pSkin2003->GradientFill(&dc, rectGradient,
			pSkin2003->GetDockbarLeftColor(),
			pSkin2003->GetDockbarRightColor(),
			GRADIENT_FILL_RECT_H);
		dc.FillSolidRect(rectSolid, pSkin2003->GetDockbarRightColor());
	}
}


// COXStatusbarSkin
//


// COXStatusbarSkinClassic
//

void COXStatusbarSkinClassic::OnPaintStatusbar( COXStatusBar* pStatusBar )
{
	pStatusBar->Default();

	CClientDC DC(pStatusBar);
	pStatusBar->UpdateAllPanes(FALSE, TRUE);

	// Draw the text for each pane, and the window resize gripper
	DrawStatusBarPanes(&DC, pStatusBar );
	DrawFlatPanes(&DC, pStatusBar);

	for (int i=0; i < pStatusBar->GetCount(); i++)
	{
		AFX_STATUSPANE* pSBP=pStatusBar->_GetPanePtr(i);
		ASSERT(pSBP!=NULL);

		if (!(pSBP->nStyle & SBPS_DISABLED))
		{
			COXStatusBar::CBmpInfo* info=(COXStatusBar::CBmpInfo*)pStatusBar->m_PaneBmp[i];
			if(info != NULL)
				// This pane is a pane with a bitmap, so draw the bitmap
				pStatusBar->DrawStatusBmp(&DC, i, pSBP->nStyle);
		}
	}
}

// COXStatusbarSkinXP
//

COXStatusbarSkinXP::COXStatusbarSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
}

COXStatusbarSkinXP::~COXStatusbarSkinXP()
{
}

void COXStatusbarSkinXP::OnPaintStatusbar( COXStatusBar* pStatusBar )
{
	CPaintDC DC(pStatusBar);
	pStatusBar->UpdateAllPanes(FALSE, TRUE);

	// Draw the text for each pane, and the window resize gripper
	DrawStatusBarPanes(&DC, pStatusBar);
	DrawFlatPanes(&DC, pStatusBar);
	DrawGripper(&DC, pStatusBar);

	for (int i=0; i < pStatusBar->GetCount(); i++)
	{
		AFX_STATUSPANE* pSBP=pStatusBar->_GetPanePtr(i);
		ASSERT(pSBP!=NULL);

		if (!(pSBP->nStyle & SBPS_DISABLED))
		{
			COXStatusBar::CBmpInfo* info=(COXStatusBar::CBmpInfo*)pStatusBar->m_PaneBmp[i];
			if(info != NULL)
				// This pane is a pane with a bitmap, so draw the bitmap
				pStatusBar->DrawStatusBmp(&DC, i, pSBP->nStyle);
		}
	}
}

void COXStatusbarSkinXP::DrawStatusBarPanes(CDC* pDC, COXStatusBar* pStatusBar)
{
	// Draw the background of the entire status bar
	CRect rectClient;
	pStatusBar->GetClientRect(rectClient);
	pDC->FillSolidRect(rectClient, GetSysColor(COLOR_BTNFACE));

	DRAWITEMSTRUCT drawItemStruct;
	CRect rcItem;
	int cxWidth;
	UINT nID, nStyle;
	BYTE keyState[256];
	::GetKeyboardState( keyState );

	drawItemStruct.hDC = pDC->GetSafeHdc();

    for (int nIndex = 0; nIndex < pStatusBar->m_nCount; nIndex++)
    {
		pStatusBar->GetItemRect( nIndex, rcItem );
		pStatusBar->GetPaneInfo( nIndex, nID, nStyle, cxWidth );
		
		if (nIndex == pStatusBar->m_nCount - 1)
			rcItem.right = rcItem.left + cxWidth + 6;

		// prepare the background for each item on the statusbar
		switch( nID )
		{
		case ID_INDICATOR_CAPS:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_CAPITAL] & 1 );
			break;
		case ID_INDICATOR_NUM:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_NUMLOCK] & 1 );
			break;
		case ID_INDICATOR_SCRL:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_SCROLL] & 1 );
			break;
		default:
			// draw custom panes
			drawItemStruct.itemID = nIndex;
			drawItemStruct.rcItem = rcItem;
			pStatusBar->DrawItem( &drawItemStruct );
		}
	}
}

void COXStatusbarSkinXP::DrawPaneText( CDC *pDc, CRect rPane, COXStatusBar* pStatusBar, int nIndex, BOOL enabled )
{
	CFont *oldFont = pDc->SelectObject( pStatusBar->GetFont());

	if ( enabled == TRUE )
		pDc->SetTextColor( GetSysColor( COLOR_BTNTEXT ));
	else
		pDc->SetTextColor(m_pSkinXP->GetDisabledTextColor());

	pDc->SetBkMode( TRANSPARENT );
	pDc->DrawText( pStatusBar->GetPaneText( nIndex ), rPane, DT_CENTER|DT_VCENTER|DT_SINGLELINE );

	pDc->SelectObject( oldFont );
}

void COXStatusbarSkinXP::DrawFlatPanes(CDC* pDC, COXStatusBar* pStatusBar)
{
	CRect rcItem;
	CBrush brush;
	brush.CreateSolidBrush(m_pSkinXP->GetStatusPaneColor());
    for (int i = 0; i < pStatusBar->m_nCount; i++)
    {
		pStatusBar->GetItemRect(i, rcItem);
		if (i == pStatusBar->m_nCount - 1)
		{
			int cxWidth;
			UINT nID, nStyle;
			pStatusBar->GetPaneInfo(i, nID, nStyle, cxWidth );
			rcItem.right = rcItem.left + cxWidth + 6;
		}
		pDC->FrameRect(rcItem, &brush);
	}
}

void COXStatusbarSkinXP::DrawGripper(CDC* pDC, COXStatusBar* pStatusBar)
{
	CFrameWnd* pParentFrame = pStatusBar->GetParentFrame();
	if (pParentFrame != NULL && (pParentFrame->GetStyle() & WS_THICKFRAME) == 0)
		return; // we don't need a gripper since the thick frame style is not set
	
	if (pParentFrame != NULL && (pParentFrame->GetStyle() & WS_MAXIMIZE) != 0)
		return; // we don't need a gripper since the frame is maximized

	CRect rClient;
	pStatusBar->GetClientRect( rClient );
	int nSize = rClient.Height()%2 ? rClient.Height() - 1 : rClient.Height();
	// calculate the gripper area
	rClient.left = rClient.right - nSize;

	pDC->FillSolidRect(rClient, GetSysColor(COLOR_BTNFACE));

	// create the gray pen
	CPen grayPen( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ));
	CPen *oldPen = NULL;
	
	for ( int nIndex = 0; nIndex < nSize; nIndex += 3 )
	{
		oldPen = pDC->SelectObject( &grayPen );
		pDC->MoveTo( rClient.right - nIndex, rClient.bottom );
		pDC->LineTo( rClient.right, rClient.bottom - nIndex );

		nIndex ++;
		pDC->SelectObject( oldPen );
		(CPen*)pDC->SelectObject( ::GetStockObject( WHITE_PEN ));
		pDC->MoveTo( rClient.right - nIndex, rClient.bottom );
		pDC->LineTo( rClient.right, rClient.bottom - nIndex );

		oldPen = NULL;
	}
}

// COXStatusbarSkin2003
//

COXStatusbarSkin2003::COXStatusbarSkin2003(COXSkin2003* pSkin2003) :
	COXStatusbarSkinXP(pSkin2003)
{
}

COXStatusbarSkin2003::~COXStatusbarSkin2003()
{
}

void COXStatusbarSkin2003::DrawGradientBackground(CDC* pDC, LPCRECT lpRect)
{
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	CRect rectTop(lpRect);
	rectTop.bottom = rectTop.top + 3;
	pSkin2003->GradientFill(pDC, rectTop,
		pSkin2003->GetStatusbarTopColor(),
		pSkin2003->GetStatusbarMiddleColor(),
		GRADIENT_FILL_RECT_V);

	CRect rectBottom(lpRect);
	rectBottom.top = rectBottom.bottom - 5;
	pSkin2003->GradientFill(pDC, rectBottom,
		pSkin2003->GetStatusbarMiddleColor(),
		pSkin2003->GetStatusbarBottomColor(),
		GRADIENT_FILL_RECT_V);

	CRect rectMiddle(lpRect);
	rectMiddle.top = rectTop.bottom;
	rectMiddle.bottom = rectBottom.top;
	pDC->FillSolidRect(rectMiddle, pSkin2003->GetStatusbarMiddleColor());
}

void COXStatusbarSkin2003::DrawStatusBarPanes(CDC* pDC, COXStatusBar* pStatusBar)
{
	// Draw the background of the entire status bar
	CRect rectClient;
	pStatusBar->GetClientRect(rectClient);

	DrawGradientBackground(pDC, rectClient);

	DRAWITEMSTRUCT drawItemStruct;
	CRect rcItem;
	int cxWidth;
	UINT nID, nStyle;
	BYTE keyState[256];
	::GetKeyboardState( keyState );

	drawItemStruct.hDC = pDC->GetSafeHdc();

    for (int nIndex = 0; nIndex < pStatusBar->m_nCount; nIndex++)
    {
		pStatusBar->GetItemRect( nIndex, rcItem );
		pStatusBar->GetPaneInfo( nIndex, nID, nStyle, cxWidth );
		
		if (nIndex == pStatusBar->m_nCount - 1)
			rcItem.right = rcItem.left + cxWidth + 6;

		// prepare the background for each item on the statusbar
		switch( nID )
		{
		case ID_INDICATOR_CAPS:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_CAPITAL] & 1 );
			break;
		case ID_INDICATOR_NUM:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_NUMLOCK] & 1 );
			break;
		case ID_INDICATOR_SCRL:
			DrawPaneText( pDC, rcItem, pStatusBar, nIndex, keyState[VK_SCROLL] & 1 );
			break;
		default:
			// draw custom panes
			drawItemStruct.itemID = nIndex;
			drawItemStruct.rcItem = rcItem;
			pStatusBar->DrawItem( &drawItemStruct );
		}
	}
}

void COXStatusbarSkin2003::DrawGripper(CDC* pDC, COXStatusBar* pStatusBar)
{
	CFrameWnd* pParentFrame = pStatusBar->GetParentFrame();
	if (pParentFrame != NULL && (pParentFrame->GetStyle() & WS_THICKFRAME) == 0)
		return; // we don't need a gripper since the thick frame style is not set
	
	if (pParentFrame != NULL && (pParentFrame->GetStyle() & WS_MAXIMIZE) != 0)
		return; // we don't need a gripper since the frame is maximized

	CRect rClient;
	pStatusBar->GetClientRect( rClient );
	int nSize = rClient.Height()%2 ? rClient.Height() - 1 : rClient.Height();
	// calculate the gripper area
	rClient.left = rClient.right - nSize;

	CRect rectBackground(rClient);
	rectBackground.left += 3;
	DrawGradientBackground(pDC, rectBackground);

	// Draw the gripper
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			// Do not draw the top half
			if (i + j < 2)
				continue;

			CRect rectDot;
			rectDot.left = rClient.left + 7 + i * 4;
			rectDot.top = rClient.top + 7 + j * 4;
			rectDot.right = rectDot.left + 2;
			rectDot.bottom = rectDot.top + 2;

			pDC->FillSolidRect(rectDot,  pSkin2003->GetGripperStripesShadowColor());
			rectDot.OffsetRect(-1, -1);
			pDC->FillSolidRect(rectDot, pSkin2003->GetGripperColor());
		}
	}
}

void COXStatusbarSkin2003::DrawFlatPanes(CDC* pDC, COXStatusBar* pStatusBar)
{
	CRect rcItem;
    for (int i = 0; i < pStatusBar->m_nCount; i++)
    {
		pStatusBar->GetItemRect(i, rcItem);
		if (i == pStatusBar->m_nCount - 1)
		{
			int cxWidth;
			UINT nID, nStyle;
			pStatusBar->GetPaneInfo(i, nID, nStyle, cxWidth );
			rcItem.right = rcItem.left + cxWidth + 6;
		}

		rcItem.left = rcItem.right++;
		rcItem.DeflateRect(0, 2, 0, 2);
		pDC->FillSolidRect(rcItem,  m_pSkinXP->GetSeparatorColor());
		rcItem.OffsetRect(1, 1);
		pDC->FillSolidRect(rcItem,  RGB(255, 255, 255)); // This color is always white
	}
}

// COXFrameSkin
//


// COXFrameSkinClassic
//


// COXFrameSkinXP
//

COXFrameSkinXP::COXFrameSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
}

void COXFrameSkinXP::DrawViewBorder(CView* pView)
{
	CWindowDC dc(pView);
	CRect rectWindow;
	pView->GetWindowRect(rectWindow);
	CPoint ptOffset = rectWindow.TopLeft();
	rectWindow.OffsetRect(-ptOffset.x, -ptOffset.y);

	CBrush brush;
	brush.CreateSolidBrush(m_pSkinXP->GetBorderColor());
	dc.FrameRect(rectWindow, &brush);
}

void COXFrameSkinXP::OnNcCalcSizeView(LPARAM lParam, CView* /*pView*/)
{
	NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*) lParam;
	lpncsp->rgrc[0].left -= 1;
	lpncsp->rgrc[0].top -= 1;
	lpncsp->rgrc[0].right += 1;
	lpncsp->rgrc[0].bottom += 1;
}

// COXFrameSkin2003
//

COXFrameSkin2003::COXFrameSkin2003(COXSkin2003* pSkin2003) :
	COXFrameSkinXP(pSkin2003)
{
}

COLORREF COXFrameSkin2003::GetBackgroundColor()
{
	return m_pSkinXP->GetDockbarBackgroundColor();
}

COLORREF COXFrameSkin2003::GetBorderColor()
{
	return m_pSkinXP->GetBorderColor();
}

// COXTabSkin
//


// COXTabSkinClassic
//

void COXTabSkinClassic::OnPaintTabCtrl(CTabCtrl* pTabCtrl)
{
	COXSkinnedTabCtrl* pSkinnedTab = DYNAMIC_DOWNCAST(COXSkinnedTabCtrl, pTabCtrl);
	if (pSkinnedTab != NULL)
		pSkinnedTab->Default(); 

// Code to handle vertical orientation in XP themed mode

	if( IsThemed() && (pTabCtrl->GetStyle()&TCS_VERTICAL) )
	{
		int nTabCount = pTabCtrl->GetItemCount();
		int nSel = pTabCtrl->GetCurSel();
	
		DRAWITEMSTRUCT dis;
		dis.CtlType = ODT_TAB;
		dis.CtlID = pTabCtrl->GetDlgCtrlID();
		dis.hwndItem = pTabCtrl->GetSafeHwnd();
		dis.hDC = GetDC(dis.hwndItem);
		dis.itemAction = ODA_DRAWENTIRE;

		for ( int nIndex = 0; nIndex < nTabCount; nIndex++ )
		{			
			if (nIndex != nSel)
				dis.itemState = ODS_SELECTED;
			else
				dis.itemState = 0;
			
			dis.itemID = nIndex;
			
			pTabCtrl->GetItemRect(nIndex, &dis.rcItem);	

			RECT r2 = dis.rcItem;
			int ht = r2.bottom - r2.top;

			TCHAR buf[255];
			TCITEM tabItem;
			tabItem.mask = TCIF_TEXT|TCIF_IMAGE;
			tabItem.pszText = buf;
			tabItem.cchTextMax = sizeof( buf );
			pTabCtrl->GetItem( nIndex, &tabItem );
			CString tempStr( tabItem.pszText );
			
			if ((tabItem.mask & TCIF_IMAGE) && tabItem.iImage >= 0)
			{
				CImageList* pImage = pTabCtrl->GetImageList();
				if ( pImage != NULL )
				{					
					IMAGEINFO iInfo;
					pImage->GetImageInfo( tabItem.iImage, &iInfo );						
					
					if( pTabCtrl->GetStyle()&TCS_BOTTOM )
						ht -= 10;
					else
						ht -= iInfo.rcImage.bottom - iInfo.rcImage.top + 10;
															
				}
			}

			r2.top += ht;
			r2.bottom += ht;

			//////////////////////////////////////////////////////////////////
			// v9.3 update 02 - the NONCLIENTMETRICS struct is an int larger 
			// on Vista vs XP (iPaddedBorderWidth added). Code compiled for 
			// WINVER 0x0600 will fail the call to SystemParametersInfo on XP.
			// Code compiled for XP should still run on Vista.

			int ncmSize = sizeof( NONCLIENTMETRICS );

#			if WINVER >= 0x0600
			// compiled for Vista - check for OS version
			OSVERSIONINFO vi={ sizeof(OSVERSIONINFO) };
			ASSERT(GetVersionEx(&vi));
			if(vi.dwMajorVersion < 6) {
				// running on lesser version - adjust size of NONCLIENTMETRICS struct
				ncmSize -= sizeof( int );
			}
#			endif

			NONCLIENTMETRICS nclim={ ncmSize };
			VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncmSize, &nclim, 0));
			// end NONCLIENTMETRICS mods v9.3 update 02
			/////////////////////////////////////////////////

			::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
				sizeof(NONCLIENTMETRICS),&nclim,0);
			LOGFONT lf = nclim.lfMenuFont;			
			lf.lfEscapement = 900;			 
			HFONT hf = CreateFontIndirect(&lf);

			HFONT oldf = (HFONT)SelectObject(dis.hDC,(HGDIOBJ)hf);
			SetBkMode(dis.hDC, TRANSPARENT);
			DrawText(dis.hDC,tempStr,-1,&r2,DT_NOCLIP);
			SelectObject(dis.hDC,(HGDIOBJ)oldf);
			DeleteObject(hf);			
		}
		
		ReleaseDC(dis.hwndItem,dis.hDC);
	}

// End of custom code to handle XP themed mode and vertical orientation

};

void COXTabSkinClassic::DrawMDITabBorder(CDC* pDC, LPCRECT lpRect, COXTabWorkspace* /*pTabWorkspace*/)
{
	pDC->Draw3dRect(lpRect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHILIGHT));
}

// COXTabSkinXP
//

// predefined margin size
#define TAB_MARGIN 3

COXTabSkinXP::COXTabSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;

	m_sepPen.CreatePen( PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW) );

	//////////////////////////////////////////////////////////////////
	// v9.3 update 02 - the NONCLIENTMETRICS struct is an int larger 
	// on Vista vs XP (iPaddedBorderWidth added). Code compiled for 
	// WINVER 0x0600 will fail the call to SystemParametersInfo on XP.
	// Code compiled for XP should still run on Vista.

	int ncmSize = sizeof( NONCLIENTMETRICS );

#	if WINVER >= 0x0600
	// compiled for Vista - check for OS version
	OSVERSIONINFO vi={ sizeof(OSVERSIONINFO) };
	ASSERT(GetVersionEx(&vi));
	if(vi.dwMajorVersion < 6) {
		// running on lesser version - adjust size of NONCLIENTMETRICS struct
		ncmSize -= sizeof( int );
	}
#	endif

	NONCLIENTMETRICS nclim={ ncmSize };
	VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncmSize, &nclim, 0));
	// end NONCLIENTMETRICS mods v9.3 update 02
	/////////////////////////////////////////////////

	m_tabFont.CreateFontIndirect(&nclim.lfMenuFont);

	m_btnFill.CreateSolidBrush( m_pSkinXP->GetInactiveTabTextColor() );
	m_btnLine.CreatePen( PS_SOLID, 1, m_pSkinXP->GetInactiveTabTextColor() );
}

void COXTabSkinXP::DrawMDITabBorder(CDC* pDC, LPCRECT lpRect, COXTabWorkspace* /*pTabWorkspace*/)
{
	pDC->Draw3dRect(lpRect, m_pSkinXP->GetBorderColor(),m_pSkinXP->GetBorderColor());
}

void COXTabSkinXP::OnNcPaintTabClient(COXTabClientWnd* pTabClient)
{
	pTabClient->Default();
	
	CWindowDC dc(pTabClient);
	CRect rectWindow;
	pTabClient->GetWindowRect(rectWindow);
	CPoint ptOffset = rectWindow.TopLeft();
	rectWindow.OffsetRect(-ptOffset.x, -ptOffset.y);

	// Get the client rectangle in window coordionates
	CRect rectClient;
	pTabClient->GetClientRect(rectClient);
	pTabClient->ClientToScreen(rectClient);
	rectClient.OffsetRect(-ptOffset.x, -ptOffset.y);
	dc.ExcludeClipRect(rectClient);

	// Draw the border
	CBrush brBorder;
	brBorder.CreateSolidBrush(::GetSysColor(COLOR_3DFACE));
	dc.FrameRect(rectWindow, &brBorder);
	CBrush brBackground;
	brBackground.CreateSolidBrush(::GetSysColor(COLOR_3DDKSHADOW));
	rectWindow.DeflateRect(1, 1);
	dc.FrameRect(rectWindow, &brBackground);
}

void COXTabSkinXP::OnPaintTabCtrl(CTabCtrl* pTabCtrl)
{
	CPaintDC dc(pTabCtrl); // device context for painting
	// retrieve the client area size info
	CRect clientRect;
	pTabCtrl->GetClientRect(&clientRect);
	// create and initialize memory DC to draw on
	CDC memDc, itemMemDc;
	CBitmap bmpMem, bmpItemMem, *pOldItemMemBmp, *pOldMemBmp;
	bmpMem.CreateCompatibleBitmap( &dc, clientRect.right, clientRect.bottom );
	bmpItemMem.CreateCompatibleBitmap( &dc, clientRect.Width(), clientRect.Height());
	// create memory DC fot the entire tab control
	memDc.CreateCompatibleDC( &dc );
	pOldMemBmp = memDc.SelectObject( &bmpMem );
	// create memory DC for each item to draw on
	itemMemDc.CreateCompatibleDC( &dc );
	pOldItemMemBmp = itemMemDc.SelectObject( &bmpItemMem );

	// check if we have already subclassed the up-down control
	COXSkinnedSpinCtrl* pUpDown = GetSpinCtrl(pTabCtrl);
	if (pUpDown != NULL && pUpDown->GetSafeHwnd() == NULL )
	{
		// we have not, check if it was created by looping through all client windows
		int intnRet;
		CRect upDnRect;
		CWnd* pWnd = pTabCtrl->GetWindow(GW_CHILD);

		while(pWnd)
		{
			TCHAR buf[] = _T("msctls_updown32");
			intnRet= ::GetClassName(pWnd->m_hWnd,buf,sizeof(buf)/sizeof(buf[0]));
			if( _tcscmp(buf, _T("msctls_updown32")) != 0 )
			{
				pWnd=pWnd->GetWindow(GW_HWNDNEXT);
			}
			else
			{ 
				//The msctls_updown32 control isfound.
				//
				//Subclass common msctls_updown32 control
				pUpDown->SubclassWindow(pWnd->m_hWnd);

				pWnd=0;
			}
		}
	}

	// draw background of the entire control
	DrawBackground(&memDc, clientRect, pTabCtrl);
	
	// Draw the tab work area
	CRect rPage( clientRect );
	pTabCtrl->AdjustRect(FALSE, rPage);

	// Draw a border around the child window
	CRect rectChild;
	COX3DTabViewContainer* p3DTVC = DYNAMIC_DOWNCAST(COX3DTabViewContainer, pTabCtrl);
	if (p3DTVC != NULL)
	{
		rectChild = p3DTVC->m_rectPage;
		rectChild.InflateRect(1, 1);
	}
	else
	{
		rectChild = rPage;
		rectChild.bottom -= 1;
	}

	CBrush brushBorder;
	brushBorder.CreateSolidBrush(::GetSysColor(COLOR_3DSHADOW));
	memDc.FrameRect(rectChild, &brushBorder);
	
	// draw the solid line above the work area
	if ( pTabCtrl->GetRowCount() <= 1 )
	{
		if ( pTabCtrl->GetStyle()&TCS_BOTTOM )
		{
			// draw background for the button area
			memDc.FillSolidRect( clientRect.left, rPage.bottom + TAB_MARGIN,
							  clientRect.right, clientRect.bottom,
							  m_pSkinXP->GetTabButtonsBackgroundColor());
			// draw a separator line
			memDc.SelectObject( ::GetStockObject( BLACK_PEN ));
			memDc.MoveTo( clientRect.left, rPage.bottom + TAB_MARGIN - 1 );
			memDc.LineTo( clientRect.right, rPage.bottom + TAB_MARGIN - 1 );
		}
		else
		{
			// draw background for the button area
			memDc.FillSolidRect( clientRect.left, clientRect.top,
							  clientRect.right, rPage.top - TAB_MARGIN,
							  m_pSkinXP->GetTabButtonsBackgroundColor());
			// draw a separator line
			memDc.SelectObject( ::GetStockObject( WHITE_PEN ));
			memDc.MoveTo( clientRect.left, rPage.top - TAB_MARGIN );
			memDc.LineTo( clientRect.right, rPage.top - TAB_MARGIN );
		}
	}

	// also paint the tabs
	int nTabCount = pTabCtrl->GetItemCount();
	int nSel = pTabCtrl->GetCurSel();

	// the tab control does not contain any items
	if ( nTabCount == 0 )
	{
		memDc.SelectObject( pOldMemBmp );
		itemMemDc.SelectObject( pOldItemMemBmp );
		return;
	}

	// Draw individual tab items
	DRAWITEMSTRUCT dis;
	dis.CtlType = ODT_TAB;
	dis.CtlID = pTabCtrl->GetDlgCtrlID();
	dis.hwndItem = pTabCtrl->GetSafeHwnd();
	dis.hDC = itemMemDc.GetSafeHdc();
	dis.itemAction = ODA_DRAWENTIRE;

	for ( int nIndex = 0; nIndex < nTabCount; nIndex++ )
	{
		// initialize the draw item structure for each of the tabs
		if (nIndex != nSel)
		{
			dis.itemID = nIndex;
			dis.itemState = 0;
			pTabCtrl->GetItemRect(nIndex, &dis.rcItem);
			DrawItem(&dis, pTabCtrl);
			DrawItemBorder(&dis, pTabCtrl);

			if ( AdjustItemRect( nIndex, &dis.rcItem, pTabCtrl ))
			{
				int width = dis.rcItem.right - dis.rcItem.left;
				int height = dis.rcItem.bottom - dis.rcItem.top;
				//Copy drawing from memory device context to the screen
				memDc.BitBlt( dis.rcItem.left,dis.rcItem.top,width,
					height,&itemMemDc,dis.rcItem.left,dis.rcItem.top,SRCCOPY);
			}
		}
	}

	// draw the selected item
	dis.itemID = nSel;
	dis.itemState = ODS_SELECTED;
	pTabCtrl->GetItemRect(nSel, &dis.rcItem);
	DrawItem(&dis, pTabCtrl);
	DrawItemBorder(&dis, pTabCtrl);

	if ( AdjustItemRect( nSel, &dis.rcItem, pTabCtrl ))
	{
		int width = dis.rcItem.right - dis.rcItem.left;
		int height = dis.rcItem.bottom - dis.rcItem.top;
		//Copy drawing from memory device context to the screen
		memDc.BitBlt( dis.rcItem.left,dis.rcItem.top,width,
			height,&itemMemDc,dis.rcItem.left,dis.rcItem.top,SRCCOPY);
	}

	//Copy drawing from memory device context to the screen
	dc.BitBlt( clientRect.left, clientRect.top, clientRect.Width(),
			   clientRect.Height(), &memDc,
			   clientRect.left, clientRect.top, SRCCOPY);

	// a final clean up
	memDc.SelectObject( pOldMemBmp );
	itemMemDc.SelectObject( pOldItemMemBmp );

	// make sure that the spin control is also redrawn
	if (pUpDown != NULL && pUpDown->GetSafeHwnd() != NULL )
		if ( pUpDown->IsWindowVisible())
			pUpDown->Invalidate();
}

void COXTabSkinXP::DrawBackground(CDC* pDC, LPCRECT lpRect, CTabCtrl* /*pTabCtrl*/)
{
	pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_3DFACE));
}

void COXTabSkinXP::AdjustChildItemRect(LPRECT pRectChild, int iInflateValue, CTabCtrl* pTabCtrl)
{
	// Determine which side the tabs are on

	const int iMinMargin = 8;

	CRect rectClient;
	pTabCtrl->GetClientRect(rectClient);
	if (rectClient.IsRectEmpty())
		return;
	CRect rectItem(rectClient);
	pTabCtrl->AdjustRect(FALSE, rectItem);

	CRect rectMargins;
	rectMargins.left = rectItem.left - rectClient.left;
	rectMargins.top = rectItem.top - rectClient.top;
	rectMargins.right = rectClient.right - rectItem.right;
	rectMargins.bottom =  rectClient.bottom - rectItem.bottom;

	// Check each of the 4 sides and if we do not have buttons inflate it
	if (rectMargins.left < iMinMargin)
		pRectChild->left -= iInflateValue;
	if (rectMargins.top < iMinMargin)
		pRectChild->top -= iInflateValue;
	if (rectMargins.right < iMinMargin)
		pRectChild->right += iInflateValue;
	if (rectMargins.bottom < iMinMargin)
		pRectChild->bottom += iInflateValue;
}

void COXTabSkinXP::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct, CTabCtrl* pTabCtrl)
{
	CDC dc;
	dc.Attach( lpDrawItemStruct->hDC );
	CRect rcItem = lpDrawItemStruct->rcItem;

	if ( lpDrawItemStruct->itemState == ODS_SELECTED )
	{
		dc.FillSolidRect(&rcItem, ::GetSysColor(COLOR_3DFACE));
		dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
	}
	else
	{
		dc.FillSolidRect(&rcItem, m_pSkinXP->GetTabButtonsBackgroundColor());
		dc.SetTextColor(m_pSkinXP->GetInactiveTabTextColor());
	}

	TCHAR buf[255];
	TCITEM tabItem;
	//Get text of item.
	tabItem.mask = TCIF_TEXT|TCIF_IMAGE;
	tabItem.pszText = buf;
	tabItem.cchTextMax = sizeof( buf );
	pTabCtrl->GetItem( lpDrawItemStruct->itemID, &tabItem );
	CString tempStr( tabItem.pszText );

	rcItem.top += 3;

	// draw the icon
	if ((tabItem.mask & TCIF_IMAGE) && tabItem.iImage >= 0)
	{
		CImageList* pImage = pTabCtrl->GetImageList();
		if ( pImage != NULL )
		{
			// get information about the icon to draw
			IMAGEINFO iInfo;
			pImage->GetImageInfo( tabItem.iImage, &iInfo );
			// calculate the statring point for the image to be drawn, try to vertically center
			CPoint ptStart( rcItem.left + 3, rcItem.top - 1 );

			pImage->Draw( &dc, tabItem.iImage, ptStart, ILD_TRANSPARENT );

			// reduce the rectangle by the size of the image
			rcItem.left += ( iInfo.rcImage.right - iInfo.rcImage.left ) + 3;
		}
	}

	// draw the tab's text
	CFont *pOldFont = dc.SelectObject( &m_tabFont );
	dc.DrawText( tempStr, &rcItem, DT_CENTER );
	dc.SelectObject( pOldFont );
	rcItem.top -= 3;

	// draw focus rectangle
	if ( lpDrawItemStruct->itemState == ODS_SELECTED &&
		 ( pTabCtrl->GetStyle()&TCS_FOCUSNEVER) == 0 )
	{
		CRect rect( rcItem );
		rect.DeflateRect( 2, 2 );
		dc.DrawFocusRect( rect );
	}

	dc.Detach();
}

void COXTabSkinXP::DrawItemBorder(LPDRAWITEMSTRUCT lpDrawItemStruct, CTabCtrl* pTabCtrl)
{
	CDC dc;
	dc.Attach( lpDrawItemStruct->hDC );

	if ( pTabCtrl->GetStyle()&TCS_BOTTOM )
	{
		if ( lpDrawItemStruct->itemState == ODS_SELECTED )
		{
			// draw the white line (on the left)
			dc.SelectObject( GetStockObject( WHITE_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
			dc.LineTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
			dc.SelectObject( GetStockObject( BLACK_PEN ));
			// draw the bottom
			dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
			// draw the black outline on right
			dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top );
			dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 1 );
		}
		else// draw the inactive button
		{
			if ( IsNextButtonSelected(lpDrawItemStruct->itemID, pTabCtrl) == FALSE )
			{	// draw the separators between the bottons
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top + 3 );
				dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 3 );
				dc.SelectObject( pOldBrush );
			}

			// determine the position of this button in relation to the child window
			// it is important to know if the button is in the bottom or top and in which
			// row of tabs
			CRect rPage;
			pTabCtrl->GetClientRect( rPage );
			pTabCtrl->AdjustRect( FALSE, rPage );

			int nPosDifference = lpDrawItemStruct->rcItem.top - rPage.bottom;
			// Question 1, is the tab on top or bottom
			if ( nPosDifference > TAB_MARGIN )
			{	// the tab is on top, in a row other than the immediate below the client area
				// draw the separator line at the top of the item
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
				dc.SelectObject( pOldBrush );
			}
			else if ( nPosDifference >= 0 )
			{	// the tab is on top
				// draw the black line at the top
				dc.SelectObject( GetStockObject( BLACK_PEN ));
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
			}
			else
			{	// the tab is on the of the window
				// draw the separator line at the bottom of the item
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.SelectObject( pOldBrush );
			}
		}
	}
	else
	{
		if ( lpDrawItemStruct->itemState == ODS_SELECTED )
		{
			// draw the white line (on the left)
			dc.SelectObject( GetStockObject( WHITE_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
			dc.LineTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
			// draw the top
			dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
			// draw the black outline on right
			dc.SelectObject( GetStockObject( BLACK_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top + 1 );
			dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 1 );
		}
		else// draw the inactive button
		{
			if ( IsNextButtonSelected(lpDrawItemStruct->itemID, pTabCtrl) == FALSE )
			{
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top + 3 );
				dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 3 );
				dc.SelectObject( pOldBrush );
			}

			// determine the position of this button in relation to the child window
			// it is important to know if the button is in the bottom or top and in which
			// row of tabs
			CRect rPage;
			pTabCtrl->GetClientRect( rPage );
			pTabCtrl->AdjustRect( FALSE, rPage );

			int nPosDifference = rPage.top - lpDrawItemStruct->rcItem.top;
			// Question 1, is the tab on top or bottom
			if ( nPosDifference > ( lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top + TAB_MARGIN ))
			{	// the tab is on top, in a row other than the immediate above the client area
				// draw the white line at the bottom
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.SelectObject( pOldBrush );
			}
			else if ( nPosDifference > 0 )
			{	// the tab is on top
				// draw the white line at the bottom
				dc.SelectObject( GetStockObject( WHITE_PEN ));
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
			}
			else
			{	// the tab is on the bottom
				// draw the separator line above
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
				dc.SelectObject( pOldBrush );
			}
		}
	}

	dc.Detach();
}

// COXTabSkin2003
//

COXTabSkin2003::COXTabSkin2003(COXSkin2003* pSkin2003) :
	COXTabSkinXP(pSkin2003)
{

}

COXTabSkin2003::~COXTabSkin2003()
{
}

void COXTabSkin2003::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct, CTabCtrl* pTabCtrl)
{
	CDC dc;
	dc.Attach( lpDrawItemStruct->hDC );
	CRect rcItem = lpDrawItemStruct->rcItem;

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	if (lpDrawItemStruct->itemState == ODS_SELECTED)
	{
		if (pTabCtrl->GetStyle() & TCS_BOTTOM)
			pSkin2003->GradientFill(&dc, rcItem,
				pSkin2003->GetTabItemDarkColor(),
				pSkin2003->GetTabItemLightColor(),
				GRADIENT_FILL_RECT_V);
		else
			pSkin2003->GradientFill(&dc, rcItem,
				 pSkin2003->GetTabItemLightColor(),
				 pSkin2003->GetTabItemDarkColor(),
				GRADIENT_FILL_RECT_V);

		dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
	}
	else
	{
		if (pTabCtrl->GetStyle() & TCS_BOTTOM)
			pSkin2003->GradientFill(&dc, rcItem,
				pSkin2003->GetTabBackgroundLightColor(),
				pSkin2003->GetTabBackgroundDarkColor(),
				GRADIENT_FILL_RECT_V);
		else
			pSkin2003->GradientFill(&dc, rcItem,
				pSkin2003->GetTabBackgroundDarkColor(),
				pSkin2003->GetTabBackgroundLightColor(),
				GRADIENT_FILL_RECT_V);

		dc.SetTextColor(m_pSkinXP->GetInactiveTabTextColor());
	}

	TCHAR buf[255];
	TCITEM tabItem;
	//Get text of item.
	tabItem.mask = TCIF_TEXT|TCIF_IMAGE;
	tabItem.pszText = buf;
	tabItem.cchTextMax = sizeof( buf );
	pTabCtrl->GetItem( lpDrawItemStruct->itemID, &tabItem );
	CString tempStr( tabItem.pszText );

	rcItem.top += 3;

	// draw the icon
	if ((tabItem.mask & TCIF_IMAGE) && tabItem.iImage >= 0)
	{
		CImageList* pImage = pTabCtrl->GetImageList();
		if ( pImage != NULL )
		{
			// get information about the icon to draw
			IMAGEINFO iInfo;
			pImage->GetImageInfo( tabItem.iImage, &iInfo );
			// calculate the statring point for the image to be drawn, try to vertically center
			CPoint ptStart( rcItem.left + 3, rcItem.top - 1 );

			pImage->Draw( &dc, tabItem.iImage, ptStart, ILD_TRANSPARENT );

			// reduce the rectangle by the size of the image
			rcItem.left += ( iInfo.rcImage.right - iInfo.rcImage.left ) + 3;
		}
	}

	// draw the tab's text
	CFont *pOldFont = dc.SelectObject( &m_tabFont );
	int iOldMode = dc.SetBkMode(TRANSPARENT);
	dc.DrawText( tempStr, &rcItem, DT_CENTER );
	dc.SetBkMode(iOldMode);
	dc.SelectObject( pOldFont );
	rcItem.top -= 3;

	// draw focus rectangle
	if ( lpDrawItemStruct->itemState == ODS_SELECTED &&
		 ( pTabCtrl->GetStyle()&TCS_FOCUSNEVER) == 0 )
	{
		CRect rect( rcItem );
		rect.DeflateRect( 2, 2 );
		dc.DrawFocusRect( rect );
	}

	dc.Detach();
}

void COXTabSkin2003::DrawBackground(CDC* pDC, LPCRECT lpRect, CTabCtrl* /*pTabCtrl*/)
{
	pDC->FillSolidRect(lpRect, m_pSkinXP->GetDockbarBackgroundColor());
}

void COXTabSkin2003::OnPaintTabCtrl(CTabCtrl* pTabCtrl)
{
	CPaintDC dc(pTabCtrl); // device context for painting
	// retrieve the client area size info
	CRect clientRect;
	pTabCtrl->GetClientRect(&clientRect);
	// create and initialize memory DC to draw on
	CDC memDc, itemMemDc;
	CBitmap bmpMem, bmpItemMem, *pOldItemMemBmp, *pOldMemBmp;
	bmpMem.CreateCompatibleBitmap( &dc, clientRect.right, clientRect.bottom );
	bmpItemMem.CreateCompatibleBitmap( &dc, clientRect.Width(), clientRect.Height());
	// create memory DC fot the entire tab control
	memDc.CreateCompatibleDC( &dc );
	pOldMemBmp = memDc.SelectObject( &bmpMem );
	// create memory DC for each item to draw on
	itemMemDc.CreateCompatibleDC( &dc );
	pOldItemMemBmp = itemMemDc.SelectObject( &bmpItemMem );

	// check if we have alredy subclassed the up-down control
	COXSkinnedSpinCtrl* pUpDown = GetSpinCtrl(pTabCtrl);
	if (pUpDown != NULL && pUpDown->GetSafeHwnd() == NULL )
	{
		// we have not, check if it was created by looping through all client windows
		int intnRet;
		CRect upDnRect;
		CWnd* pWnd = pTabCtrl->GetWindow(GW_CHILD);

		while(pWnd)
		{
			TCHAR buf[] = _T("msctls_updown32");
			intnRet= ::GetClassName(pWnd->m_hWnd,buf,sizeof(buf)/sizeof(buf[0]));
			if( _tcscmp(buf, _T("msctls_updown32")) != 0 )
			{
				pWnd=pWnd->GetWindow(GW_HWNDNEXT);
			}
			else
			{ 
				//The msctls_updown32 control isfound.
				//
				//Subclass common msctls_updown32 control
				pUpDown->SubclassWindow(pWnd->m_hWnd);

				pWnd=0;
			}
		}
	}

	// draw background of the entire control
	DrawBackground(&memDc, clientRect, pTabCtrl);
	
	// Draw the tab work area
	CRect rPage( clientRect );
	pTabCtrl->AdjustRect(FALSE, rPage);

	// Draw a border around the child window
	CRect rectChild;
	COX3DTabViewContainer* p3DTVC = DYNAMIC_DOWNCAST(COX3DTabViewContainer, pTabCtrl);
	if (p3DTVC != NULL)
	{
		rectChild = p3DTVC->m_rectPage;
		rectChild.InflateRect(1, 1);
	}
	else
	{
		rectChild = rPage;
		rectChild.bottom -= 1;
	}

	CBrush brushBorder;
	brushBorder.CreateSolidBrush(::GetSysColor(COLOR_3DSHADOW));
	memDc.FrameRect(rectChild, &brushBorder);
	
	// draw the solid line above the work area
	if ( pTabCtrl->GetRowCount() <= 1 )
	{
		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		if ( pTabCtrl->GetStyle()&TCS_BOTTOM )
		{
			// draw background for the button area
			pSkin2003->GradientFill(&memDc, CRect(clientRect.left, rPage.bottom + TAB_MARGIN,
							  clientRect.right, clientRect.bottom),
				pSkin2003->GetTabBackgroundLightColor(),
				pSkin2003->GetTabBackgroundDarkColor(),
				GRADIENT_FILL_RECT_V);

			// draw a separator line
			memDc.SelectObject( ::GetStockObject( BLACK_PEN ));
			memDc.MoveTo( clientRect.left, rPage.bottom + TAB_MARGIN - 1 );
			memDc.LineTo( clientRect.right, rPage.bottom + TAB_MARGIN - 1 );
		}
		else
		{
			// draw background for the button area
			pSkin2003->GradientFill(&memDc, CRect(clientRect.left, clientRect.top,
							  clientRect.right, rPage.top - TAB_MARGIN),
				pSkin2003->GetTabBackgroundDarkColor(),
				pSkin2003->GetTabBackgroundLightColor(),
				GRADIENT_FILL_RECT_V);

			// draw a separator line
			memDc.SelectObject( ::GetStockObject( WHITE_PEN ));
			memDc.MoveTo( clientRect.left, rPage.top - TAB_MARGIN );
			memDc.LineTo( clientRect.right, rPage.top - TAB_MARGIN );
		}
	}

	// also paint the tabs
	int nTabCount = pTabCtrl->GetItemCount();
	int nSel = pTabCtrl->GetCurSel();

	// the tab control does not contain any items
	if ( nTabCount == 0 )
	{
		memDc.SelectObject( pOldMemBmp );
		itemMemDc.SelectObject( pOldItemMemBmp );
		return;
	}

	// Draw individual tab items
	DRAWITEMSTRUCT dis;
	dis.CtlType = ODT_TAB;
	dis.CtlID = pTabCtrl->GetDlgCtrlID();
	dis.hwndItem = pTabCtrl->GetSafeHwnd();
	dis.hDC = itemMemDc.GetSafeHdc();
	dis.itemAction = ODA_DRAWENTIRE;

	for ( int nIndex = 0; nIndex < nTabCount; nIndex++ )
	{
		// initialize the draw item structure for each of the tabs
		if (nIndex != nSel)
		{
			dis.itemID = nIndex;
			dis.itemState = 0;
			pTabCtrl->GetItemRect(nIndex, &dis.rcItem);
			DrawItem(&dis, pTabCtrl);
			DrawItemBorder(&dis, pTabCtrl);

			if ( AdjustItemRect( nIndex, &dis.rcItem, pTabCtrl ))
			{
				int width = dis.rcItem.right - dis.rcItem.left;
				int height = dis.rcItem.bottom - dis.rcItem.top;
				//Copy drawing from memory device context to the screen
				memDc.BitBlt( dis.rcItem.left,dis.rcItem.top,width,
					height,&itemMemDc,dis.rcItem.left,dis.rcItem.top,SRCCOPY);
			}
		}
	}

	// draw the selected item
	dis.itemID = nSel;
	dis.itemState = ODS_SELECTED;
	pTabCtrl->GetItemRect(nSel, &dis.rcItem);
	DrawItem(&dis, pTabCtrl);
	DrawItemBorder(&dis, pTabCtrl);

	if ( AdjustItemRect( nSel, &dis.rcItem, pTabCtrl ))
	{
		int width = dis.rcItem.right - dis.rcItem.left;
		int height = dis.rcItem.bottom - dis.rcItem.top;
		//Copy drawing from memory device context to the screen
		memDc.BitBlt( dis.rcItem.left,dis.rcItem.top,width,
			height,&itemMemDc,dis.rcItem.left,dis.rcItem.top,SRCCOPY);
	}

	//Copy drawing from memory device context to the screen
	dc.BitBlt( clientRect.left, clientRect.top, clientRect.Width(),
			   clientRect.Height(), &memDc,
			   clientRect.left, clientRect.top, SRCCOPY);

	// a final clean up
	memDc.SelectObject( pOldMemBmp );
	itemMemDc.SelectObject( pOldItemMemBmp );

	// make sure that the spin control is also redrawn
	if (pUpDown != NULL && pUpDown->GetSafeHwnd() != NULL )
		if ( pUpDown->IsWindowVisible())
			pUpDown->Invalidate();
}

void COXTabSkin2003::DrawItemBorder(LPDRAWITEMSTRUCT lpDrawItemStruct, CTabCtrl* pTabCtrl)
{
	CDC dc;
	dc.Attach( lpDrawItemStruct->hDC );

	if ( pTabCtrl->GetStyle()&TCS_BOTTOM )
	{
		if ( lpDrawItemStruct->itemState == ODS_SELECTED )
		{
			// draw the white line (on the left)
			dc.SelectObject( GetStockObject( WHITE_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
			dc.LineTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
			dc.SelectObject( GetStockObject( BLACK_PEN ));
			// draw the bottom
			dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
			// draw the black outline on right
			dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top );
			dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 1 );
		}
		else// draw the inactive button
		{
			if ( IsNextButtonSelected(lpDrawItemStruct->itemID, pTabCtrl) == FALSE )
			{	// draw the separators between the bottons
				CRect rectSep(lpDrawItemStruct->rcItem.right - 1,
					lpDrawItemStruct->rcItem.top + 3,
					lpDrawItemStruct->rcItem.right,
					lpDrawItemStruct->rcItem.bottom - 3);

				dc.FillSolidRect(rectSep,  m_pSkinXP->GetBorderColor());
			}

			// determine the position of this button in relation to the child window
			// it is important to know if the button is in the bottom or top and in which
			// row of tabs
			CRect rPage;
			pTabCtrl->GetClientRect( rPage );
			pTabCtrl->AdjustRect( FALSE, rPage );

			int nPosDifference = lpDrawItemStruct->rcItem.top - rPage.bottom;
			// Question 1, is the tab on top or bottom
			if ( nPosDifference > TAB_MARGIN )
			{	// the tab is on top, in a row other than the immediate below the client area
				// draw the separator line at the top of the item
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
				dc.SelectObject( pOldBrush );
			}
			else if ( nPosDifference >= 0 )
			{	// the tab is on top
				// draw the black line at the top
				dc.SelectObject( GetStockObject( BLACK_PEN ));
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
			}
			else
			{	// the tab is on the of the window
				// draw the separator line at the bottom of the item
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.SelectObject( pOldBrush );
			}
		}
	}
	else
	{
		if ( lpDrawItemStruct->itemState == ODS_SELECTED )
		{
			// draw the white line (on the left)
			dc.SelectObject( GetStockObject( WHITE_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
			dc.LineTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
			// draw the top
			dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
			// draw the black outline on right
			dc.SelectObject( GetStockObject( BLACK_PEN ));
			dc.MoveTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.top + 1 );
			dc.LineTo( lpDrawItemStruct->rcItem.right - 1, lpDrawItemStruct->rcItem.bottom - 1 );
		}
		else// draw the inactive button
		{
			if ( IsNextButtonSelected(lpDrawItemStruct->itemID, pTabCtrl) == FALSE )
			{
				CRect rectSep(lpDrawItemStruct->rcItem.right - 1,
					lpDrawItemStruct->rcItem.top + 3,
					lpDrawItemStruct->rcItem.right,
					lpDrawItemStruct->rcItem.bottom - 3);

				dc.FillSolidRect(rectSep,  m_pSkinXP->GetBorderColor());
			}

			// determine the position of this button in relation to the child window
			// it is important to know if the button is in the bottom or top and in which
			// row of tabs
			CRect rPage;
			pTabCtrl->GetClientRect( rPage );
			pTabCtrl->AdjustRect( FALSE, rPage );

			int nPosDifference = rPage.top - lpDrawItemStruct->rcItem.top;
			// Question 1, is the tab on top or bottom
			if ( nPosDifference > ( lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top + TAB_MARGIN ))
			{	// the tab is on top, in a row other than the immediate above the client area
				// draw the white line at the bottom
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.SelectObject( pOldBrush );
			}
			else if ( nPosDifference > 0 )
			{	// the tab is on top
				// draw the white line at the bottom
				dc.SelectObject( GetStockObject( WHITE_PEN ));
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - 1 );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom - 1 );
			}
			else
			{	// the tab is on the bottom
				// draw the separator line above
				CPen *pOldBrush = dc.SelectObject( &m_sepPen );
				dc.MoveTo( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
				dc.LineTo( lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.top );
				dc.SelectObject( pOldBrush );
			}
		}
	}

	dc.Detach();
}

void COXTabSkin2003::OnPaintSpinCtrl(COXSkinnedSpinCtrl* pSpinCtrl)
{
	CPaintDC dc(pSpinCtrl); // device context for painting
	// retrieve the client area size info
	CRect clientRect;
	pSpinCtrl->GetClientRect( clientRect );
	// create and initialize memory DC to draw on
	CDC itemMemDc;
	CBitmap bmpMem,*pOldItemMemBmp;
	itemMemDc.CreateCompatibleDC( &dc );
	bmpMem.CreateCompatibleBitmap( &dc,clientRect.Width(), clientRect.Height());
	pOldItemMemBmp = itemMemDc.SelectObject( &bmpMem );

	// Draw the background
	
	CTabCtrl* pTabCtrl = (CTabCtrl*) pSpinCtrl->GetParent();
	CRect rectClient;
	pTabCtrl->GetWindowRect(&rectClient);
	CRect rectPage(rectClient);
	pTabCtrl->AdjustRect(FALSE, rectPage);
	pSpinCtrl->ScreenToClient(rectClient);
	pSpinCtrl->ScreenToClient(rectPage);

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	if (pTabCtrl->GetStyle() & TCS_BOTTOM)
	{
		// draw background for the button area
		pSkin2003->GradientFill(&itemMemDc, CRect(rectClient.left, rectPage.top + TAB_MARGIN,
						  rectClient.right, rectClient.bottom),
			pSkin2003->GetTabBackgroundLightColor(),
			pSkin2003->GetTabBackgroundDarkColor(),
			GRADIENT_FILL_RECT_V);
	}
	else
	{
		// draw background for the button area
		pSkin2003->GradientFill(&itemMemDc, CRect(rectClient.left, rectClient.top,
						  rectClient.right, rectPage.top),
			pSkin2003->GetTabBackgroundDarkColor(),
			pSkin2003->GetTabBackgroundLightColor(),
			GRADIENT_FILL_RECT_V);
	}

	// adjust the rect to provide extended border
	if (!( pTabCtrl->GetStyle()&TCS_BOTTOM ))
		clientRect.top += 2;
	else
		clientRect.bottom -= 2;

	clientRect.left += 2;
	clientRect.right -= 2;

	// calculate the sizes of the buttons
	int midPoint = ( clientRect.right - clientRect.left ) / 2;
	int btnWidth = midPoint - 1;
	CRect downRect( clientRect.left, clientRect.top, clientRect.left + btnWidth, clientRect.bottom );
	CRect upRect( midPoint, clientRect.top, midPoint + btnWidth, clientRect.bottom );

	DrawDownArrow(&itemMemDc, downRect, pSpinCtrl);
	DrawUpArrow(&itemMemDc, upRect, pSpinCtrl);

	CPoint mousePos;
	::GetCursorPos( &mousePos );
	pSpinCtrl->ScreenToClient( &mousePos );

	int lower, upper;
	pSpinCtrl->GetRange32( lower, upper );
	// draw frame
	if ( upRect.PtInRect( mousePos ) && LOWORD(pSpinCtrl->GetPos()) != upper )
	{
		DrawArrowBorder(&itemMemDc, upRect, pSpinCtrl);
	}
	else if ( downRect.PtInRect( mousePos ) && LOWORD(pSpinCtrl->GetPos()) != 0 )
	{
		DrawArrowBorder(&itemMemDc, downRect, pSpinCtrl);
	}
	//Copy drawing from memory device context to the screen
	dc.BitBlt( clientRect.left,clientRect.top,clientRect.Width(),
		clientRect.Height(),&itemMemDc,clientRect.left,clientRect.top,SRCCOPY);
	// a final clean up
	itemMemDc.SelectObject( pOldItemMemBmp );
}

// This function returns a pointer to the spin control of a tab container
COXSkinnedSpinCtrl* COXTabSkinXP::GetSpinCtrl(CTabCtrl* pTabContainer)
{
	COXSkinnedTabCtrl* pSkinnedTabCtrl = DYNAMIC_DOWNCAST(COXSkinnedTabCtrl, pTabContainer);
	if (pSkinnedTabCtrl != NULL)
		return &pSkinnedTabCtrl->m_updown;

	return NULL;
}

void COXTabSkinXP::OnPaintSpinCtrl(COXSkinnedSpinCtrl* pSpinCtrl)
{
	CPaintDC dc(pSpinCtrl); // device context for painting
	// retrieve the client area size info
	CRect clientRect;
	pSpinCtrl->GetClientRect( clientRect );
	// create and initialize memory DC to draw on
	CDC itemMemDc;
	CBitmap bmpMem,*pOldItemMemBmp;
	itemMemDc.CreateCompatibleDC( &dc );
	bmpMem.CreateCompatibleBitmap( &dc,clientRect.Width(), clientRect.Height());
	pOldItemMemBmp = itemMemDc.SelectObject( &bmpMem );

	// clear the background
	itemMemDc.FillSolidRect( clientRect,  m_pSkinXP->GetTabButtonsBackgroundColor() );
	// adjust the rect to provide extended border
	if (!( pSpinCtrl->GetParent()->GetStyle()&TCS_BOTTOM ))
		clientRect.top += 2;
	else
		clientRect.bottom -= 2;

	clientRect.left += 2;
	clientRect.right -= 2;

	// calculate the sizes of the buttons
	int midPoint = ( clientRect.right - clientRect.left ) / 2;
	int btnWidth = midPoint - 1;
	CRect downRect( clientRect.left, clientRect.top, clientRect.left + btnWidth, clientRect.bottom );
	CRect upRect( midPoint, clientRect.top, midPoint + btnWidth, clientRect.bottom );

	DrawDownArrow(&itemMemDc, downRect, pSpinCtrl);
	DrawUpArrow(&itemMemDc, upRect, pSpinCtrl);

	CPoint mousePos;
	::GetCursorPos( &mousePos );
	pSpinCtrl->ScreenToClient( &mousePos );

	int lower, upper;
	pSpinCtrl->GetRange32( lower, upper );
	// draw frame
	if ( upRect.PtInRect( mousePos ) && LOWORD(pSpinCtrl->GetPos()) != upper )
	{
		DrawArrowBorder(&itemMemDc, upRect, pSpinCtrl);
	}
	else if ( downRect.PtInRect( mousePos ) && LOWORD(pSpinCtrl->GetPos()) != 0 )
	{
		DrawArrowBorder(&itemMemDc, downRect, pSpinCtrl);
	}
	//Copy drawing from memory device context to the screen
	dc.BitBlt( clientRect.left,clientRect.top,clientRect.Width(),
		clientRect.Height(),&itemMemDc,clientRect.left,clientRect.top,SRCCOPY);
	// a final clean up
	itemMemDc.SelectObject( pOldItemMemBmp );
}

void COXTabSkinXP::DrawDownArrow(CDC* pDc, CRect btnRect, COXSkinnedSpinCtrl* pSpinCtrl)
{
	CBrush *pOldBrush = NULL;
	CPen *pOldPen = pDc->SelectObject( &m_btnLine );

	if ( LOWORD(pSpinCtrl->GetPos()) != 0 )
		pOldBrush = pDc->SelectObject( &m_btnFill );

	// draw the down arrow
	CSize arrowSize( 4, 8 );
	CPoint points[4];
	int xMargin = ( btnRect.right - btnRect.left - arrowSize.cx ) / 2;
	int yMargin = ( btnRect.bottom - btnRect.top - arrowSize.cy ) / 2;
	int midPoint = btnRect.top + yMargin + ( arrowSize.cy / 2 );
	points[0].x = btnRect.left + xMargin;
	points[0].y = midPoint - 1;
	points[1].x = btnRect.left + xMargin + arrowSize.cx;
	points[1].y = btnRect.top + yMargin - 1;
	points[2].x = btnRect.left + xMargin + arrowSize.cx;
	points[2].y = btnRect.top + yMargin + arrowSize.cy - 1;
	points[3].x = btnRect.left + xMargin;
	points[3].y = midPoint - 1;

	pDc->Polygon( points, 4 );

	// clean up
	if ( pOldBrush != NULL )
		pDc->SelectObject( pOldBrush );

	pDc->SelectObject( pOldPen );
}

void COXTabSkinXP::DrawUpArrow(CDC* pDc, CRect btnRect, COXSkinnedSpinCtrl* pSpinCtrl)
{
	int lower, upper;
	pSpinCtrl->GetRange32( lower, upper );
	CBrush *pOldBrush = NULL;
	CPen *pOldPen = pDc->SelectObject( &m_btnLine );

	if ( LOWORD(pSpinCtrl->GetPos()) != upper )
		pOldBrush = pDc->SelectObject( &m_btnFill );

	// draw the down arrow
	CSize arrowSize( 4, 8 );
	CPoint points[4];
	int xMargin = ( btnRect.right - btnRect.left - arrowSize.cx ) / 2;
	int yMargin = ( btnRect.bottom - btnRect.top - arrowSize.cy ) / 2;
	int midPoint = btnRect.top + yMargin + ( arrowSize.cy / 2 );
	points[0].x = btnRect.left + xMargin + arrowSize.cx;
	points[0].y = midPoint - 1;
	points[1].x = btnRect.left + xMargin;
	points[1].y = btnRect.top + yMargin - 1;
	points[2].x = btnRect.left + xMargin;
	points[2].y = btnRect.top + yMargin + arrowSize.cy - 1;
	points[3].x = btnRect.left + xMargin + arrowSize.cx;
	points[3].y = midPoint - 1;

	pDc->Polygon( points, 4 );

	// clean up
	if ( pOldBrush != NULL )
		pDc->SelectObject( pOldBrush );

	pDc->SelectObject( pOldPen );
}

// this function will get the proper rect for a tab, and it will check if it
// overlaps the up-down control.  If it does than the tab's rect will be adjusted.
BOOL COXTabSkinXP::AdjustItemRect(int /*nIndex*/, RECT *tabRect, CTabCtrl* pTabCtrl)
{
	// before drawing item, check if it overlaps the spin control
	COXSkinnedSpinCtrl* pUpDown = GetSpinCtrl(pTabCtrl);
	if (pUpDown != NULL && pUpDown->GetSafeHwnd() != NULL )
	{
		if ( pUpDown->IsWindowVisible())
		{
			CRect spinRect, tabclientRect;
			pUpDown->GetClientRect( spinRect );
			pTabCtrl->GetClientRect( tabclientRect );

			if ( tabRect->left > ( tabclientRect.right - spinRect.Width()))
				return FALSE;

			if ( tabRect->right <= ( tabclientRect.left + TAB_MARGIN ))
				return FALSE;

			if ( tabRect->right > ( tabclientRect.right - spinRect.Width()))
				// the right edge of the tab button extends over the up-down control
				tabRect->right = tabclientRect.right - spinRect.Width();
		}
	}
	
	return TRUE;
}

BOOL COXTabSkinXP::IsNextButtonSelected(int nItemID, CTabCtrl* pTabCtrl)
{
	int nCount = pTabCtrl->GetItemCount();

	if ( nItemID < nCount - 1 )
	{
		if ( pTabCtrl->GetItemState( nItemID + 1, TCIS_BUTTONPRESSED ) == TCIS_BUTTONPRESSED )
			return TRUE;
	}
	return FALSE;
}

void COXTabSkinXP::DrawArrowBorder(CDC* pDc, CRect btnRect, COXSkinnedSpinCtrl* /*pSpinCtrl*/)
{
	btnRect.DeflateRect( 1, 1 );

	if ( GetKeyState( VK_LBUTTON ) < 0 )
	{
		// 0,0,0
		pDc->SelectObject( GetStockObject( BLACK_PEN ));
		pDc->MoveTo( btnRect.left, btnRect.bottom );
		pDc->LineTo( btnRect.left, btnRect.top );
		pDc->LineTo( btnRect.right, btnRect.top );
		// 241,239,226
		pDc->SelectObject( GetStockObject( WHITE_PEN ));
		pDc->LineTo( btnRect.right, btnRect.bottom );
		pDc->LineTo( btnRect.left, btnRect.bottom );
	}
	else
	{
		// 241,239,226
		pDc->SelectObject( GetStockObject( WHITE_PEN ));
		pDc->MoveTo( btnRect.left, btnRect.bottom );
		pDc->LineTo( btnRect.left, btnRect.top );
		pDc->LineTo( btnRect.right, btnRect.top );
		// 0,0,0
		pDc->SelectObject( GetStockObject( BLACK_PEN ));
		pDc->LineTo( btnRect.right, btnRect.bottom );
		pDc->LineTo( btnRect.left, btnRect.bottom );
	}
}


// COXMenuSkin
//


// COXMenuSkinClassic
//

#include "OXBitmapMenu.h"
#include "OXBitmapMenuOrganizer.h"

COXMenuSkinClassic::COXMenuSkinClassic()
{
	// Initialize the dimension constants structure
	m_DimensionConstants.m_nGapLeftBitmap = 2;
	m_DimensionConstants.m_nGapBitmapText = 8;	
	m_DimensionConstants.m_nGapTextAcclrtr = 2;	
	m_DimensionConstants.m_nGapAcclrtrRight = 3;
	m_DimensionConstants.m_nGapVertText = 4;	
	m_DimensionConstants.m_nGapVertBitmap = 3;
	m_DimensionConstants.m_nSeparatorHeight = ID_OXBITMAPMENU_SEPARATOR_HEIGHT;
	m_DimensionConstants.m_nMinBitmapWidth = 0;
	m_DimensionConstants.m_nGapMenuItems = 12;
}

void COXMenuSkinClassic::DistributeSpace(UINT /*nState*/, COXImageInfo* pImageInfo, LPRECT lpItemRect,
										 CRect& rectButton, CRect& rectImage, CRect& rectText1,
										 CRect& rectText2, COXBitmapMenu* pBitmapMenu)
{
	CRect rectItem(lpItemRect);
	OXDIMENSIONCONSTANTS& oxdc = GetDimentionConstants();

	// Compute the image and button rectangle
	if(pImageInfo != NULL)
	{
		// Get the actual bitmap rect
		IMAGEINFO ii;
		::ZeroMemory(&ii, sizeof(ii));
		pImageInfo->GetImageList()->GetImageInfo(pImageInfo->GetIndex(), &ii);
		
		// Center it vertically in the item rect
		CRect bitmapRect= ii.rcImage;
		bitmapRect -= bitmapRect.TopLeft();
		int nVertGap=(rectItem.Height() - bitmapRect.Height()) / 2;

		ASSERT(bitmapRect.Width() <= rectItem.Width());

		rectImage=bitmapRect;
		rectImage += rectItem.TopLeft();
		rectImage += CPoint(oxdc.m_nGapLeftBitmap, nVertGap);

		// Compute the button rectangle
		rectButton=rectImage;
		rectButton.InflateRect(2, 2);
	}

	// Compute the rectangle for the text in front of the tab 
	rectText1=rectItem;
	rectText1.left=oxdc.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + oxdc.m_nGapBitmapText;
	rectText1.right=rectText1.left + pBitmapMenu->m_nStringExtent;

	// Compute the rectangle for the text after the tab (shortcut key)
	rectText2=rectItem;
	rectText2.right -= oxdc.m_nGapAcclrtrRight;
	rectText2.left=rectText2.right - pBitmapMenu->m_nAcceleratorExtent;
	int nGapTextHorz=(rectText2.left - rectText1.right) / 2;
	rectText2 -= CPoint(nGapTextHorz, 0);

	// Center the text vertically
	int nGapTextVert=(rectItem.Height() - pBitmapMenu->m_nTextHeight) / 2;
	rectText1.InflateRect(0, -nGapTextVert);
	rectText2.top=rectText1.top;
	rectText2.bottom=rectText1.bottom;
}

void COXMenuSkinClassic::DrawBackground(CDC* pDC, UINT nState, COXImageInfo* pImageInfo, LPRECT lpItemRect, LPRECT lpButtonRect, COXBitmapMenu* pBitmapMenu)
{
	CRect itemRect(lpItemRect);
	CRect buttonRect(lpButtonRect);

	BOOL bSelected=nState & ODS_SELECTED;
	BOOL bChecked=nState & ODS_CHECKED;
	BOOL bHidden=nState & OXODS_HIDDEN;

	COLORREF clrBackground=::GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU); 

	if((bHidden && !pImageInfo->IsDefaultImgList()) || (bChecked && !bSelected))
	{
		HBRUSH hBrush=pBitmapMenu->HBrushDitherCreate(::GetSysColor(COLOR_MENU),
			::GetSysColor(COLOR_BTNHIGHLIGHT));
		if(hBrush!=NULL)
		{
			::FillRect(pDC->GetSafeHdc(),buttonRect,hBrush);
			::DeleteObject((HGDIOBJ)hBrush);
		}
	}
	else
	{
		// Draw the image on a special background depending on selection, 
		// check state and Default image or not
		COLORREF clrBtnBackground=::GetSysColor(bSelected ? 
			(bChecked ? COLOR_MENU : (pImageInfo->IsDefaultImgList() ? 
			COLOR_HIGHLIGHT : COLOR_MENU)) : 
			(bChecked ? COLOR_3DHILIGHT : COLOR_MENU)); 
		pDC->FillSolidRect(&buttonRect, clrBtnBackground);
	}

	if(!bHidden || bSelected)
	{
		itemRect.left=__max(buttonRect.right, m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + 
			(!bChecked ? (pImageInfo->IsDefaultImgList() ? -1 : 1) : 2));
		itemRect.bottom -= 1;
		CBrush brush;
		brush.CreateSolidBrush(clrBackground);
		pDC->FillRect(&itemRect,&brush);
	}
	else
	{
		HBRUSH hBrush=pBitmapMenu->HBrushDitherCreate(::GetSysColor(COLOR_MENU),
			::GetSysColor(COLOR_BTNHIGHLIGHT));
		if(hBrush!=NULL)
		{
			::FillRect(pDC->GetSafeHdc(),itemRect,hBrush);
			::DeleteObject((HGDIOBJ)hBrush);
		}
	}

	if(bHidden && !bSelected)
	{
		if(nState & OXODS_HIDDENFIRST)
		{
			CPen pen(PS_SOLID,1,::GetSysColor(COLOR_3DSHADOW));
			CPen* pOldPen=pDC->SelectObject(&pen);
			pDC->MoveTo(itemRect.TopLeft());
			pDC->LineTo(itemRect.right,itemRect.top);
			pDC->SelectObject(pOldPen);
		}

		if(nState & OXODS_HIDDENLAST)
		{
			CPen pen(PS_SOLID,1,::GetSysColor(COLOR_3DHILIGHT));
			CPen* pOldPen=pDC->SelectObject(&pen);
			pDC->MoveTo(itemRect.left,itemRect.bottom-1);
			pDC->LineTo(itemRect.right,itemRect.bottom-1);
			pDC->SelectObject(pOldPen);
		}
	}
}

void COXMenuSkinClassic::DrawButton(CDC* pDC, UINT nState,  COXImageInfo* pImageInfo, LPRECT lpButtonRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	BOOL bSelected=nState & ODS_SELECTED;
	BOOL bDisabled=nState & ODS_DISABLED;
	BOOL bChecked=nState & ODS_CHECKED;

	// Draw edge around the image according to the state of the item
	// (The background has already been filled with the right color)
	if(bSelected && !bDisabled && !bChecked && !pImageInfo->IsDefaultImgList())
	{
		pDC->DrawEdge(lpButtonRect, BDR_RAISEDINNER, BF_RECT);
	}
	else if(bChecked)
	{
		pDC->DrawEdge(lpButtonRect, BDR_SUNKENOUTER, BF_RECT);
	}
}

void COXMenuSkinClassic::DrawImage(CDC* pDC, UINT nState, COXImageInfo* pImageInfo, LPRECT lpImageRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect imageRect(lpImageRect);

	BOOL bDisabled=nState & ODS_DISABLED;
	BOOL bChecked=nState & ODS_CHECKED;
	BOOL bSelected=nState & ODS_SELECTED;

	if(pImageInfo->IsDefaultImgList() && !bChecked)
	{
		// The default checkmark is not drawn when it isn't checked
		return;
	}

	int nIndex=pImageInfo->GetIndex();
	if(bSelected && pImageInfo->GetHotIndex()!=-1)
	{
		nIndex=pImageInfo->GetHotIndex();
	}

	if(!bDisabled)
	{
		pImageInfo->GetImageList()->Draw(pDC, nIndex, 
			imageRect.TopLeft(), ILD_NORMAL|ILD_TRANSPARENT); 
	}
	else
	{
		HICON hIcon=pImageInfo->GetImageList()->ExtractIcon(nIndex);
		pDC->DrawState(
			imageRect.TopLeft(),imageRect.Size(),hIcon,DSS_DISABLED,(HBRUSH)NULL);
		VERIFY(::DestroyIcon(hIcon));
	}
}

void COXMenuSkinClassic::DrawText(CDC* pDC, UINT nState, LPCTSTR lpszText, LPRECT lpText1Rect, LPRECT lpText2Rect, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect text1Rect(lpText1Rect);
	CRect text2Rect(lpText2Rect);

	BOOL bSelected=nState & ODS_SELECTED;
	BOOL bDisabled=nState & ODS_DISABLED;

	// Split the text (in front of and after the tab)
	CString sText(lpszText);
	int nTabCharIndex=sText.Find(_T('\t'));
	CString sAfterTab;
	CString sBeforeTab;
	if(nTabCharIndex != -1)
	{
		sBeforeTab=sText.Left(nTabCharIndex);
		sAfterTab=sText.Mid(nTabCharIndex + 1);
	}
	else
	{
		sBeforeTab=sText;
		ASSERT(sAfterTab.IsEmpty());
	}

	// Draw the text
	// Sets the foreground color of the text based on its selection state
	COLORREF clrForeground=::GetSysColor(bDisabled ? COLOR_GRAYTEXT : 
		(bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); 
	COLORREF clrOldForeground=pDC->SetTextColor(clrForeground);

	// set background filling mode
	int nOldBkMode=pDC->SetBkMode(TRANSPARENT);

	UINT nFlags=0;
	CRect newText2Rect(0,0,0,0);
	int nHorzAlign=0;
	if(bDisabled && !bSelected)
		nFlags |= DSS_DISABLED;

	pDC->DrawState(text1Rect.TopLeft(), text1Rect.Size(), sBeforeTab.GetBuffer(0),
		nFlags, TRUE, sBeforeTab.GetLength(), (CBrush*)NULL);

	// ... First calculate text width so we can right-align it
	pDC->DrawText(sAfterTab, newText2Rect, DT_CALCRECT | DT_SINGLELINE);
	nHorzAlign=text2Rect.Width() - newText2Rect.Width();
	if(!sAfterTab.IsEmpty())
	{
		pDC->DrawState(text2Rect.TopLeft() + CPoint(nHorzAlign, 0), 
			newText2Rect.Size(), sAfterTab.GetBuffer(0),
			nFlags, TRUE, sAfterTab.GetLength(), (CBrush*)NULL);
	}

	pDC->SetTextColor(clrOldForeground); 
	pDC->SetBkMode(nOldBkMode);
}

void COXMenuSkinClassic::DrawSeparator(CDC* pDC, LPRECT lpItemRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect itemRect(lpItemRect);
	ASSERT(pDC!=NULL);
	itemRect.DeflateRect(2,0);
	itemRect.top+=itemRect.Height()/2-1;
	itemRect.bottom=itemRect.top+2;
	pDC->Draw3dRect(itemRect,::GetSysColor(COLOR_BTNSHADOW),
		::GetSysColor(COLOR_BTNHILIGHT));
}

void COXMenuSkinClassic::DrawCustomized(CDC* pDC, LPRECT lpItemRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	ASSERT(pDC!=NULL);
	pDC->DrawDragRect(lpItemRect,CSize(2,2),CRect(0,0,0,0),CSize(0,0),NULL,NULL);
}

void COXMenuSkinClassic::DrawInsertMark(CDC* pDC, LPRECT lpItemRect, BOOL bBefore, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect itemRect(lpItemRect);
	itemRect.DeflateRect(2,0);

	ASSERT(pDC!=NULL);
	if(bBefore)
	{
		itemRect.top-=2;
		itemRect.bottom=itemRect.top+3;
	}
	else
	{
		itemRect.bottom+=1;
		itemRect.top=itemRect.bottom-3;
	}

	pDC->MoveTo(itemRect.TopLeft());
	pDC->LineTo(itemRect.left+1,itemRect.top+1);
	pDC->LineTo(itemRect.right-1,itemRect.top+1);
	pDC->LineTo(itemRect.right,itemRect.top);
	pDC->LineTo(itemRect.right,itemRect.bottom);
	pDC->LineTo(itemRect.right-1,itemRect.bottom-1);
	pDC->LineTo(itemRect.left+1,itemRect.bottom-1);
	pDC->LineTo(itemRect.left,itemRect.bottom);
	pDC->LineTo(itemRect.TopLeft());
}

void COXMenuSkinClassic::DrawSubmenuItem(CDC* pDC, UINT nState, LPCTSTR lpszText, COXImageInfo* pImageInfo, 
									LPRECT lpItemRect, LPRECT lpButtonRect, LPRECT lpText1Rect, LPRECT lpText2Rect, COXBitmapMenu* pBitmapMenu)
{
	ASSERT(pDC!=NULL);
	pBitmapMenu->DrawBackground(pDC,nState,pImageInfo,lpItemRect,lpButtonRect);

	if(pBitmapMenu->IsInCustomizationMode())
	{
		// draw right aligned arrow
		//
		COLORREF clrShadow=::GetSysColor(COLOR_BTNSHADOW);
		CFont font;
		CFont* pOldFont=NULL;
		if((font.CreateFont(GetSystemMetrics(SM_CYMENUCHECK), 0, 0, 0, 
			FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET, 0,0,0,0, _T("Marlett"))) != NULL)
		{
			pOldFont=(CFont*)pDC->SelectObject(&font);
		}
		int nOldBkMode=pDC->SetBkMode(TRANSPARENT);
		COLORREF oldTextColor=CLR_NONE;
		if((nState&ODS_DISABLED)==ODS_DISABLED)
		{
			oldTextColor=pDC->SetTextColor(clrShadow);
		}
		// draw arrow symbol
		pDC->DrawText(_T("8"),lpText2Rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
		if((nState&ODS_DISABLED)==ODS_DISABLED)
		{
			pDC->SetTextColor(oldTextColor);
		}
		pDC->SetBkMode(nOldBkMode);
		if(pOldFont != NULL)
		{
			pDC->SelectObject(pOldFont);
		}
		//
		//////////////////////////////
	}

	DrawText(pDC,nState,lpszText,lpText1Rect,lpText2Rect,pBitmapMenu);
}

LRESULT COXMenuSkinClassic::MenuPopupWndProc(WNDPROC origWndProc, HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	// Call the default
	return ::CallWindowProc(origWndProc, hWnd, nMsg, wParam, lParam);
}

void COXMenuSkinClassic::DrawExpansionItem(CDC* pDC, LPRECT lpItemRect, UINT nState, COXBitmapMenu* /*pBitmapMenu*/)
{
	ASSERT(pDC!=NULL);

	BOOL bSelected=nState & ODS_SELECTED;
	BOOL bDisabled=nState & ODS_DISABLED;

	CFont font;
	VERIFY(font.CreateFont(GetSystemMetrics(SM_CYMENUCHECK),0,0,0,
		FW_NORMAL,0,0,0,SYMBOL_CHARSET,0,0,0,0,_T("Marlett")));
	CFont* pOldFont=pDC->SelectObject(&font);
	int nOldBkMode=pDC->SetBkMode(TRANSPARENT);
	COLORREF clrText=::GetSysColor(bDisabled ? COLOR_GRAYTEXT : 
		(bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); 
	COLORREF oldTextColor=pDC->SetTextColor(clrText);

	pDC->DrawText(_T("6"),lpItemRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);

	pDC->SetTextColor(oldTextColor);
	pDC->SetBkMode(nOldBkMode);
	pDC->SelectObject(pOldFont);
}

// COXMenuSkinXP
//

COXMenuSkinXP::COXMenuSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;

	// Initialize the dimension constants structure
	m_DimensionConstants.m_nGapLeftBitmap = 3;
	m_DimensionConstants.m_nGapRightBitmap = 5;
	m_DimensionConstants.m_nGapBitmapText = 15;	
	m_DimensionConstants.m_nGapTextAcclrtr = 12;	
	m_DimensionConstants.m_nGapAcclrtrRight = 6;
	m_DimensionConstants.m_nGapVertText = 10;	
	m_DimensionConstants.m_nGapVertBitmap = 4;
	m_DimensionConstants.m_nSeparatorHeight = 3;
	m_DimensionConstants.m_nMinBitmapWidth = 16;
	m_DimensionConstants.m_nGapMenuItems = 16;
}

COXMenuSkinXP::~COXMenuSkinXP()
{
	m_mapHWNDtoPos.RemoveAll();
}

void COXMenuSkinXP::DistributeSpace(UINT /*nState*/, COXImageInfo* pImageInfo, LPRECT lpItemRect,
										 CRect& rectButton, CRect& rectImage, CRect& rectText1,
										 CRect& rectText2, COXBitmapMenu* pBitmapMenu)
{
	CRect rectItem(lpItemRect);
	OXDIMENSIONCONSTANTS& oxdc = GetDimentionConstants();

	// Compute the image and button rectangle
	if(pImageInfo != NULL)
	{
		// Get the actual bitmap rect
		IMAGEINFO ii;
		::ZeroMemory(&ii, sizeof(ii));
		pImageInfo->GetImageList()->GetImageInfo(pImageInfo->GetIndex(), &ii);
		
		// Center it vertically in the item rect
		CRect bitmapRect= ii.rcImage;
		bitmapRect -= bitmapRect.TopLeft();
		int nVertGap=(rectItem.Height() - bitmapRect.Height()) / 2;

		ASSERT(bitmapRect.Width() <= rectItem.Width());

		rectImage=bitmapRect;
		rectImage += rectItem.TopLeft();
		rectImage += CPoint(oxdc.m_nGapLeftBitmap, nVertGap);

		// Compute the button rectangle
		rectButton = rectImage;
		rectButton.left = rectItem.left + 1;
		rectButton.top = rectItem.top + 1;
		rectButton.bottom = rectItem.bottom - 1;
		rectButton.right = rectButton.left + pBitmapMenu->m_nBitmapExtent + 4;
		if (pImageInfo->IsDefaultImgList())
		{
			// This is a check box
			// The image rectangle needs to be in the middle of the button
			int iHorizontalDiff = rectButton.Width() - rectImage.Width();
			rectImage.OffsetRect(iHorizontalDiff / 2 - 1, 0);
		}
	}

	// Compute the rectangle for the text in front of the tab 
	rectText1=rectItem;
	rectText1.left=oxdc.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + oxdc.m_nGapBitmapText;
	rectText1.right=rectText1.left + pBitmapMenu->m_nStringExtent;

	// Compute the rectangle for the text after the tab (shortcut key)
	rectText2=rectItem;
	rectText2.right -= oxdc.m_nGapAcclrtrRight;
	rectText2.left=rectText2.right - pBitmapMenu->m_nAcceleratorExtent;
	int nGapTextHorz=(rectText2.left - rectText1.right) / 2;
	rectText2 -= CPoint(nGapTextHorz, 0);

	// Center the text vertically
	int nGapTextVert=(rectItem.Height() - pBitmapMenu->m_nTextHeight) / 2;
	rectText1.InflateRect(0, -nGapTextVert);
	rectText2.top=rectText1.top;
	rectText2.bottom=rectText1.bottom;
}

void COXMenuSkinXP::DrawBackground(CDC* pDC, UINT nState, COXImageInfo* /*pImageInfo*/, LPRECT lpItemRect, LPRECT /*lpButtonRect*/, COXBitmapMenu* pBitmapMenu)
{
	bool bSelected = (nState & ODS_SELECTED) != 0;
	bool bHidden = (nState & OXODS_HIDDEN) != 0;
	bool bDisabled = (nState & ODS_DISABLED) != 0;

	if(bSelected && !bDisabled)
	{
		// Selected item
		CPen pen;
		pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
		CBrush brush;
		brush.CreateSolidBrush(m_pSkinXP->GetHotItemColor());

		CPen* pOldPen = pDC->SelectObject(&pen);
		CBrush* pOldBrush = pDC->SelectObject(&brush);
		pDC->Rectangle(lpItemRect);
		pDC->SelectObject(pOldBrush);
		pDC->SelectObject(pOldPen);
	}
	else
	{
		// Normal item
		CBrush brushFace;
		brushFace.CreateSolidBrush(m_pSkinXP->GetMenuFaceColor());
		pDC->FillRect(lpItemRect, &brushFace);

		CBrush brushIconArea;
		if (bHidden)
			brushIconArea.CreateSolidBrush(m_pSkinXP->GetHiddenItemBackgroundColor());
		else
			brushIconArea.CreateSolidBrush(m_pSkinXP->GetBackgroundColor());
		CRect rectIconArea(lpItemRect);
		rectIconArea.right = m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapRightBitmap;
		pDC->FillRect(rectIconArea, &brushIconArea);
	}
}

void COXMenuSkinXP::AdjustExpansionItemHeight(UINT& nItemHeight, COXBitmapMenu* /*pBitmapMenu*/)
{
	nItemHeight = nItemHeight / 2 + 1;
}

void COXMenuSkinXP::DrawButton(CDC* pDC, UINT nState,  COXImageInfo* /*pImageInfo*/, LPRECT lpButtonRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	BOOL bSelected=nState & ODS_SELECTED;
	BOOL bChecked=nState & ODS_CHECKED;
	if (!bChecked)
		return;

	// Set up the brish and the pen
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
	CBrush brush;
	if (bSelected)
		brush.CreateSolidBrush(m_pSkinXP->GetHotSelectedItemColor());
	else
		brush.CreateSolidBrush(m_pSkinXP->GetCheckedItemColor());

	// Draw the rectangle
	CPen* pOldPen = pDC->SelectObject(&pen);
	CBrush* pOldBrush = pDC->SelectObject(&brush);
	pDC->Rectangle(lpButtonRect);
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
}

void COXMenuSkinXP::DrawImage(CDC* pDC, UINT nState, COXImageInfo* pImageInfo, LPRECT lpImageRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	BOOL bDisabled=nState & ODS_DISABLED;
	BOOL bChecked=nState & ODS_CHECKED;
	BOOL bSelected=nState & ODS_SELECTED;

	if(pImageInfo->IsDefaultImgList() && !bChecked)
	{
		// The default checkmark is not drawn when it isn't checked
		return;
	}

	CRect imageRect(lpImageRect);
	int nIndex=pImageInfo->GetIndex();
	if(bSelected && pImageInfo->GetHotIndex()!=-1)
	{
		nIndex=pImageInfo->GetHotIndex();
	}

	if (bDisabled)
	{
		// Draw a gray image
		CBrush brush;
		brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
		HICON hIcon = pImageInfo->GetImageList()->ExtractIcon(nIndex);
		if (hIcon != NULL)
		{
			pDC->DrawState(imageRect.TopLeft(), imageRect.Size(), hIcon, DST_ICON | DSS_MONO, &brush);
			::DestroyIcon(hIcon);
		}
	}
	else if (bSelected && !bChecked)
	{
		// Raised with a shadow
		CImageList* pImageList = pImageInfo->GetImageList();
		CPoint ptTopLeft = imageRect.TopLeft();

		// Draw the image shadow first
		ptTopLeft.x += 1;
		ptTopLeft.y += 1;
		CBrush brush;
		brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
		CBrush* pOldBrush = pDC->SelectObject(&brush);		
		COLORREF clrOldBkColor = pDC->SetBkColor(RGB(255, 255, 255));
		pImageList->DrawIndirect(pDC, nIndex, ptTopLeft, imageRect.Size(),
			CPoint(0, 0), ILD_ROP | ILD_MASK, 0x00B8074A);
		pDC->SetBkColor(clrOldBkColor);
		pDC->SelectObject(pOldBrush);
		
		ptTopLeft.x -= 2;
		ptTopLeft.y -= 2;

		// Draw the image
		pImageList->Draw(pDC, nIndex, ptTopLeft, ILD_TRANSPARENT);
	}
	else
	{
		// Normal image
		pImageInfo->GetImageList()->Draw(pDC, nIndex, imageRect.TopLeft(), ILD_TRANSPARENT);
	}
}


COLORREF COXMenuSkinXP::DarkenColor(long lScale, COLORREF lColor)
{ 
	long R = MulDiv(GetRValue(lColor), (255 - lScale), 255);
	long G = MulDiv(GetGValue(lColor), (255 - lScale), 255);
	long B = MulDiv(GetBValue(lColor), (255 - lScale), 255);

	return RGB(R, G, B); 
}

// Wrapper function for ::GetPixel(...) that facilitates the shadow buffering
COLORREF GetShadowPixel(HDC hDC, int iXPos, int iYPos, bool bUseSavedShadow)
{
	if (bUseSavedShadow)
		return 0; // we don't need this pixel

	return ::GetPixel(hDC, iXPos, iYPos);

}

// Wrapper function for ::SetPixelV(...) that facilitates the shadow buffering
void SetShadowPixel(HDC hDC, int iXPos, int iYPos, COLORREF clr, bool bSaveShadow, bool bUseSavedShadow, OXSHADOWARRAY* pShadowArray, int& iIndex)
{
	if (bUseSavedShadow)
		::SetPixelV(hDC, iXPos, iYPos, pShadowArray->GetAt(iIndex++));
	else
		::SetPixelV(hDC, iXPos, iYPos, clr);

	if (bSaveShadow)
		pShadowArray->Add(clr);
}

// Draws a menu shadow for the given rectangle
// v9.3 update 01 modification Manfred Drasch for DrawMenuShadow change
// #define MenuIsOnTop		1	
// #define MenuIsOnLeft	2
// For added parameter nMenPos all other values ignored
// end modification Manfred Drasch
void COXMenuSkinXP::DrawMenuShadow(HDC hDC, LPRECT lpRect, LPRECT lpItemRect, OXSHADOWARRAY* pShadowArray, int nMenPos/* = 0*/)
{
	int iArrayIndex = 0;
	bool bSaveShadow, bUseSavedShadow;
	if (pShadowArray == NULL)
	{
		// We don't need to use the shadow array
		bSaveShadow = false;
		bUseSavedShadow = false;
	}
	else if (pShadowArray->GetSize() == 0)
	{
		// Save the shadow in the array
		bSaveShadow = true;
		bUseSavedShadow = false;
	}
	else
	{
		// Use the shadow from the array
		bSaveShadow = false;
		bUseSavedShadow = true;
	}

	CRect rectMenuItem(lpItemRect); // the rectangle of the menu item in screen coordinates
	CRect rectMenu(lpRect);


	// Draw the shadow - get the pixels from the desktop, darken them
	// and place them on the popup window
	HDC hDesktopDC = ::GetWindowDC(::GetDesktopWindow());

	// copy desktop to mem DC and work with that for Get/Set pixel (Vista bug)
	CDC* pDC = CDC::FromHandle(hDesktopDC);

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC);
	CBitmap bitmap;
	bitmap.CreateCompatibleBitmap(pDC, rectMenu.Width(), rectMenu.Height());
	CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);

	// working with a mem bitmap at 0,0 for GetPixel
	dcMem.BitBlt(0,0, rectMenu.Width(), rectMenu.Height(), pDC, rectMenu.left, rectMenu.top, SRCCOPY);

	int x, y;
	CPoint pt;
	COLORREF clr;

	int iLeft = 4;	
	int iTop =  4;
	int iRight = rectMenu.Width();
	int iBottom = rectMenu.Height();

	// Right shadow 
	for (x = 1; x <= 4; x++)
	{
		// Copy the top right pixels
		for (y = 1; y <= 4; y++)
		{
			pt.x = iRight - x;
			pt.y = iTop + y - 4 - 1;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}

		// Top right corner
		for (y = 4; y >= 1; y--)
		{
			pt.x = iRight - x;
			pt.y = iTop + y - 1;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			if( (nMenPos == MenuIsOnLeft) && (pt.y >= rectMenuItem.top - 1 && pt.y <= rectMenuItem.bottom) )
				SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
			else
				// Darken the pixel
				SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}

		// Vertical line
		for (y = iTop + 4; y <= iBottom - 4 - 1; y++)
		{
			pt.x = iRight - x;
			pt.y = y;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			if( (nMenPos == MenuIsOnLeft) && (y >= rectMenuItem.top - 1 && y <= rectMenuItem.bottom) )
				SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
			else
				SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(15 * x, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}

		// Bottom right corner
		for (y = 1; y <= 4; y++)
		{
			pt.x = iRight - x;
			pt.y = iBottom - y;
			clr = GetShadowPixel(dcMem.m_hDC,  pt.x, pt.y, bUseSavedShadow);
			SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y,  clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}
	} 

	// Bottom shadow
	for (y = 1; y <= 4; y++)
	{
		// Copy the bottom left pixels
		for (x = 1; x <= 4; x++)
		{
			pt.x = iLeft - x;
			pt.y = iBottom - y;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}

		// Bottom left corner
		for (x = 1; x <= 4; x++)
		{
			pt.x = iLeft - x + 4;
			pt.y = iBottom - y;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			if( (nMenPos == MenuIsOnTop) && (pt.x >= rectMenuItem.left - 1 && pt.x <= rectMenuItem.right) )
				SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
			else
				// Darken the pixel
				SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * (5 - x) * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}
		
		// Horizontal line
		for (x = iLeft + 4; x <= iRight - 5; x++)
		{
			pt.x = x;
			pt.y = iBottom - y;
			clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
			if( (nMenPos == MenuIsOnTop) && (x >= rectMenuItem.left - 1 && x <= rectMenuItem.right) )
				SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
			else
				// Darken the pixel
				SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(15 * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
		}
	} 

	// done with bitmap here
	dcMem.SelectObject(pOldBitmap);
	bitmap.DeleteObject();

// 	// Draw the intersection of the item rectangle and the shadow
// 	{
// 		CRect rectIntersection;
// 		rectIntersection.IntersectRect(lpRect, lpItemRect);
// 		rectIntersection.OffsetRect(-lpRect->left, -lpRect->top);
// 		FillIntersectionRect(hDC, rectIntersection);
// 		HPEN hPen = ::CreatePen(PS_SOLID, 1, m_pSkinXP->GetMenuBorderColor());
// 		HPEN hOldPen = (HPEN) ::SelectObject(hDC, hPen);
// 
// 		if (rectIntersection.Width() > rectIntersection.Height())
// 		{
// 			// We have a bottom menu
// 			::MoveToEx(hDC, rectIntersection.left, rectIntersection.top, NULL);
// 			::LineTo(hDC, rectIntersection.left, rectIntersection.bottom);
// 			::MoveToEx(hDC, rectIntersection.right - 1, rectIntersection.top, NULL);
// 			::LineTo(hDC, rectIntersection.right - 1, rectIntersection.bottom);
// 		}
// 		else
// 		{
// 			// We have a right menu
// 			::MoveToEx(hDC, rectIntersection.left, rectIntersection.top, NULL);
// 			::LineTo(hDC, rectIntersection.right, rectIntersection.top);
// 			::MoveToEx(hDC, rectIntersection.left, rectIntersection.bottom - 1, NULL);
// 			::LineTo(hDC, rectIntersection.right, rectIntersection.bottom - 1);
// 		}
// 		::SelectObject(hDC, hOldPen);
// 		::DeleteObject(hPen);
// 	}

	::ReleaseDC(0, hDesktopDC);
}

/*
The four different types of menu item shadows are:
		 _______________
1.		|				| 
		|				|\
		|	  File		| |
		|				| |
		|_______________| |
 
		 _______________
2.		|				| 
		|				|
		|	  File		|
		|				|
		|_______________|
		   \_____________

	     _______________
3.		|				| 
		|				|\
		|	  File		| |
		|				| |
		|_______________| |
		 ________________/

		 _______________
4.		|				| | 
		|				| |
		|	  File		| |
		|				| |
		|_______________| |
		   \_____________/
*/
void COXMenuSkinXP::DrawMenuItemShadow(HDC hDC, LPRECT lpRect, UINT nMenuItemShadowType)
{
//	int iLeft = lpRect->left + 4;
//	int iTop = lpRect->top + 4;
//	int iRight = lpRect->right;
//	int iBottom = lpRect->bottom;

	// Draw the shadow - get the pixels from the desktop, darken them
	// and place them on the popup window
	HDC hDesktopDC = ::GetWindowDC(::GetDesktopWindow());
	int x, y;
	CPoint pt;
	COLORREF clr;

	CDC* pDC = CDC::FromHandle(hDesktopDC);

	CRect rectMenu(lpRect);

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC);
	CBitmap bitmap;
	bitmap.CreateCompatibleBitmap(pDC, rectMenu.Width(), rectMenu.Height());
	CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
	
	// working with a mem bitmap at 0,0 for GetPixel
	dcMem.BitBlt(0,0, rectMenu.Width(), rectMenu.Height(), pDC, rectMenu.left, rectMenu.top, SRCCOPY);

	int iLeft = 4;	
	int iTop =  4;
	int iRight = rectMenu.Width();
	int iBottom = rectMenu.Height();

	if (nMenuItemShadowType != 2)
	{
		// Right shadow
		for (x = 1; x <= 4; x++)
		{ 
			if (nMenuItemShadowType != 4)
			{
				// Copy the top right pixels
				for (y = 1; y <= 4; y++)
				{
					pt.x = iRight - x;
					pt.y = iTop + y - 4 - 1;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, clr);
				}

				// Top right corner
				for (y = 4; y >= 1; y--)
				{
					pt.x = iRight - x;
					pt.y = iTop + y - 1;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y, clr));
				}

				// Vertical line
				for (y = iTop + 4; y <= iBottom - 4 - 1; y++)
				{
					pt.x = iRight - x;
					pt.y = y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(15 * x, clr));
				}
			}
			else
			{
				// Just a vertical line from the top
				for (y = 1; y <= iBottom - 4 - 1; y++)
				{
					pt.x = iRight - x;
					pt.y = y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(15 * x, clr));
				}
			}

			// Bottom right corner
			if (nMenuItemShadowType != 1)
			{
				for (y = 1; y <= 4; y++)
				{
					pt.x = iRight - x;
					pt.y = iBottom - y;
					clr = GetPixel(dcMem.m_hDC,  pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y,  clr));
				}
			}
		} 
	}

	if (nMenuItemShadowType != 1)
	{
		// Bottom shadow
		for (y = 1; y <= 4; y++)
		{
			if (nMenuItemShadowType != 3)
			{
				// Copy the bottom left pixels
				for (x = 1; x <= 4; x++)
				{
					pt.x = iLeft - x;
					pt.y = iBottom - y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, clr);
				}

				// Bottom left corner
				for (x = 1; x <= 4; x++)
				{
					pt.x = iLeft - x + 4;
					pt.y = iBottom - y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(3 * (5 - x) * y, clr));
				}
				
				// Horizontal line
				for (x = iLeft + 4; x <= iRight - 5; x++)
				{
					pt.x = x;
					pt.y = iBottom - y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(15 * y, clr));
				}
			}
			else
			{
				// Horizontal line stretching all the way from the left coordinate
				for (x = 1; x <= iRight - 5; x++)
				{
					pt.x = x;
					pt.y = iBottom - y;
					clr = GetPixel(dcMem.m_hDC, pt.x, pt.y);
//					pt.Offset(-lpRect->left, -lpRect->top);
					SetPixel(hDC, pt.x, pt.y, DarkenColor(15 * y, clr));
				}
			}
		}
	}

	dcMem.SelectObject(pOldBitmap);
	::ReleaseDC(0, hDesktopDC);
}


LRESULT COXMenuSkinXP::MenuPopupWndProc(WNDPROC origWndProc, HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	//TRACE(_T("\n%u for %u"), nMsg, hWnd);

	switch (nMsg)
	{
		case WM_CREATE:
		{
			//TRACE(_T("\nWM_DESTROY for %u"), hWnd);
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				// Add this container window to the stack of COXBitmapMenu
				pBitmapMenu->m_PopupWndStack.Push(hWnd);
			}
		}
		break;

		case WM_DESTROY:
		{
			//TRACE(_T("\nWM_DESTROY for %u"), hWnd);
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				// Remove this window from the stack of COXBitmapMenu
				pBitmapMenu->m_PopupWndStack.Remove(hWnd);

				if (GetVersion() >= 0x80000000)
				{
					// For Win9x if this is a popup menu we need to refresh the previous menu
					HWND hPreviousWnd = pBitmapMenu->m_PopupWndStack.Pop();
					if (hPreviousWnd != NULL)
						::SendMessage(hPreviousWnd, WM_NCPAINT, 1, 0);
				}
			}
		}
		break;

		case WM_ERASEBKGND:
		{
			//TRACE(_T("\nWM_ERASEBKGND for %u"), hWnd);
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				return 0;
			}
		}
		break;


		// v9.3 update 01 modifications Manfred Drasch
		case WM_NCPAINT:
		{
			// For Windows95/98/ME/NT/XP we must perform the drawing here
			//TRACE(_T("\nWM_NCPAINT for %u"), hWnd);
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				// Get the window DC
				HDC hDC;
				if (wParam != 1)
					hDC = GetDCEx(hWnd, (HRGN)wParam, DCX_WINDOW | DCX_INTERSECTRGN);
				else
					hDC = GetWindowDC(hWnd);
				if (hDC == NULL)
					return 0;
				
				CDC* pDC = CDC::FromHandle(hDC);

				// Get the frame rectangle
				CRect rectFrame;
				::GetWindowRect(hWnd, rectFrame);
				CPoint ptOffset = rectFrame.TopLeft();
				rectFrame.OffsetRect(-ptOffset.x, -ptOffset.y);
				rectFrame.right -= 4;
				rectFrame.bottom -= 4;

				// Exclude the client rectangle
				CRect rectClient(rectFrame);
				rectClient.DeflateRect(3, 3, 3, 3);
				pDC->ExcludeClipRect(rectClient);

				// Draw the shadow
				CRect rectWnd;
				::GetWindowRect(hWnd, rectWnd);
				CPoint ptTopLeft;
				m_mapHWNDtoPos.Lookup(hWnd, ptTopLeft);
				m_mapHWNDtoPos.RemoveKey(hWnd);

				// Interrupt the menu frame where it meets the menu item
				CRect rectDropDownItem(pBitmapMenu->m_rectDropDownItem);
				rectDropDownItem.OffsetRect(-ptOffset.x, -ptOffset.y);

				bool fDrawJoiningLine = TRUE;

				int nOffset1 = 0;	// Multimonitor!
				int nOffset2 = 0;
				// Get the rectangle of the monitor closest to the menu rectangle
				CRect rctMonitor;
				HMONITOR hMonitor = ::MonitorFromRect(pBitmapMenu->m_rectDropDownItem, MONITOR_DEFAULTTONEAREST);
				MONITORINFO mi;
				mi.cbSize = sizeof(MONITORINFO);
				if(hMonitor!=NULL && ::GetMonitorInfo(hMonitor, &mi))
				{
					rctMonitor = mi.rcMonitor;
					if ((pBitmapMenu->m_rectDropDownItem.left < 0) && (pBitmapMenu->m_rectDropDownItem.right >= 0))
					{
						if (rctMonitor.left < 0)
							nOffset1 = pBitmapMenu->m_rectDropDownItem.right + 1;
						else
							nOffset2 = pBitmapMenu->m_rectDropDownItem.left;
					}
					else if (pBitmapMenu->m_rectDropDownItem.right >= rctMonitor.right)
					{
						nOffset1 = pBitmapMenu->m_rectDropDownItem.right - rctMonitor.right + 1;
					}
				}

				if (rectDropDownItem.bottom == rectFrame.top)
				{
					// The drop down item is on top of the menu
					rectDropDownItem.top = 0;
					rectDropDownItem.bottom = 1;
					rectDropDownItem.left = rectDropDownItem.left + 1 - nOffset2;
					rectDropDownItem.right = rectDropDownItem.right - 1 - nOffset1;
					DrawMenuShadow(pDC->m_hDC, rectWnd, rectDropDownItem, pBitmapMenu->m_PopupWndStack.GetShadowArray(hWnd));
				}
				else if (rectDropDownItem.top == rectFrame.bottom)
				{
					// The drop down item is at the bottom of the menu
					rectDropDownItem.bottom = rectDropDownItem.top;
					rectDropDownItem.top = rectDropDownItem.bottom - 1;
					rectDropDownItem.left = rectDropDownItem.left + 1 - nOffset2;
					rectDropDownItem.right = rectDropDownItem.right - 1 - nOffset1;
					DrawMenuShadow(pDC->m_hDC, rectWnd, rectDropDownItem, pBitmapMenu->m_PopupWndStack.GetShadowArray(hWnd), MenuIsOnTop);
				}
				else if (rectDropDownItem.right == rectFrame.left)
				{
					// The drop down item is on the left of the menu
					rectDropDownItem.left = 0;
					rectDropDownItem.right = 1;
					rectDropDownItem.bottom -= 1;
					rectDropDownItem.top += 1;
					DrawMenuShadow(pDC->m_hDC, rectWnd, rectDropDownItem, pBitmapMenu->m_PopupWndStack.GetShadowArray(hWnd));
				}
				else if (rectDropDownItem.left == rectFrame.right)
				{
					// The drop down item is on the right of the menu
					rectDropDownItem.right = rectDropDownItem.left;
					rectDropDownItem.left = rectDropDownItem.right - 1;
					rectDropDownItem.bottom -= 1;
					rectDropDownItem.top += 1;
					DrawMenuShadow(pDC->m_hDC, rectWnd, rectDropDownItem, pBitmapMenu->m_PopupWndStack.GetShadowArray(hWnd), MenuIsOnLeft);
				}
				else
				{
					DrawMenuShadow(pDC->m_hDC, rectWnd, rectDropDownItem, pBitmapMenu->m_PopupWndStack.GetShadowArray(hWnd));
					fDrawJoiningLine = false;
				}

				// Draw the menu frame etc.	after !!! DrawMenuShadow()
				pDC->FillSolidRect(rectFrame, m_pSkinXP->GetMenuFaceColor());
				DrawItemStrip(pDC, CRect(rectFrame.left, rectFrame.top + 2,
					rectFrame.left + m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + 8,
					rectFrame.bottom - 4));
				CBrush brush;
//				brush.CreateSolidBrush(m_pSkinXP->GetMenuBorderColor());
				brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
				pDC->FrameRect(rectFrame, &brush);

				if (fDrawJoiningLine)
					DrawJoiningLine(pDC, rectDropDownItem);

				::ReleaseDC(hWnd, hDC);
				return 0;
			}
		}
		break;

		case WM_PRINT:
		{
			// For Windows 2000 we must perform the drawing here

			//TRACE(_T("\nWM_PRINT"));
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				MSG msg;
				while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
				{
					::TranslateMessage(&msg);
					::DispatchMessage(&msg);
				}	

				// Get the window rectangle
				CRect rectWindow;
				::GetWindowRect(hWnd, rectWindow);
				rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

				// Draw the client to a memory dc
				CDC* pDC = CDC::FromHandle((HDC) wParam);
				CDC dcMem;
				dcMem.CreateCompatibleDC(pDC);
				CBitmap bitmap;
				bitmap.CreateCompatibleBitmap(pDC, rectWindow.Width(), rectWindow.Height());
				CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
				dcMem.IntersectClipRect(rectWindow);

				// Get the client to paint
				CPoint ptOldOrigin = dcMem.SetViewportOrg(3, 3);
				SendMessage(hWnd, WM_PRINTCLIENT, (WPARAM) dcMem.m_hDC, lParam);
				dcMem.SetViewportOrg(ptOldOrigin);

				// Draw the shadow if not drawn by XP
				CRect rectWnd;
				::GetWindowRect(hWnd, rectWnd);
				CPoint ptTopLeft;
				m_mapHWNDtoPos.Lookup(hWnd, ptTopLeft);
				m_mapHWNDtoPos.RemoveKey(hWnd);
				int iWidth = rectWnd.Width();
				int iHeight = rectWnd.Height();
				rectWnd.left = ptTopLeft.x;
				rectWnd.top = ptTopLeft.y;
				rectWnd.right = ptTopLeft.x + iWidth;
				rectWnd.bottom = ptTopLeft.y + iHeight;

				// Determine the frame rectangle
				CRect rectFrame(rectWindow);
				rectFrame.DeflateRect(0, 0, 4, 4);

				// Exclude the client rectangle
				CRect rectClient(rectFrame);
				rectClient.DeflateRect(3, 3, 3, 3);
				dcMem.ExcludeClipRect(rectClient);

				// Draw the menu frame
				dcMem.FillSolidRect(rectFrame, m_pSkinXP->GetMenuFaceColor());
				DrawItemStrip(&dcMem, CRect(rectFrame.left, rectFrame.top + 2,
					rectFrame.left + m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + 8,
					rectFrame.bottom - 4));
				CBrush brush;
				brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
				dcMem.FrameRect(rectFrame, &brush);

				// Interrupt the menu frame where it meets the menu item
				CRect rectDropDownItem(pBitmapMenu->m_rectDropDownItem);
				rectDropDownItem.OffsetRect(-rectWnd.left, -rectWnd.top);

				int nOffset1 = 0;	// Multimonitor!
				int nOffset2 = 0;
				// Get the rectangle of the monitor closest to the menu rectangle
				CRect rctMonitor;
				HMONITOR hMonitor = ::MonitorFromRect(pBitmapMenu->m_rectDropDownItem, MONITOR_DEFAULTTONEAREST);
				MONITORINFO mi;
				mi.cbSize = sizeof(MONITORINFO);
				if(hMonitor!=NULL && ::GetMonitorInfo(hMonitor, &mi))
				{
					rctMonitor = mi.rcMonitor;
					if ((pBitmapMenu->m_rectDropDownItem.left < 0) && (pBitmapMenu->m_rectDropDownItem.right >= 0))
					{
						if (rctMonitor.left < 0)
							nOffset1 = pBitmapMenu->m_rectDropDownItem.right + 1;
						else
							nOffset2 = pBitmapMenu->m_rectDropDownItem.left;
					}
					else if (pBitmapMenu->m_rectDropDownItem.right >= rctMonitor.right)
					{
						nOffset1 = pBitmapMenu->m_rectDropDownItem.right - rctMonitor.right + 1;
					}
				}

				if (rectDropDownItem.bottom == rectFrame.top)
				{
					// The drop down item is on top of the menu
					rectDropDownItem.top = 0;
					rectDropDownItem.bottom = 1;
					rectDropDownItem.left = rectDropDownItem.left + 1 - nOffset2;
					rectDropDownItem.right = rectDropDownItem.right - 1 - nOffset1;
					DrawJoiningLine(&dcMem, rectDropDownItem);
					DrawMenuShadow(dcMem.m_hDC, rectWnd, rectDropDownItem, NULL);
				}
				else if (rectDropDownItem.top == rectFrame.bottom)
				{
					// The drop down item is at the bottom of the menu
					rectDropDownItem.bottom = rectDropDownItem.top;
					rectDropDownItem.top = rectDropDownItem.bottom - 1;
					rectDropDownItem.left = rectDropDownItem.left + 1 - nOffset2;
					rectDropDownItem.right = rectDropDownItem.right - 1 - nOffset1;
					DrawJoiningLine(&dcMem, rectDropDownItem);
					DrawMenuShadow(dcMem.m_hDC, rectWnd, rectDropDownItem, NULL, MenuIsOnTop);
				}
				else if (rectDropDownItem.right == rectFrame.left)
				{
					// The drop down item is on the left of the menu
					rectDropDownItem.left = 0;
					rectDropDownItem.right = 1;
					rectDropDownItem.bottom -= 1;
					rectDropDownItem.top += 1;
					DrawJoiningLine(&dcMem, rectDropDownItem);
					DrawMenuShadow(dcMem.m_hDC, rectWnd, rectDropDownItem, NULL);
				}
				else if (rectDropDownItem.left == rectFrame.right)
				{
					// The drop down item is on the right of the menu
					rectDropDownItem.right = rectDropDownItem.left;
					rectDropDownItem.left = rectDropDownItem.right - 1;
					rectDropDownItem.bottom -= 1;
					rectDropDownItem.top += 1;
					DrawJoiningLine(&dcMem, rectDropDownItem);
					DrawMenuShadow(dcMem.m_hDC, rectWnd, rectDropDownItem, NULL, MenuIsOnLeft);
				}
				else
					DrawMenuShadow(dcMem.m_hDC, rectWnd, rectDropDownItem, NULL);


				// Copy the memory DC to the window DC
				pDC->BitBlt(0, 0, rectWindow.Width(), rectWindow.Height(), &dcMem, 0, 0, SRCCOPY);
				dcMem.SelectObject(pOldBitmap);

				return 0;
			}
		}
		break;
		// end section modifications Manfred Drasch

		case WM_WINDOWPOSCHANGING:
		{
			_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
			COXBitmapMenu* pBitmapMenu = DYNAMIC_DOWNCAST(COXBitmapMenu,
				CMenu::FromHandle(pThreadState->m_hTrackingMenu));
			if (pBitmapMenu != NULL)
			{
				// Make the window larger so it can fit the shadow
				WINDOWPOS* pWP = (WINDOWPOS*) lParam;
				pWP->cx += 4;
				pWP->cy += 4;

				// Save the top left point (only used for Windows 2000/XP)
				CPoint ptTopLeft;
				ptTopLeft.x = pWP->x;
				ptTopLeft.y = pWP->y;
				m_mapHWNDtoPos.SetAt(hWnd, ptTopLeft);
			}
		}
		break;

		default:
			break;
	}

	return ::CallWindowProc(origWndProc, hWnd, nMsg, wParam, lParam);	
}

void COXMenuSkinXP::DrawJoiningLine(CDC* pDC, LPRECT lpRect)
{
	CBrush brushBG;
	brushBG.CreateSolidBrush(m_pSkinXP->GetBackgroundColor());

	pDC->FrameRect(lpRect, &brushBG);
}

void COXMenuSkinXP::FillIntersectionRect(HDC hDC, LPRECT lpRect)
{
	CDC dc;
	dc.Attach(hDC);
	dc.FillSolidRect(lpRect, m_pSkinXP->GetBackgroundColor());
	dc.Detach();
}

void COXMenuSkinXP::DrawItemStrip(CDC* pDC, LPRECT lpStripRect)
{
	pDC->FillSolidRect(lpStripRect->left,
		lpStripRect->top,
		lpStripRect->right,
		lpStripRect->bottom,
		m_pSkinXP->GetBackgroundColor());
}

void COXMenuSkinXP::OnNcPaintCustomizePopupWnd(COXBitmapMenuPopupWnd* pPopupWnd)
{
	CWindowDC dc(pPopupWnd);

	CRect rectWindow;
	pPopupWnd->GetWindowRect(rectWindow);
	rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

	// Draw the menu frame
	dc.FillSolidRect(rectWindow, m_pSkinXP->GetMenuFaceColor());
	dc.FillSolidRect(rectWindow.left, rectWindow.top + 2,
		rectWindow.left + m_DimensionConstants.m_nGapLeftBitmap + pPopupWnd->m_pBitmapMenu->m_nBitmapExtent + 7,
		rectWindow.bottom - 4, m_pSkinXP->GetBackgroundColor());
	CBrush brush;
	brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
	dc.FrameRect(rectWindow, &brush);
}

void COXMenuSkinXP::OnPaintShadowedItemWnd(COXShadowedItemWnd* pShadowedItemWnd)
{
	CPaintDC dc(pShadowedItemWnd); // device context for painting

	// Get the rectangle of the selected item
	CRect rectItem;
	pShadowedItemWnd->GetClientRect(rectItem);
	rectItem.DeflateRect(0, 0, 4, 4);

	// Draw the frame of the selected item
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_BTNSHADOW));
	CPen* pOldPen = dc.SelectObject(&pen);

	CRect rect;
	pShadowedItemWnd->GetWindowRect(rect);

	if (pShadowedItemWnd->m_nPosFlags & OX_TPM_BOTTOM)
	{
		// The popup menu is below the item
		dc.MoveTo(rectItem.left, rectItem.bottom);
		dc.LineTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.right - 1, rectItem.top);
		dc.LineTo(rectItem.right - 1, rectItem.bottom + 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 1);
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_RIGHT)
	{
		// The popup menu is to the right of the item
		dc.MoveTo(rectItem.right, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.bottom - 1);
		dc.LineTo(rectItem.right, rectItem.bottom - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 2);	
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_TOP)
	{
		// The popup menu is above the item
		dc.MoveTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.bottom - 1);
		dc.LineTo(rectItem.right - 1, rectItem.bottom - 1);
		dc.LineTo(rectItem.right - 1, rectItem.top - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 4);
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_LEFT)
	{
		// The popup menu is to the left of the item
		dc.MoveTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.right, rectItem.top);
		dc.LineTo(rectItem.right, rectItem.bottom - 1);
		dc.LineTo(rectItem.left - 1, rectItem.bottom - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 3);
	}
}

void COXMenuSkinXP::DrawText(CDC* pDC, UINT nState, LPCTSTR lpszText, LPRECT lpText1Rect, LPRECT lpText2Rect, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect text1Rect(lpText1Rect);
	CRect text2Rect(lpText2Rect);

	BOOL bDisabled=nState & ODS_DISABLED;

	// Split the text (in front of and after the tab)
	CString sText(lpszText);
	int nTabCharIndex=sText.Find(_T('\t'));
	CString sAfterTab;
	CString sBeforeTab;
	if(nTabCharIndex != -1)
	{
		sBeforeTab=sText.Left(nTabCharIndex);
		sAfterTab=sText.Mid(nTabCharIndex + 1);
	}
	else
	{
		sBeforeTab=sText;
		ASSERT(sAfterTab.IsEmpty());
	}

	// Draw the text
	// Sets the foreground color of the text based on its selection state
	COLORREF clrForeground;
	if (bDisabled)
		clrForeground = m_pSkinXP->GetDisabledMenuTextColor();
	else
		clrForeground = ::GetSysColor(COLOR_MENUTEXT);
	
	COLORREF clrOldForeground=pDC->SetTextColor(clrForeground);

	// set background filling mode
	int nOldBkMode=pDC->SetBkMode(TRANSPARENT);

	UINT nFlags=0;
	CRect newText2Rect(0,0,0,0);
	int nHorzAlign=0;
	pDC->DrawState(text1Rect.TopLeft(), text1Rect.Size(), sBeforeTab.GetBuffer(0),
		nFlags, TRUE, sBeforeTab.GetLength(), (CBrush*)NULL);

	// ... First calculate text width so we can right-align it
	pDC->DrawText(sAfterTab, newText2Rect, DT_CALCRECT | DT_SINGLELINE);
	nHorzAlign=text2Rect.Width() - newText2Rect.Width();
	if(!sAfterTab.IsEmpty())
	{
		pDC->DrawState(text2Rect.TopLeft() + CPoint(nHorzAlign, 0), 
			newText2Rect.Size(), sAfterTab.GetBuffer(0),
			nFlags, TRUE, sAfterTab.GetLength(), (CBrush*)NULL);
	}

	pDC->SetTextColor(clrOldForeground); 
	pDC->SetBkMode(nOldBkMode);
}

void COXMenuSkinXP::DrawSeparator(CDC* pDC, LPRECT lpItemRect, COXBitmapMenu* pBitmapMenu)
{
	CRect rectItem(lpItemRect);

	// First draw the background
	CBrush brushFace;
	brushFace.CreateSolidBrush(m_pSkinXP->GetMenuFaceColor());
	pDC->FillRect(lpItemRect, &brushFace);

	CBrush brushIconArea;
	brushIconArea.CreateSolidBrush(m_pSkinXP->GetBackgroundColor());
	CRect rectIconArea(lpItemRect);
	rectIconArea.right =m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapRightBitmap;
	pDC->FillRect(rectIconArea, &brushIconArea);

	// Draw the separator line
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetSeparatorColor());
	CPen* pOldPen = pDC->SelectObject(&pen);
	pDC->MoveTo(m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapBitmapText,
		rectItem.CenterPoint().y);
	pDC->LineTo(rectItem.right, rectItem.CenterPoint().y);
	pDC->SelectObject(pOldPen);
}

void COXMenuSkinXP::DrawCustomized(CDC* pDC, LPRECT lpItemRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	// Draw a black rectangle, 2 pixels wide
	CBrush brush;
	brush.CreateSolidBrush(::GetSysColor(COLOR_BTNTEXT));

	CRect rectItem(lpItemRect);
	pDC->FrameRect(rectItem, &brush);
	rectItem.DeflateRect(1, 1);
	pDC->FrameRect(rectItem, &brush);
}

void COXMenuSkinXP::DrawInsertMark(CDC* pDC, LPRECT lpItemRect, BOOL bBefore, COXBitmapMenu* /*pBitmapMenu*/)
{
	CRect itemRect(lpItemRect);
	itemRect.DeflateRect(2,0);

	ASSERT(pDC!=NULL);
	if(bBefore)
	{
		itemRect.top-=2;
		itemRect.bottom=itemRect.top+3;
	}
	else
	{
		itemRect.bottom+=1;
		itemRect.top=itemRect.bottom-3;
	}

	pDC->MoveTo(itemRect.TopLeft());
	pDC->LineTo(itemRect.left+1,itemRect.top+1);
	pDC->LineTo(itemRect.right-1,itemRect.top+1);
	pDC->LineTo(itemRect.right,itemRect.top);
	pDC->LineTo(itemRect.right,itemRect.bottom);
	pDC->LineTo(itemRect.right-1,itemRect.bottom-1);
	pDC->LineTo(itemRect.left+1,itemRect.bottom-1);
	pDC->LineTo(itemRect.left,itemRect.bottom);
	pDC->LineTo(itemRect.TopLeft());
}

void COXMenuSkinXP::DrawSubmenuItem(CDC* pDC, UINT nState, LPCTSTR lpszText, COXImageInfo* pImageInfo, 
									LPRECT lpItemRect, LPRECT lpButtonRect, LPRECT lpText1Rect, LPRECT lpText2Rect, COXBitmapMenu* pBitmapMenu)
{
	ASSERT(pDC!=NULL);
	pBitmapMenu->DrawBackground(pDC,nState,pImageInfo,lpItemRect,lpButtonRect);

	/*
	// draw right aligned arrow
	//
	COLORREF clrShadow=::GetSysColor(COLOR_BTNSHADOW);
	CFont font;
	CFont* pOldFont=NULL;
	if((font.CreateFont(GetSystemMetrics(SM_CYMENUCHECK), 0, 0, 0, 
		FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET, 0,0,0,0, _T("Marlett"))) != NULL)
	{
		pOldFont=(CFont*)pDC->SelectObject(&font);
	}
	int nOldBkMode=pDC->SetBkMode(TRANSPARENT);
	COLORREF oldTextColor=CLR_NONE;
	if((nState&ODS_DISABLED)==ODS_DISABLED)
	{
		oldTextColor=pDC->SetTextColor(clrShadow);
	}

	// draw arrow symbol
	CRect rectText2(lpText2Rect);
	rectText2.OffsetRect(lpItemRect->right - rectText2.right, 0);
	pDC->DrawText(_T("8"),rectText2,DT_RIGHT|DT_VCENTER|DT_SINGLELINE);
	if((nState&ODS_DISABLED)==ODS_DISABLED)
	{
		pDC->SetTextColor(oldTextColor);
	}
	pDC->SetBkMode(nOldBkMode);
	if(pOldFont != NULL)
	{
		pDC->SelectObject(pOldFont);
	}
	//
	//////////////////////////////
	*/

	DrawText(pDC,nState,lpszText,lpText1Rect,lpText2Rect,pBitmapMenu);
}

void COXMenuSkinXP::DrawExpansionItem(CDC* pDC, LPRECT lpItemRect, UINT nState, COXBitmapMenu* /*pBitmapMenu*/)
{
	ASSERT(pDC!=NULL);

	BOOL bDisabled=nState & ODS_DISABLED;

	CFont font;
	VERIFY(font.CreateFont(GetSystemMetrics(SM_CYMENUCHECK),0,0,0,
		FW_NORMAL,0,0,0,SYMBOL_CHARSET,0,0,0,0,_T("Marlett")));
	CFont* pOldFont=pDC->SelectObject(&font);
	int nOldBkMode=pDC->SetBkMode(TRANSPARENT);
	
	COLORREF clrText;
	if (bDisabled)
		clrText = m_pSkinXP->GetSeparatorColor();
	else
		clrText = ::GetSysColor(COLOR_MENUTEXT);

	COLORREF oldTextColor=pDC->SetTextColor(clrText);

	pDC->DrawText(_T("6"),lpItemRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);

	pDC->SetTextColor(oldTextColor);
	pDC->SetBkMode(nOldBkMode);
	pDC->SelectObject(pOldFont);
}


// COXMenuSkin2003
//

COXMenuSkin2003::COXMenuSkin2003(COXSkin2003* pSkin2003) :
	COXMenuSkinXP(pSkin2003)
{

}

COXMenuSkin2003::~COXMenuSkin2003()
{

}

void COXMenuSkin2003::DrawBackground(CDC* pDC, UINT nState, COXImageInfo* /*pImageInfo*/, LPRECT lpItemRect, LPRECT /*lpButtonRect*/, COXBitmapMenu* pBitmapMenu)
{
	bool bSelected = (nState & ODS_SELECTED) != 0;
	bool bHidden = (nState & OXODS_HIDDEN) != 0;
	bool bDisabled = (nState & ODS_DISABLED) != 0;

	if(bSelected && !bDisabled)
	{
		// Selected item
		CPen pen;
		pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
		CBrush brush;
		brush.CreateSolidBrush(m_pSkinXP->GetHotItemColor());

		CPen* pOldPen = pDC->SelectObject(&pen);
		CBrush* pOldBrush = pDC->SelectObject(&brush);
		pDC->Rectangle(lpItemRect);
		pDC->SelectObject(pOldBrush);
		pDC->SelectObject(pOldPen);
	}
	else
	{
		// Normal item
		CBrush brushFace;
		brushFace.CreateSolidBrush(m_pSkinXP->GetMenuFaceColor());
		pDC->FillRect(lpItemRect, &brushFace);

		CRect rectIconArea(lpItemRect);
		rectIconArea.left -= 2;
		rectIconArea.right = m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapRightBitmap;

		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		COLORREF clrMenuStripLeftColor = pSkin2003->GetMenuStripLeftColor();
		COLORREF clrMenuStripRightColor = pSkin2003->GetMenuStripRightColor();
		if (bHidden)
		{
			// We need to darken the colors
			clrMenuStripLeftColor = pSkin2003->Blend3Colors(
				clrMenuStripLeftColor, 0, 0, 0.93f, 0.07f, 0);
			
			clrMenuStripRightColor = pSkin2003->Blend3Colors(
				clrMenuStripRightColor, 0, 0, 0.93f, 0.07f, 0);
		}

		pSkin2003->GradientFill(pDC, rectIconArea,
			clrMenuStripLeftColor,
			clrMenuStripRightColor,
			GRADIENT_FILL_RECT_H);
	}
}

void COXMenuSkin2003::DrawItemStrip(CDC* pDC, LPRECT lpStripRect)
{
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	lpStripRect->bottom += 2;
	pSkin2003->GradientFill(pDC, lpStripRect,
		pSkin2003->GetMenuStripLeftColor(),
		pSkin2003->GetMenuStripRightColor(),
		GRADIENT_FILL_RECT_H);
}

void COXMenuSkin2003::DrawSeparator(CDC* pDC, LPRECT lpItemRect, COXBitmapMenu* pBitmapMenu)
{
	CRect rectItem(lpItemRect);

	// First draw the background
	CBrush brushFace;
	brushFace.CreateSolidBrush(m_pSkinXP->GetMenuFaceColor());
	pDC->FillRect(lpItemRect, &brushFace);

	CRect rectIconArea(lpItemRect);
	rectIconArea.left -= 2;
	rectIconArea.right = m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapRightBitmap;

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pSkin2003->GradientFill(pDC, rectIconArea,
		pSkin2003->GetMenuStripLeftColor(),
		pSkin2003->GetMenuStripRightColor(),
		GRADIENT_FILL_RECT_H);

	// Draw the separator line
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetSeparatorColor());
	CPen* pOldPen = pDC->SelectObject(&pen);
	pDC->MoveTo(m_DimensionConstants.m_nGapLeftBitmap + pBitmapMenu->m_nBitmapExtent + m_DimensionConstants.m_nGapBitmapText,
		rectItem.CenterPoint().y);
	pDC->LineTo(rectItem.right, rectItem.CenterPoint().y);
	pDC->SelectObject(pOldPen);
}

void COXMenuSkin2003::DrawImage(CDC* pDC, UINT nState, COXImageInfo* pImageInfo, LPRECT lpImageRect, COXBitmapMenu* /*pBitmapMenu*/)
{
	BOOL bDisabled=nState & ODS_DISABLED;
	BOOL bChecked=nState & ODS_CHECKED;
	BOOL bSelected=nState & ODS_SELECTED;

	if(pImageInfo->IsDefaultImgList() && !bChecked)
	{
		// The default checkmark is not drawn when it isn't checked
		return;
	}

	CRect imageRect(lpImageRect);
	int nIndex=pImageInfo->GetIndex();
	if(bSelected && pImageInfo->GetHotIndex()!=-1)
	{
		nIndex=pImageInfo->GetHotIndex();
	}

	if (bDisabled)
	{
		// Draw a gray image
		CBrush brush;
		brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
		HICON hIcon = pImageInfo->GetImageList()->ExtractIcon(nIndex);
		if (hIcon != NULL)
		{
			pDC->DrawState(imageRect.TopLeft(), imageRect.Size(), hIcon, DST_ICON | DSS_MONO, &brush);
			::DestroyIcon(hIcon);
		}
	}
	else
	{
		// Normal image
		pImageInfo->GetImageList()->Draw(pDC, nIndex, imageRect.TopLeft(), ILD_TRANSPARENT);
	}
}

void COXMenuSkin2003::DrawJoiningLine(CDC* pDC, LPRECT lpRect)
{
	CRect rect(lpRect);

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pSkin2003->GradientFill(pDC, rect,
		pSkin2003->GetMenubarItemLightColor(),
		pSkin2003->GetMenubarItemDarkColor(),
		GRADIENT_FILL_RECT_V);
}

void COXMenuSkin2003::OnPaintShadowedItemWnd(COXShadowedItemWnd* pShadowedItemWnd)
{
	CPaintDC dc(pShadowedItemWnd); // device context for painting

	TBBUTTON tbb;
	CToolBarCtrl& ctrl = pShadowedItemWnd->m_pCoolToolbar->GetToolBarCtrl();
	ctrl.GetButton(pShadowedItemWnd->m_iMenuItem, &tbb);
	CRect rectMenuItem;
	ctrl.GetItemRect(pShadowedItemWnd->m_iMenuItem, rectMenuItem);
	ctrl.ClientToScreen(rectMenuItem);
	pShadowedItemWnd->ScreenToClient(rectMenuItem);
	COXToolbarSkinXP* pToolbarSkinXP = (COXToolbarSkinXP*) pShadowedItemWnd->m_pCoolToolbar->GetToolbarSkin();
	
	// Draw the item gradient background
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pSkin2003->GradientFill(&dc, rectMenuItem,
		pSkin2003->GetMenubarItemLightColor(),
		pSkin2003->GetMenubarItemDarkColor(),
		GRADIENT_FILL_RECT_V);

	// Draw the item
	pToolbarSkinXP->DrawItem(&dc, &tbb, rectMenuItem, pShadowedItemWnd->m_pCoolToolbar, FALSE);

	// Get the rectangle of the selected item
	CRect rectItem;
	pShadowedItemWnd->GetClientRect(rectItem);
	rectItem.DeflateRect(0, 0, 4, 4);

	// Draw the frame of the selected item
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, pSkin2003->GetMenuBorderColor());
	CPen* pOldPen = dc.SelectObject(&pen);

	CRect rect;
	pShadowedItemWnd->GetWindowRect(rect);

	if (pShadowedItemWnd->m_nPosFlags & OX_TPM_BOTTOM)
	{
		// The popup menu is below the item
		dc.MoveTo(rectItem.left, rectItem.bottom);
		dc.LineTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.right - 1, rectItem.top);
		dc.LineTo(rectItem.right - 1, rectItem.bottom + 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 1);
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_RIGHT)
	{
		// The popup menu is to the right of the item
		dc.MoveTo(rectItem.right, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.bottom - 1);
		dc.LineTo(rectItem.right, rectItem.bottom - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 2);	
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_TOP)
	{
		// The popup menu is above the item
		dc.MoveTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.left, rectItem.bottom - 1);
		dc.LineTo(rectItem.right - 1, rectItem.bottom - 1);
		dc.LineTo(rectItem.right - 1, rectItem.top - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 4);
	}
	else if (pShadowedItemWnd->m_nPosFlags & OX_TPM_LEFT)
	{
		// The popup menu is to the left of the item
		dc.MoveTo(rectItem.left, rectItem.top);
		dc.LineTo(rectItem.right, rectItem.top);
		dc.LineTo(rectItem.right, rectItem.bottom - 1);
		dc.LineTo(rectItem.left - 1, rectItem.bottom - 1);
		dc.SelectObject(pOldPen);
		
		// Draw the shadow
		DrawMenuItemShadow(dc.m_hDC, rect, 3);
	}
}

// COXShortcutBarSkin
//

void COXShortcutBarSkin::DrawHeader(LPDRAWITEMSTRUCT lpDrawItemStruct, COXShortcutBar * bar)
{
	HSHBGROUP hGroup=(HSHBGROUP)(INT_PTR)lpDrawItemStruct->itemID;
	ASSERT(hGroup);

	BOOL bFlat=((bar->GetBarStyle() & SHBS_FLATGROUPBUTTON)==SHBS_FLATGROUPBUTTON);

	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);	

	// Get the header rect
	CRect rectHeader(lpDrawItemStruct->rcItem);	

	// Save DC
	int nSavedDC=dc.SaveDC();
	ASSERT(nSavedDC);

	// get background colors
	COLORREF clrBackground=bar->GetGroupHeaderBkColor(hGroup);
	VERIFY(clrBackground!=ID_COLOR_NONE);
	// invert colors for dragging group
	if(bar->GetDragGroup()==hGroup)
	{
		clrBackground=InvertColor(clrBackground);
	}

	// Draw FrameRect
	COLORREF clrTopLeft=UpdateColor(clrBackground,64);
	COLORREF clrBottomRight=UpdateColor(clrBackground,-128);
	if(bFlat)
	{
		if(bar->GetDragGroup()==hGroup || bar->m_bCreatingDragImage)
		{
			dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
			rectHeader.DeflateRect(1,1);
			dc.Draw3dRect(rectHeader,clrBackground,clrBackground);
			rectHeader.DeflateRect(1,1);
		}
		else if(bar->m_hPressedGroup!=NULL)
		{
			if(hGroup==bar->m_hPressedGroup)
			{
				if(hGroup==bar->m_hLastMouseIsOverGroup)
				{
					dc.Draw3dRect(rectHeader,clrBottomRight,clrBackground);
					rectHeader.DeflateRect(1,1);
					dc.Draw3dRect(rectHeader,clrBottomRight,clrTopLeft);
					rectHeader.DeflateRect(1,1);
				}
				else
				{
					dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
					rectHeader.DeflateRect(1,1);
					dc.Draw3dRect(rectHeader,clrBackground,clrBottomRight);
					rectHeader.DeflateRect(1,1);
				}
			}
			else
			{
				dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
				rectHeader.DeflateRect(1,1);
				dc.Draw3dRect(rectHeader,clrBackground,clrBackground);
				rectHeader.DeflateRect(1,1);
			}
		}
		else
		{
			if(hGroup==bar->m_hLastMouseIsOverGroup)
			{
				dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
				rectHeader.DeflateRect(1,1);
				dc.Draw3dRect(rectHeader,clrBackground,clrBottomRight);
				rectHeader.DeflateRect(1,1);
			}
			else
			{
				dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
				rectHeader.DeflateRect(1,1);
				dc.Draw3dRect(rectHeader,clrBackground,clrBackground);
				rectHeader.DeflateRect(1,1);
			}
		}
	}
	else
	{
		dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
		rectHeader.DeflateRect(1,1);
		dc.Draw3dRect(rectHeader,clrTopLeft,clrBottomRight);
		rectHeader.DeflateRect(1,1);
	}

	// Fill the background
	CBrush brush(clrBackground);
	dc.FillRect(rectHeader,&brush);	

	// Labels are offset by a certain amount  
	// This offset is related to the width of a space character
	int offset=dc.GetTextExtent(_T(" "),1).cx*2;
	rectHeader.left+=offset;
	rectHeader.right-=offset;	

	rectHeader.left+=DrawHeaderImage(hGroup, bar, &dc, rectHeader.TopLeft());

	DrawHeaderText(hGroup, bar, &dc, rectHeader, bar->GetGroupHeaderTextFormat(hGroup), false);

	DrawDropTarget(hGroup, bar, &dc, lpDrawItemStruct);

	// Restore dc	
	dc.RestoreDC(nSavedDC);
	// Detach the dc before returning	
	dc.Detach();	
}

void COXShortcutBarSkin::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
{
}

int COXShortcutBarSkin::DrawHeaderImage(HSHBGROUP hGroup, COXShortcutBar * bar, CDC *pDC, POINT topLeft )
{
	int width = 0;

	// Draw header image
	int nImage=(bar->GetExpandedGroup()==hGroup) ? 
		bar->GetGroupImageExpanded(hGroup) : bar->GetGroupImage(hGroup);
	if(nImage>=0)
	{
		ASSERT(bar->m_pImageList);
		if(bar->m_pImageList!=NULL)
		{
			bar->m_pImageList->Draw(pDC,nImage, topLeft,ILD_TRANSPARENT);
			// Adjust the rect further
			IMAGEINFO iInfo;
			VERIFY(bar->m_pImageList->GetImageInfo(nImage,&iInfo));
			width=iInfo.rcImage.right-iInfo.rcImage.left;	
		}
	}

	return width;
}

void COXShortcutBarSkin::DrawHeaderText(HSHBGROUP hGroup, COXShortcutBar * bar, CDC * pDC, RECT rectHeader, UINT nFormat, bool alwaysBold)
{
	// Get the text and format	
	CString sText=bar->GetGroupText(hGroup);
	if(rectHeader.right>rectHeader.left && !sText.IsEmpty())
	{
		// set transparent mode
		pDC->SetBkMode(TRANSPARENT);

		// set text color
		COLORREF clrText=bar->GetGroupHeaderTextColor(hGroup);
		VERIFY(clrText!=ID_COLOR_NONE);
		// invert colors for dragging group
		if(bar->GetDragGroup()==hGroup)
			clrText=InvertColor(clrText);
		pDC->SetTextColor(clrText);	

		// set text font
		CFont* pOldFont=NULL;
		LPLOGFONT pLF=bar->GetGroupHeaderTextFont(hGroup);
		ASSERT(pLF);
		CFont font;
		VERIFY(font.CreateFontIndirect(pLF));
		pOldFont=pDC->SelectObject(&font);

		// update font if specific SHBS_BOLDEXPANDEDGROUP style is set
		if(((bar->GetBarStyle()&SHBS_BOLDEXPANDEDGROUP)!=0 && bar->GetExpandedGroup()==hGroup) || alwaysBold)
		{
			// make it bold
			CFont* pFont=pDC->GetCurrentFont();
			ASSERT(pFont);
			LOGFONT lf;
			VERIFY(pFont->GetLogFont(&lf));
			lf.lfWeight=lf.lfWeight==0 ? FW_NORMAL : lf.lfWeight;
			lf.lfWeight+=FW_BOLD-FW_NORMAL;
			lf.lfWeight=lf.lfWeight>1000 ? 1000 : lf.lfWeight;

			if(pOldFont!=NULL)
				pDC->SelectObject(pOldFont);
			if((HFONT)font!=NULL)
				font.DeleteObject();
			VERIFY(font.CreateFontIndirect(&lf));
			pOldFont=pDC->SelectObject(&font);
		}

		pDC->DrawText(sText,&rectHeader,nFormat);

		if(pOldFont!=NULL)
		{
			pDC->SelectObject(pOldFont);
		}
	}
}

void COXShortcutBarSkin::DrawDropTarget(HSHBGROUP hGroup, COXShortcutBar * bar, CDC *pDC, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// get background colors
	COLORREF clrBackground=bar->GetGroupHeaderBkColor(hGroup);
	VERIFY(clrBackground!=ID_COLOR_NONE);
	// invert colors for dragging group
	if(bar->GetDragGroup()==hGroup)
	{
		clrBackground=InvertColor(clrBackground);
	}

	// drop target effect for drop target group
	HSHBGROUP hDragGroup=bar->GetDragGroup();
	HSHBGROUP hDropHilightGroup=bar->GetDropHilightGroup();
	if(hDropHilightGroup!=NULL && hDropHilightGroup==hGroup && 
		hDropHilightGroup!=hDragGroup)
	{
		ASSERT(hDragGroup);

		// use red color to draw the effect
		COLORREF clrDragDropEffect=RGB(255,0,0);
		// if the header background color is to close to red then use blue one
		if(IsColorCloseTo(clrDragDropEffect,clrBackground,64))
		{
			clrDragDropEffect=RGB(0,0,255);
		}

		// get orders of drop target and drag groups
		int nDropHilightOrder=bar->GetGroupOrder(hDropHilightGroup);
		ASSERT(bar->VerifyOrder(nDropHilightOrder));
		int nDragOrder=bar->GetGroupOrder(hDragGroup);
		ASSERT(bar->VerifyOrder(nDragOrder));

		CRect rect=lpDrawItemStruct->rcItem;	

		CBrush brush(clrDragDropEffect);
		pDC->FrameRect(rect,&brush);

		rect.DeflateRect(4,4);
		CPen pen(PS_SOLID,1,clrDragDropEffect);
		CPen* pOldPen=pDC->SelectObject(&pen);

		// drag group will be placed after drag target group
		if(nDropHilightOrder<nDragOrder)
		{
			// left up arrow
			pDC->MoveTo(rect.left+2,rect.top+9);
			pDC->LineTo(rect.left+2,rect.top+3);

			pDC->MoveTo(rect.left+3,rect.top+9);
			pDC->LineTo(rect.left+3,rect.top+3);

			pDC->MoveTo(rect.left+4,rect.top+9);
			pDC->LineTo(rect.left+4,rect.top+3);

			pDC->MoveTo(rect.left,rect.top+3);
			pDC->LineTo(rect.left+7,rect.top+3);

			pDC->MoveTo(rect.left+1,rect.top+2);
			pDC->LineTo(rect.left+6,rect.top+2);

			pDC->MoveTo(rect.left+2,rect.top+1);
			pDC->LineTo(rect.left+5,rect.top+1);

			pDC->MoveTo(rect.left+3,rect.top);
			pDC->LineTo(rect.left+4,rect.top);

			// right up arrow
			pDC->MoveTo(rect.right-2,rect.top+9);
			pDC->LineTo(rect.right-2,rect.top+3);

			pDC->MoveTo(rect.right-3,rect.top+9);
			pDC->LineTo(rect.right-3,rect.top+3);

			pDC->MoveTo(rect.right-4,rect.top+9);
			pDC->LineTo(rect.right-4,rect.top+3);

			pDC->MoveTo(rect.right,rect.top+3);
			pDC->LineTo(rect.right-7,rect.top+3);

			pDC->MoveTo(rect.right-1,rect.top+2);
			pDC->LineTo(rect.right-6,rect.top+2);

			pDC->MoveTo(rect.right-2,rect.top+1);
			pDC->LineTo(rect.right-5,rect.top+1);

			pDC->MoveTo(rect.right-3,rect.top);
			pDC->LineTo(rect.right-4,rect.top);
		}
		// drag group will be placed before drag target group
		else if(nDropHilightOrder>nDragOrder)
		{
			// left down arrow
			pDC->MoveTo(rect.left+2,rect.bottom-9);
			pDC->LineTo(rect.left+2,rect.bottom-3);

			pDC->MoveTo(rect.left+3,rect.bottom-9);
			pDC->LineTo(rect.left+3,rect.bottom-3);

			pDC->MoveTo(rect.left+4,rect.bottom-9);
			pDC->LineTo(rect.left+4,rect.bottom-3);

			pDC->MoveTo(rect.left,rect.bottom-3);
			pDC->LineTo(rect.left+7,rect.bottom-3);

			pDC->MoveTo(rect.left+1,rect.bottom-2);
			pDC->LineTo(rect.left+6,rect.bottom-2);

			pDC->MoveTo(rect.left+2,rect.bottom-1);
			pDC->LineTo(rect.left+5,rect.bottom-1);

			pDC->MoveTo(rect.left+3,rect.bottom);
			pDC->LineTo(rect.left+4,rect.bottom);

			// right down arrow
			pDC->MoveTo(rect.right-2,rect.bottom-9);
			pDC->LineTo(rect.right-2,rect.bottom-3);

			pDC->MoveTo(rect.right-3,rect.bottom-9);
			pDC->LineTo(rect.right-3,rect.bottom-3);

			pDC->MoveTo(rect.right-4,rect.bottom-9);
			pDC->LineTo(rect.right-4,rect.bottom-3);

			pDC->MoveTo(rect.right,rect.bottom-3);
			pDC->LineTo(rect.right-7,rect.bottom-3);

			pDC->MoveTo(rect.right-1,rect.bottom-2);
			pDC->LineTo(rect.right-6,rect.bottom-2);

			pDC->MoveTo(rect.right-2,rect.bottom-1);
			pDC->LineTo(rect.right-5,rect.bottom-1);

			pDC->MoveTo(rect.right-3,rect.bottom);
			pDC->LineTo(rect.right-4,rect.bottom);
		}
		else
		{
			ASSERT(FALSE);
		}

		if(pOldPen!=NULL)
		{
			pDC->SelectObject(pOldPen);
		}
	}
}


// COXShortcutBarSkinClassic
//
COLORREF COXShortcutBarSkinClassic::GetBackgroundColor(CWnd* /*pWnd*/)
{
	return GetSysColor(COLOR_3DSHADOW);
}

COLORREF COXShortcutBarSkinClassic::GetGroupTextColor(COXShortcutBar* /*pShortcutBar*/)
{
	return ::GetSysColor(COLOR_CAPTIONTEXT);
}

void COXShortcutBarSkinClassic::DrawItemBorder(CDC* pDC, LPCRECT lpRect, BOOL bHot, BOOL bSelected, COXSHBListCtrl* pSHBListCtrl)
{
	COLORREF clrTopLeft = UpdateColor(pSHBListCtrl->GetBkColor(), 64);
	COLORREF clrBottomRight = UpdateColor(pSHBListCtrl->GetBkColor(), -128);

	if (bSelected)
		pDC->Draw3dRect(lpRect, clrBottomRight, clrTopLeft); // sunken
	else if (bHot)
		pDC->Draw3dRect(lpRect, clrTopLeft, clrBottomRight); // raised
}

COLORREF COXShortcutBarSkinClassic::UpdateColor(COLORREF clr, int nOffset)
{
	ASSERT(abs(nOffset)<256);

	int rValue=GetRValue(clr)+nOffset;
	int gValue=GetGValue(clr)+nOffset;
	int bValue=GetRValue(clr)+nOffset;
	if(nOffset>0)
	{
		rValue=rValue>255 ? 255 : rValue;
		gValue=gValue>255 ? 255 : gValue;
		bValue=bValue>255 ? 255 : bValue;
	}
	else
	{
		rValue=rValue<0 ? 0 : rValue;
		gValue=gValue<0 ? 0 : gValue;
		bValue=bValue<0 ? 0 : bValue;
	}

	return RGB(rValue,gValue,bValue);
}

void COXShortcutBarSkinClassic::FillBackground(CDC* pDC, LPCRECT lpRect, CWnd* pWnd, BOOL bHasBackgroundColor, COLORREF clrBackgroundColor)
{
	CRect rect(lpRect);
	if (pWnd->IsKindOf(RUNTIME_CLASS(COXSHBListCtrl)))
			rect.OffsetRect(-rect.left, -rect.top);
	
	// Determine the background color
	if (bHasBackgroundColor)
		pDC->FillSolidRect(rect, clrBackgroundColor);
	else
		pDC->FillSolidRect(rect, GetBackgroundColor(pWnd));
}

// COXShortcutBarSkinXP
//

COXShortcutBarSkinXP::COXShortcutBarSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
	m_bAnimate = true;
}

COLORREF COXShortcutBarSkinXP::GetBackgroundColor(CWnd* /*pWnd*/)
{
	return m_pSkinXP->GetBackgroundColor();
}

COLORREF COXShortcutBarSkinXP::GetGroupTextColor(COXShortcutBar* /*pShortcutBar*/)
{
	return ::GetSysColor(COLOR_WINDOWTEXT);
}

void COXShortcutBarSkinXP::DrawItemBorder(CDC* pDC, LPCRECT lpRect, BOOL bHot, BOOL bSelected, COXSHBListCtrl* /*pSHBListCtrl*/)
{
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
	CPen* pOldPen = pDC->SelectObject(&pen);

	CBrush brush;
	if (bHot && bSelected)
		brush.CreateSolidBrush(m_pSkinXP->GetHotSelectedItemColor());
	else if (bHot)
		brush.CreateSolidBrush(m_pSkinXP->GetHotItemColor());
	else if (bSelected)
		brush.CreateSolidBrush(m_pSkinXP->GetCheckedItemColor());

	CBrush* pOldBrush = pDC->SelectObject(&brush);

	pDC->Rectangle(lpRect);

	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
}

void COXShortcutBarSkinXP::FillBackground(CDC* pDC, LPCRECT lpRect, CWnd* pWnd, BOOL bHasBackgroundColor, COLORREF clrBackgroundColor)
{
	CRect rect(lpRect);
	if (pWnd->IsKindOf(RUNTIME_CLASS(COXSHBListCtrl)))
			rect.OffsetRect(-rect.left, -rect.top);
	
	if (bHasBackgroundColor)
		pDC->FillSolidRect(rect, clrBackgroundColor);	
	else
		pDC->FillSolidRect(rect, GetBackgroundColor(pWnd));
}

void COXShortcutBarSkinXP::DrawTopHeader(COXShortcutBar * /*bar*/, CDC * /*pDC*/) 
{
}


// COXShortcutBarSkin2003
//

COXShortcutBarSkin2003::COXShortcutBarSkin2003(COXSkin2003* pSkin2003) :
	COXShortcutBarSkinXP(pSkin2003)
{
	m_bAnimate = false;
}

COXShortcutBarSkin2003::~COXShortcutBarSkin2003()
{
	m_bAnimate = false;
}

void COXShortcutBarSkin2003::DrawHeader(LPDRAWITEMSTRUCT lpDrawItemStruct, COXShortcutBar * bar)
{
	HSHBGROUP hGroup=(HSHBGROUP)(INT_PTR)lpDrawItemStruct->itemID;
	ASSERT(hGroup);

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);	

	// Get the header rect
	CRect rect(lpDrawItemStruct->rcItem);	

	// Save DC
	int nSavedDC=dc.SaveDC();
	ASSERT(nSavedDC);

//	if(bar->GetDragGroup()==hGroup || bar->m_bCreatingDragImage)

	if(bar->GetExpandedGroup()==hGroup)
	{
		if(hGroup==bar->m_hLastMouseIsOverGroup)
		{
		pSkin2003->FourPointGradientFill(&dc, rect,
			pSkin2003->GetSelShortcutBarDarkColor(), 
			pSkin2003->GetSelShortcutBarDarkColor(), 
			pSkin2003->GetSelShortcutBarLightColor(),
			pSkin2003->GetSelShortcutBarLightColor()); 
		}
		else
		{
			pSkin2003->FourPointGradientFill(&dc, rect,
				pSkin2003->GetSelShortcutBarLightColor(),
				pSkin2003->GetSelShortcutBarLightColor(), 
				pSkin2003->GetSelShortcutBarDarkColor(), 
				pSkin2003->GetSelShortcutBarDarkColor());
		}
	}
	else if(hGroup==bar->m_hLastMouseIsOverGroup)
{
		pSkin2003->FourPointGradientFill(&dc, rect,
			pSkin2003->GetHotShortcutBarLightColor(),
			pSkin2003->GetHotShortcutBarLightColor(), 
			pSkin2003->GetHotShortcutBarDarkColor(), 
			pSkin2003->GetHotShortcutBarDarkColor());
	}
	else
	{
		pSkin2003->FourPointGradientFill(&dc, rect,
			pSkin2003->GetShortcutBarLightColor(),
			pSkin2003->GetShortcutBarLightColor(), 
			pSkin2003->GetShortcutBarDarkColor(), 
			pSkin2003->GetShortcutBarDarkColor());
	}

	dc.FillSolidRect(rect.left, rect.bottom - 1, rect.right - rect.left, 1, RGB(0, 45, 150));

	CRect rectImage(rect);
	rectImage.OffsetRect(6,6);
	
	rectImage.left += DrawHeaderImage(hGroup, bar, &dc, rectImage.TopLeft()) + 6;
	DrawHeaderText(hGroup, bar, &dc, rectImage, DT_VCENTER, true);
	DrawDropTarget(hGroup, bar, &dc, lpDrawItemStruct);


	// Restore dc	
	dc.RestoreDC(nSavedDC);
	// Detach the dc before returning	
	dc.Detach();
}


void COXShortcutBarSkin2003::FillBackground(CDC* pDC, LPCRECT lpRect, CWnd* pWnd, BOOL bHasBackgroundColor, COLORREF clrBackgroundColor)
{
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	CRect rect(lpRect);

	// If this DC belogs to the COXSHBListCtrl class we need to do some
	// coordinate transformations
	COXSHBListCtrl* pSHBListCtrl = DYNAMIC_DOWNCAST(COXSHBListCtrl, pWnd);
	if (pSHBListCtrl != NULL)
	{
		CRect rectClient;
		pSHBListCtrl->m_pShortcutBar->GetClientRect(rectClient);

		CRect rectShortcutBar, rectSHBListCtrl;
		pSHBListCtrl->m_pShortcutBar->GetWindowRect(rectShortcutBar);
		pSHBListCtrl->GetWindowRect(rectSHBListCtrl);

		CPoint ptOffset(rectSHBListCtrl.left - rectShortcutBar.left,
			rectSHBListCtrl.top - rectShortcutBar.top);

		rect.left = -rect.left - ptOffset.x;
		rect.top = -rect.top - ptOffset.y;
		rect.right = rect.left + rectClient.Width();
		rect.bottom = rect.top + rectClient.Height();
	}

	if (bHasBackgroundColor)
		pDC->FillSolidRect(rect, clrBackgroundColor);
	else
		pSkin2003->FourPointGradientFill(pDC, rect,
			pSkin2003->GetShortcutBarLightColor(),
			pSkin2003->GetShortcutBarDarkColor(), 
			pSkin2003->GetShortcutBarDarkColor(), 
			pSkin2003->GetShortcutBarDarkColor());
}

void COXShortcutBarSkin2003::DrawTopHeader(COXShortcutBar * bar, CDC * pDC) 
{	
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	CRect rcHeader;
	bar->GetClientRect(&rcHeader);
	rcHeader.bottom = DFLT_TOPHDRHEIGHT2003;
	pSkin2003->FourPointGradientFill(pDC, &rcHeader,  RGB(85,131,211), RGB(85,131,211), RGB(3,56,147), RGB(3,56,147));

	// Get the text and format	
	HSHBGROUP hGroup=bar->GetExpandedGroup();
	CString sText=bar->GetGroupText(hGroup);
	if(!sText.IsEmpty())
	{
		// set transparent mode
		pDC->SetBkMode(TRANSPARENT);

		// set text color
		pDC->SetTextColor(RGB(255, 255, 255));	

		// set text font
		CFont* pOldFont=NULL;
		LPLOGFONT pLF=bar->GetGroupHeaderTextFont(hGroup);
		ASSERT(pLF);
		pLF->lfHeight = 22;
		pLF->lfWeight= FW_BOLD;
		CFont font;
		VERIFY(font.CreateFontIndirect(pLF));
		pOldFont=pDC->SelectObject(&font);

		CRect rcText(rcHeader);
		rcText.OffsetRect(6, 2);

		pDC->DrawText(sText,&rcText, DT_VCENTER);

		if(pOldFont!=NULL)
		{
			pDC->SelectObject(pOldFont);
		}
	}

	pDC->ExcludeClipRect(rcHeader);
}

// COXSkin
//

COXSkin::COXSkin() :
	m_pToolbarSkin(NULL),
	m_pMenuSkin(NULL),
	m_pMenubarSkin(NULL),
	m_pDockbarSkin(NULL),
	m_pTabSkin(NULL),
	m_pShortcutBarSkin(NULL),
	m_pMiniFrameSkin(NULL),
	m_pStatusbarSkin(NULL),
	m_pFrameSkin(NULL)
{

}

COXSkin::~COXSkin()
{
	if (m_pToolbarSkin != NULL)
		delete m_pToolbarSkin;

	if (m_pMenuSkin != NULL)
		delete m_pMenuSkin;

	if (m_pMenubarSkin != NULL)
		delete m_pMenubarSkin;

	if (m_pDockbarSkin != NULL)
		delete m_pDockbarSkin;

	if (m_pTabSkin != NULL)
		delete m_pTabSkin;

	if (m_pShortcutBarSkin != NULL)
		delete m_pShortcutBarSkin;

	if (m_pMiniFrameSkin != NULL)
		delete m_pMiniFrameSkin;
	
	if (m_pStatusbarSkin != NULL)
		delete m_pStatusbarSkin;

	if (m_pFrameSkin != NULL)
		delete m_pFrameSkin;
}

CString COXSkin::GetName() const
{
	return m_strName;
}

COXToolbarSkin* COXSkin::GetToolbarSkin() const
{
	return m_pToolbarSkin;
}

COXMenuSkin* COXSkin::GetMenuSkin() const
{
	return m_pMenuSkin;
}

COXDockbarSkin* COXSkin::GetDockbarSkin() const
{
	return m_pDockbarSkin;
}

COXTabSkin* COXSkin::GetTabSkin() const
{
	return m_pTabSkin;
}

COXShortcutBarSkin* COXSkin::GetShortcutBarSkin() const
{
	return m_pShortcutBarSkin;
}

COXToolbarSkin* COXSkin::GetMenubarSkin() const
{
	return m_pMenubarSkin;
}

COXMiniFrameSkin* COXSkin::GetMiniFrameSkin() const
{
	return m_pMiniFrameSkin;
}

COXStatusbarSkin* COXSkin::GetStatusbarSkin() const
{
	return m_pStatusbarSkin;
}

COXFrameSkin* COXSkin::GetFrameSkin() const
{
	return m_pFrameSkin;
}

void COXSkin::SetToolbarSkin(COXToolbarSkin* pToolbarSkin)
{
	if (m_pToolbarSkin != NULL)
		delete m_pToolbarSkin;

	m_pToolbarSkin = pToolbarSkin;
}

void COXSkin::SetTabSkin(COXTabSkin* pTabSkin)
{
	if (m_pTabSkin != NULL)
		delete m_pTabSkin;

	m_pTabSkin = pTabSkin;
}

void COXSkin::SetStatusbarSkin(COXStatusbarSkin* pStatusbarSkin)
{
	if (m_pStatusbarSkin != NULL)
		delete m_pStatusbarSkin;

	m_pStatusbarSkin = pStatusbarSkin;
}

void COXSkin::SetShortcutBarSkin(COXShortcutBarSkin* pShortcutBarSkin)
{
	if (m_pShortcutBarSkin != NULL)
		delete m_pShortcutBarSkin;

	m_pShortcutBarSkin = pShortcutBarSkin;
}

void COXSkin::SetMiniFrameSkin(COXMiniFrameSkin* pMiniFrameSkin)
{
	if (m_pMiniFrameSkin != NULL)
		delete m_pMiniFrameSkin;

	m_pMiniFrameSkin = pMiniFrameSkin;
}

void COXSkin::SetMenuSkin(COXMenuSkin* pMenuSkin)
{
	if (m_pMenuSkin != NULL)
		delete m_pMenuSkin;

	m_pMenuSkin = pMenuSkin;
}

void COXSkin::SetMenubarSkin(COXToolbarSkin* pMenubarSkin)
{
	if (m_pMenubarSkin != NULL)
		delete m_pMenubarSkin;

	m_pMenubarSkin = pMenubarSkin;
}

void COXSkin::SetFrameSkin(COXFrameSkin* pFrameSkin)
{
	if (m_pFrameSkin != NULL)
		delete m_pFrameSkin;

	m_pFrameSkin = pFrameSkin;
}

void COXSkin::SetDockbarSkin(COXDockbarSkin* pDockbarSkin)
{
	if (m_pDockbarSkin != NULL)
		delete m_pDockbarSkin;

	m_pDockbarSkin = pDockbarSkin;
}

CString COXSkin::GetProperty(LPCTSTR lpszName) const
{
	CString strValue;
	BOOL bResult = m_mapProperties.Lookup(lpszName, strValue);
	if (bResult)
		return strValue;
	else
		return _T("");
}

void COXSkin::SetProperty(LPCTSTR lpszName, LPCTSTR lpszValue)
{
	m_mapProperties.SetAt(lpszName, lpszValue);
}


// COXSkinClassic
//

COXSkinClassic::COXSkinClassic()
{
	m_strName = _T("Classic");
    m_pToolbarSkin = new COXToolbarSkinClassic();
    m_pMenuSkin = new COXMenuSkinClassic();
    m_pMenubarSkin = new COXToolbarSkinClassic();
    m_pDockbarSkin = new COXDockbarSkinClassic();
    m_pTabSkin = new COXTabSkinClassic();
    m_pShortcutBarSkin = new COXShortcutBarSkinClassic();
	m_pMiniFrameSkin = new COXMiniFrameSkinClassic();
	m_pStatusbarSkin = new COXStatusbarSkinClassic();
	m_pFrameSkin = new COXFrameSkinClassic();
}

COXSkinClassic::~COXSkinClassic()
{

}

/////////////////////////////////////////////////////////////////////////////
// COXSkinnedApp

IMPLEMENT_DYNCREATE(COXSkinnedApp, CWinApp)

COXSkinnedApp::COXSkinnedApp() :
	m_pCurrentSkin(NULL)
{
	// Add the skins
	AddSkin(new COXSkinClassic());
	AddSkin(new COXSkinXP());
	AddSkin(new COXSkin2003());
	SetCurrentSkin(_T("Office XP"));
}

COXSkinnedApp::~COXSkinnedApp()
{
	POSITION pos = m_mapSkins.GetStartPosition();
	while (pos != NULL)
	{
		CString strName;
		COXSkin* pSkin;
		m_mapSkins.GetNextAssoc(pos, strName, (void*&) pSkin);
		delete pSkin;
	}

	m_mapSkins.RemoveAll();
}

COXSkin* COXSkinnedApp::GetCurrentSkin()
{
	return m_pCurrentSkin;
}

void COXSkinnedApp::AddSkin(COXSkin* pSkin)
{

	m_mapSkins.SetAt(pSkin->GetName(), pSkin);
}

BOOL COXSkinnedApp::RemoveSkin(LPCTSTR lpszName)
{
	return m_mapSkins.RemoveKey(lpszName);
}

COXSkin* COXSkinnedApp::GetSkin(LPCTSTR lpszName)
{
	COXSkin* pSkin;
	BOOL bRes = m_mapSkins.Lookup(lpszName, (void*&) pSkin);
	if (bRes == FALSE)
		pSkin = NULL;

	return pSkin;
}

BOOL COXSkinnedApp::SetCurrentSkin(COXSkin* pSkin)
{
	COXSkin* pTempSkin = NULL;
	BOOL bRes = m_mapSkins.Lookup(pSkin->GetName(), (void*&) pTempSkin);
	if (bRes == FALSE)
	{
		m_pCurrentSkin = NULL;
		return FALSE;
	}

	m_currentSkin = pSkin->GetType();

	m_pCurrentSkin = pTempSkin;

	// Redraw the main window and all its descendents
	// Redraw the main window and all its descendents
	CWnd* pWnd = AfxGetMainWnd();
	if (pWnd != NULL && ::IsWindow(pWnd->m_hWnd))
	{
		UpdateFloatingWindows(pWnd);
		UpdateChildrenRec(pWnd);
	}

	return TRUE;
}

BOOL COXSkinnedApp::SetCurrentSkin(OXAppSkins skin)
{
	switch (skin)
	{
	case OXSkinClassic:
		return SetCurrentSkin(_T("Classic"));
		break;
	case OXSkinOfficeXP:
		return SetCurrentSkin(_T("Office XP"));
		break;
	case OXSkinOffice2003:
		return SetCurrentSkin(_T("Office 2003"));
		break;
	default:
		return FALSE;
	}
}


BOOL COXSkinnedApp::SetCurrentSkin(LPCTSTR lpszName)
{
	COXSkin* pTempSkin = NULL;
	BOOL bRes = m_mapSkins.Lookup(lpszName, (void*&) pTempSkin);
	if (bRes == FALSE)
	{
		m_pCurrentSkin = NULL;
		return FALSE;
	}

	m_pCurrentSkin = pTempSkin;
	m_currentSkin = pTempSkin->GetType();

	// Redraw the main window and all its descendents
	CWnd* pWnd = AfxGetMainWnd();
	if (pWnd != NULL && ::IsWindow(pWnd->m_hWnd))
	{
		UpdateFloatingWindows(pWnd);
		UpdateChildrenRec(pWnd);
	}

	return TRUE;
}

// Causes all direct and indirect children to recalculate their layouts and redraw.
// This is a recursive function.
void COXSkinnedApp::UpdateChildrenRec(CWnd* pWnd)
{
	// Update this window first
	CRect rectClient;
	pWnd->GetClientRect(rectClient);

	if ((pWnd->GetStyle() & WS_MAXIMIZE) == 0)
		pWnd->SendMessage(WM_SIZE, 0, MAKELONG(rectClient.right, rectClient.bottom));

	pWnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
		SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
	pWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);

	// Update all children
	CWnd* pChild = pWnd->GetWindow(GW_CHILD);
	while (pChild != NULL)
	{
		UpdateChildrenRec(pChild);
		pChild = pChild->GetWindow(GW_HWNDNEXT);
	}
}

// COXSkin2003
//

COXSkin2003::COXSkin2003() : COXSkinXP(TRUE)
{
	m_strName = _T("Office 2003");
    m_pToolbarSkin = new COXToolbarSkin2003(this);
    m_pMenuSkin = new COXMenuSkin2003(this);
    m_pMenubarSkin = new COXToolbarSkinXP(this);
    m_pDockbarSkin = new COXDockbarSkin2003(this);
    m_pTabSkin = new COXTabSkin2003(this);
    m_pShortcutBarSkin = new COXShortcutBarSkin2003(this);
	m_pMiniFrameSkin = new COXMiniFrameSkinXP(this);
	m_pStatusbarSkin = new COXStatusbarSkin2003(this);
	m_pFrameSkin = new COXFrameSkin2003(this);

	m_hMsimg32DLL = ::LoadLibrary(_T("Msimg32.dll"));
	if (m_hMsimg32DLL != NULL)
		m_fpGradientFill = ::GetProcAddress(m_hMsimg32DLL, "GradientFill");
}

COXSkin2003::~COXSkin2003()
{
	if (m_hMsimg32DLL != NULL)
		::FreeLibrary(m_hMsimg32DLL);
}

// This function wraps Msimg32.dll's ::GradientFill, so that we do not need SDK installed
// in order to use it.
BOOL COXSkin2003::GradientFill(CDC* pDC, LPCRECT lpRect, COLORREF clrLeft, COLORREF clrRight, ULONG dwMode)
{
	if (m_hMsimg32DLL == NULL)
		return GradientFillManual(pDC, lpRect, clrLeft, clrRight, dwMode);

	BOOL (PASCAL* pfnGradientFill)(
		HDC hdc,
		TRIVERTEX* pVertex,
		ULONG dwNumVertex, 
		PVOID pMesh,
		ULONG dwNumMesh,
		ULONG dwMode) = NULL;

	TRIVERTEX vert[2];
	GRADIENT_RECT grect;

	grect.UpperLeft = 0;
	vert[0].x = lpRect->left;
	vert[0].y = lpRect->top;
	vert[0].Alpha = 0;
	vert[0].Red = (COLOR16) (GetRValue(clrLeft) * 255);
	vert[0].Green = (COLOR16) (GetGValue(clrLeft) * 255);
	vert[0].Blue = (COLOR16) (GetBValue(clrLeft) * 255);

	grect.LowerRight = 1;
	vert[1].x = lpRect->right;
	vert[1].y = lpRect->bottom;
	vert[1].Alpha = 0;
	vert[1].Red = (COLOR16) (GetRValue(clrRight) * 255);
	vert[1].Green = (COLOR16) (GetGValue(clrRight) * 255);
	vert[1].Blue = (COLOR16) (GetBValue(clrRight) * 255);

	(FARPROC&) pfnGradientFill = m_fpGradientFill;
	return (*pfnGradientFill)(pDC->m_hDC, vert, 2, &grect, 1, dwMode);
}

// This function is just to accomodate platforms where the ::GradientFill() API is not present.
BOOL COXSkin2003::GradientFillManual(CDC* pDC, LPCRECT lpRect, COLORREF clrLeft, COLORREF clrRight, ULONG dwMode)
{
	CRect rect(lpRect);

	// First break down the colors
	int iLeftRed = GetRValue(clrLeft);
	int iLeftGreen = GetGValue(clrLeft);
	int iLeftBlue = GetBValue(clrLeft);

	int iRightRed = GetRValue(clrRight);
	int iRightGreen = GetGValue(clrRight);
	int iRightBlue = GetBValue(clrRight);

	if (dwMode == GRADIENT_FILL_RECT_H)
	{

		for (int i = 0; i < rect.Width(); i++)
		{
			// Determine the current color
			int iRed = iLeftRed + (i * (iRightRed - iLeftRed) / rect.Width());
			int iGreen = iLeftGreen + (i * (iRightGreen - iLeftGreen) / rect.Width());
			int iBlue = iLeftBlue + (i * (iRightBlue - iLeftBlue) / rect.Width());

			CPen pen;
			pen.CreatePen(PS_SOLID, 1, RGB(iRed, iGreen, iBlue));
			CPen* pOldPen = pDC->SelectObject(&pen);

			pDC->MoveTo(rect.left + i, rect.top);
			pDC->LineTo(rect.left + i, rect.bottom);

			pDC->SelectObject(pOldPen);
		}
	}
	else // vertical
	{
		for (int i = 0; i < rect.Height(); i++)
		{
			// Determine the current color
			int iRed = iLeftRed + (i * (iRightRed - iLeftRed) / rect.Height());
			int iGreen = iLeftGreen + (i * (iRightGreen - iLeftGreen) / rect.Height());
			int iBlue = iLeftBlue + (i * (iRightBlue - iLeftBlue) / rect.Height());

			CPen pen;
			pen.CreatePen(PS_SOLID, 1, RGB(iRed, iGreen, iBlue));
			CPen* pOldPen = pDC->SelectObject(&pen);

			pDC->MoveTo(rect.left, rect.top + i);
			pDC->LineTo(rect.right, rect.top + i);

			pDC->SelectObject(pOldPen);		
		}
	}
	
	return TRUE;
}

BOOL COXSkin2003::FourPointGradientFill(CDC* pDC, LPCRECT lpRect,
									  COLORREF clrTopLeft, COLORREF clrTopRight,
									  COLORREF clrBottomLeft, COLORREF clrBottomRight)
{
	if (m_hMsimg32DLL == NULL)
		return FourPointGradientFillManual(pDC, lpRect, clrTopLeft, clrTopRight,
			clrBottomLeft, clrBottomRight);

	BOOL (PASCAL* pfnGradientFill)(
		HDC hdc,
		TRIVERTEX* pVertex,
		ULONG dwNumVertex, 
		PVOID pMesh,
		ULONG dwNumMesh,
		ULONG dwMode) = NULL;

	TRIVERTEX vert[6];
	GRADIENT_TRIANGLE gtriangle[2];

	// First triangle	 _______
	//					|      /
	//					|    /
	//					|  /
	//					|/

	gtriangle[0].Vertex1 = 0;
	vert[0].x = lpRect->left;
	vert[0].y = lpRect->top;
	vert[0].Alpha = 0;
	vert[0].Red = (COLOR16) (GetRValue(clrTopLeft) * 255);
	vert[0].Green = (COLOR16) (GetGValue(clrTopLeft) * 255);
	vert[0].Blue = (COLOR16) (GetBValue(clrTopLeft) * 255);

	gtriangle[0].Vertex2 = 1;
	vert[1].x = lpRect->right;
	vert[1].y = lpRect->top;
	vert[1].Alpha = 0;
	vert[1].Red = (COLOR16) (GetRValue(clrTopRight) * 255);
	vert[1].Green = (COLOR16) (GetGValue(clrTopRight) * 255);
	vert[1].Blue = (COLOR16) (GetBValue(clrTopRight) * 255);

	gtriangle[0].Vertex3 = 2;
	vert[2].x = lpRect->left;
	vert[2].y = lpRect->bottom;
	vert[2].Alpha = 0;
	vert[2].Red = (COLOR16) (GetRValue(clrBottomLeft) * 255);
	vert[2].Green = (COLOR16) (GetGValue(clrBottomLeft) * 255);
	vert[2].Blue = (COLOR16) (GetBValue(clrBottomLeft) * 255);


	// Second triangle		    /|
	//						  /	 |
	//						/	 |
	//					  /______|
	//				

	gtriangle[1].Vertex1 = 3;
	vert[3].x = lpRect->right;
	vert[3].y = lpRect->top;
	vert[3].Alpha = 0;
	vert[3].Red = (COLOR16) (GetRValue(clrTopRight) * 255);
	vert[3].Green = (COLOR16) (GetGValue(clrTopRight) * 255);
	vert[3].Blue = (COLOR16) (GetBValue(clrTopRight) * 255);

	gtriangle[1].Vertex2 = 4;
	vert[4].x = lpRect->left;
	vert[4].y = lpRect->bottom;
	vert[4].Alpha = 0;
	vert[4].Red = (COLOR16) (GetRValue(clrBottomLeft) * 255);
	vert[4].Green = (COLOR16) (GetGValue(clrBottomLeft) * 255);
	vert[4].Blue = (COLOR16) (GetBValue(clrBottomLeft) * 255);

	gtriangle[1].Vertex3 = 5;
	vert[5].x = lpRect->right;
	vert[5].y = lpRect->bottom;
	vert[5].Alpha = 0;
	vert[5].Red = (COLOR16) (GetRValue(clrBottomRight) * 255);
	vert[5].Green = (COLOR16) (GetGValue(clrBottomRight) * 255);
	vert[5].Blue = (COLOR16) (GetBValue(clrBottomRight) * 255);


	(FARPROC&) pfnGradientFill = m_fpGradientFill;
	return (*pfnGradientFill)(pDC->m_hDC, vert, 6, gtriangle, 2, GRADIENT_FILL_TRIANGLE);
}

// This function is just to accomodate platforms where the ::GradientFill() API is not present.
BOOL COXSkin2003::FourPointGradientFillManual(CDC* pDC, LPCRECT lpRect,
									  COLORREF clrTopLeft, COLORREF clrTopRight,
									  COLORREF clrBottomLeft, COLORREF /*clrBottomRight*/)
{
	CRect rect(lpRect);

	if (rect.Width() < rect.Height())
		return GradientFillManual(pDC, lpRect, clrTopLeft, clrTopRight, GRADIENT_FILL_RECT_H);
	else
		return GradientFillManual(pDC, lpRect, clrTopLeft, clrBottomLeft, GRADIENT_FILL_RECT_V);
}

void COXSkin2003::DrawGripperStripes(CDC* pDC, CRect &rect, bool bHorizontal)
{
	CPen pen, penShadow;
	pen.CreatePen(PS_SOLID, 1, GetGripperColor());
	penShadow.CreatePen(PS_SOLID, 1, GetGripperStripesShadowColor());
	CPen* pOldPen = pDC->SelectObject(&pen);

	if (bHorizontal)
	{
		int iYPos = rect.top;
		while (iYPos <= rect.bottom)
		{
			pDC->MoveTo(rect.left, iYPos);
			pDC->LineTo(rect.right, iYPos);
			pDC->MoveTo(rect.left, iYPos + 1);
			pDC->LineTo(rect.right, iYPos + 1);

			CPen* pPrevPen = pDC->SelectObject(&penShadow);
			pDC->MoveTo(rect.left + 1, iYPos + 2);
			pDC->LineTo(rect.right + 1, iYPos + 1);
			pDC->MoveTo(rect.left + 1, iYPos + 2);
			pDC->LineTo(rect.right + 1, iYPos + 2);
			pDC->SelectObject(pPrevPen);

			iYPos += 4;
		}
	}
	else // vertical
	{
		int iXPos = rect.left;
		while (iXPos <= rect.right)
		{
			pDC->MoveTo(iXPos, rect.top);
			pDC->LineTo(iXPos, rect.bottom);
			pDC->MoveTo(iXPos + 1, rect.top);
			pDC->LineTo(iXPos + 1, rect.bottom);			
		
			CPen* pPrevPen = pDC->SelectObject(&penShadow);
			pDC->MoveTo(iXPos + 2, rect.top + 1);
			pDC->LineTo(iXPos + 1, rect.bottom + 1);
			pDC->MoveTo(iXPos + 2, rect.top + 1);
			pDC->LineTo(iXPos + 2, rect.bottom + 1);
			pDC->SelectObject(pPrevPen);			
			
			iXPos += 4;
		}
	}

	pDC->SelectObject(pOldPen);
}

// Draws an Office 2003 style frame button with a gradient background
void COXSkin2003::DrawFrameButton(CDC* pDC, CRect& rcButton, UINT uType, BOOL bDisabled, BOOL bInvertFace, COLORREF clrBackground, CWnd* pParentWnd)
{
	// First determine some colors
	COLORREF clrDisabled = 0;
	if (bDisabled)
	{
		if (bInvertFace)
		{
			bInvertFace = FALSE;
			clrDisabled = ModifyColor(clrBackground, 64, 64, 64);
		}
		else
			clrDisabled = ModifyColor(clrBackground, -96, -96, -96);
	}

	// Get the cursor position in window coordinates
	CPoint ptCursor;
	::GetCursorPos(&ptCursor);
	CRect rectWindow;
	pParentWnd->GetWindowRect(rectWindow);
	ptCursor.Offset(-rectWindow.left, -rectWindow.top);

	bool bLeftButtonDown = (pParentWnd->GetCapture() != NULL);

	// Determine the colors
	CBrush brush;
	brush.m_hObject = NULL;
	if (bLeftButtonDown && rcButton.PtInRect(ptCursor))
	{
		// Pressed
		brush.CreateSolidBrush(GetHotSelectedItemColor());
	}
	else if (rcButton.PtInRect(ptCursor))
	{
		// Hot
		brush.CreateSolidBrush(GetHotItemColor());
	}

	///////////////////////// Perform the drawing
	// Draw to a memory dc to avoid flashing
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap bmpMem;
	CRect rectMem(rcButton);
	rectMem.OffsetRect(-rectMem.left, -rectMem.top);
	bmpMem.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
	CBitmap* pOldBmp = dc.SelectObject(&bmpMem);

	if (brush.m_hObject != NULL && !bDisabled)
	{
		// Draw a frame
		CBrush* pOldBrush = dc.SelectObject(&brush);
		CPen penBorder;
		penBorder.CreatePen(PS_SOLID, 1, GetActiveBorderColor());
		CPen* pOldPen = dc.SelectObject(&penBorder);
		dc.Rectangle(rectMem);
		dc.SelectObject(pOldPen);
		dc.SelectObject(pOldBrush);
	}
	else
	{
		if (pParentWnd->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
		{
			// Draw a gradient background
			CRect rectMain;
			pParentWnd->GetParentFrame()->GetWindowRect(rectMain);

			// Get the botton screen rectangle
			CRect rectButton(rcButton);
			pParentWnd->GetParentFrame()->ClientToScreen(rectButton);

			int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
			if (iWidth < rectMain.Width())
				iWidth = rectMain.Width();

			CRect rectGradient;
			rectGradient.left = rectMain.left - rectButton.left;
			rectGradient.right = rectGradient.left + iWidth;
			rectGradient.top = 0;
			rectGradient.bottom = rectButton.Height();

			CRect rectSolid(rectGradient);
			rectGradient.right = rectGradient.CenterPoint().x;
			rectSolid.left = rectGradient.right;

			GradientFill(&dc, rectGradient,
				GetDockbarLeftColor(),
				GetDockbarRightColor(),
				GRADIENT_FILL_RECT_H);
			dc.FillSolidRect(rectSolid, GetDockbarRightColor());
		}
		else if (pParentWnd->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)))
		{
			// Draw a gradient background
			
			COXSizeControlBar* pControlBar = (COXSizeControlBar*) pParentWnd;
			
			CRect rectMain = pControlBar->m_rectGripper;
			pControlBar->ClientToScreen(rectMain);

			// Get the botton screen rectangle
			CRect rectButton(rcButton);
			pParentWnd->ClientToScreen(rectButton);

			CRect rectGradient;
			if (pControlBar->m_dwStyle & CBRS_ORIENT_HORZ)
			{
				rectGradient.left = -rcButton.left;
				rectGradient.right = rectGradient.left + rectMain.Width();
				rectGradient.top = 0;
				rectGradient.bottom = rcButton.Height();

				GradientFill(&dc, rectGradient,
					GetControlBarLightColor(),
					GetControlBarDarkColor(),
					GRADIENT_FILL_RECT_H);
			}
			else
			{
				rectGradient.left = 0;
				rectGradient.right = rcButton.Width();
				rectGradient.top = -rcButton.top;
				rectGradient.bottom = rectGradient.top + rectMain.Height();

				GradientFill(&dc, rectGradient,
					GetControlBarLightColor(),
					GetControlBarDarkColor(),
					GRADIENT_FILL_RECT_V);
			}
		}
	}

	// Draw the symbol transparently
	CDC dcSymbol;
	dcSymbol.CreateCompatibleDC(pDC);
	CBitmap bmpSymbol;
	CRect rcSymbol(rectMem);
	rcSymbol.DeflateRect(2, 2);
	bmpSymbol.CreateCompatibleBitmap(pDC, rcSymbol.Width(), rcSymbol.Height());
	CBitmap* pOldBitmap = dcSymbol.SelectObject(&bmpSymbol);
	dcSymbol.DrawFrameControl(CRect(-2, -2, rcSymbol.Width() + 2, rcSymbol.Height() + 2),
		DFC_CAPTION, DFCS_FLAT | uType);

	COLORREF clrTransparent = ::GetSysColor(COLOR_BTNFACE);

	if (bLeftButtonDown && rcButton.PtInRect(ptCursor))
	{
		// Pressed, so invert the face color of the symbol
		dcSymbol.BitBlt(0, 0, rcSymbol.Width(), rcSymbol.Height(), &dcSymbol, 0, 0, PATINVERT);
		clrTransparent = InvertColor(clrTransparent);
	}
	else if (bInvertFace && !(rcButton.PtInRect(ptCursor)))
	{
		// Invert the face color
		dcSymbol.BitBlt(0, 0, rcSymbol.Width(), rcSymbol.Height(), &dcSymbol, 0, 0, PATINVERT);
		clrTransparent = InvertColor(clrTransparent);
	}

	dcSymbol.SelectObject(pOldBitmap);
	DrawTransparentBitmap(&bmpSymbol, &dc, 2, 2, rcSymbol.Width(), rcSymbol.Height(), clrTransparent);

	if (bDisabled)
	{
		// Draw a disabled button
		dc.SelectObject(pOldBmp);

		CBitmap bmpDisabled;
		bmpDisabled.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
		pOldBmp = dc.SelectObject(&bmpDisabled);

		dc.FillSolidRect(CRect(0, 0, rcButton.Width(), rcButton.Height()), clrDisabled);
		DrawTransparentBitmap(&bmpMem, &dc, 0, 0, rcButton.Width(), rcButton.Height(), 0);

		// Copy the memory dc to the real dc
		pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
		dc.SelectObject(pOldBmp);	
	}
	else
	{
		// Copy the memory dc to the real dc
		pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
		dc.SelectObject(pOldBmp);
	}
}


COLORREF COXSkin2003::GetToolbarLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 78% window background color, 22% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.78f, 0.22f, 0);
	}
}

COLORREF COXSkin2003::GetToolbarDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		// 4% window background color, 96% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.04f, 0.96f, 0);
	}
}

COLORREF COXSkin2003::GetMenuStripLeftColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 86% window background color, 14% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.86f, 0.14f, 0);
	}
}

COLORREF COXSkin2003::GetMenuStripRightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		// 8% window background color, 92% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.08f, 0.92f, 0);
	}
}

// Returns the color of the gripper
COLORREF COXSkin2003::GetGripperColor()
{

	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT),0 , 0,
			0.7f, 0.3f, 0);
	}
	else
	{
		return COXSkinXP::GetGripperColor();
	}
}

COLORREF COXSkin2003::GetGripperStripesShadowColor()
{
	return ::GetSysColor(COLOR_WINDOW);
}

COLORREF COXSkin2003::GetControlBarLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 73% window background color, 27% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.73f, 0.27f, 0);
	}
}

COLORREF COXSkin2003::GetControlBarDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		return ::GetSysColor(COLOR_3DFACE);
	}
}

COLORREF COXSkin2003::GetDockbarLeftColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.5f, 0.5f, 0);
	}
	else
	{
		return ::GetSysColor(COLOR_3DFACE);
	}
}

COLORREF COXSkin2003::GetDockbarRightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.7f, 0.3f, 0);
	}
	else
	{
		// 80% window background color, 20% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.8f, 0.2f, 0);
	}
}

COLORREF COXSkin2003::GetTabBackgroundLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 78% window background color, 22% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.78f, 0.22f, 0);
	}
}

COLORREF COXSkin2003::GetTabBackgroundDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		// 4% window background color, 96% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.04f, 0.96f, 0);
	}
}

COLORREF COXSkin2003::GetTabItemLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 73% window background color, 27% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.73f, 0.27f, 0);
	}
}

COLORREF COXSkin2003::GetTabItemDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return GetDockbarRightColor();
	}
	else
	{
		return ::GetSysColor(COLOR_3DFACE);
	}
}

COLORREF COXSkin2003::GetMenubarItemLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 86% window background color, 14% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.86f, 0.14f, 0);
	}
}

COLORREF COXSkin2003::GetMenubarItemDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		// 58% window background color, 42% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.58f, 0.42f, 0);
	}
}

COLORREF COXSkin2003::GetShortcutBarLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.95f, 0.05f, 0);
	}
	else
	{
		// 86% window background color, 14% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.86f, 0.14f, 0);
	}
}

COLORREF COXSkin2003::GetShortcutBarDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.5f, 0.5f, 0);
	}
	else
	{
		return GetBackgroundColor();
	}
}

COLORREF COXSkin2003::GetHotShortcutBarLightColor()
{
	return GetShortcutBarLightColor();
}

COLORREF COXSkin2003::GetHotShortcutBarDarkColor()
{
	return RGB(247,192,91);
}

COLORREF COXSkin2003::GetSelShortcutBarLightColor()
{
	return GetShortcutBarLightColor();
}

COLORREF COXSkin2003::GetSelShortcutBarDarkColor()
{
	return RGB(238,149,21);
}


COLORREF COXSkin2003::GetStatusbarTopColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.3f, 0.3f, 0.4f);
	}
	else
	{
		return ::GetSysColor(COLOR_3DSHADOW);
	}
}

COLORREF COXSkin2003::GetStatusbarMiddleColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.6f, 0.4f, 0);
	}
	else
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.5f, 0.5f, 0);
	}
}

COLORREF COXSkin2003::GetStatusbarBottomColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.3f, 0.7f, 0);
	}
	else
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.2f, 0.8f, 0);
	}	
}

COLORREF COXSkin2003::GetHotItemColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 238, 194);
	else
		return COXSkinXP::GetHotItemColor();
}

COLORREF COXSkin2003::GetCheckedItemColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 192, 111);
	else
		return COXSkinXP::GetCheckedItemColor();
}

COLORREF COXSkin2003::GetHotSelectedItemColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(254, 128, 62);
	else
		return COXSkinXP::GetHotSelectedItemColor();
}

COLORREF COXSkin2003::GetHotToolbarItemLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 244, 204);
	else
		return COXSkinXP::GetHotItemColor();
}

COLORREF COXSkin2003::GetHotToolbarItemDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 208, 145);
	else
		return COXSkinXP::GetHotItemColor();
}

COLORREF COXSkin2003::GetCheckedToolbarItemLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 213, 140);
	else
		return COXSkinXP::GetCheckedItemColor();
}

COLORREF COXSkin2003::GetCheckedToolbarItemDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 173, 85);
	else
		return COXSkinXP::GetCheckedItemColor();
}

COLORREF COXSkin2003::GetHotSelectedToolbarItemLightColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(254, 145, 78);
	else
		return COXSkinXP::GetHotSelectedItemColor();
}

COLORREF COXSkin2003::GetHotSelectedToolbarItemDarkColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return RGB(255, 211, 142);
	else
		return COXSkinXP::GetHotSelectedItemColor();
}

// Returns the color of the border of a hot item
COLORREF COXSkin2003::GetActiveBorderColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
		return ModifyColor(m_UxTheme.GetThemeSysColor(hTheme, COLOR_ACTIVECAPTION),
			0, -84, -99);
	else
		return ::GetSysColor(COLOR_HIGHLIGHT);
}

// Returns the face color of the menu
COLORREF COXSkin2003::GetMenuFaceColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return RGB(246, 246, 246);
	}
	else
	{
		// 86% window background color, 14% 3DFace color
		return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
			0.86f, 0.14f, 0);
	}
}

// Returns the border color of the menu
COLORREF COXSkin2003::GetMenuBorderColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(m_UxTheme.GetThemeSysColor(hTheme, COLOR_ACTIVECAPTION),
			0, 0,
			0.55f, 0.45f, 0);
	}
	else
	{
		return ::GetSysColor(COLOR_BTNSHADOW);
	}
}

// Returns the background color of the toolbar
COLORREF COXSkin2003::GetBackgroundColor()
{
	return COXSkinXP::GetBackgroundColor();
}

// Returns the background color of the dockbar
COLORREF COXSkin2003::GetDockbarBackgroundColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return GetDockbarRightColor();
	}
	else
	{
		return ::GetSysColor(COLOR_3DFACE);
	}
}

COLORREF COXSkin2003::GetInactiveTabTextColor()
{
	return ::GetSysColor(COLOR_BTNTEXT);
}

// Returns the color of the separators
COLORREF COXSkin2003::GetSeparatorColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(::GetSysColor(COLOR_WINDOW),
			m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0,
			0.2f, 0.8f, 0);
	}
	else
	{
		return COXSkinXP::GetSeparatorColor();
	}
}

// Returns the color of the splitter line
COLORREF COXSkin2003::GetSplitterLineColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return GetShortcutBarDarkColor();
	}
	else
	{
		return COXSkinXP::GetSeparatorColor();
	}
}

COLORREF COXSkin2003::GetBorderColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return Blend3Colors(m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT), 0, 0,
			0.5f, 0.5f, 0);
	}
	else
	{
		return COXSkinXP::GetSeparatorColor();
	}
}

COLORREF COXSkin2003::GetMiniFrameCaptionColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT);
	}
	else
	{
		return COXSkinXP::GetMiniFrameCaptionColor();
	}
}

COLORREF COXSkin2003::GetMiniFrameCaptionTextColor()
{
	return COXSkinXP::GetMiniFrameCaptionTextColor();
}

COLORREF COXSkin2003::GetMiniFrameBorderColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return m_UxTheme.GetThemeSysColor(hTheme, COLOR_HIGHLIGHT);
	}
	else
	{
		return COXSkinXP::GetMiniFrameBorderColor();
	}
}

COLORREF COXSkin2003::GetMiniFrameLightBorderColor()
{
	return GetDockbarBackgroundColor();
}

COLORREF COXSkin2003::GetDisabledTextColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return RGB(141, 141, 141);
	}
	else
	{
		return COXSkinXP::GetDisabledTextColor();
	}
}

COLORREF COXSkin2003::GetDisabledMenuTextColor()
{
	HTHEME hTheme = m_UxTheme.OpenThemeData(NULL, _T("button"));
	if (hTheme != NULL)
	{
		return RGB(141, 141, 141);
	}
	else
	{
		return COXSkinXP::GetDisabledMenuTextColor();
	}
}

// COXSkinXP
//

COXSkinXP::COXSkinXP()
{
	m_strName = _T("Office XP");
    m_pToolbarSkin = new COXToolbarSkinXP(this);
    m_pMenuSkin = new COXMenuSkinXP(this);
    m_pMenubarSkin = new COXToolbarSkinXP(this);
    m_pDockbarSkin = new COXDockbarSkinXP(this);
    m_pTabSkin = new COXTabSkinXP(this);
    m_pShortcutBarSkin = new COXShortcutBarSkinXP(this);
	m_pMiniFrameSkin = new COXMiniFrameSkinXP(this);
	m_pStatusbarSkin = new COXStatusbarSkinXP(this);
	m_pFrameSkin = new COXFrameSkinXP(this);
}

COXSkinXP::~COXSkinXP()
{

}

// This function modifies the given color by adding the values passed for red gree and blue.
COLORREF COXSkinXP::ModifyColor(COLORREF crBase, int iRed, int iGreen, int iBlue)
{
	int iBaseRed = GetRValue(crBase);
	int iBaseGreen = GetGValue(crBase);
	int iBaseBlue = GetBValue(crBase);

	iBaseRed += iRed;
	if (iBaseRed > 255)
		iBaseRed = 255;

	iBaseGreen += iGreen;
	if (iBaseGreen > 255)
		iBaseGreen = 255;

	iBaseBlue += iBlue;
	if (iBaseBlue > 255)
		iBaseBlue = 255;
	
	return RGB(iBaseRed, iBaseGreen, iBaseBlue);
}

COLORREF COXSkinXP::ModifyColor(COLORREF crBase, float fRed, float fGreen, float fBlue)
{
	int iBaseRed = GetRValue(crBase);
	int iBaseGreen = GetGValue(crBase);
	int iBaseBlue = GetBValue(crBase);

	iBaseRed = (int) (iBaseRed * fRed);
	if (iBaseRed > 255)
		iBaseRed = 255;

	iBaseGreen = (int) (iBaseGreen * fGreen);
	if (iBaseGreen > 255)
		iBaseGreen = 255;

	iBaseBlue = (int) (iBaseBlue * fBlue);
	if (iBaseBlue > 255)
		iBaseBlue = 255;
	
	return RGB(iBaseRed, iBaseGreen, iBaseBlue);
}

COLORREF COXSkinXP::Blend3Colors(COLORREF clrFirst, COLORREF clrSecond, COLORREF clrThird, float fFirts, float fSecond, float fThird)
{
	int iFirstRed = GetRValue(clrFirst);
	int iFirstGreen = GetGValue(clrFirst);
	int iFirstBlue = GetBValue(clrFirst);

	int iSecondRed = GetRValue(clrSecond);
	int iSecondGreen = GetGValue(clrSecond);
	int iSecondBlue = GetBValue(clrSecond);

	int iThirdRed = GetRValue(clrThird);
	int iThirdGreen = GetGValue(clrThird);
	int iThirdBlue = GetBValue(clrThird);

	int iRed = (int) (iFirstRed * fFirts + iSecondRed * fSecond + iThirdRed * fThird);
	if (iRed > 255)
		iRed = 255;

	int iGreen = (int) (iFirstGreen * fFirts + iSecondGreen * fSecond + iThirdGreen * fThird);
	if (iGreen > 255)
		iGreen = 255;

	int iBlue = (int) (iFirstBlue * fFirts + iSecondBlue * fSecond + iThirdBlue * fThird);
	if (iBlue > 255)
		iBlue = 255;
	
	return RGB(iRed, iGreen, iBlue);
}

// Returns the color of the gripper
COLORREF COXSkinXP::GetGripperColor()
{
	// The stripe color if the button shadow color incremented by 32
	return ModifyColor(::GetSysColor(COLOR_BTNSHADOW), 32, 32, 32);
}

// Returns the color of the separators
COLORREF COXSkinXP::GetSeparatorColor()
{
	// The separator color if the button shadow color incremented by 38
	return ModifyColor(::GetSysColor(COLOR_BTNSHADOW), 38, 38, 38);
}

COLORREF COXSkinXP::GetBorderColor()
{
	return ::GetSysColor(COLOR_3DSHADOW);
}

// Returns the color of the background color of the toolbar
COLORREF COXSkinXP::GetBackgroundColor()
{
	// 16% window background color, 84% 3DFace color
	return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
		0.16f, 0.84f, 0);
}

// Returns the background color of the dockbar
COLORREF COXSkinXP::GetDockbarBackgroundColor()
{
	return ::GetSysColor(COLOR_BTNFACE);
}

// Returns the background color of the icon of a hidden item
COLORREF COXSkinXP::GetHiddenItemBackgroundColor()
{
	// The button face color decremented by 8
	return ModifyColor(::GetSysColor(COLOR_BTNFACE), -8, -8, -8);
}

// Returns the color of a hot item
COLORREF COXSkinXP::GetHotItemColor()
{
	// 70% window background color, 30% selected item color
	return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_HIGHLIGHT), 0,
		0.7f, 0.3f, 0);
}

// Returns the color of a hot selected item
COLORREF COXSkinXP::GetHotSelectedItemColor()
{
	// 50% window background color, 50% selected item color
	return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_HIGHLIGHT), 0, 
		0.5f, 0.5f, 0);
}

// Returns the color of a checked item
COLORREF COXSkinXP::GetCheckedItemColor()
{
	// 42% 3DFace color, 48% window background color, 10% highlight color
	return Blend3Colors(::GetSysColor(COLOR_3DFACE), ::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_HIGHLIGHT), 
		0.42f, 0.48f, 0.10f);
}

// Returns the color of the border of a hot item
COLORREF COXSkinXP::GetActiveBorderColor()
{
	return ::GetSysColor(COLOR_HIGHLIGHT);
}

// Returns the color of the text of a normal item
COLORREF COXSkinXP::GetTextColor()
{
	return ::GetSysColor(COLOR_BTNTEXT);
}

// Returns the color of the text of a selected item
COLORREF COXSkinXP::GetSelectedTextColor()
{
	return ::GetSysColor(COLOR_HIGHLIGHTTEXT);
}

// Returns the color of the border of the mini frame window
COLORREF COXSkinXP::GetMiniFrameBorderColor()
{
	// The color is the button shadow color decremented by 9
	return ModifyColor(::GetSysColor(COLOR_BTNSHADOW), -9, -9, -9);
}

COLORREF COXSkinXP::GetMiniFrameLightBorderColor()
{
	return GetBackgroundColor();
}

// Returns the face color of the menu
COLORREF COXSkinXP::GetMenuFaceColor()
{
	// 86% window background color, 14% 3DFace color
	return Blend3Colors(::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), 0,
		0.86f, 0.14f, 0);
}

// Returns the face color of the menu
COLORREF COXSkinXP::GetMenuBorderColor()
{
	return ::GetSysColor(COLOR_BTNSHADOW);
}

// Returns the background color of the tab buttons is a tab control
COLORREF COXSkinXP::GetTabButtonsBackgroundColor()
{
	return ModifyColor(::GetSysColor(COLOR_3DFACE), 1.2f, 1.2f, 1.2f);
}

// Returns the text color of an inselected tab button
COLORREF COXSkinXP::GetInactiveTabTextColor()
{
	return ModifyColor(::GetSysColor(COLOR_GRAYTEXT), -8, -12, -22);
}

// Returns the color of border of a status bar pan
COLORREF COXSkinXP::GetStatusPaneColor()
{
	return ModifyColor(::GetSysColor(COLOR_BTNFACE), 17, 12, 16);
}

COLORREF COXSkinXP::InvertColor(COLORREF clr)
{
	int iBaseRed = GetRValue(clr);
	int iBaseGreen = GetGValue(clr);
	int iBaseBlue = GetBValue(clr);

	return RGB(255 - iBaseRed, 255 - iBaseGreen, 255 - iBaseBlue);
}

void COXSkinXP::DrawTransparentBitmap(CBitmap* pBitmap, CDC* pDestDC, int x, int y, int nWidth, int nHeight, COLORREF clrTransColor)
{
	COLORREF crOldBack = pDestDC->SetBkColor(RGB(255, 255, 255));
	COLORREF crOldText = pDestDC->SetTextColor(RGB(0, 0, 0));
	CDC dcImage, dcTrans;

	// Create two memory dcs for the image and the mask
	dcImage.CreateCompatibleDC(pDestDC);
	dcTrans.CreateCompatibleDC(pDestDC);

	// Select the image into the appropriate dc
	CBitmap* pOldBitmapImage = dcImage.SelectObject(pBitmap);

	// Create the mask bitmap
	CBitmap bitmapTrans;
	bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

	// Select the mask bitmap into the appropriate dc
	CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

	// Build mask based on transparent colour
	dcImage.SetBkColor(clrTransColor);
	dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);

	// Do the work - True Mask method - cool if not actual display
	pDestDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
	pDestDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
	pDestDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);

	// Restore settings
	dcImage.SelectObject(pOldBitmapImage);
	dcTrans.SelectObject(pOldBitmapTrans);
	pDestDC->SetBkColor(crOldBack);
	pDestDC->SetTextColor(crOldText);
}

// Draws an Office XP style frame button
void COXSkinXP::DrawFrameButton(CDC* pDC, CRect& rcButton, UINT uType, BOOL bDisabled, BOOL bInvertFace, COLORREF clrBackground, CWnd* pParentWnd)
{
	// First determine some colors
	COLORREF clrDisabled = 0;
	if (bDisabled)
	{
		if (bInvertFace)
		{
			bInvertFace = FALSE;
			clrDisabled = ModifyColor(clrBackground, 64, 64, 64);
		}
		else
			clrDisabled = ModifyColor(clrBackground, -96, -96, -96);
	}

	// Get the cursor position in window coordinates
	CPoint ptCursor;
	::GetCursorPos(&ptCursor);
	CRect rectWindow;
	pParentWnd->GetWindowRect(rectWindow);
	ptCursor.Offset(-rectWindow.left, -rectWindow.top);

	bool bLeftButtonDown = (pParentWnd->GetCapture() != NULL);

	// Determine the colors
	CBrush brush;
	brush.m_hObject = NULL;
	if (bLeftButtonDown && rcButton.PtInRect(ptCursor))
	{
		// Pressed
		brush.CreateSolidBrush(GetHotSelectedItemColor());
	}
	else if (rcButton.PtInRect(ptCursor))
	{
		// Hot
		brush.CreateSolidBrush(GetHotItemColor());
	}

	///////////////////////// Perform the drawing
	// Draw to a memory dc to avoid flashing
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap bmpMem;
	CRect rectMem(rcButton);
	rectMem.OffsetRect(-rectMem.left, -rectMem.top);
	bmpMem.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
	CBitmap* pOldBmp = dc.SelectObject(&bmpMem);

	if (brush.m_hObject != NULL && !bDisabled)
	{
		// Draw a frame
		CBrush* pOldBrush = dc.SelectObject(&brush);
		CPen penBorder;
		penBorder.CreatePen(PS_SOLID, 1, GetActiveBorderColor());
		CPen* pOldPen = dc.SelectObject(&penBorder);
		dc.Rectangle(rectMem);
		dc.SelectObject(pOldPen);
		dc.SelectObject(pOldBrush);
	}
	else
		dc.FillSolidRect(rectMem, clrBackground);

	// Draw the symbol transparently
	CDC dcSymbol;
	dcSymbol.CreateCompatibleDC(pDC);
	CBitmap bmpSymbol;
	CRect rcSymbol(rectMem);
	rcSymbol.DeflateRect(2, 2);
	bmpSymbol.CreateCompatibleBitmap(pDC, rcSymbol.Width(), rcSymbol.Height());
	CBitmap* pOldBitmap = dcSymbol.SelectObject(&bmpSymbol);
	dcSymbol.DrawFrameControl(CRect(-2, -2, rcSymbol.Width() + 2, rcSymbol.Height() + 2),
		DFC_CAPTION, DFCS_FLAT | uType);

	COLORREF clrTransparent = ::GetSysColor(COLOR_BTNFACE);

	if (bLeftButtonDown && rcButton.PtInRect(ptCursor))
	{
		// Pressed, so invert the face color of the symbol
		dcSymbol.BitBlt(0, 0, rcSymbol.Width(), rcSymbol.Height(), &dcSymbol, 0, 0, PATINVERT);
		clrTransparent = InvertColor(clrTransparent);
	}
	else if (bInvertFace && !(rcButton.PtInRect(ptCursor)))
	{
		// Invert the face color
		dcSymbol.BitBlt(0, 0, rcSymbol.Width(), rcSymbol.Height(), &dcSymbol, 0, 0, PATINVERT);
		clrTransparent = InvertColor(clrTransparent);
	}

	dcSymbol.SelectObject(pOldBitmap);
	DrawTransparentBitmap(&bmpSymbol, &dc, 2, 2, rcSymbol.Width(), rcSymbol.Height(), clrTransparent);

	if (bDisabled)
	{
		// Draw a disabled button
		dc.SelectObject(pOldBmp);

		CBitmap bmpDisabled;
		bmpDisabled.CreateCompatibleBitmap(pDC, rectMem.Width(), rectMem.Height());
		pOldBmp = dc.SelectObject(&bmpDisabled);

		dc.FillSolidRect(CRect(0, 0, rcButton.Width(), rcButton.Height()), clrDisabled);
		DrawTransparentBitmap(&bmpMem, &dc, 0, 0, rcButton.Width(), rcButton.Height(), 0);

		// Copy the memory dc to the real dc
		pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
		dc.SelectObject(pOldBmp);	
	}
	else
	{
		// Copy the memory dc to the real dc
		pDC->BitBlt(rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), &dc, 0, 0, SRCCOPY);
		dc.SelectObject(pOldBmp);
	}
}

COLORREF COXSkinXP::GetMiniFrameCaptionColor()
{
	return ::GetSysColor(COLOR_BTNSHADOW);
}

COLORREF COXSkinXP::GetMiniFrameCaptionTextColor()
{
	return ::GetSysColor(COLOR_CAPTIONTEXT);
}

COLORREF COXSkinXP::GetDisabledTextColor()
{
	return ::GetSysColor(COLOR_GRAYTEXT);
}

COLORREF COXSkinXP::GetDisabledMenuTextColor()
{
	return GetSeparatorColor();
}

// COXToolbarSkin
//




// COXToolbarSkinClassic.cpp
//

void COXToolbarSkinClassic::DrawGripper(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
    if (pCoolToolbar->m_dwStyle & CBRS_FLOATING)
		return;		// no gripper if floating

	COLORREF clrHilight=::GetSysColor(COLOR_BTNHILIGHT);
	COLORREF clrShadow=::GetSysColor(COLOR_BTNSHADOW);
	
	CRect rect(lpRect);
	CRect gripperRect(lpRect);

	if (pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ) 
	{
		gripperRect.DeflateRect(1, 1);
		gripperRect.OffsetRect(0, 1);
		// gripper at left
		if (pCoolToolbar->m_pDockContext != NULL)
		{
			// EnableDocking was called
			gripperRect.left += 2;
			gripperRect.bottom -= 2;
		}
		else
		{
			if (pCoolToolbar->m_dwStyle & CBRS_BORDER_BOTTOM)
			{
				gripperRect.top -= 2;
				gripperRect.bottom -= 2;
			}
		}
		gripperRect.right = gripperRect.left + 3;
        pDC->Draw3dRect(gripperRect, clrHilight, clrShadow);
		gripperRect.OffsetRect(3, 0);
        pDC->Draw3dRect(gripperRect, clrHilight, clrShadow);

		rect.left = gripperRect.right + 1;
	} 
	else 
	{
		gripperRect.DeflateRect(0, 1, 2, 1);
		gripperRect.OffsetRect(0, 1);
		// gripper at top
		if (pCoolToolbar->m_pDockContext == NULL)
		{
			// EnableDocking was not called
			gripperRect.right += 2;
		}
		else
		{
			gripperRect.left += 2;
		}
		gripperRect.bottom = gripperRect.top + 3;
		pDC->Draw3dRect(gripperRect, clrHilight, clrShadow);
		gripperRect.OffsetRect(0, 3);
        pDC->Draw3dRect(gripperRect, clrHilight, clrShadow);

		rect.top = gripperRect.bottom + 1;
	}
}

void COXToolbarSkinClassic::DrawNonClientArea(CDC* pDC, LPCRECT /*lpRect*/, COXCoolToolBar* pCoolToolbar)
{
	// get window DC that is clipped to the non-client area
	CRect rectClient;
	pCoolToolbar->GetClientRect(rectClient);
	CRect rectWindow;
	pCoolToolbar->GetWindowRect(rectWindow);
	pCoolToolbar->ScreenToClient(rectWindow);
	rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
	rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

	// draw borders in non-client area
	if(!pCoolToolbar->IsCool())
	{
		// only if CoolToolBar is not used in CoolBar
		pCoolToolbar->DrawBorders(pDC, rectWindow);

		// fixing for spurious edges
		if((pCoolToolbar->m_dwStyle&CBRS_BORDER_3D)==0)
		{
			rectWindow.InflateRect(1,1);
		}
	}

	// erase parts not drawn
	pDC->IntersectClipRect(rectWindow);
	pDC->ExcludeClipRect(rectClient);
	pDC->FillSolidRect(rectWindow, ::GetSysColor(COLOR_3DFACE));
}

void COXToolbarSkinClassic::DrawSeparator(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
	CRect rc(lpRect);
	COLORREF clrHilight = ::GetSysColor(COLOR_BTNHILIGHT);
	COLORREF clrShadow = ::GetSysColor(COLOR_BTNSHADOW);
	
    BOOL bHorz= ((pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ) !=0 ) ? TRUE : FALSE;
	// make sure, this separator is not a placeholder for
	// another control.
	if (rc.Width() <= 8) 
	{
		if (bHorz) 
		{
			// draw the separator bar in the middle
			int x = (rc.left + rc.right) / 2;
			rc.left = x - 1;
			rc.right = x + 1;
			pDC->Draw3dRect(rc, clrShadow, clrHilight);
		} 
		else 
		{
			// draw the separator bar in the middle
			UINT nButtonWidth = pCoolToolbar->GetButtonsSize().cx;
			rc.left = rc.left - nButtonWidth;
			rc.right = rc.left + nButtonWidth;
			rc.top=rc.bottom + 1;
			rc.bottom = rc.top + 3;
			int y = (rc.top+rc.bottom) / 2;
			rc.top = y - 1;
			rc.bottom = y + 1;
			pDC->Draw3dRect(rc, clrShadow, clrHilight);
		}
	}
}

void COXToolbarSkinClassic::DrawCustomizedButton(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* /*pCoolToolbar*/)
{
	pDC->DrawDragRect(lpRect, CSize(2,2), CRect(0,0,0,0), CSize(0,0), NULL, NULL);
}

void COXToolbarSkinClassic::OnCustomDraw(NMHDR*& pNotify, LRESULT*& pResult, COXCoolToolBar* pCoolToolbar)
{
	// in new version of comctl32.dll(4.71)
	// we use toolbar specific custom draw structure 
	LPNMTBCUSTOMDRAW pTBCDRW=NULL;
	LPNMCUSTOMDRAW pCDRW=NULL;
	if(pCoolToolbar->m_dwComCtlVersion>=_IE40_COMCTL_VERSION)
	{
		pTBCDRW=(LPNMTBCUSTOMDRAW)pNotify;
		pCDRW=&pTBCDRW->nmcd;
	}
	else
	{
		pCDRW=(LPNMCUSTOMDRAW)pNotify;
	}

	OXCTB_CUSTOMDRAW cd;
	if(pCoolToolbar->m_dwComCtlVersion>=_IE40_COMCTL_VERSION)
	{
		ASSERT(pTBCDRW!=NULL);
		cd.pCustomDraw=(LPNMCUSTOMDRAW)pTBCDRW;
	}
	else
	{
		cd.pCustomDraw=pCDRW;
	}
	cd.hdr.hwndFrom=pCDRW->hdr.hwndFrom;
	cd.hdr.idFrom=pCDRW->hdr.idFrom;
	cd.hdr.code=OXCTBN_CUSTOMDRAW;
	cd.result=CDRF_DODEFAULT;
	cd.bDoDefault=TRUE;

	CWnd* pParentWnd=NULL;
	if(pCoolToolbar->IsFloating())
	{
		pParentWnd=pCoolToolbar->GetTopLevelParent();
	}
	else
	{
		pParentWnd=pCoolToolbar->GetParentFrame();
	}

	ASSERT(pParentWnd != NULL);

	pParentWnd->SendMessage(WM_NOTIFY,cd.hdr.idFrom,(LPARAM)&cd);

	if(pCDRW->dwDrawStage==CDDS_PREPAINT && 
		pCoolToolbar->GetToolBarCtrl().GetButtonCount()>0)
	{
		CRect rect;
		pCoolToolbar->GetItemRect(0,&rect);
	}

	if(!cd.bDoDefault)
	{
		*pResult=cd.result;
	}
	else
	{
		CDC dc;
		dc.Attach(pTBCDRW->nmcd.hdc);

		*pResult = CDRF_DODEFAULT;
		switch( pCDRW->dwDrawStage )
		{
		case CDDS_PREPAINT:
			{
				// Draw the background
				DrawBackground(&dc, pCoolToolbar);

				/////////
				// draw separators
				/////////
				// in new version of comctl32.dll(4.71)
				// separators are drawn automatically
				// well, you have a chance to draw your own separator even
				// if new version of comctl32.dll installed. But you shouldn't 
				// forget that native separators will be drawn anyway
				if(pCoolToolbar->m_dwComCtlVersion<_IE40_COMCTL_VERSION)
				{
					if(pCoolToolbar->IsFlat() && pCoolToolbar->m_bSeparator)
					{
						int nBitmap; 
						UINT uID, uStyleState;
						CRect rc;
						for(int nIndex=0; 
							nIndex<pCoolToolbar->GetToolBarCtrl().GetButtonCount(); nIndex++)
						{
							pCoolToolbar->GetButtonInfo(nIndex, uID, uStyleState, nBitmap);
							WORD wStyle=LOWORD(uStyleState);
							WORD wState=HIWORD(uStyleState);
							if(wStyle==TBSTYLE_SEP && wState!=TBSTATE_HIDDEN) 
							{
								if(!(wState & TBSTATE_WRAP))
								{
									pCoolToolbar->GetItemRect(nIndex,&rc);
									rc.top-=1;
									pCoolToolbar->DrawSeparator(dc,rc);
								}
								else
								{
									CBrush brush(::GetSysColor(COLOR_BTNFACE));
									dc.FillRect(&rc,&brush);
								}
							}
						}
					}
				}

				// draw custom button in customized state if set
				int nCustomizedButton=pCoolToolbar->GetCustomizedButton();
				if(nCustomizedButton!=-1 && pCoolToolbar->IsCustomButton(nCustomizedButton))
				{
					CRect rect;
					pCoolToolbar->GetItemRect(nCustomizedButton,rect);
					pCoolToolbar->DrawCustomizedButton(dc,rect);
				}


				*pResult = CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW;
				break;
			}

		case CDDS_ITEMPREPAINT:
			{
				*pResult = CDRF_NOTIFYPOSTPAINT;	// request for ITEMPOSTPAINT
 
				CRect rectButton(pCDRW->rc);
				CRect rectBackground(pCDRW->rc);
				if(!pCoolToolbar->GetToolBarCtrl().IsButtonHidden(PtrToInt(pCDRW->dwItemSpec))) 
				{
					if(pCDRW->uItemState & CDIS_CHECKED)
					{
						if(pCDRW->uItemState & CDIS_HOT)
						{
							// set text color
							if(pCoolToolbar->GetSelectedTextColor() != CLR_DEFAULT)
							{
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									pTBCDRW->clrText = pCoolToolbar->GetSelectedTextColor();
								}
								else
								{
									::SetTextColor(pCDRW->hdc, pCoolToolbar->GetSelectedTextColor());
								}
							}

							// draw border
							if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetSelectedBorderColor());
								dc.FrameRect(rectButton,&brush);
								rectBackground.DeflateRect(1,1,1,1);
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOEDGES;
								}
							}

							// draw background
							if(pCoolToolbar->GetSelectedBkColor() != CLR_DEFAULT)
							{
								dc.FillSolidRect(rectBackground,pCoolToolbar->GetSelectedBkColor());
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOETCHEDEFFECT;
								}
							}
						}
						else
						{
							// set text color
							if(pCoolToolbar->GetCheckedTextColor() != CLR_DEFAULT)
							{
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									pTBCDRW->clrText = pCoolToolbar->GetCheckedTextColor();
								}
								else
								{
									::SetTextColor(pCDRW->hdc, pCoolToolbar->GetCheckedTextColor());
								}
							}

							// draw border
							if(pCoolToolbar->GetCheckedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetCheckedBorderColor());
								dc.FrameRect(rectButton,&brush);
								rectBackground.DeflateRect(1,1,1,1);
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOEDGES;
								}
							}

							// draw background
							if(pCoolToolbar->GetCheckedBkColor() != CLR_DEFAULT)
							{
								dc.FillSolidRect(rectBackground,pCoolToolbar->GetCheckedBkColor());
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOETCHEDEFFECT;
								}
							}
						}
					}
					else if(pCDRW->uItemState & CDIS_HOT)
					{
						if(pCDRW->uItemState & CDIS_SELECTED)
						{
							// set text color
							if(pCoolToolbar->GetSelectedTextColor() != CLR_DEFAULT)
							{
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									pTBCDRW->clrText = pCoolToolbar->GetSelectedTextColor();
								}
								else
								{
									::SetTextColor(pCDRW->hdc, pCoolToolbar->GetSelectedTextColor());
								}
							}

							// draw border
							if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetSelectedBorderColor());
								dc.FrameRect(rectButton,&brush);
								rectBackground.DeflateRect(1,1,1,1);
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOEDGES;
								}
							}

							// draw background
							if(pCoolToolbar->GetSelectedBkColor() != CLR_DEFAULT)
							{
								dc.FillSolidRect(rectBackground,pCoolToolbar->GetSelectedBkColor());
							}
						}
						else
						{
							// set text color
							if(pCoolToolbar->GetHotTextColor() != CLR_DEFAULT)
							{
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									pTBCDRW->clrText = pCoolToolbar->GetHotTextColor();
								}
								else
								{
									::SetTextColor(pCDRW->hdc, pCoolToolbar->GetHotTextColor());
								}
							}

							// draw border
							if(pCoolToolbar->GetHotBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetHotBorderColor());
								dc.FrameRect(rectButton,&brush);
								rectBackground.DeflateRect(1,1,1,1);
								if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
								{
									*pResult |= TBCDRF_NOEDGES;
								}
							}

							// draw background
							if(pCoolToolbar->GetHotBkColor() != CLR_DEFAULT)
							{
								dc.FillSolidRect(rectBackground,pCoolToolbar->GetHotBkColor());
							}
						}
					}
					else if(pCDRW->uItemState & CDIS_SELECTED)
					{
						// set text color
						if(pCoolToolbar->GetSelectedTextColor() != CLR_DEFAULT)
						{
							if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
							{
								pTBCDRW->clrText = pCoolToolbar->GetSelectedTextColor();
							}
							else
							{
								::SetTextColor(pCDRW->hdc, pCoolToolbar->GetSelectedTextColor());
							}
						}

						// draw border
						if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
						{
							CBrush brush(pCoolToolbar->GetSelectedBorderColor());
							dc.FrameRect(rectButton,&brush);
							rectBackground.DeflateRect(1,1,1,1);
							if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
							{
								*pResult |= TBCDRF_NOEDGES;
							}
						}

						// draw background
						if(pCoolToolbar->GetSelectedBkColor() != CLR_DEFAULT)
						{
							dc.FillSolidRect(rectBackground,pCoolToolbar->GetSelectedBkColor());
						}
					}
					else
					{
						// set text color
						if(pCoolToolbar->GetDefaultTextColor() != CLR_DEFAULT)
						{
							if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
							{
								pTBCDRW->clrText = pCoolToolbar->GetDefaultTextColor();
							}
							else
							{
								::SetTextColor(pCDRW->hdc, pCoolToolbar->GetDefaultTextColor());
							}
						}

						// draw border
						if(pCoolToolbar->GetDefaultBorderColor() != CLR_DEFAULT)
						{
							CBrush brush(pCoolToolbar->GetDefaultBorderColor());
							dc.FrameRect(rectButton,&brush);
							rectBackground.DeflateRect(1,1,1,1);
							if(pCoolToolbar->m_dwComCtlVersion >= _IE40_COMCTL_VERSION)
							{
								*pResult |= TBCDRF_NOEDGES;
							}
						}

						// draw background
						if(pCoolToolbar->GetDefaultBkColor() != CLR_DEFAULT)
						{
							dc.FillSolidRect(rectBackground,pCoolToolbar->GetDefaultBkColor());
						}
					}
				}

				break;
			}

		case CDDS_ITEMPOSTPAINT:
			{
				int nIndex=pCoolToolbar->CommandToIndex(PtrToUint(pCDRW->dwItemSpec));

				if(!pCoolToolbar->GetToolBarCtrl().IsButtonHidden(PtrToInt(pCDRW->dwItemSpec)) && 
					pCoolToolbar->IsDropDownArrow() && (pCoolToolbar->GetButtonStyle(nIndex) & TBSTYLE_DROPDOWN))
				{
					CRect rectDropDownArrow(pCDRW->rc);
					rectDropDownArrow.left = 
						rectDropDownArrow.right - pCoolToolbar->GetDropDownArrowWidth();

					// draw border around drop down button
					if(pCDRW->uItemState & CDIS_CHECKED)
					{
						if(pCDRW->uItemState & CDIS_HOT)
						{
							if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetSelectedBorderColor());
								dc.FrameRect(rectDropDownArrow,&brush);
							}
						}
						else
						{
							if(pCoolToolbar->GetCheckedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetCheckedBorderColor());
								dc.FrameRect(rectDropDownArrow,&brush);
							}
						}
					}
					else if(pCDRW->uItemState & CDIS_HOT)
					{
						if(pCDRW->uItemState & CDIS_SELECTED)
						{
							if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetSelectedBorderColor());
								dc.FrameRect(rectDropDownArrow,&brush);
							}
						}
						else
						{
							if(pCoolToolbar->GetHotBorderColor() != CLR_DEFAULT)
							{
								CBrush brush(pCoolToolbar->GetHotBorderColor());
								dc.FrameRect(rectDropDownArrow,&brush);
							}
						}
					}
					else if(pCDRW->uItemState & CDIS_SELECTED)
					{
						if(pCoolToolbar->GetSelectedBorderColor() != CLR_DEFAULT)
						{
							CBrush brush(pCoolToolbar->GetSelectedBorderColor());
							dc.FrameRect(rectDropDownArrow,&brush);
						}
					}
					else
					{
						if(pCoolToolbar->GetDefaultBorderColor() != CLR_DEFAULT)
						{
							CBrush brush(pCoolToolbar->GetDefaultBorderColor());
							dc.FrameRect(rectDropDownArrow,&brush);
						}
					}
				}

				if(pCoolToolbar->IsButtonCustomized(nIndex) && !pCoolToolbar->IsCustomButton(nIndex))
				{
					CRect rect;
					pCoolToolbar->GetItemRect(nIndex,rect);
					pCoolToolbar->DrawCustomizedButton(dc,rect);
				}
#if _MFC_VER<=0x0421
				else if(pCDRW->uItemState & CDIS_CHECKED)
				{
					CRect rect;
					GetItemRect(nIndex,rect);

					if(IsDropDownArrow() && GetButtonStyle(nIndex) & TBSTYLE_DROPDOWN)
					{
						rect.right-=m_nDropDownArrowWidth;
					}

					COLORREF clrHilight=::GetSysColor(COLOR_BTNHILIGHT);
					COLORREF clrShadow=::GetSysColor(COLOR_BTNSHADOW);
					dc.Draw3dRect(rect,clrShadow,clrHilight);
				}
#endif	//	_MFC_VER<=0x0421
				break;
			}

		case CDDS_POSTPAINT:
			{
				break;
			}

		default:
			{
				// CToolBar does not send other draw-stages than the above.
				//TRACE(_T("Unknown draw stage ...\n"));
				break;
			}
		}

		dc.Detach();
	}
}

void COXToolbarSkinClassic::DrawBackground(CDC* pDC, COXCoolToolBar* pCoolToolbar)
{
	CRect rcClient;
	pCoolToolbar->GetClientRect(rcClient);

	pDC->FillSolidRect(rcClient, ::GetSysColor(COLOR_BTNFACE));
}

void COXToolbarSkinClassic::DrawMenuButtons(CDC* pDC, COXMenuBar* pMenuBar)
{
	ASSERT(pMenuBar->m_pFrameWnd!=NULL);
	ASSERT(::IsWindow(pMenuBar->m_pFrameWnd->m_hWnd));
	ASSERT_KINDOF(CMDIFrameWnd,pMenuBar->m_pFrameWnd);

    BOOL bMaximize=FALSE;
	CMDIChildWnd* pChild=((CMDIFrameWnd*)pMenuBar->m_pFrameWnd)->MDIGetActive(&bMaximize);
	if(pChild==NULL || !bMaximize)
		return;

	ASSERT(!pMenuBar->m_rectCloseBtn.IsRectEmpty());
	if(pMenuBar->m_rectCloseBtn.IsRectEmpty())
		return;

	DWORD dwStyle=pChild->GetStyle();

	UINT nPushState;

	// close button
	nPushState=(pMenuBar->m_pressedBtn==OX_MNU_CLOSEBTN) ? DFCS_PUSHED : 0;
	pDC->DrawFrameControl(&pMenuBar->m_rectCloseBtn,DFC_CAPTION,
		DFCS_CAPTIONCLOSE|nPushState);

	// Max/restore button
	if(!pMenuBar->m_rectRestoreBtn.IsRectEmpty())
	{
		UINT nState=DFCS_CAPTIONRESTORE;
		if((dwStyle&WS_MAXIMIZEBOX)==0)
			nState|=DFCS_INACTIVE;
		nPushState=(pMenuBar->m_pressedBtn==OX_MNU_RESTOREBTN) ? DFCS_PUSHED : 0;
		pDC->DrawFrameControl(&pMenuBar->m_rectRestoreBtn,DFC_CAPTION,nState|nPushState);
	}

	// Minimize button
	if(!pMenuBar->m_rectMinimizeBtn.IsRectEmpty())
	{
		UINT nState=DFCS_CAPTIONMIN;
		if((dwStyle&WS_MINIMIZEBOX)==0)
			nState|=DFCS_INACTIVE;
		nPushState=(pMenuBar->m_pressedBtn==OX_MNU_MINIMIZEBTN) ? DFCS_PUSHED : 0;
		pDC->DrawFrameControl(&pMenuBar->m_rectMinimizeBtn,DFC_CAPTION,nState|nPushState);
	}
}

// COXToolbarSkinXP
//

COXToolbarSkinXP::COXToolbarSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
}

void COXToolbarSkinXP::DrawGripper(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
    if (pCoolToolbar->m_dwStyle & CBRS_FLOATING)
		return;		// no gripper if floating

	CRect rect(lpRect);
	CRect gripperRect(lpRect);

	if (pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ) 
	{
		gripperRect.DeflateRect(2, 6, 2, 5);
		// gripper at left
		if (pCoolToolbar->m_pDockContext != NULL)
		{
			// EnableDocking was called
			gripperRect.left += 2;
			gripperRect.bottom -= 2;
		}
		else
		{
			if (pCoolToolbar->m_dwStyle & CBRS_BORDER_BOTTOM)
			{
				gripperRect.top -= 2;
				gripperRect.bottom -= 2;
			}
		}
		gripperRect.right = gripperRect.left + 3;
        DrawGripperStripes(pDC, gripperRect, true);
	} 
	else // vertical
	{
		gripperRect.DeflateRect(3, 4, 7, 4);
		// gripper at top
		if (pCoolToolbar->m_pDockContext == NULL)
		{
			// EnableDocking was not called
			gripperRect.right += 2;
		}
		else
		{
			gripperRect.left += 2;
		}
		gripperRect.bottom = gripperRect.top + 3;
		DrawGripperStripes(pDC, gripperRect, false);
	}
}

void COXToolbarSkinXP::DrawNonClientArea(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
	CRect rcNonClient(lpRect);
	
	// Get the client rectangle in window coordinates
	CRect rcClient, rectWindow;
	pCoolToolbar->GetWindowRect(rectWindow);
	pCoolToolbar->GetClientRect(rcClient);
	pCoolToolbar->ClientToScreen(rcClient);
	rcClient.OffsetRect(-rectWindow.left, -rectWindow.top);
	
	// Clip out the client area
//	pDC->ExcludeClipRect(rcClient);

	// Fill the background
	if (pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
		pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_BTNFACE));
	else
		pDC->FillSolidRect(lpRect, m_pSkinXP->GetBackgroundColor());

	// Draw the border
	CRect rcBorder(lpRect);
	CBrush brush;
	brush.CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));

	pDC->FrameRect(rcBorder, &brush);
	rcBorder.DeflateRect(1, 1);
	pDC->FrameRect(rcBorder, &brush);
	rcBorder.DeflateRect(1, 1);

	// Draw the corner pixels
	COLORREF clrCorner = ::GetSysColor(COLOR_BTNFACE);
	pDC->SetPixelV(rcBorder.TopLeft(), clrCorner);
	pDC->SetPixelV(rcBorder.right - 1, rcBorder.top, clrCorner);
	pDC->SetPixelV(rcBorder.right - 1, rcBorder.bottom - 1, clrCorner);
	pDC->SetPixelV(rcBorder.left, rcBorder.bottom - 1, clrCorner);
}

void COXToolbarSkinXP::DrawSeparator(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* /*pCoolToolbar*/)
{
	CRect rect(lpRect);

	if (rect.Height() > rect.Width()) 
	{
		// Horizontal separator
		rect.left = rect.CenterPoint().x - 1;
		rect.right = rect.left + 1;
	} 
	else 
	{
		// Vertical separator
		rect.top = rect.CenterPoint().y - 1;
		rect.bottom = rect.top + 1;
	}

	pDC->FillSolidRect(rect,  m_pSkinXP->GetSeparatorColor());
}

// Draws the button when in customize mode
void COXToolbarSkinXP::DrawCustomizedButton(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* /*pCoolToolbar*/)
{
	// Draw a black rectangle, 2 pixels wide
	CBrush brush;
	brush.CreateSolidBrush(::GetSysColor(COLOR_BTNTEXT));

	CRect rectItem(lpRect);
	pDC->FrameRect(rectItem, &brush);
	rectItem.DeflateRect(1, 1);
	pDC->FrameRect(rectItem, &brush);
}

void COXToolbarSkinXP::DrawGripperStripes(CDC* pDC, CRect &rect, bool bHorizontal)
{
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, m_pSkinXP->GetGripperColor());
	CPen* pOldPen = pDC->SelectObject(&pen);

	if (bHorizontal)
	{
		int iYPos = rect.top;
		while (iYPos <= rect.bottom)
		{
			pDC->MoveTo(rect.left, iYPos);
			pDC->LineTo(rect.right, iYPos);
			iYPos += 2;
		}
	}
	else // vertical
	{
		int iXPos = rect.left;
		while (iXPos <= rect.right)
		{
			pDC->MoveTo(iXPos, rect.top);
			pDC->LineTo(iXPos, rect.bottom);
			iXPos += 2;
		}
	}

	pDC->SelectObject(pOldPen);
}

void COXToolbarSkinXP::OnCustomDraw(NMHDR*& pNotify, LRESULT*& pResult, COXCoolToolBar* pCoolToolbar)
{
	// The toolbar needs to have the TBSTYLE_FLAT style in order for this skin to work
	// in new version of comctl32.dll(4.71)
	// we use toolbar specific custom draw structure 

	LPNMTBCUSTOMDRAW pTBCDRW=NULL;
	LPNMCUSTOMDRAW pCDRW=NULL;
	if(pCoolToolbar->m_dwComCtlVersion>=_IE40_COMCTL_VERSION)
	{
		pTBCDRW=(LPNMTBCUSTOMDRAW)pNotify;
		pCDRW=&pTBCDRW->nmcd;
	}
	else
	{
		pCDRW=(LPNMCUSTOMDRAW)pNotify;
	}

	OXCTB_CUSTOMDRAW cd;
	if(pCoolToolbar->m_dwComCtlVersion>=_IE40_COMCTL_VERSION)
	{
		ASSERT(pTBCDRW!=NULL);
		cd.pCustomDraw=(LPNMCUSTOMDRAW)pTBCDRW;
	}
	else
	{
		cd.pCustomDraw=pCDRW;
	}
	cd.hdr.hwndFrom=pCDRW->hdr.hwndFrom;
	cd.hdr.idFrom=pCDRW->hdr.idFrom;
	cd.hdr.code=OXCTBN_CUSTOMDRAW;
	cd.result=CDRF_DODEFAULT;
	cd.bDoDefault=TRUE;

	CWnd* pParentWnd=NULL;
	if(pCoolToolbar->IsFloating())
	{
		pParentWnd=pCoolToolbar->GetTopLevelParent();
	}
	else
	{
		pParentWnd=pCoolToolbar->GetParentFrame();
	}

	ASSERT(pParentWnd != NULL);

	pParentWnd->SendMessage(WM_NOTIFY,cd.hdr.idFrom,(LPARAM)&cd);

	if(pCDRW->dwDrawStage==CDDS_PREPAINT && 
		pCoolToolbar->GetToolBarCtrl().GetButtonCount()>0)
	{
		CRect rect;
		pCoolToolbar->GetItemRect(0,&rect);
	}

	if(!cd.bDoDefault)
	{
		*pResult=cd.result;
	}
	else
	{
		CDC dc;
		dc.Attach(pTBCDRW->nmcd.hdc);

		// Draw to a memory dc in order to avoid flashing
		CDC dcMem;
		dcMem.CreateCompatibleDC(&dc);
		CBitmap bmpMem;
		CRect rectMem;
		pCoolToolbar->GetClientRect(rectMem);
		rectMem.OffsetRect(-rectMem.left, -rectMem.top);
		bmpMem.CreateCompatibleBitmap(&dc, rectMem.Width(), rectMem.Height());
		CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);

		*pResult = CDRF_DODEFAULT;
		switch( pCDRW->dwDrawStage )
		{
		case CDDS_PREPAINT:
			{
				// Draw the background
				DrawBackground(&dcMem, pCoolToolbar);

				// Draw each item
				CToolBarCtrl& ctrl = pCoolToolbar->GetToolBarCtrl();
				int iButonCount = ctrl.GetButtonCount();
				for (int i = 0; i < iButonCount; i++)
				{
					TBBUTTON tbb;
					ctrl.GetButton(i, &tbb);

					// Do not draw hidden items
					if (tbb.fsState & TBSTATE_HIDDEN)
						continue;

					CRect rectItem;
					ctrl.GetItemRect(i, rectItem);

					// Draw either a button or a separator
					if (tbb.fsStyle & TBSTYLE_SEP)
					{
						if (tbb.fsState & TBSTATE_WRAP)
						{
							// We have a horizontal separator
							CRect rectSep;
							pCoolToolbar->GetClientRect(rectSep);
							rectSep.bottom = rectItem.bottom;
							rectSep.top = rectItem.bottom - rectItem.Width();

							pCoolToolbar->DrawSeparator(dcMem, rectSep);
						}
						else // vertical separator
						{
							if (rectItem.Height() > rectItem.Width())
								pCoolToolbar->DrawSeparator(dcMem, rectItem);
						}
					}
					else // button
						DrawItem(&dcMem, &tbb, rectItem, pCoolToolbar);

					// If this is a customized button draw a border around it
					if (pCoolToolbar->IsButtonCustomized(i) && !pCoolToolbar->IsCustomButton(i))
						pCoolToolbar->DrawCustomizedButton(dcMem, rectItem);
				}

				// Draw the insert mark if any
				DrawInsertMark(&dcMem, pCoolToolbar);

				*pResult = CDRF_SKIPDEFAULT;
				break;
			}

		}

		dc.BitBlt(0, 0, rectMem.right, rectMem.bottom, &dcMem, 0, 0, SRCCOPY);
		dcMem.SelectObject(pOldBmp);
		dc.Detach();
	}
}

void COXToolbarSkinXP::DrawItem(CDC* pDC, TBBUTTON* pTBB, LPCRECT lpRectItem, COXCoolToolBar* pCoolToolbar, BOOL bDrawBackground)
{
	// Determine the state flags
	bool bSelected = ((pTBB->fsState & TBSTATE_PRESSED) != 0);
	bool bHot = (pCoolToolbar->GetToolBarCtrl().GetHotItem() == pCoolToolbar->CommandToIndex(pTBB->idCommand));
	bool bDisabled = ((pTBB->fsState & TBSTATE_ENABLED) == 0);
	bool bChecked = ((pTBB->fsState & TBSTATE_CHECKED) != 0);

	// v9.3 update 01 modification Manfred Drasch - for drawing in Vista
    if(pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
    {
        COXMenuBar* pMenuBar=DYNAMIC_DOWNCAST(COXMenuBar,pCoolToolbar);
        if(pMenuBar!=NULL)
        {
            if(bSelected)
                bHot = (pMenuBar->m_nActiveMenuItem == pCoolToolbar->CommandToIndex(pTBB->idCommand));
        }
	}
	// end modification Manfred Drasch

	DWORD dwStyleEx = pCoolToolbar->GetStyleEx();

	if (pCoolToolbar->m_iDropDownIndex == pTBB->idCommand)
	{
		// We have a droped drop down button
		pCoolToolbar->m_iDropDownIndex = -1;

		if (bDrawBackground)
			DrawDroppedItemBackground(pDC, lpRectItem);

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, true, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bSelected && bHot)
	{
		// Selected and hot
		if (bDrawBackground)
			DrawItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				m_pSkinXP->GetHotSelectedItemColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetSelectedTextColor(), pCoolToolbar);
	}
	else if (bChecked && bHot)
	{
		// Checked and hot - same as selected and hot
		if (bDrawBackground)
			DrawItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				m_pSkinXP->GetHotSelectedItemColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetSelectedTextColor(), pCoolToolbar);
	}
	else if (bChecked)
	{
		// Just chequed
		if (bDrawBackground)
			DrawItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				m_pSkinXP->GetCheckedItemColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bHot)
	{
		// Just hot
		if (bDrawBackground)
			DrawItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				m_pSkinXP->GetHotItemColor());

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, true, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bSelected)
	{
		// This is a menu item, so decrease the height
		if (bDrawBackground)
		{
			CRect rectItem(lpRectItem);
			rectItem.DeflateRect(0, 1);
			DrawDroppedItemBackground(pDC, rectItem);
		}

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, true, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bDisabled)
	{
		// Disabled
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, true, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, ::GetSysColor(COLOR_GRAYTEXT), pCoolToolbar);
	}
	else
	{
		// Normal
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);		
	}
}

void COXToolbarSkinXP::DrawItemBackground(CDC* pDC, TBBUTTON* pTBB, DWORD dwStyleEx, LPCRECT lpRect, COLORREF crBorder, COLORREF crInside)
{
	// Fill the inside
	CRect rect(lpRect);
	rect.DeflateRect(1, 1);
	pDC->FillSolidRect(rect, crInside);
	rect.InflateRect(1, 1);

	if (pTBB->iBitmap == -1 && (pTBB->fsStyle & TBSTYLE_DROPDOWN) && !(dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
	{
		// This is a menu item, so decrease the height
		rect.DeflateRect(0, 1);
	}

	// Draw the borders
	CBrush brush;
	brush.CreateSolidBrush(crBorder);
	pDC->FrameRect(rect, &brush);

	// If this is drop arrow button, frame the arrow part
	if ((pTBB->fsStyle & TBSTYLE_DROPDOWN) && (dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
		pDC->FrameRect(GetDropArrowRect(pDC, rect), &brush);
}

// Draws a raised background with a shadow
void COXToolbarSkinXP::DrawDroppedItemBackground(CDC* pDC, LPCRECT lpRect)
{
	CRect rectFill(lpRect);
	pDC->FillSolidRect(rectFill, m_pSkinXP->GetBackgroundColor());
}

// Draws the icon of the button according to the button's state
void COXToolbarSkinXP::DrawItemIcon(CDC* pDC, TBBUTTON* pTBB, DWORD dwStyleEx, LPCRECT lpRect, bool bRaised, bool bHot, bool bGrayed, COXCoolToolBar* pCoolToolbar)
{
	if (pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
		return;

	if (pTBB->iBitmap == -1)
		return; // there is no icon

	CToolBarCtrl& ctrl = pCoolToolbar->GetToolBarCtrl();
	CImageList* pImageList = ctrl.GetImageList();
	CRect rcItem(lpRect);
	
	// If this is a drop down item the rectangle needs to be decremented
	if ((pTBB->fsStyle & TBSTYLE_DROPDOWN)  && (dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
	{
		CRect rectDropArrow = GetDropArrowRect(pDC, lpRect);
		rcItem.right -= rectDropArrow.Width();

		// Might as well draw the down arrow here
		CFont fontWebdings;
		fontWebdings.CreatePointFont(80, _T("Marlett"));
		CFont* pOldFont = pDC->SelectObject(&fontWebdings);
		int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
		pDC->DrawText(_T("6"), rectDropArrow, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		pDC->SetBkMode(iOldBkMode);
		pDC->SelectObject(pOldFont);
	}

	// Get the image rectangle and size
	CRect rectImage = GetIconRect(pTBB->idCommand, pCoolToolbar);
	CSize sizeImage(rectImage.Width(), rectImage.Height());

	// Determine the top left coordinate of the icon
	CPoint ptTopLeft;
	CString strText = pCoolToolbar->GetButtonText(pCoolToolbar->CommandToIndex(pTBB->idCommand));
	if (strText.IsEmpty())
	{
		// There is not text, so the icon is in the middle of the button	
		ptTopLeft.x = rcItem.left + (rcItem.Width() - sizeImage.cx) / 2;
		ptTopLeft.y = rcItem.top + (rcItem.Height() - sizeImage.cy) / 2;
	}
	else // there is text
	{
		if (pCoolToolbar->IsList())
		{
			// The icon is on the left
			ptTopLeft.x = rcItem.left + 3;
			ptTopLeft.y = rcItem.top + (rcItem.Height() - sizeImage.cy) / 2;
		}
		else // not list
		{
			// The icon is on top
			ptTopLeft.x = rcItem.left + (rcItem.Width() - sizeImage.cx) / 2;
			ptTopLeft.y = rcItem.top + 3;
		}
	}

	if (bHot)
	{
		// Hot image - raised with a shadow

		CImageList* pHotImageList = ctrl.GetHotImageList();
		if (pHotImageList == NULL)
			pHotImageList = pImageList;

		if (bRaised) // raised icon with a shadow
		{
			// Draw the image shadow first
			ptTopLeft.x += 1;
			ptTopLeft.y += 1;
			CBrush brush;
			brush.CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
			CBrush* pOldBrush = pDC->SelectObject(&brush);
			COLORREF clrOldBkColor = pDC->SetBkColor(RGB(255, 255, 255));
			pHotImageList->DrawIndirect(pDC, pTBB->iBitmap, ptTopLeft, sizeImage,
				CPoint(0, 0), ILD_ROP | ILD_MASK, 0x00B8074A);
			pDC->SetBkColor(clrOldBkColor);
			pDC->SelectObject(pOldBrush);

			ptTopLeft.x -= 2;
			ptTopLeft.y -= 2;
		}

		// Draw the image
		pHotImageList->Draw(pDC, pTBB->iBitmap, ptTopLeft, ILD_TRANSPARENT);
	}
	else if (bGrayed)
	{
		// Disabled image - grayed

		CImageList* pDisabledImageList = ctrl.GetDisabledImageList();
		if (pDisabledImageList != NULL)
			pDisabledImageList->Draw(pDC, pTBB->iBitmap, ptTopLeft, ILD_TRANSPARENT);
		else
		{
			CBrush brush;
			brush.CreateSolidBrush(m_pSkinXP->GetDisabledTextColor());
			HICON hIcon = pImageList->ExtractIcon(pTBB->iBitmap);
			if (hIcon != NULL)
			{
				pDC->DrawState(ptTopLeft, sizeImage, hIcon, DST_ICON | DSS_MONO, &brush);
				::DestroyIcon(hIcon);
			}
		}
	}
	else
	{
		// Normal
		pImageList->Draw(pDC, pTBB->iBitmap, ptTopLeft, ILD_TRANSPARENT);
	}
}

void COXToolbarSkinXP::DrawBackground(CDC* pDC, COXCoolToolBar* pCoolToolbar)
{
	CRect rcClient;
	pCoolToolbar->GetClientRect(rcClient);

	if (pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
		pDC->FillSolidRect(rcClient, ::GetSysColor(COLOR_BTNFACE));
	else
		pDC->FillSolidRect(rcClient, m_pSkinXP->GetBackgroundColor());
}

void COXToolbarSkinXP::OnPaintComboBox(COXSkinnedComboBox* pComboBox)
{
	pComboBox->Default();
	CPaintDC dc(pComboBox);
	DrawComboBox(pComboBox);
}

void COXToolbarSkinXP::DrawComboBox(COXSkinnedComboBox* pComboBox)
{
	CClientDC dc(pComboBox);

	CRect rect;
	pComboBox->GetClientRect(rect);
	POINT ptCursor;
	::GetCursorPos(&ptCursor);
	pComboBox->ScreenToClient(&ptCursor);

	// Determine and exclude the edit box rectangle
	CRect rectEdit(rect);
	rectEdit.DeflateRect(3, 3, rect.Height() - 2, 3);

	dc.ExcludeClipRect(rectEdit);
	rectEdit.InflateRect(1, 1);
	if (pComboBox->m_bCommonControls6)
		rectEdit.right += 3;

	// Determine the button rectangle
	CRect rectButton(rect);
	rectButton.DeflateRect(2, 2, 3, 2);
	rectButton.left = rectEdit.Width() + 2;

	// Fill the background
	dc.FillSolidRect(rect, m_pSkinXP->GetBackgroundColor());

	// Draw the inner white border
	CBrush brushWhite;
	COLORREF clrWhite = ::GetSysColor(COLOR_WINDOW);
	brushWhite.CreateSolidBrush(clrWhite);
	rectEdit.InflateRect(1, 1, 0, 0);
	dc.FillSolidRect(rectEdit, clrWhite);

	rectButton.InflateRect(1, 1, 0, 0);
	dc.FrameRect(rectButton, &brushWhite);

	// The combo box can have three states - normal, hot and dropped
	// Determine the state of the combo box
	CBrush brush;
	COLORREF clrArrow = ::GetSysColor(COLOR_BTNTEXT);
	if (pComboBox->GetDroppedState())
	{
		// The combo box is dropped

		brush.CreateSolidBrush(m_pSkinXP->GetHotSelectedItemColor());
		clrArrow = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
	}
	else if (rect.PtInRect(ptCursor) || CWnd::GetFocus() == pComboBox ||
		(CWnd::GetFocus() && CWnd::GetFocus()->GetParent() == pComboBox))
	{
		// The combo box is hot
		brush.CreateSolidBrush(m_pSkinXP->GetHotItemColor());
	}

	// Perform the drawing of a droped or hot combo box
	if (brush.m_hObject != NULL)
	{
		rectEdit.InflateRect(1, 1, 0, 1);
		rectButton.InflateRect(0, 1, 1, 1);

		// Draw the button
		CPen penBorder;
		penBorder.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
		CPen* pOldPen = dc.SelectObject(&penBorder);
		CBrush* pOldBrush = dc.SelectObject(&brush);
		dc.Rectangle(rectButton);
		dc.SelectObject(pOldBrush);
		dc.Rectangle(rectEdit);
		dc.SelectObject(pOldPen);
	}
	
	// Draw the drop arrow
	CPoint ptCenter = rectButton.CenterPoint();
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, clrArrow);
	CPen* pOldPen = dc.SelectObject(&pen);
	dc.MoveTo(ptCenter.x - 2, ptCenter.y - 1);
	dc.LineTo(ptCenter.x + 3, ptCenter.y - 1);
	dc.MoveTo(ptCenter.x - 1, ptCenter.y);
	dc.LineTo(ptCenter.x + 2, ptCenter.y);
	dc.SetPixelV(ptCenter.x, ptCenter.y + 1, clrArrow);
	dc.SelectObject(pOldPen);
}

void COXToolbarSkinXP::DrawWndFrame(CWnd* pWnd)
{
	CWindowDC dc(pWnd);

	CRect rect;
	pWnd->GetWindowRect(rect);
	CRect rectWindow(rect);
	pWnd->ScreenToClient(&rect);
	CPoint ptOffset(-rect.left, -rect.top);
	rect.OffsetRect(ptOffset);

	// Exclude the client rectangle
	CRect rectClient;
	pWnd->GetClientRect(rectClient);
	rectClient.OffsetRect(ptOffset);
	dc.ExcludeClipRect(rectClient);

	// Fill the background
	dc.FillSolidRect(rect, m_pSkinXP->GetBackgroundColor());

	// Draw the inner white border
	CBrush brushWhite;
	COLORREF clrWhite = ::GetSysColor(COLOR_WINDOW);
	brushWhite.CreateSolidBrush(clrWhite);
	rect.DeflateRect(1, 1);
	dc.FillSolidRect(rect, clrWhite);

	// Determine the state of the edit box
	CPoint ptCursor;
	::GetCursorPos(&ptCursor);
	if (rectWindow.PtInRect(ptCursor) || CWnd::GetFocus() == pWnd)
	{
		// The combo box is hot - draw the border
		rect.InflateRect(1, 1);
		CBrush brush;
		brush.CreateSolidBrush(m_pSkinXP->GetActiveBorderColor());
		dc.FrameRect(rect, &brush);
	}
}

// Draw the text in the specified rectangle
void COXToolbarSkinXP::DrawItemText(CDC* pDC, TBBUTTON* pTBB, DWORD dwStyleEx, LPCRECT lpRectItem, COLORREF clrText, COXCoolToolBar* pCoolToolbar)
{
	CString strText;

	// This is either a toolbar or a menubar
	COXMenuBar* pMenuBar = DYNAMIC_DOWNCAST(COXMenuBar, pCoolToolbar);
	if (pMenuBar != NULL && (pTBB->fsStyle & TBSTYLE_DROPDOWN) && !(dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
		strText = pMenuBar->GetItemText(pTBB->idCommand - 1);
	else
		strText = pCoolToolbar->GetButtonText(pCoolToolbar->CommandToIndex(pTBB->idCommand));

	if (strText.IsEmpty())
		return; // there is no text
	
	CRect rectItem(lpRectItem);

	// Get the image rectangle and size
	CRect rectImage = GetIconRect(pTBB->idCommand, pCoolToolbar);
	CSize sizeImage(rectImage.Width(), rectImage.Height());
	
	// If this is a drop down item the rectangle needs to be decremented
	if ((pTBB->fsStyle & TBSTYLE_DROPDOWN)  && (dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
	{
		CRect rectDropArrow = GetDropArrowRect(pDC, lpRectItem);
		rectItem.right -= rectDropArrow.Width();
	}

	CRect rectIcon = GetIconRect(pTBB->idCommand, pCoolToolbar);

	// Determine the text rectangle
	if (pCoolToolbar->IsList())
	{
		// The text needs to be to the right of the icon
		rectItem.left += sizeImage.cx + 6;
		rectItem.right -= 3;
	}
	else // not list
	{
		// The text needs to be under the icon
		rectItem.top += rectIcon.Height() + 1;
		rectItem.DeflateRect(3, 3);
	}

	DWORD dwDTFlags = DT_WORDBREAK | DT_END_ELLIPSIS;
	if (pCoolToolbar->GetTextRows() == 1)
		dwDTFlags |= DT_SINGLELINE;
	
	if (pCoolToolbar->IsList())
		dwDTFlags |= DT_VCENTER;
	else
		dwDTFlags |= DT_CENTER;

	COLORREF clrOldColor = pDC->SetTextColor(clrText);
	CFont* pOldFont = pDC->SelectObject(pCoolToolbar->GetFont());
	int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
	pDC->DrawText(strText, rectItem, dwDTFlags);
	pDC->SetBkMode(iOldBkMode);
	pDC->SelectObject(pOldFont);
	pDC->SetTextColor(clrOldColor);
}

// Returns the rectangle of the item's icon
CRect COXToolbarSkinXP::GetIconRect(DWORD dwCommandID, COXCoolToolBar* pCoolToolbar)
{
	CImageList* pImageList = pCoolToolbar->GetToolBarCtrl().GetImageList();

	// Get the image index of the item
	int iImageIndex;
	UINT nDummy;
	pCoolToolbar->GetButtonInfo(pCoolToolbar->CommandToIndex(dwCommandID), nDummy, nDummy, iImageIndex);

	if (iImageIndex == -1)
		return CRect(0, 0, 0, 0); // no icon

	// Get the image rectangle and size
	IMAGEINFO img_info;
	pImageList->GetImageInfo(iImageIndex, &img_info);

	return img_info.rcImage;
}

// Determine the rectangle of the drop arrow button
CRect COXToolbarSkinXP::GetDropArrowRect(CDC* pDC, LPCRECT lpRectItem)
{
	CRect rectItem(lpRectItem);

	// Determine the width of the drop arrow character
	CFont fontWebdings;
	fontWebdings.CreatePointFont(80, _T("Marlett"));
	CFont* pOldFont = pDC->SelectObject(&fontWebdings);
	CRect rectChar(0, 0, 0, 0);
	pDC->DrawText(_T("6"), rectChar, DT_CALCRECT);
	pDC->SelectObject(pOldFont);

	rectItem.left = rectItem.right - rectChar.right - 4;
	return rectItem;
}

// Draws the insert mark of the toolbar when in customize mode
void COXToolbarSkinXP::DrawInsertMark(CDC* pDC, COXCoolToolBar* pCoolToolbar)
{
	// Get the insert mark
	CToolBarCtrl& ctrl = pCoolToolbar->GetToolBarCtrl();
	TBINSERTMARK tbim;
	ctrl.GetInsertMark(&tbim);

	if (tbim.iButton == -1)
		return; // there is no insert mark

	// Determine the position rectangle of the insert mark
	CRect rectMark;
	pCoolToolbar->GetItemRect(tbim.iButton, &rectMark);
	if (tbim.dwFlags == 0)
	{
		// The insert mark is before the button
		rectMark.right = rectMark.left + 3;
	}
	else if (tbim.dwFlags & TBIMHT_AFTER)
	{
		// The insert mark is after the button
		rectMark.left = rectMark.right - 3;
	}
	else
		return;

	// Do the actual drawing
	pDC->FillSolidRect(rectMark, ::GetSysColor(COLOR_BTNTEXT));
}

void COXToolbarSkinXP::DrawMenuButtons(CDC* pDC, COXMenuBar* pMenuBar)
{
	ASSERT(pMenuBar->m_pFrameWnd!=NULL);
	ASSERT(::IsWindow(pMenuBar->m_pFrameWnd->m_hWnd));
	ASSERT_KINDOF(CMDIFrameWnd,pMenuBar->m_pFrameWnd);

    BOOL bMaximize=FALSE;
	CMDIChildWnd* pChild=((CMDIFrameWnd*)pMenuBar->m_pFrameWnd)->MDIGetActive(&bMaximize);
	if(pChild==NULL || !bMaximize)
		return;

	ASSERT(!pMenuBar->m_rectCloseBtn.IsRectEmpty());
	if(pMenuBar->m_rectCloseBtn.IsRectEmpty())
		return;

	// close button
	m_pSkinXP->DrawFrameButton(pDC, pMenuBar->m_rectCloseBtn, DFCS_CAPTIONCLOSE,
		FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);

	// Max/restore button
	if (!pMenuBar->m_rectRestoreBtn.IsRectEmpty())
		m_pSkinXP->DrawFrameButton(pDC, pMenuBar->m_rectRestoreBtn, DFCS_CAPTIONRESTORE,
		FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);

	// Minimize button
	if (!pMenuBar->m_rectMinimizeBtn.IsRectEmpty())
		m_pSkinXP->DrawFrameButton(pDC, pMenuBar->m_rectMinimizeBtn, DFCS_CAPTIONMIN,
		FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);
}

// COXToolbarSkin2003
//

COXToolbarSkin2003::COXToolbarSkin2003(COXSkin2003* pSkin2003) :
	COXToolbarSkinXP(pSkin2003)
{
}

COXToolbarSkin2003::~COXToolbarSkin2003()
{
}

void COXToolbarSkin2003::DrawBackground(CDC* pDC, COXCoolToolBar* pCoolToolbar)
{
	CRect rcClient;
	pCoolToolbar->GetWindowRect(rcClient);
	pCoolToolbar->ScreenToClient(rcClient);

	if (pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
	{
		CRect rectMain;
		pCoolToolbar->GetParentFrame()->GetWindowRect(rectMain);

		// Get the toolbar screen rectangle
		CRect rectToolbar;
		pCoolToolbar->GetWindowRect(rectToolbar);

		int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
		if (iWidth < rectMain.Width())
			iWidth = rectMain.Width();

		CRect rectGradient;
		rectGradient.left = rectMain.left - rectToolbar.left - 2;
		rectGradient.right = rectGradient.left + iWidth;
		rectGradient.top = 0;
		rectGradient.bottom = rectToolbar.Height();

		CRect rectSolid(rectGradient);
		rectGradient.right = rectGradient.CenterPoint().x;
		rectSolid.left = rectGradient.right;

		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		pSkin2003->GradientFill(pDC, rectGradient,
			pSkin2003->GetDockbarLeftColor(),
			pSkin2003->GetDockbarRightColor(),
			GRADIENT_FILL_RECT_H);
		pDC->FillSolidRect(rectSolid, pSkin2003->GetDockbarRightColor());
	}
	else
	{
		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		if (pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ)
			pSkin2003->GradientFill(pDC, rcClient,
				pSkin2003->GetToolbarLightColor(),
				pSkin2003->GetToolbarDarkColor(),
				GRADIENT_FILL_RECT_V);
		else
			pSkin2003->GradientFill(pDC, rcClient,
				pSkin2003->GetToolbarLightColor(),
				pSkin2003->GetToolbarDarkColor(),
				GRADIENT_FILL_RECT_H);
	}
}

void COXToolbarSkin2003::DrawNonClientArea(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
	CRect rcNonClient(lpRect);

	// Get the client rectangle in window coordinates
	CRect rcClient, rectWindow;
	pCoolToolbar->GetWindowRect(rectWindow);
	pCoolToolbar->GetClientRect(rcClient);
	pCoolToolbar->ClientToScreen(rcClient);
	rcClient.OffsetRect(-rectWindow.left, -rectWindow.top);
	
	// Clip out the client area
	pDC->ExcludeClipRect(rcClient);

	// Fill the background

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	// Draw the border gradient first, which should match the dockbar
	
	if (pCoolToolbar->m_pDockBar != NULL)
	{
		CRect rectMain;
		pCoolToolbar->GetParentFrame()->GetWindowRect(rectMain);

		// Get the toolbar screen rectangle
		CRect rectToolbar;
		pCoolToolbar->GetWindowRect(rectToolbar);

		int iWidth = ::GetSystemMetrics(SM_CXSCREEN);
		if (iWidth < rectMain.Width())
			iWidth = rectMain.Width();

		CRect rectGradient;
		rectGradient.left = rectMain.left - rectToolbar.left;
		rectGradient.right = rectGradient.left + iWidth;
		rectGradient.top = 0;
		rectGradient.bottom = rectToolbar.Height();

		CRect rectSolid(rectGradient);
		rectGradient.right = rectGradient.CenterPoint().x;
		rectSolid.left = rectGradient.right;

		if (::GetVersion() >= 0x80000000)
			// Adoid a problem with the ::GradientFill() API in Win98 and ME
			pSkin2003->GradientFillManual(pDC, rectGradient,
				pSkin2003->GetDockbarLeftColor(),
				pSkin2003->GetDockbarRightColor(),
				GRADIENT_FILL_RECT_H);
		else
			pSkin2003->GradientFill(pDC, rectGradient,
				pSkin2003->GetDockbarLeftColor(),
				pSkin2003->GetDockbarRightColor(),
				GRADIENT_FILL_RECT_H);

		pDC->FillSolidRect(rectSolid, pSkin2003->GetDockbarRightColor());
	}
	else
		pDC->FillSolidRect(rcNonClient, pSkin2003->GetDockbarBackgroundColor());


	if (!pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
	{
		CRect rectInner(lpRect);
		rectInner.DeflateRect(2, 2);

		// Save the four corner pixels
		COLORREF clrPixels[4];
		clrPixels[0] = pDC->GetPixel(rectInner.TopLeft());
		clrPixels[1] = pDC->GetPixel(rectInner.right - 1, rectInner.top);
		clrPixels[2] = pDC->GetPixel(rectInner.left, rectInner.bottom - 1);
		clrPixels[3] = pDC->GetPixel(rectInner.right - 1, rectInner.bottom - 1);

		// Now draw the toolbar gradient
		ULONG ulGradientOrientation;
		if (pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ)
			ulGradientOrientation = GRADIENT_FILL_RECT_V;
		else
			ulGradientOrientation = GRADIENT_FILL_RECT_H;

		if (::GetVersion() >= 0x80000000)
			// Adoid a problem with the ::GradientFill() API in Win98 and ME
			pSkin2003->GradientFillManual(pDC, rectInner,
				pSkin2003->GetToolbarLightColor(),
				pSkin2003->GetToolbarDarkColor(),
				ulGradientOrientation);
		else
			pSkin2003->GradientFill(pDC, rectInner,
				pSkin2003->GetToolbarLightColor(),
				pSkin2003->GetToolbarDarkColor(),
				ulGradientOrientation);

		// Restore the four corner pixels
		pDC->SetPixelV(rectInner.TopLeft(), clrPixels[0]);
		pDC->SetPixelV(rectInner.right - 1, rectInner.top, clrPixels[1]);
		pDC->SetPixelV(rectInner.left, rectInner.bottom - 1, clrPixels[2]);
		pDC->SetPixelV(rectInner.right - 1, rectInner.bottom - 1, clrPixels[3]);
	}
}

void COXToolbarSkin2003::DrawGripper(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* pCoolToolbar)
{
    if (pCoolToolbar->m_dwStyle & CBRS_FLOATING)
		return;		// no gripper if floating

	CRect rect(lpRect);
	CRect gripperRect(lpRect);
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	if (pCoolToolbar->m_dwStyle & CBRS_ORIENT_HORZ) 
	{
		gripperRect.DeflateRect(2, 6, 2, 5);
		gripperRect.OffsetRect(1, 0);
		// gripper at left
		if (pCoolToolbar->m_pDockContext != NULL)
		{
			// EnableDocking was called
			gripperRect.left += 2;
			gripperRect.bottom -= 2;
		}
		else
		{
			if (pCoolToolbar->m_dwStyle & CBRS_BORDER_BOTTOM)
			{
				gripperRect.top -= 2;
				gripperRect.bottom -= 2;
			}
		}
		gripperRect.right = gripperRect.left + 2;
        pSkin2003->DrawGripperStripes(pDC, gripperRect, true);
	} 
	else // vertical
	{
		gripperRect.DeflateRect(3, 4, 7, 4);
		gripperRect.OffsetRect(0, 1);
		// gripper at top
		if (pCoolToolbar->m_pDockContext == NULL)
		{
			// EnableDocking was not called
			gripperRect.right += 2;
		}
		else
		{
			gripperRect.left += 2;
		}
		gripperRect.bottom = gripperRect.top + 2;
		pSkin2003->DrawGripperStripes(pDC, gripperRect, false);
	}
}

void COXToolbarSkin2003::DrawSeparator(CDC* pDC, LPCRECT lpRect, COXCoolToolBar* /*pCoolToolbar*/)
{
	CRect rect(lpRect);

	if (rect.Height() > rect.Width()) 
	{
		// Horizontal separator
		rect.left = rect.CenterPoint().x - 1;
		rect.right = rect.left + 1;
		rect.top += 4;
		rect.bottom -= 4;
	} 
	else 
	{
		// Vertical separator
		rect.top = rect.CenterPoint().y - 1;
		rect.bottom = rect.top + 1;
		rect.left += 4;
		rect.right -= 4;
	}

	pDC->FillSolidRect(rect,  m_pSkinXP->GetSeparatorColor());
	rect.OffsetRect(1, 1);
	pDC->FillSolidRect(rect,  RGB(255,255,255)); // This color is always white
}

void COXToolbarSkin2003::DrawMenuButtons(CDC* pDC, COXMenuBar* pMenuBar)
{
	ASSERT(pMenuBar->m_pFrameWnd!=NULL);
	ASSERT(::IsWindow(pMenuBar->m_pFrameWnd->m_hWnd));
	ASSERT_KINDOF(CMDIFrameWnd,pMenuBar->m_pFrameWnd);

    BOOL bMaximize=FALSE;
	CMDIChildWnd* pChild=((CMDIFrameWnd*)pMenuBar->m_pFrameWnd)->MDIGetActive(&bMaximize);
	if(pChild==NULL || !bMaximize)
		return;

	ASSERT(!pMenuBar->m_rectCloseBtn.IsRectEmpty());
	if(pMenuBar->m_rectCloseBtn.IsRectEmpty())
		return;

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	// close button
	pSkin2003->DrawFrameButton(pDC, pMenuBar->m_rectCloseBtn, DFCS_CAPTIONCLOSE,
		FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);

	// Max/restore button
	if (!pMenuBar->m_rectRestoreBtn.IsRectEmpty())
		pSkin2003->DrawFrameButton(pDC, pMenuBar->m_rectRestoreBtn, DFCS_CAPTIONRESTORE,
			FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);

	// Minimize button
	if (!pMenuBar->m_rectMinimizeBtn.IsRectEmpty())
		pSkin2003->DrawFrameButton(pDC, pMenuBar->m_rectMinimizeBtn, DFCS_CAPTIONMIN,
			FALSE, FALSE, ::GetSysColor(COLOR_BTNFACE), pMenuBar);
}

// Draws a raised background with a shadow
void COXToolbarSkin2003::DrawDroppedItemBackground(CDC* /*pDC*/, LPCRECT /*lpRect*/)
{

}

void COXToolbarSkin2003::DrawItem(CDC* pDC, TBBUTTON* pTBB, LPCRECT lpRectItem, COXCoolToolBar* pCoolToolbar, BOOL bDrawBackground)
{
	// Determine the state flags
	bool bSelected = ((pTBB->fsState & TBSTATE_PRESSED) != 0);
	bool bHot = (pCoolToolbar->GetToolBarCtrl().GetHotItem() == pCoolToolbar->CommandToIndex(pTBB->idCommand));
	bool bDisabled = ((pTBB->fsState & TBSTATE_ENABLED) == 0);
	bool bChecked = ((pTBB->fsState & TBSTATE_CHECKED) != 0);

	// v9.3 update 01 modification Manfred Drasch - for drawing in Vista
    if(pCoolToolbar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
    {
        COXMenuBar* pMenuBar=DYNAMIC_DOWNCAST(COXMenuBar,pCoolToolbar);
        if(pMenuBar!=NULL)
        {
            if(bSelected)
                bHot = (pMenuBar->m_nActiveMenuItem == pCoolToolbar->CommandToIndex(pTBB->idCommand));
        }
	}
	// end modification Manfred Drasch

	DWORD dwStyleEx = pCoolToolbar->GetStyleEx();
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	if (pCoolToolbar->m_iDropDownIndex == pTBB->idCommand)
	{
		// We have a droped drop down button
		pCoolToolbar->m_iDropDownIndex = -1;

		if (bDrawBackground)
			DrawDroppedItemBackground(pDC, lpRectItem);

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bSelected && bHot)
	{
		// Selected and hot
		if (bDrawBackground)
			DrawGradientItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				pSkin2003->GetHotSelectedToolbarItemLightColor(),
				pSkin2003->GetHotSelectedToolbarItemDarkColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetSelectedTextColor(), pCoolToolbar);
	}
	else if (bChecked && bHot)
	{
		// Checked and hot - same as selected and hot
		if (bDrawBackground)
			DrawGradientItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				pSkin2003->GetHotSelectedToolbarItemLightColor(),
				pSkin2003->GetHotSelectedToolbarItemDarkColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetSelectedTextColor(), pCoolToolbar);
	}
	else if (bChecked)
	{
		// Just chequed
		if (bDrawBackground)
			DrawGradientItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				pSkin2003->GetCheckedToolbarItemLightColor(),
				pSkin2003->GetCheckedToolbarItemDarkColor());
		
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bHot)
	{
		// Just hot
		if (bDrawBackground)
			DrawGradientItemBackground(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetActiveBorderColor(),
				pSkin2003->GetHotToolbarItemLightColor(),
				pSkin2003->GetHotToolbarItemDarkColor());

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bSelected)
	{
		// This can only be a menu item, so decrease the height
		if (bDrawBackground)
		{
			CRect rectItem(lpRectItem);
			rectItem.DeflateRect(0, 1);
			DrawDroppedItemBackground(pDC, rectItem);
		}

		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, true, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);
	}
	else if (bDisabled)
	{
		// Disabled
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, true, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetDisabledTextColor(), pCoolToolbar);
	}
	else
	{
		// Normal
		DrawItemIcon(pDC, pTBB, dwStyleEx, lpRectItem, false, false, false, pCoolToolbar);
		DrawItemText(pDC, pTBB, dwStyleEx, lpRectItem, m_pSkinXP->GetTextColor(), pCoolToolbar);		
	}
}

void COXToolbarSkin2003::DrawGradientItemBackground(CDC* pDC, TBBUTTON* pTBB, DWORD dwStyleEx, LPCRECT lpRect, COLORREF crBorder, COLORREF crInsideLight, COLORREF crInsideDark)
{
	// Fill the inside
	CRect rect(lpRect);
	rect.DeflateRect(1, 1);

	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
	pSkin2003->GradientFill(pDC, rect, crInsideLight, crInsideDark, GRADIENT_FILL_RECT_V);
	rect.InflateRect(1, 1);

	if (pTBB->iBitmap == -1 && (pTBB->fsStyle & TBSTYLE_DROPDOWN) && !(dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
	{
		// This is a menu item, so decrease the height
		rect.DeflateRect(0, 1);
	}

	// Draw the borders
	CBrush brush;
	brush.CreateSolidBrush(crBorder);
	pDC->FrameRect(rect, &brush);

	// If this is drop arrow button, frame the arrow part
	if ((pTBB->fsStyle & TBSTYLE_DROPDOWN) && (dwStyleEx & TBSTYLE_EX_DRAWDDARROWS))
		pDC->FrameRect(GetDropArrowRect(pDC, rect), &brush);
}

void COXToolbarSkin2003::DrawComboBox(COXSkinnedComboBox* pComboBox)
{
	CClientDC dc(pComboBox);
	COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;

	CRect rect;
	pComboBox->GetClientRect(rect);
	POINT ptCursor;
	::GetCursorPos(&ptCursor);
	pComboBox->ScreenToClient(&ptCursor);

	// Determine and exclude the combo box rectangle
	CRect rectCombo(rect);
	rectCombo.DeflateRect(3, 3, rect.Height() - 2, 3);

	dc.ExcludeClipRect(rectCombo);
	rectCombo.InflateRect(1, 1);
	if (pComboBox->m_bCommonControls6)
		rectCombo.right += 3;

	// Determine the button rectangle
	CRect rectButton(rect);
	rectButton.DeflateRect(2, 2, 3, 2);
	rectButton.left = rectCombo.Width() + 2;

	// Fill the background - must match the toolbar background
	{
		COXCoolToolBar* pToolbar = (COXCoolToolBar*) pComboBox->GetParent();

		CRect rectToolbar;
		pToolbar->GetWindowRect(rectToolbar);

		// Get the combo box rectangle
		CRect rectCombo;
		pComboBox->GetWindowRect(rectCombo);
		rectCombo.OffsetRect(-rectToolbar.left, -rectToolbar.top);

		CRect rectGradient(rect);
		rectGradient.top = -rectCombo.top;
		rectGradient.bottom = rectGradient.top + rectToolbar.Height();

		// Limit the drawing to the combo box
		dc.IntersectClipRect(rect);

		pSkin2003->GradientFill(&dc, rectGradient,
			pSkin2003->GetTabBackgroundLightColor(),
			pSkin2003->GetTabBackgroundDarkColor(),
			GRADIENT_FILL_RECT_V);
	}

	// Draw the inner white border
	CBrush brushWhite;
	COLORREF clrWhite = ::GetSysColor(COLOR_WINDOW);
	brushWhite.CreateSolidBrush(clrWhite);
	rectCombo.InflateRect(1, 1, 0, 0);
	dc.FillSolidRect(rectCombo, clrWhite);

	rectButton.InflateRect(1, 1, 0, 0);
	dc.FrameRect(rectButton, &brushWhite);

	// The combo box can have three states - normal, hot and dropped
	// Determine the state of the combo box
	BOOL bHotOrSelected = FALSE;
	COLORREF clrLightColor = 0, clrDarkColor = 0;
	COLORREF clrArrow = ::GetSysColor(COLOR_BTNTEXT);
	if (pComboBox->GetDroppedState())
	{
		// The combo box is dropped
		bHotOrSelected = TRUE;
		clrLightColor = pSkin2003->GetHotSelectedToolbarItemLightColor();
		clrDarkColor = pSkin2003->GetHotSelectedToolbarItemDarkColor();
		clrArrow = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
	}
	else if (rect.PtInRect(ptCursor) || CWnd::GetFocus() == pComboBox ||
		(CWnd::GetFocus() && CWnd::GetFocus()->GetParent() == pComboBox))
	{
		// The combo box is hot
		bHotOrSelected = TRUE;
		clrLightColor = pSkin2003->GetHotToolbarItemLightColor();
		clrDarkColor = pSkin2003->GetHotToolbarItemDarkColor();
	}

	// Perform the drawing of a droped or hot combo box
	if (bHotOrSelected)
	{
		rectCombo.InflateRect(1, 1, 0, 1);
		rectButton.InflateRect(0, 1, 1, 1);

		// Draw the button
		CPen penBorder;
		penBorder.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
		CPen* pOldPen = dc.SelectObject(&penBorder);
		dc.Rectangle(rectButton);

		CRect rectGradient(rectButton);
		rectGradient.DeflateRect(1, 1);
		pSkin2003->GradientFill(&dc, rectGradient, clrLightColor, clrDarkColor,
			GRADIENT_FILL_RECT_V);

		dc.Rectangle(rectCombo);
		dc.SelectObject(pOldPen);
	}
	
	// Draw the drop arrow
	CPoint ptCenter = rectButton.CenterPoint();
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, clrArrow);
	CPen* pOldPen = dc.SelectObject(&pen);
	dc.MoveTo(ptCenter.x - 2, ptCenter.y - 1);
	dc.LineTo(ptCenter.x + 3, ptCenter.y - 1);
	dc.MoveTo(ptCenter.x - 1, ptCenter.y);
	dc.LineTo(ptCenter.x + 2, ptCenter.y);
	dc.SetPixelV(ptCenter.x, ptCenter.y + 1, clrArrow);
	dc.SelectObject(pOldPen);
}

void COXToolbarSkin2003::DrawWndFrame(CWnd* pWnd)
{
	CWindowDC dc(pWnd);

	CRect rect;
	pWnd->GetWindowRect(rect);
	CRect rectWindow(rect);
	pWnd->ScreenToClient(&rect);
	CPoint ptOffset(-rect.left, -rect.top);
	rect.OffsetRect(ptOffset);

	// Exclude the client rectangle
	CRect rectClient;
	pWnd->GetClientRect(rectClient);
	rectClient.OffsetRect(ptOffset);
	dc.ExcludeClipRect(rectClient);

	// Fill the background
	// Fill the background - must match the toolbar background
	{
		COXCoolToolBar* pToolbar = (COXCoolToolBar*) pWnd->GetParent();

		CRect rectToolbar;
		pToolbar->GetWindowRect(rectToolbar);

		// Get the combo box rectangle
		CRect rectCombo;
		pWnd->GetWindowRect(rectCombo);
		rectCombo.OffsetRect(-rectToolbar.left, -rectToolbar.top);

		CRect rectGradient(rect);
		rectGradient.top = -rectCombo.top;
		rectGradient.bottom = rectGradient.top + rectToolbar.Height();

		COXSkin2003* pSkin2003 = (COXSkin2003*) m_pSkinXP;
		if (::GetVersion() >= 0x80000000)
			// Adoid a problem with the ::GradientFill() API in Win98 and ME
			pSkin2003->GradientFillManual(&dc, rectGradient,
				pSkin2003->GetTabBackgroundLightColor(),
				pSkin2003->GetTabBackgroundDarkColor(),
				GRADIENT_FILL_RECT_V);
		else
			pSkin2003->GradientFill(&dc, rectGradient,
				pSkin2003->GetTabBackgroundLightColor(),
				pSkin2003->GetTabBackgroundDarkColor(),
				GRADIENT_FILL_RECT_V);
	}

	// Draw the inner white border
	CBrush brushWhite;
	COLORREF clrWhite = ::GetSysColor(COLOR_WINDOW);
	brushWhite.CreateSolidBrush(clrWhite);
	rect.DeflateRect(1, 1);
	dc.FillSolidRect(rect, clrWhite);

	// Determine the state of the edit box
	CPoint ptCursor;
	::GetCursorPos(&ptCursor);
	if (rectWindow.PtInRect(ptCursor) || CWnd::GetFocus() == pWnd)
	{
		// The combo box is hot - draw the border
		rect.InflateRect(1, 1);
		CBrush brush;
		brush.CreateSolidBrush(m_pSkinXP->GetActiveBorderColor());
		dc.FrameRect(rect, &brush);
	}
}

// COXMiniFrameSkin
//



// COXMiniFrameSkinClassic
//

BOOL COXMiniFrameSkinClassic::OnNcActivate(BOOL bActive, COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	// CMiniDockFrameWnd class assumes if there is only 1 bar, 
	// then it's at position 1 in the array
	CControlBar* pBar=((COXSizeDockBar *)&pMiniDockFrameWnd->m_wndDockBar)->GetFirstControlBar();
	if(pBar!=NULL)
	{
		ASSERT_KINDOF(CControlBar, pBar);
		ASSERT(pBar->m_pDockContext != NULL);
		if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
		{
			COXMDIChildWndSizeDock* pMDIChild=((COXSizeViewBar*)pBar)->m_pChildWnd;
			if(::IsWindow(pMDIChild->m_hWnd))
			{
				if(pMDIChild->MDIGetActive()!=pMDIChild && bActive)
					return FALSE;
				else
					return (BOOL)pMiniDockFrameWnd->Default();
			}
		}
	}

	return ((CMiniDockFrameWnd*) pMiniDockFrameWnd)->OnNcActivate(bActive);
}

void COXMiniFrameSkinClassic::OnNcPaint(COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	pMiniDockFrameWnd->Default();
}


// COXMiniFrameSkinXP
//

COXMiniFrameSkinXP::COXMiniFrameSkinXP(COXSkinXP* pSkinXP)
{
	m_pSkinXP = pSkinXP;
	m_fontCaption.CreatePointFont(85, _T("Tahoma BOLD"));
}

BOOL COXMiniFrameSkinXP::OnNcActivate(BOOL /*bActive*/, COXSizableMiniDockFrameWnd* /*pMiniDockFrameWnd*/)
{
	return TRUE;
}

// Draw the Office XP style caption of the mini frame window
void COXMiniFrameSkinXP::OnNcPaint(COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	// Get the window rectangle and the DC
	CWindowDC dc(pMiniDockFrameWnd);
	CRect rect(0,0,0,0);
	pMiniDockFrameWnd->GetWindowRect(rect);
	pMiniDockFrameWnd->ScreenToClient(rect);
	CPoint ptOffset = rect.TopLeft();
	rect.OffsetRect(-ptOffset.x, -ptOffset.y);

	// Excluse the client rectangle from the clipping region
	CRect rectClient;
	pMiniDockFrameWnd->GetClientRect(rectClient);
	rectClient.OffsetRect(-ptOffset.x, -ptOffset.y);
	dc.ExcludeClipRect(rectClient);

	// Fill the outer dark rectangle
	COLORREF clrOuter = m_pSkinXP->GetMiniFrameBorderColor();
	dc.FillSolidRect(rect, clrOuter);
	
	// Fill the inner light rectangle
	rect.DeflateRect(2, 2);
	dc.FillSolidRect(rect, m_pSkinXP->GetMiniFrameLightBorderColor());

	// Draw the 4 corner points
	dc.SetPixelV(rect.TopLeft(), clrOuter);
	dc.SetPixelV(rect.right - 1, rect.top, clrOuter);
	dc.SetPixelV(rect.right - 1, rect.bottom - 1, clrOuter);
	dc.SetPixelV(rect.left, rect.bottom - 1, clrOuter);

	DrawCaption(pMiniDockFrameWnd);
}

void COXMiniFrameSkinXP::DrawCaption(COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	// Get the window rectangle and the DC
	CWindowDC dc(pMiniDockFrameWnd);
	CRect rectCaption = GetCaptionRect(pMiniDockFrameWnd);

	// Draw the backbround of the caption
	dc.FillSolidRect(rectCaption, m_pSkinXP->GetMiniFrameCaptionColor());

	// Get the caption text
	CString strCaption;
	pMiniDockFrameWnd->GetWindowText(strCaption);

	// Draw the text
	CFont* pOldFont = dc.SelectObject(&m_fontCaption);
	COLORREF clrOld = dc.SetTextColor(m_pSkinXP->GetMiniFrameCaptionTextColor());
	rectCaption.DeflateRect(3, 0);
	dc.DrawText(strCaption, rectCaption, DT_SINGLELINE | DT_VCENTER);
	dc.SetTextColor(clrOld);
	dc.SelectObject(pOldFont);

	DrawCaptionButtons(pMiniDockFrameWnd);
}

// Returns the rectangle of the caption bar
CRect COXMiniFrameSkinXP::GetCaptionRect(COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	CRect rect(0,0,0,0);
	pMiniDockFrameWnd->GetWindowRect(rect);
	pMiniDockFrameWnd->ScreenToClient(rect);
	CPoint ptOffset = rect.TopLeft();
	rect.OffsetRect(-ptOffset.x, -ptOffset.y);

	// Get the caption rectangle
	rect.DeflateRect(2, 2);
	CRect rectCaption;
	rectCaption.left = rect.left + 1;
	rectCaption.top = rect.top + 1;
	rectCaption.right = rect.right - 1;
	rectCaption.bottom = rectCaption.top - ptOffset.y - 5;

	return rectCaption;
}

// Draws the maximize button in Office XP style
BOOL COXMiniFrameSkinXP::DrawCaptionButtons(COXSizableMiniDockFrameWnd* pMiniDockFrameWnd)
{
	if (pMiniDockFrameWnd->GetSystemMenu(FALSE)->GetMenuItemCount() == 0)
		return TRUE; // do not draw if the button is disabled

	// Determine the button rectangle
	CRect rect = GetCaptionRect(pMiniDockFrameWnd);
	rect.left = rect.right - rect.Height();

	// Get the cursor position in window coordinates
	POINT ptCursor;
	::GetCursorPos(&ptCursor);
	pMiniDockFrameWnd->ScreenToClient(&ptCursor);
	ptCursor.x += 4;
	ptCursor.y += rect.Height() + 4;
	
	// Determine the state of the button
	bool bLeftButtonDown = (::GetKeyState(VK_LBUTTON) < 0);
	CRect rectTest(rect);
	rectTest.DeflateRect(0, 0, 1, 1);
	BOOL bMouseOnClose = rectTest.PtInRect(ptCursor);

	// Determine the colors
	COLORREF clrX;
	CBrush brush;
	brush.m_hObject = NULL;
	if (bMouseOnClose && bLeftButtonDown)
	{
		// Pressed
		clrX = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
		brush.CreateSolidBrush(m_pSkinXP->GetHotSelectedItemColor());
	}
	else if (bMouseOnClose)
	{
		// Hot
		clrX = ::GetSysColor(COLOR_BTNTEXT);
		brush.CreateSolidBrush(m_pSkinXP->GetHotItemColor());
	}
	else
	{
		// Normal - just the X
		clrX = m_pSkinXP->GetMiniFrameCaptionTextColor();
	}

	// Draw to a memory dc to avoid flashing
	CWindowDC dcWindow(pMiniDockFrameWnd);
	CDC dc;
	dc.CreateCompatibleDC(&dcWindow);
	CBitmap bmpMem;
	CRect rectButton(rect);
	rectButton.OffsetRect(-rect.left, -rect.top);
	bmpMem.CreateCompatibleBitmap(&dcWindow, rectButton.Width(), rectButton.Height());
	CBitmap* pOldBmp = dc.SelectObject(&bmpMem);

	// Perform the drawing
	if (brush.m_hObject != NULL)
	{
		// Draw a frame
		CBrush* pOldBrush = dc.SelectObject(&brush);
		CPen penBorder;
		penBorder.CreatePen(PS_SOLID, 1, m_pSkinXP->GetActiveBorderColor());
		CPen* pOldPen = dc.SelectObject(&penBorder);
		dc.Rectangle(rectButton);
		dc.SelectObject(pOldPen);
		dc.SelectObject(pOldBrush);
	}
	else
		dc.FillSolidRect(rectButton, m_pSkinXP->GetMiniFrameCaptionColor());

	// Draw the "x" inside the button
	CRect rectX(rectButton);
	rectX.DeflateRect(4, 4, 5, 5);
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, clrX);
	CPen* pOldPen = dc.SelectObject(&pen);
	for (int i = 0; i < 2; i++)
	{
		dc.MoveTo(rectX.left, rectX.top);
		dc.LineTo(rectX.right + 1, rectX.bottom + 1);
		dc.MoveTo(rectX.right, rectX.top);
		dc.LineTo(rectX.left - 1, rectX.bottom + 1);
		rectX.OffsetRect(1, 0);
	}

	dc.SelectObject(pOldPen);

	// Copy the memory dc to the window dc
	dcWindow.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);
	dc.SelectObject(pOldBmp);

	return TRUE;
}

// Floating windows are not always children of the main frame, so we need to iterate
// through all top level windows.
void COXSkinnedApp::UpdateFloatingWindows(CWnd* pMainWnd)
{
	HWND hMainWnd = pMainWnd->m_hWnd;

	// Walk through all top-level windows
	HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
	while (hWnd != NULL)
	{
		CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
		if (pWnd != NULL && hMainWnd != hWnd && AfxIsDescendant(hMainWnd, hWnd))
			if (pWnd->IsKindOf(RUNTIME_CLASS(COXSizableMiniDockFrameWnd)))
				UpdateChildrenRec(pWnd);

		hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
	}
}

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
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions