Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

MFC extension library - A plugin to handle owner drawn menus

, 11 May 2004 CPOL
Continuation of the Plugin Architecture series
// CODMenu class plug-in for the MFC plug-in architecture
// Code copyright: R.I.Allen for plug-in stuff
// Most owner drawn menu code copyright Brent Corcum - modified by RA
// Some plug-in implementation of the CODMenu class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ODMenu.h"
#include <afxpriv.h>  //SK: makes A2W and other spiffy AFX macros work

#ifdef _DEBUG
#include "DebugMenu.h"
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// static variables
#define BCMENU_GAP 1

#if _MFC_VER <0x400
#error This code does not work on Versions of MFC prior to 4.0
#endif

CFont CODMenu::m_menuFont;
CFont CODMenu::m_menuFontBold;
int CODMenu::m_iconX = 16;
int	CODMenu::m_iconY = 15;
std::map<int, int> CODMenu::m_commandToImage;
CImageList CODMenu::m_buttonImages;
CImageList CODMenu::m_disabledImages;
#ifdef _DEBUG
int CODMenu::m_pluggedInCount = 0;
#endif

enum Win32Type
{
	Win32s,
	WinNT3,
	Win95,
	Win98,
	WinME,
	WinNT4,
	Win2000,
	WinXP
};

extern Win32Type IsShellType();
static Win32Type g_Shell = IsShellType();

CODMenu	plugIn(false);

IMPLEMENT_DYNCREATE(CODMenu, CPlugInMap)

CODMenu::CODMenu()
{
	m_bSysMenu = false;
	m_minSystemMenuWidth = 0;
}

CODMenu::CODMenu(bool special)
{
    UNREFERENCED_PARAMETER(special);
	AddObject();
	// construct the menu font object used to measure all items
	LOGFONT m_lf;
	
	ZeroMemory((PVOID) &m_lf,sizeof(LOGFONT));
	
	NONCLIENTMETRICS nm;
	nm.cbSize = sizeof(NONCLIENTMETRICS);
	VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm, 0));
	// these fonts should auto destroy when the DLL unloads
	// create the normal menu item font
	m_lf = nm.lfMenuFont;
	m_menuFont.CreateFontIndirect(&m_lf);
	// create the default menu item font (bold)
	m_lf.lfWeight = FW_BOLD;
	m_menuFontBold.CreateFontIndirect(&m_lf);

	// image lists used, note the 500 max images!
	m_buttonImages.Create(m_iconX, m_iconY, ILC_COLOR32 | ILC_MASK, 1, 500);
	m_disabledImages.Create(m_iconX, m_iconY, ILC_COLOR32 | ILC_MASK, 1, 500);
}

CODMenu::~CODMenu()
{
	TRACE("CODMenu::~CODMenu()\n");
}

BEGIN_MESSAGE_MAP(CODMenu, CPlugInMap)
	//{{AFX_MSG_MAP(CODMenu)
	ON_WM_INITMENUPOPUP()
	ON_WM_MEASUREITEM()
	ON_WM_DRAWITEM()
	//}}AFX_MSG_MAP
#ifdef _DEBUG
	ON_COMMAND(ID_DEBUGMENU_MENUICONPREVIEW, OnMenuDebug)
	ON_UPDATE_COMMAND_UI(ID_DEBUGMENU_MENUICONPREVIEW, OnUpdateMenuDebug)
#endif
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CODMenu message handlers

bool CODMenu::IsPlugInFor(CRuntimeClass *pClass)
{
    UNREFERENCED_PARAMETER(pClass);
	// this is a plug in for all possible window types
	return true;
}

CPlugInMap* CODMenu::CreateMapObject()
{
#ifdef _DEBUG
	m_pluggedInCount++;
#endif
	return new CODMenu;
}

void CODMenu::EnumerateAndLoadToolbars()
{
	// This procedure is called by the InitialiseDLL function

	// When we intialise, we need to enumerate all the toolbar
	// resources in all the plug-in DLLs and the application
	// this allows us to generate a map of menu items which have toolbar
	// images available for them
	
	// First enumerate and use the appplications toolbar(s)
	CPlugInApp *pApp = static_cast<CPlugInApp*>(AfxGetApp());
	if (pApp)
	{
		TRACE("Enumerating application\n");
		EnumResourceNames(pApp->m_hInstance, RT_TOOLBAR,(ENUMRESNAMEPROC)EnumResNameProc, 0);
		
		// now enumerate all the plug-in DLL toolbars
		int dllCount = pApp->GetPlugInDLLCount();
		for(int dll = 0 ; dll < dllCount; dll++)
		{
			TRACE("Enumerating DLL %1d\n", dll);
			EnumResourceNames(pApp->GetDLL(dll)->GetHInstance(), RT_TOOLBAR,(ENUMRESNAMEPROC)EnumResNameProc, 0);
		}
	}

	// we now have all the toolbars loaded into the main image list m_buttonImages
	// generate the disabled versions of the images used
	CBitmap	disabledImage;
	CWindowDC dc(NULL);

	dc.SaveDC();
	disabledImage.CreateCompatibleBitmap(&dc, m_iconX, m_iconY);
	dc.SelectObject(&disabledImage);
	for(int image = 0 ; image < m_buttonImages.GetImageCount() ; image++)
	{
		CBitmap bmp;
		GetBitmapFromImageList(&dc, &m_buttonImages, image, bmp);
		DitherBlt3(&dc, bmp, ::GetSysColor(COLOR_3DFACE));
		m_disabledImages.Add(&bmp, ::GetSysColor(COLOR_3DFACE));
	}
	dc.RestoreDC(-1);
}

BOOL CALLBACK CODMenu::EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
{
    UNREFERENCED_PARAMETER(lParam);
	TRACE("Toolbar found, module %x, Type %1d, Name %1d\n", hModule, lpszType, lpszName);
	// There should be 2 resources,one of type RT_TOOLBAR, which enumerates the command IDs
	// the other of type RT_BITMAP, which are the images for each button

	// load in the RT_TOOLBAR button indexes
	HRSRC hrsrcToolbar = ::FindResource(hModule, lpszName, lpszType);
	HGLOBAL hToolbar = ::LoadResource(hModule, hrsrcToolbar);
	int size = ::SizeofResource(hModule, hrsrcToolbar);

	WORD* pToolbarData =(WORD*)::LockResource(hToolbar);
	// from examination of a toolbar resource, the layout it:
	// WORD : Version number(usually 1)
	// WORD : X_SIZE of image(16)
	// WORD : Y_SIZE of image(15)
	// WORD : NUMBER OF TOOLBAR BUTTONS
	// x * WORD : TOOLBAR BUTTON ID's
	// NOTE THAT A TOOLBAR BUTTON ID OF 0 IS A SEPARATOR
	if (pToolbarData[0] == 0x0001)
	{
		// we recognise this toolbar version, go ahead
		if (pToolbarData[1] == m_iconX && pToolbarData[2] == m_iconY)
		{
			// buttons are the correct size for a menu, lets load these images
			CBitmap	toolbarBitmap;
			// make sure we load the bitmap image from the correct module
			HINSTANCE old = AfxGetResourceHandle();
			AfxSetResourceHandle(hModule);
			toolbarBitmap.LoadBitmap(lpszName);
			AfxSetResourceHandle(old);

			// extract the IDs of each toolbar button
			for(int buttonIndex = 0 ; buttonIndex < pToolbarData[3] ; buttonIndex++)
			{

				if (pToolbarData[4 + buttonIndex] != 0)
				{
					// this is not a separator
					// make sure there is not already a map entry for this button
					if (m_commandToImage.find(pToolbarData[4 + buttonIndex]) == m_commandToImage.end())
					{
						// does not exist, add it
						m_commandToImage[pToolbarData[4 + buttonIndex]] = m_commandToImage.size();
					}
					else
					{
						TRACE("Warning, duplicate toolbar button %1d found, using first\n", 
								pToolbarData[4 + buttonIndex]);
					}
				}
			}
			// add the toolbar images on mass
			m_buttonImages.Add(&toolbarBitmap, ::GetSysColor(COLOR_3DFACE));
			toolbarBitmap.DeleteObject();
		}
	}
	// return TRUE to keep enumerting any other toolbar resources in the same module
	return TRUE;
}

void CODMenu::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
    UNREFERENCED_PARAMETER(nIndex);
	if (IsPostCall())
	{
		// iterate any menu about to be displayed and make sure
		// all the items have the ownerdrawn style set
		// We receive a WM_INITMENUPOPUP as each menu is displayed, even if the user
		// switches menus or brings up a sub menu. This means we only need to
		// set the style at the current popup level.
		// we also set the user item data to the index into the menu to allow
		// us to measure/draw the item correctly later
		//
		if (pPopupMenu != NULL)
		{
			m_bSysMenu = (bSysMenu != FALSE);
			m_menuBeingProcessed = pPopupMenu->m_hMenu;	// only valid for measure item calls
			int itemCount = pPopupMenu->GetMenuItemCount();
			for(int item = 0; item < itemCount; item++)
			{
				int itemID = pPopupMenu->GetMenuItemID(item);
				// make sure we do not change the state of the menu items as
				// we set the owner drawn style
				MENUITEMINFO	itemInfo;

				memset(&itemInfo, 0, sizeof(MENUITEMINFO));
				itemInfo.cbSize = sizeof(MENUITEMINFO);

				itemInfo.fMask = MIIM_STATE;
				pPopupMenu->GetMenuItemInfo(item, 
						&itemInfo, 
						TRUE);				// by position
				pPopupMenu->ModifyMenu(item, 
						itemInfo.fState | MF_BYPOSITION | MF_OWNERDRAW, 
						itemID,
						(LPCTSTR)item);
			}
		}
	}
}

void CODMenu::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
    UNREFERENCED_PARAMETER(nIDCtl);
	// check that the call is for an owner drawn menu
	if (IsPreCall() && lpMeasureItemStruct->CtlType == ODT_MENU)
	{
		MeasureItem(lpMeasureItemStruct);
		// we have handled it, stop it flowing through regular MFC
		SuppressThisMessage();
	}
}

void CODMenu::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    UNREFERENCED_PARAMETER(nIDCtl);
	if (IsPreCall() && lpDrawItemStruct->CtlType == ODT_MENU)
	{
		DrawItem(lpDrawItemStruct);
		// we have handled it, stop it flowing through regular MFC
		SuppressThisMessage();
	}
}

// FROM THIS POINT ONWARDS THE CODE IS A MODIFIED VERSION OF BRENT CORCUMS BCMENU CLASS

void CODMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
	USES_CONVERSION;
	MENUITEMINFO	itemInfo;
	CString			menuText;

	memset(&itemInfo, 0, sizeof(MENUITEMINFO));
	itemInfo.cbSize = sizeof(MENUITEMINFO);

	itemInfo.fMask = MIIM_STATE;
	::GetMenuItemInfo(m_menuBeingProcessed, lpMIS->itemData, TRUE, &itemInfo);

	UINT state = itemInfo.fState;
	
	int BCMENU_PAD = 4;
	if (lpMIS->itemID == 0)			// drawing a separator
	{
		lpMIS->itemWidth = 0;
		int temp = GetSystemMetrics(SM_CYMENU) >> 1;
		if (IsLunaMenuStyle())
			lpMIS->itemHeight = 3;
		else
			lpMIS->itemHeight = temp > (m_iconY + BCMENU_PAD) / 2 ? temp :(m_iconY + BCMENU_PAD) / 2;
	}
	else
	{
		// Obtain the width of the text:
		TCHAR	buffer[_MAX_PATH];
		CWnd *pWnd = AfxGetMainWnd();   // Get main window
		if (pWnd == NULL)
			pWnd = CWnd::GetDesktopWindow();
		CDC *pDC = pWnd->GetDC();    // Get device context
		CFont* pFont = NULL; // Select menu font in...

        TRACE("State is %x\n", state);
		
        // always measure using the bold version of the font
        //if (state & ODS_DEFAULT)
		pFont = pDC->SelectObject(&m_menuFontBold);
		//else
		//	pFont = pDC->SelectObject(&m_menuFont);// Select menu font in...

		::GetMenuString(m_menuBeingProcessed, lpMIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
  
		//Get pointer to text SK
		const wchar_t *lpstrText = A2W(buffer);
		 
		SIZE size;
		size.cx = 0;
		size.cy = 0;
		
		if (Win32s != g_Shell)
		{
			VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText, wcslen(lpstrText), &size)); //SK should also work on 95
			if (m_minSystemMenuWidth == 0)
			{
				SIZE minSize;
				const wchar_t *pMinText = L"Close     Alt + F4";
				// need to initialise
				::GetTextExtentPoint32W(pDC->m_hDC, pMinText, wcslen(pMinText), &minSize);
				if (IsLunaMenuStyle())
					m_minSystemMenuWidth = m_iconX + BCMENU_PAD + 8 + minSize.cx;
				else 
					m_minSystemMenuWidth = m_iconX + minSize.cx + m_iconX + BCMENU_GAP;
			}
		}
#ifndef UNICODE //can't be UNICODE for Win32s
		else
		{
			//it's Win32suckx
			RECT rect;
			rect.left = 0;
			rect.top = 0;
			size.cy = DrawText(pDC->m_hDC,
					(LPCTSTR)lpstrText, 
					wcslen(lpstrText), 
					&rect, 
					DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
			//+3 makes at least three pixels space to the menu border
			size.cx = rect.right - rect.left + 3;
			size.cx += 3 * (size.cx / wcslen(lpstrText));
			if (m_minSystemMenuWidth == 0)
			{
				CRect minSize;
				const wchar_t *pMinText = L"Close     Alt + F4";
				DrawText(pDC->m_hDC,
						(LPCTSTR)pMinText, 
						wcslen(pMinText), 
						&minSize, 
						DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);				// need to initialise
				if (IsLunaMenuStyle())
					m_minSystemMenuWidth = m_iconX + BCMENU_PAD + 8 + minSize.Width();
				else 
					m_minSystemMenuWidth = m_iconX + minSize.Width() + m_iconX + BCMENU_GAP;
			}
		}
#endif  
		
		CSize t = CSize(size);
		pDC->SelectObject(pFont); // Select old font in
		pWnd->ReleaseDC(pDC); // Release the DC

		// Set width and height:		
		if (IsLunaMenuStyle())
			lpMIS->itemWidth = m_iconX + BCMENU_PAD + 8 + t.cx;
		else 
			lpMIS->itemWidth = m_iconX + t.cx + m_iconX + BCMENU_GAP;
		int temp = GetSystemMetrics(SM_CYMENU);
		lpMIS->itemHeight = temp > m_iconY + BCMENU_PAD ? temp : m_iconY + BCMENU_PAD;
	}
	if (m_bSysMenu)
	{
		// solve problem with system menu items which we do not receive a WM_MEASUREITEM for
		if (lpMIS->itemWidth < m_minSystemMenuWidth)
		{
			// set to minimum width for correct draw
			lpMIS->itemWidth = m_minSystemMenuWidth;
		}
	}
}

void CODMenu::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
    TRACE("State is %x\n", lpDIS->itemState);
	ASSERT(lpDIS != NULL);
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
		DrawItem_Win9xNT2000(lpDIS);
	else
	{
		if (IsWinXPLuna())
		{
			DrawItem_WinXP(lpDIS);
		}
		else
		{
			DrawItem_Win9xNT2000(lpDIS);
		}	
	}
}


static CPINFO CPInfo;

Win32Type IsShellType()
{
	Win32Type ShellType;
	DWORD winVer;
	OSVERSIONINFO osvi;
	
	winVer=GetVersion();
	if (winVer<0x80000000)
	{/*NT */
		ShellType = WinNT3;
		memset(&osvi, 0, sizeof(OSVERSIONINFO));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&osvi);
		if (osvi.dwMajorVersion == 4L)
			ShellType = WinNT4;
		else if (osvi.dwMajorVersion == 5L && osvi.dwMinorVersion == 0L)
			ShellType = Win2000;
		else if (osvi.dwMajorVersion == 5L && osvi.dwMinorVersion == 1L)
			ShellType = WinXP;
	}
	else if (LOBYTE(LOWORD(winVer)) < 4)
		ShellType = Win32s;
	else
	{
		ShellType = Win95;
		memset(&osvi, 0, sizeof(OSVERSIONINFO));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&osvi);
		if (osvi.dwMajorVersion == 4L && osvi.dwMinorVersion == 10L)
			ShellType = Win98;
		else if (osvi.dwMajorVersion == 4L && osvi.dwMinorVersion == 90L)
			ShellType = WinME;
	}
	return ShellType;
}

BOOL CODMenu::IsLunaMenuStyle()
{
	if (IsWinXPLuna())
	{
		return TRUE;
	}
	return(FALSE);
}

BOOL CODMenu::IsNewShell()
{
	return(g_Shell >= Win95);
}

BOOL CODMenu::IsWinXPLuna()
{
	if (g_Shell == WinXP)
	{
		if (IsWindowsClassicTheme())
			return(FALSE);
		else
			return(TRUE);
	}
	return(FALSE);
}

BOOL CODMenu::IsWindowsClassicTheme()
{
	TCHAR Buf[_MAX_PATH+10];
	HKEY hKey;
	DWORD size;
	DWORD type; 
	long lRetCode; 
	static BOOL XPTheme_returnflag = FALSE;
	static BOOL XPTheme_checkflag = FALSE;
	
	if (XPTheme_checkflag)
		return(XPTheme_returnflag);

	XPTheme_checkflag = TRUE;
	lRetCode = RegOpenKeyEx(
			HKEY_CURRENT_USER, 
			_T("Software\\Microsoft\\Plus!\\Themes\\Current"), 
			0,
			KEY_READ,
			&hKey); 
	if (lRetCode == ERROR_SUCCESS)
	{ 
		size = _MAX_PATH;
		type = REG_SZ;
		lRetCode=::RegQueryValueEx(
			hKey,
			NULL,
			NULL,
			&type,
			(unsigned char *)Buf,
			&size);
		if (lRetCode == ERROR_SUCCESS)
		{
			TCHAR szClassicTheme[]=_T("Windows Classic.theme");
			int len = lstrlen(Buf);
			if (len >= lstrlen(szClassicTheme))
			{
				if (!lstrcmpi(&Buf[len - lstrlen(szClassicTheme)], szClassicTheme))
				{
					XPTheme_returnflag = TRUE;
				}
			}
		}
		RegCloseKey(hKey); 
	}
	return(XPTheme_returnflag);
}

void CODMenu::DrawItem_Win9xNT2000(LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);

	CDC*		pDC = CDC::FromHandle(lpDIS->hDC);
	CRect		rect;
	CBrush		brBackground;
	COLORREF	clrBack;
	UINT		state = lpDIS->itemState;
	MENUITEMINFO info;
	memset(&info, 0, sizeof(MENUITEMINFO));
	info.cbSize = sizeof(MENUITEMINFO);
	info.fMask = MIIM_CHECKMARKS;
	::GetMenuItemInfo((HMENU)lpDIS->hwndItem, lpDIS->itemID, MF_BYCOMMAND, &info);

	if (IsWinXPLuna())
		clrBack = GetSysColor(COLOR_3DFACE);
	else 
		clrBack = GetSysColor(COLOR_MENU);
	
	brBackground.CreateSolidBrush(clrBack);

	if (lpDIS->itemID == 0)			// drawing a separator
	{
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect(rect, &brBackground);
		rect.top += (rect.Height() >> 1);
		pDC->DrawEdge(&rect, EDGE_ETCHED, BF_TOP);
	}
	else
	{
		CRect	rect2;
		BOOL	standardflag = FALSE;
		BOOL	selectedflag = FALSE;
		BOOL	disableflag = FALSE;
		BOOL	checkflag = FALSE;
		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
		CBrush	m_brSelect;
		CPen	penBack;
		int		dy;
		int		nIconNormal = -1;
		
		// set some colors
		penBack.CreatePen(PS_SOLID, 0, clrBack);
		m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
		
		// draw the colored rectangle portion
		
		rect.CopyRect(&lpDIS->rcItem);
		rect2 = rect;
		
		// draw the up/down/focused/disabled state
		CString strText;
		TCHAR buffer[_MAX_PATH];
		::GetMenuString((HMENU)lpDIS->hwndItem, lpDIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
		strText = buffer;
		
		if (m_commandToImage.find(lpDIS->itemID) != m_commandToImage.end())
		{
			nIconNormal = m_commandToImage[lpDIS->itemID];
		}
		
		if (state & ODS_CHECKED && nIconNormal < 0)
		{
			if (state & ODS_SELECTED)
				checkflag = TRUE;
		}
		else if (nIconNormal != -1)
		{
			standardflag = TRUE;
			if (state & ODS_SELECTED && !(state & ODS_GRAYED))
				selectedflag = TRUE;
			else if (state & ODS_GRAYED) 
				disableflag = TRUE;
		}
		
		if (state & ODS_SELECTED)
		{
			// draw the down edges
			
			CPen *pOldPen = pDC->SelectObject(&penBack);
			
			// You need only Text highlight and thats what you get
			
			if (checkflag || standardflag || selectedflag || disableflag || state & ODS_CHECKED)
				rect2.SetRect(rect.left + m_iconX + 4 + BCMENU_GAP, rect.top, rect.right, rect.bottom);
			pDC->FillRect(rect2, &m_brSelect);
			
			pDC->SelectObject(pOldPen);
			crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
		}
		else 
		{
			CPen *pOldPen = pDC->SelectObject(&penBack);
			pDC->FillRect(rect, &brBackground);
			pDC->SelectObject(pOldPen);
			
			// draw the up edges	
			pDC->Draw3dRect(rect, clrBack, clrBack);
		}
		
		// draw the text if there is any
		//We have to paint the text only if the image is nonexistant
		
		dy =(rect.Height() - 4 - m_iconY) / 2;
		dy = dy < 0 ? 0 : dy;
		
		if (checkflag || standardflag || selectedflag || disableflag)
		{
			rect2.SetRect(rect.left + 1, rect.top + 1 + dy, rect.left + m_iconX + 3, rect.top + m_iconY + 3 + dy);
			pDC->Draw3dRect(rect2, clrBack, clrBack);
			if (checkflag)
			{
				pDC->FillRect(rect2, &brBackground);
				rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
				
				CPoint ptImage(rect.left + 2,rect.top + 2 + dy);
				
				rect2.SetRect(rect.left + 1, rect.top + 2 + dy, rect.left + m_iconX + 1, rect.top + m_iconY + 2 + dy);
				Draw3DCheckmark(pDC, rect2, state & ODS_SELECTED, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked);
			}
			else if (disableflag)
			{
				if (!selectedflag)
				{
					CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					pDC->Draw3dRect(rect2, clrBack, clrBack);
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else if (selectedflag)
			{
				pDC->FillRect(rect2, &brBackground);
				rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
				if (IsNewShell())
				{
					if (state & ODS_CHECKED)
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
					else
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW));
				}
				CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
				if (nIconNormal >= 0)
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
			}
			else
			{
				if (state & ODS_CHECKED)
				{
					CBrush brush;
					COLORREF col = clrBack;
					col = LightenColor(col, 0.6);
					brush.CreateSolidBrush(col);
					pDC->FillRect(rect2, &brush);
					brush.DeleteObject();
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					if (IsNewShell())
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
				}
				else
				{
					pDC->FillRect(rect2, &brBackground);
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					pDC->Draw3dRect(rect2, clrBack, clrBack);
				}
				CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
				if (nIconNormal >= 0)
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
			}
		}

		if (nIconNormal < 0 && state & ODS_CHECKED && !checkflag)
		{
			rect2.SetRect(rect.left + 1, rect.top + 2 + dy, rect.left + m_iconX + 1, rect.top + m_iconY + 2 + dy);
			if (state & ODS_CHECKED || info.hbmpUnchecked) 
			{
				Draw3DCheckmark(pDC, rect2, state & ODS_SELECTED, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked);
			}
		}
		
		//This is needed always so that we can have the space for check marks
		
		rect.left = rect.left + m_iconX + 8 + BCMENU_GAP; 
		
		if (!strText.IsEmpty())
		{			
			CFont *pFont;
			if (state & ODS_DEFAULT)
				pFont = pDC->SelectObject(&m_menuFontBold);
			else
				pFont = pDC->SelectObject(&m_menuFont);// Select menu font in...
			CRect rectt(rect.left, rect.top - 1, rect.right, rect.bottom - 1);
			
			// Find tabs
			
			CString leftStr;
			CString rightStr;

			int tablocr = strText.ReverseFind(_T('\t'));
			if (tablocr != -1)
			{
				rightStr = strText.Mid(tablocr + 1);
				leftStr = strText.Left(strText.Find(_T('\t')));
				rectt.right -= m_iconX;
			}
			else
				leftStr = strText;
			
			int iOldMode = pDC->GetBkMode();
			pDC->SetBkMode(TRANSPARENT);
			
			// Draw the text in the correct colour:
			
			UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
			UINT nFormatr = DT_RIGHT | DT_SINGLELINE | DT_VCENTER;
			if (!(state & ODS_GRAYED))
			{
				pDC->SetTextColor(crText);
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			else
			{				
				// Draw the disabled text
				if (!(state & ODS_SELECTED))
				{
					RECT offset = *rectt;
					offset.left += 1;
					offset.right += 1;
					offset.top += 1;
					offset.bottom += 1;
					pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
					pDC->DrawText(leftStr, &offset, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, &offset, nFormatr);
					pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
					pDC->DrawText(leftStr, rectt, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, rectt, nFormatr);
				}
				else
				{
					// And the standard Grey text:
					pDC->SetTextColor(clrBack);
					pDC->DrawText(leftStr, rectt, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, rectt, nFormatr);
				}
			}
			pDC->SetBkMode(iOldMode);
			pDC->SelectObject(pFont);
		}
		
		penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	brBackground.DeleteObject();
}

void CODMenu::DrawItem_WinXP(LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);

	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	CRect rect;
	CRect rect2;
	COLORREF newclrBack = GetSysColor(COLOR_3DFACE);
	COLORREF clrBack = GetSysColor(COLOR_WINDOW);
	UINT state = lpDIS->itemState;
	MENUITEMINFO info;
	memset(&info, 0, sizeof(MENUITEMINFO));
	info.cbSize = sizeof(MENUITEMINFO);
	info.fMask = MIIM_CHECKMARKS;
	::GetMenuItemInfo((HMENU)lpDIS->hwndItem, lpDIS->itemID, MF_BYCOMMAND, &info);

	clrBack = DarkenColor(clrBack, 0.02);
	CFont *pFont = NULL;
	if (!IsWinXPLuna())
		newclrBack = LightenColor(newclrBack, 0.25);
	CBrush newbrBackground;
	CBrush brBackground;
	
	brBackground.CreateSolidBrush(clrBack);
	newbrBackground.CreateSolidBrush(newclrBack);
	int BCMENU_PAD = 4;
	int barwidth = m_iconX + BCMENU_PAD;
	
	if (lpDIS->itemID == 0)			// drawing a separator
	{
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect(rect, &brBackground);
		rect2.SetRect(rect.left, rect.top, rect.left + barwidth, rect.bottom);
		rect.top += rect.Height() >> 1;
		rect.left = rect2.right + BCMENU_PAD;
		pDC->DrawEdge(&rect, EDGE_ETCHED, BF_TOP);
		pDC->FillRect(rect2, &newbrBackground);
		pDC->Draw3dRect(rect2, newclrBack, newclrBack);
	}
	else
	{
		BOOL standardflag = FALSE;
		BOOL selectedflag = FALSE;
		BOOL disableflag = FALSE;
		BOOL checkflag = FALSE;
		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
		COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
		COLORREF crSelectFill;
		if (!IsWinXPLuna())
			crSelectFill = LightenColor(crSelect, 0.85);
		else
			crSelectFill = LightenColor(crSelect, 0.7);
		CBrush m_brSelect;
		CPen penBack;
		int dx;
		int dy;
		int nIconNormal = -1;
		
		// set some colors
		penBack.CreatePen(PS_SOLID, 0, clrBack);
		m_brSelect.CreateSolidBrush(crSelectFill);
		
		// draw the colored rectangle portion
		
		rect.CopyRect(&lpDIS->rcItem);
		rect2 = rect;
		
		// draw the up/down/focused/disabled state
		
		CString strText;
		TCHAR buffer[_MAX_PATH];
		::GetMenuString((HMENU)lpDIS->hwndItem, lpDIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
		strText = buffer;
		
		if (m_commandToImage.find(lpDIS->itemID) != m_commandToImage.end())
		{
			nIconNormal = m_commandToImage[lpDIS->itemID];
		}

		if (state & ODS_CHECKED && nIconNormal < 0)
		{
			if (state & ODS_SELECTED)
				checkflag = TRUE;
		}
		else if (nIconNormal != -1)
		{
			standardflag = TRUE;
			if (state & ODS_SELECTED && !(state & ODS_GRAYED))
				selectedflag = TRUE;
			else if (state & ODS_GRAYED)
				disableflag = TRUE;
		}
		
		if (state & ODS_SELECTED)
		{
			// draw the down edges			
			CPen *pOldPen = pDC->SelectObject(&penBack);
			
			pDC->FillRect(rect, &m_brSelect);
			pDC->Draw3dRect(rect, crSelect, crSelect);
			
			pDC->SelectObject(pOldPen);
		}
		else 
		{
			rect2.SetRect(rect.left, rect.top, rect.left + barwidth, rect.bottom);
			CPen *pOldPen = pDC->SelectObject(&penBack);
			pDC->FillRect(rect, &brBackground);
			pDC->FillRect(rect2, &newbrBackground);
			pDC->SelectObject(pOldPen);
			
			// draw the up edges			
			pDC->Draw3dRect(rect, clrBack, clrBack);
			pDC->Draw3dRect(rect2, newclrBack, newclrBack);
		}
		
		// draw the text if there is any
		//We have to paint the text only if the image is nonexistant
		
		dy =(int)(0.5 + (rect.Height() - m_iconY) / 2.0);
		dy = dy < 0 ? 0 : dy;
		dx =(int)(0.5 + (barwidth - m_iconX) / 2.0);
		dx = dx < 0 ? 0 : dx;
		rect2.SetRect(rect.left + 1, rect.top + 1, rect.left + barwidth - 2, rect.bottom - 1);
		
		if (checkflag || standardflag || selectedflag || disableflag)
		{
			if (checkflag)
			{
				pDC->FillRect(rect2, &newbrBackground);
				CPoint ptImage(rect.left + dx, rect.top + dy);		
				if (state & ODS_SELECTED)
    				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
				else
    				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
			}
			else if (disableflag)
			{
				CPoint ptImage(rect.left + dx, rect.top + dy);
				if (!selectedflag)
				{
					COLORREF transparentcol = newclrBack;
					if (state & ODS_SELECTED)
						transparentcol = crSelectFill;
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
					if (state & ODS_SELECTED)
						pDC->Draw3dRect(rect, crSelect, crSelect);
				}
				else
				{
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else if (selectedflag)
			{
				CPoint ptImage(rect.left + dx, rect.top + dy);
				if (state & ODS_CHECKED)
				{
					CBrush brushin;
					brushin.CreateSolidBrush(LightenColor(crSelect, 0.55));
					pDC->FillRect(rect2, &brushin);
					brushin.DeleteObject();
					pDC->Draw3dRect(rect2, crSelect, crSelect);
					ptImage.x -= 1;
					ptImage.y -= 1;
				}
				else
					pDC->FillRect(rect2, &m_brSelect);
				if (nIconNormal >= 0)
				{
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else
			{
				if (state & ODS_CHECKED)
				{
					CBrush brushin;
					brushin.CreateSolidBrush(LightenColor(crSelect, 0.85));
					pDC->FillRect(rect2, &brushin);
					brushin.DeleteObject();
					pDC->Draw3dRect(rect2, crSelect, crSelect);
					CPoint ptImage(rect.left + dx - 1, rect.top + dy - 1);
					if (nIconNormal)
						m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
				else
				{
					pDC->FillRect(rect2, &newbrBackground);
					pDC->Draw3dRect(rect2, newclrBack, newclrBack);
					CPoint ptImage(rect.left + dx, rect.top + dy);
					if (nIconNormal >= 0)
					{
						m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
					}
				}
			}
		}
		if (nIconNormal < 0 && state & ODS_CHECKED && !checkflag)
		{
			if (state & ODS_CHECKED || info.hbmpUnchecked) 
			{
				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
			}
		}
		
		// This is needed always so that we can have the space for check marks
		rect.left = rect.left + barwidth + 8; 
		
		if (!strText.IsEmpty())
		{			
			CRect rectt(rect.left, rect.top - 1, rect.right, rect.bottom - 1);
			
			// Find tabs			
			CString leftStr;
			CString rightStr;
			int tablocr = strText.ReverseFind(_T('\t'));
			if (tablocr != -1)
			{
				rightStr = strText.Mid(tablocr + 1);
				leftStr = strText.Left(strText.Find(_T('\t')));
				rectt.right -= m_iconX;
			}
			else
				leftStr = strText;
			
			int iOldMode = pDC->GetBkMode();
			pDC->SetBkMode(TRANSPARENT);
			
			// Draw the text in the correct colour:
			
			UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
			UINT nFormatr = DT_RIGHT | DT_SINGLELINE | DT_VCENTER;
			if (!(state & ODS_GRAYED))
			{
				pDC->SetTextColor(crText);
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			else
			{
				RECT offset = *rectt;
				offset.left += 1;
				offset.right += 1;
				offset.top += 1;
				offset.bottom += 1;
				if (!IsWinXPLuna())
				{
					COLORREF graycol = GetSysColor(COLOR_GRAYTEXT);
					if (!(state & ODS_SELECTED))
						graycol = LightenColor(graycol, 0.4);
					pDC->SetTextColor(graycol);
				}
				else 
					pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			pDC->SetBkMode(iOldMode);
		}
		
		penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	brBackground.DeleteObject();
	newbrBackground.DeleteObject();
}

BOOL CODMenu::GetBitmapFromImageList(CDC* pDC, CImageList *imglist, int nIndex, CBitmap &bmp)
{
	HICON hIcon = imglist->ExtractIcon(nIndex);
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	bmp.CreateCompatibleBitmap(pDC, m_iconX, m_iconY);
	CBitmap* pOldBmp = dc.SelectObject(&bmp);
	CBrush brush;
	COLORREF newclrBack;
	newclrBack = GetSysColor(COLOR_3DFACE);
	brush.CreateSolidBrush(newclrBack);
	::DrawIconEx(
		dc.GetSafeHdc(), 
		0,
		0,
		hIcon,
		m_iconX,
		m_iconY,
		0,
		(HBRUSH)brush,
		DI_NORMAL
		);
	dc.SelectObject(pOldBmp);
	dc.DeleteDC();
	// the icon is not longer needed
	::DestroyIcon(hIcon);
	return(TRUE);
}

void CODMenu::DitherBlt3(CDC *drawdc, CBitmap &bmp, COLORREF bgcolor)
{
	GetDisabledBitmap(bmp,bgcolor);
	CDC dc;
	dc.CreateCompatibleDC(NULL);
	CBitmap *pdcOldBmp = dc.SelectObject(&bmp);
	drawdc->BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	// reset DCs
	dc.SelectObject(pdcOldBmp);
	dc.DeleteDC();
}

void CODMenu::DitherBlt2(CDC *drawdc, CBitmap &bmp, COLORREF bgcolor)
{
	// create a monochrome memory DC
	CDC ddc;
	ddc.CreateCompatibleDC(NULL);
	CBitmap bwbmp;
	bwbmp.CreateCompatibleBitmap(&ddc, m_iconX, m_iconY);
	CBitmap *pddcOldBmp = ddc.SelectObject(&bwbmp);
	
	CDC dc;
	dc.CreateCompatibleDC(NULL);
	CBitmap *pdcOldBmp = dc.SelectObject(&bmp);
	
	// build a mask
	ddc.PatBlt(0, 0, m_iconX, m_iconY, WHITENESS);
	dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
	ddc.BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
	ddc.BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCPAINT);
	
	// Copy the image from the toolbar into the memory DC
	// and draw it(grayed) back into the toolbar.
	dc.FillSolidRect(0,0, m_iconX, m_iconY, bgcolor);
	//SK: Looks better on the old shell
	dc.SetBkColor(RGB(0, 0, 0));
	dc.SetTextColor(RGB(255, 255, 255));
	CBrush brShadow;
	CBrush brHilight;
	brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
	brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
	CBrush *pOldBrush = dc.SelectObject(&brHilight);
	dc.BitBlt(0, 0, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(1, 1, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	dc.BitBlt(1, 1, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	dc.SelectObject(&brShadow);
	dc.BitBlt(0, 0, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	// reset DCs
	ddc.SelectObject(pddcOldBmp);
	ddc.DeleteDC();
	dc.SelectObject(pOldBrush);
	dc.SelectObject(pdcOldBmp);
	dc.DeleteDC();
	
	brShadow.DeleteObject();
	brHilight.DeleteObject();
	bwbmp.DeleteObject();
}

COLORREF CODMenu::LightenColor(COLORREF col, double factor)
{
	if (factor > 0.0 && factor <= 1.0)
	{
		BYTE red = GetRValue(col);
		BYTE green = GetGValue(col);
		BYTE blue = GetBValue(col);
		BYTE lightred = (BYTE)((factor * (255 - red)) + red);
		BYTE lightgreen = (BYTE)((factor * (255 - green)) + green);
		BYTE lightblue = (BYTE)((factor * (255 - blue)) + blue);
		col = RGB(lightred, lightgreen, lightblue);
	}
	return(col);
}

COLORREF CODMenu::DarkenColor(COLORREF col, double factor)
{
	if (factor > 0.0 && factor <= 1.0)
	{
		BYTE red = GetRValue(col);
		BYTE green = GetGValue(col);
		BYTE blue = GetBValue(col);
		BYTE lightred =(BYTE)(red - (factor * red));
		BYTE lightgreen =(BYTE)(green - (factor * green));
		BYTE lightblue =(BYTE)(blue - (factor * blue));
		col = RGB(lightred, lightgreen, lightblue);
	}
	return(col);
}

BOOL CODMenu::Draw3DCheckmark(CDC *dc, const CRect& rc, BOOL bSelected, HBITMAP hbmCheck)
{
	CRect rcDest = rc;
	CBrush brush;
	COLORREF col;
	if (IsWinXPLuna())
		col = GetSysColor(COLOR_3DFACE);
	else 
		col = GetSysColor(COLOR_MENU);
	if (!bSelected)
		col = LightenColor(col, 0.6);
	brush.CreateSolidBrush(col);
	dc->FillRect(rcDest,&brush);
	brush.DeleteObject();
	if (IsNewShell()) //SK: looks better on the old shell
		dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
	if (!hbmCheck)
		DrawCheckMark(dc, rc.left + 4, rc.top + 4, GetSysColor(COLOR_MENUTEXT));
	else 
		DrawRadioDot(dc, rc.left + 5, rc.top + 4, GetSysColor(COLOR_MENUTEXT));
	return TRUE;
}

BOOL CODMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck, COLORREF &colorout, BOOL selected)
{
	CBrush brushin;
	COLORREF col;
	int dx;
	int dy;
	dy = (rc.Height() >> 1) - 3;
	dy = dy < 0 ? 0 : dy;
	dx = (rc.Width() >> 1) - 3;
	dx = dx < 0 ? 0 : dx;

	if (selected)
		col = LightenColor(colorout, 0.55);
	else
		col = LightenColor(colorout, 0.85);
	brushin.CreateSolidBrush(col);
	dc->FillRect(rc, &brushin);
	brushin.DeleteObject();
	dc->Draw3dRect(rc, colorout, colorout);

	if (!hbmCheck)
		DrawCheckMark(dc, rc.left + dx, rc.top + dy, GetSysColor(COLOR_MENUTEXT), TRUE);
	else
		DrawRadioDot(dc, rc.left + dx, rc.top + dy, GetSysColor(COLOR_MENUTEXT));
	return TRUE;
}

void CODMenu::GetDisabledBitmap(CBitmap &bmp,COLORREF background)
{
	CDC ddc;
	COLORREF bgcol,col,discol;
	BITMAP BitMap;

	bmp.GetBitmap(&BitMap);
	ddc.CreateCompatibleDC(NULL);
	CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);

	// use this to get the background color, takes into account color shifting
	CDC ddc2;
	CBrush brush;
	CBitmap bmp2;
	ddc2.CreateCompatibleDC(NULL);
	bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
	col=GetSysColor(COLOR_3DFACE);
	brush.CreateSolidBrush(col);
	CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
	CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
	ddc2.FillRect(rect,&brush);
	bgcol=ddc2.GetPixel(1,1);
	brush.DeleteObject();
	ddc2.SelectObject(pddcOldBmp2);
	discol=GetSysColor(COLOR_BTNSHADOW);

	for (int i = 0; i < BitMap.bmWidth; ++i)
	{
		for (int j = 0; j <BitMap.bmHeight ; ++j)
		{
			col=ddc.GetPixel(i,j);
			if (col != bgcol)
			{
				BYTE r = GetRValue(col);
				BYTE g = GetGValue(col);
				BYTE b = GetBValue(col);
				int avgcol = (r + g + b) / 3;
				double factor = avgcol / 255.0;
				ddc.SetPixel(i, j, LightenColor(discol,factor));
			}
			else
			{
				if (background)
					ddc.SetPixel(i, j, background);
			}
		}
	}
	ddc.SelectObject(pddcOldBmp);
}

void CODMenu::DrawRadioDot(CDC *pDC, int x, int y, COLORREF color)
{
	CRect rcDot(x, y, x + 6, y + 6);
	CBrush brush;
	CPen pen;
	brush.CreateSolidBrush(color);
	pen.CreatePen(PS_SOLID, 0, color);
	CBrush *pOldBrush = pDC->SelectObject(&brush);
	CPen *pOldPen = pDC->SelectObject(&pen);
	pDC->Ellipse(&rcDot);
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	pen.DeleteObject();
	brush.DeleteObject();
}

void CODMenu::DrawCheckMark(CDC* pDC, int x, int y, COLORREF color, BOOL narrowflag)
{
	int dp = 0;
	CPen penBack;
	penBack.CreatePen(PS_SOLID, 0, color);
	CPen *pOldPen = pDC->SelectObject(&penBack);
	if (narrowflag)
		dp = 1;

	pDC->MoveTo(x, y + 2);
	pDC->LineTo(x, y + 5 - dp);
	
	pDC->MoveTo(x + 1, y + 3);
	pDC->LineTo(x + 1, y + 6 - dp);
	
	pDC->MoveTo(x + 2, y + 4);
	pDC->LineTo(x + 2, y + 7 - dp);
	
	pDC->MoveTo(x + 3, y + 3);
	pDC->LineTo(x + 3, y + 6 - dp);
	
	pDC->MoveTo(x + 4, y + 2);
	pDC->LineTo(x + 4, y + 5 - dp);
	
	pDC->MoveTo(x + 5, y + 1);
	pDC->LineTo(x + 5, y + 4 - dp);
	
	pDC->MoveTo(x + 6, y);
	pDC->LineTo(x + 6, y + 3 - dp);
	
	pDC->SelectObject(pOldPen);
	penBack.DeleteObject();
}

#ifdef _DEBUG
void CODMenu::OnMenuDebug()
{
	static int count = 0;
	if (IsPostCall())
	{
		if (count == 0)
		{
			CDebugMenu dlg;

			dlg.DoModal();
		}
		count++;
		count = count % m_pluggedInCount;
	}
}

void CODMenu::OnUpdateMenuDebug(CCmdUI *pCmdUI)
{
	if (pCmdUI->m_pMenu != NULL)
	{
		pCmdUI->m_pMenu->SetDefaultItem(ID_DEBUGMENU_MENUICONPREVIEW, FALSE);
	}
	pCmdUI->Enable(TRUE);
}
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Roger Allen
Software Developer (Senior) Sirius Analytical Instruments
United Kingdom United Kingdom
A research and development programmer working for a pharmaceutical instrument company for the past 17 years.
 
I am one of those lucky people who enjoys his work and spends more time than he should either doing work or reseaching new stuff. I can also be found on playing DDO on the Cannith server (Send a tell to "Maetrim" who is my current main)
 
I am also a keep fit fanatic, doing cross country running and am seriously into [url]http://www.ryushinkan.co.uk/[/url] Karate at this time of my life, training from 4-6 times a week and recently achieved my 1st Dan after 6 years.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411022.1 | Last Updated 12 May 2004
Article Copyright 2004 by Roger Allen
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid