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

Resource ID Organiser Add-In for Visual C++ 5.0/6.0/.NET

, 10 Jan 2005 CPOL
An application/add-in to organise and renumber resource symbol IDs
resorg103.zip
ResOrg103.exe
resorg104.zip
ResOrg104.exe
resorgaddinsetup.zip
ResOrgAddInSetup.exe
resorgaddin_executables.zip
ResOrg.exe
BXFileDialog.dll
CJ609Lib.dll
NGLib103.dll
ResOrgAddIn.dll
ResOrgCore.dll
ResOrg.cnt
resorg.fts
ResOrg.hlp
resorgnetaddinsetup.zip
ResOrgNETAddInSetup.msi
resorgnetaddin_executables.zip
ResOrgNETAddInToolWindows.ocx
ResOrgNET.exe
CJ609LibVc7.dll
NGLib103Vc7.dll
ResOrgNETAddIn.dll
ResOrgNETCore.dll
ResOrg.cnt
resorg.fts
ResOrg.hlp
ReadMe.rtf
Licence.rtf
resorgnet_executables.zip
ResOrgNET_executables
CJ609LibVc7.dll
NGLib103Vc7.dll
QHTMLight.dll
ResOrg.cnt
resorg.fts
ResOrg.hlp
ResOrgNETAddIn.dll
ResOrgNETAddInToolWindows.ocx
ResOrgNETCore.dll
resorg_demo.zip
ResOrg103.exe
resorg_executables.zip
ResOrgAddIn.dll
BXFileDialog.dll
CJ609Lib.dll
ResOrg.exe
ResOrg.cnt
resorg.fts
ResOrg.hlp
ResOrgCore.dll
NGLib103.dll
resorg_src.zip
BXFileDialog
BXFileDialog.dsp
Lib
Release
Res
bitmap2.bmp
FileOpen.bmp
filesave.bmp
CJLibrary
CJLibrary
CJLibrary.def
CJLibrary.dsp
CJLibrary.dsw
CJLibrarydep.jpg
CJLibraryStatic.dsp
Debug_Unicode
Release
Release_Unicode
res
Include
res
btn_arro.bmp
btn_explorer.bmp
button_images.bmp
cj_logo.bmp
dragging.cur
handcur.cur
headerba.bmp
hsplitba.cur
icr_hand.cur
nodraggi.cur
PushPin.bmp
Toolbar.bmp
vsplitba.cur
Lib
default.doxygen
NGLibrary
Bin
NGLibrary.def
NGLibrary.dsp
NGLibrary.dsw
Release
Res
Drives.bmp
Release
ResOrg.dsw
ResOrgAddIn
Release
Res
HtmlDoc.ico
ResOrg.ico
ResOrgDoc.ico
TBarLrge.bmp
TBarMedm.bmp
Toolbar.bmp
WorkspaceTabs.bmp
ResOrgAddIn.def
ResOrgAddIn.dsp
ResOrgAddIn.odl
ResOrgAddIn_Res.hm
ResOrgApp
Lint
Release
Res
HtmlDoc.ico
MAINFRAM.BMP
ResOrg.ico
ResOrgDoc.ico
TBarLrge.bmp
TBarMedm.bmp
Toolbar.bmp
workspace.ico
WorkspaceTabs.bmp
ResOrgApp.dsp
ResOrgApp_Res.hm
ResOrgApp_Res.resorg
ResOrgCore
Lint
Release
Res
Anna.bmp
BuildOptions.ico
ComCtl Version Prompt.rtf
File Reload Warning Ex.rtf
File Reload Warning.rtf
Global Next Symbol Value Warning Prompt.rtf
information.ico
Invalid Symbol Name.rtf
Mailing List Prompt.rtf
Next Symbol Value Warning Prompt.rtf
project context menu.bmp
project.ico
RenumWiz Completion.rtf
Report.ico
ResOrg Logo.bmp
ResOrg Updated.rtf
ResOrg.ico
resource file.ico
riverblade_logo.bmp
solution.ico
Symbol Delete Warning.rtf
Symbol Name Warning.rtf
Symbol Rename Warning.rtf
SymbolFile.ico
Symbols Delete Warning.rtf
sym_binary.ico
sym_bitmap.ico
sym_command.ico
sym_control.ico
sym_dialog.ico
sym_icon.ico
sym_menu.ico
sym_prompt.ico
sym_resource.ico
sym_string.ico
Toolbar.bmp
VcAddIn.ico
VersionCheck.ico
warning.ico
WizardHeader256.bmp
WizardWatermark256.bmp
ResOrgCore.def
ResOrgCore.dsp
ResOrgCore_Res.hm
ResOrgCore_Res.resorg
Xml
ProblemSymbolReportHtml.xsl
SymbolsReportHtml.xsl
ResOrgNETAddIn
AddIn.def
Release
Res
AddIn.rgs
HtmlDoc.ico
ResOrg.ico
ResOrgDoc.ico
Toolbar.bmp
WorkspaceTabs.bmp
ResOrgNETAddInSetup
Banner.jpg
Intro screen.jpg
Licence.rtf
ReadMe.rtf
Release
ResOrg.ico
ResOrgNETAddInSetup.vdproj
ResOrgNETAddInToolWindows
Release
Res
Edit.ico
Properties.ico
Renumber.ico
ResOrgNETAddInToolWindows.ico
ResOrgNETAddInToolWindowsCtrl.bmp
ResOrgNETAddInToolWindows.def
SatelliteDll
Release
res
AboutBoxCmd.bmp
OpenResOrgCmd.bmp
OptionsCmd.bmp
ViewMainToolWinCmd.bmp
//*************************************************************************
// CJMenu.cpp : implementation file
// Version : 3.033
// Date : April 2002
// Author : Brent Corkum
// Email :  corkum@rocscience.com
// Latest Version : http://www.rocscience.com/~corkum/BCMenu.html
// 
// Bug Fixes and portions of code supplied by:
//
// Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
// Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
// Stefan Kuhr,Reiner Jung,Martin Vladic,Kim Yoo Chul,
// Oz Solomonovich,Tongzhe Cui,Stephane Clog,Warren Stevens,
// Damir Valiulin,David Kinder,Marc Loiry
//
// You are free to use/modify this code but leave this header intact.
// This class is public domain so you are free to use it any of
// your applications (Freeware,Shareware,Commercial). All I ask is
// that you let me know so that if you have a real winner I can
// brag to my buddies that some of my code is in your app. I also
// wouldn't mind if you sent me a copy of your application since I
// like to play with new stuff.
//*************************************************************************

/****************************************************************************
 *
 * $Date: 15/12/02 17:59 $
 * $Revision: 6 $
 * $Archive: /Projects/Libraries/CJLibrary/CJLibrary/CJMenu.cpp $
 *
 * $History: CJMenu.cpp $
 * 
 * *****************  Version 6  *****************
 * User: Anna         Date: 15/12/02   Time: 17:59
 * Updated in $/Projects/Libraries/CJLibrary/CJLibrary
 * Added 2 new overloads of CCJMenu::LoadMenu() to allow the HINSTANCE of
 * the module to be specified
 *  
 * 
 * 
 * *****************  Version 5  *****************
 * User: Andy         Date: 10/05/02   Time: 14:07
 * Updated in $/Projects/Libraries/CJLibrary/CJLibrary
 * Integrated BCMenu 3.03
 *
 * *****************  Version 4  *****************
 * User: Andy         Date: 2/26/02    Time: 4:13p
 * Updated in $/Projects/Libraries/CJLibrary/CJLibrary
 * Integrated BCMenu 3.01
 * 
 * *****************  Version 3  *****************
 * User: Andy         Date: 1/14/02    Time: 8:19p
 * Updated in $/Projects/AddIns/ResOrg/CJLibrary/CJLibrary
 * XP style now suppports default menu items
 * 
 * *****************  Version 2  *****************
 * User: Andy         Date: 1/04/02    Time: 10:48p
 * Updated in $/Projects/AddIns/ResOrg/CJLibrary/CJLibrary
 * Upgraded to BCMenu 3.0 (WinXP style and lots of bug fixes)
 * 
 * *****************  Version 6  *****************
 * User: Kirk Stowell Date: 10/24/99   Time: 2:09a
 * Updated in $/CodeJock/CJLibrary
 * Upgraded to version 2.5 of BCMenu
 * 
 * *****************  Version 5  *****************
 * User: Kirk Stowell Date: 10/14/99   Time: 12:41p
 * Updated in $/CodeJock/CJLibrary
 * Added source control history to file header.
 *
 ***************************************************************************/


#include "stdafx.h"        // Standard windows header file
#include "CJMenu.h"        // CCJMenu class declaration
#include <afxpriv.h>       //SK: makes A2W and other spiffy AFX macros work

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CCJMenu_GAP 1
#ifndef OBM_CHECK
#define OBM_CHECK 32760 // from winuser.h
#endif

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

static CPINFO CPInfo;

// how the menu's are drawn in win9x/NT/2000
UINT CCJMenu::original_drawmode=CCJMenu_DRAWMODE_XP;
BOOL CCJMenu::original_select_disabled=TRUE;

// how the menu's are drawn in winXP
UINT CCJMenu::xp_drawmode=CCJMenu_DRAWMODE_XP;
BOOL CCJMenu::xp_select_disabled=FALSE;
BOOL CCJMenu::xp_draw_3D_bitmaps=TRUE;
BOOL CCJMenu::hicolor_bitmaps=FALSE;

// Variable to set how accelerators are justified. The default mode (TRUE) right
// justifies them to the right of the longes string in the menu. FALSE
// just right justifies them.
BOOL CCJMenu::xp_space_accelerators=TRUE;
BOOL CCJMenu::original_space_accelerators=TRUE;

CImageList CCJMenu::m_AllImages;
CArray<int,int&> CCJMenu::m_AllImagesID;
int CCJMenu::m_iconX = 16;
int CCJMenu::m_iconY = 15;

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


Win32Type IsShellType()
{
	Win32Type  ShellType;
	DWORD winVer;
	OSVERSIONINFO *osvi;
	
	winVer=GetVersion();
	if(winVer<0x80000000){/*NT */
		ShellType=WinNT3;
		osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
		if (osvi!=NULL){
			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;
			free(osvi);
		}
	}
	else if  (LOBYTE(LOWORD(winVer))<4)
		ShellType=Win32s;
	else{
		ShellType=Win95;
		osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
		if (osvi!=NULL){
			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;
			free(osvi);
		}
	}
	return ShellType;
}

static Win32Type g_Shell=IsShellType();

void CCJMenuData::SetAnsiString(LPCSTR szAnsiString)
{
	USES_CONVERSION;
	SetWideString(A2W(szAnsiString));  //SK:  see MFC Tech Note 059
}

CString CCJMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
//depending on the MFC-Version we are using
{
	CString strText;
	if (m_szMenuText)
    {
#ifdef UNICODE
		strText = m_szMenuText;
#else
		USES_CONVERSION;
		strText=W2A(m_szMenuText);     //SK:  see MFC Tech Note 059
#endif    
    }
	return strText;
}

CTypedPtrArray<CPtrArray, HMENU> CCJMenu::m_AllSubMenus;  // Stores list of all sub-menus

IMPLEMENT_DYNAMIC( CCJMenu, CMenu )

/*
===============================================================================
CCJMenu::CCJMenu()
CCJMenu::~CCJMenu()
-----------------

Constructor and Destructor.

===============================================================================
*/

CCJMenu::CCJMenu()
{
	m_bDynIcons = FALSE;     // O.S. - no dynamic icons by default
	disable_old_style=FALSE;
	m_selectcheck = -1;
	m_unselectcheck = -1;
	checkmaps=NULL;
	checkmapsshare=FALSE;
	// set the color used for the transparent background in all bitmaps
	m_bitmapBackground=RGB(192,192,192); //gray
	m_bitmapBackgroundFlag=FALSE;
	GetCPInfo(CP_ACP,&CPInfo);
	m_loadmenu=FALSE;
}


CCJMenu::~CCJMenu()
{
	DestroyMenu();
}

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

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

BOOL CCJMenu::IsLunaMenuStyle()
{
	if(IsWinXPLuna()){
		if(xp_drawmode==CCJMenu_DRAWMODE_XP)return(TRUE);
	}
	else{
		if(original_drawmode==CCJMenu_DRAWMODE_XP)return(TRUE);
	}
	return(FALSE);
}

CCJMenuData::~CCJMenuData()
{
	if(bitmap)
		delete(bitmap);
	
	delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
}


void CCJMenuData::SetWideString(const wchar_t *szWideString)
{
	delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
	
	if (szWideString)
    {
		m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
		if (m_szMenuText)
			wcscpy(m_szMenuText,szWideString);
    }
	else
		m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
}

BOOL CCJMenu::IsMenu(CMenu *submenu)
{
	int m;
	int numSubMenus = m_AllSubMenus.GetUpperBound();
	for(m=0;m<=numSubMenus;++m){
		if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
	}
	return(FALSE);
}

BOOL CCJMenu::IsMenu(HMENU submenu)
{
	int m;
	int numSubMenus = m_AllSubMenus.GetUpperBound();
	for(m=0;m<=numSubMenus;++m){
		if(submenu==m_AllSubMenus[m])return(TRUE);
	}
	return(FALSE);
}

BOOL CCJMenu::DestroyMenu()
{
	// Destroy Sub menus:
	int m,n;
	int numAllSubMenus = m_AllSubMenus.GetUpperBound();
	for(n = numAllSubMenus; n>= 0; n--){
		if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
	}
	int numSubMenus = m_SubMenus.GetUpperBound();
	for(m = numSubMenus; m >= 0; m--){
		numAllSubMenus = m_AllSubMenus.GetUpperBound();
		for(n = numAllSubMenus; n>= 0; n--){
			if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
		}
		CMenu *ptr=FromHandle(m_SubMenus[m]);
		BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( CCJMenu ));
		if(flag)delete((CCJMenu *)ptr);
	}
	m_SubMenus.RemoveAll();
	// Destroy menu data
	int numItems = m_MenuList.GetUpperBound();
	for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
	m_MenuList.RemoveAll();
	if(checkmaps&&!checkmapsshare){
		delete checkmaps;
		checkmaps=NULL;
	}
	// Call base-class implementation last:
	return(CMenu::DestroyMenu());
};

int CCJMenu::GetMenuDrawMode(void)
{
	if(IsWinXPLuna())return(xp_drawmode);
	return(original_drawmode);
}

BOOL CCJMenu::GetSelectDisableMode(void)
{
	if(IsLunaMenuStyle())return(xp_select_disabled);
	return(original_select_disabled);
}


/*
==========================================================================
void CCJMenu::DrawItem(LPDRAWITEMSTRUCT)
---------------------------------------

  Called by the framework when a particular item needs to be drawn.  We
  overide this to draw the menu item in a custom-fashion, including icons
  and the 3D rectangle bar.
  ==========================================================================
*/

void CCJMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)DrawItem_Win9xNT2000(lpDIS);
	else{
		if(IsWinXPLuna()){
			if(xp_drawmode==CCJMenu_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
			else DrawItem_Win9xNT2000(lpDIS);
		}
		else{
			if(original_drawmode==CCJMenu_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
			else DrawItem_Win9xNT2000(lpDIS);
		}	
	}
}

void CCJMenu::DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	CRect rect;
	UINT state = (((CCJMenuData*)(lpDIS->itemData))->nFlags);
	CBrush m_brBackground;
	COLORREF m_clrBack;

	if(IsWinXPLuna())m_clrBack=GetSysColor(COLOR_3DFACE);
	else m_clrBack=GetSysColor(COLOR_MENU);
	
	m_brBackground.CreateSolidBrush(m_clrBack);

	// remove the selected bit if it's grayed out
	if(lpDIS->itemState & ODS_GRAYED&&!original_select_disabled){
		if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
	}
	
	if(state & MF_SEPARATOR){
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect (rect,&m_brBackground);
		rect.top += (rect.Height()>>1);
		pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
	}
	else{
		CRect rect2;
		BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
		BOOL checkflag=FALSE;
		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
		CBrush m_brSelect;
		CPen m_penBack;
		int x0,y0,dy;
		int nIconNormal=-1,xoffset=-1,global_offset=-1;
		CImageList *bitmap=NULL;
		
		// set some colors
		m_penBack.CreatePen (PS_SOLID,0,m_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
		
		UINT state = lpDIS->itemState;
		CString strText;
		
		if(lpDIS->itemData != NULL){
			nIconNormal = (((CCJMenuData*)(lpDIS->itemData))->menuIconNormal);
			xoffset = (((CCJMenuData*)(lpDIS->itemData))->xoffset);
			global_offset = (((CCJMenuData*)(lpDIS->itemData))->global_offset);
			bitmap = (((CCJMenuData*)(lpDIS->itemData))->bitmap);
			strText = ((CCJMenuData*) (lpDIS->itemData))->GetString();

			if(nIconNormal<0&&global_offset>=0){
				xoffset=global_offset;
				nIconNormal=0;
				bitmap = &m_AllImages;
			}
			
			if(state&ODS_CHECKED && nIconNormal<0){
				if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
				else if(m_unselectcheck>0) checkflag=TRUE;
			}
			else if(nIconNormal != -1){
				standardflag=TRUE;
				if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
				else if(state&ODS_GRAYED) disableflag=TRUE;
			}
		}
		else{
			strText.Empty();
		}
		
		if(state&ODS_SELECTED){ // draw the down edges
			
			CPen *pOldPen = pDC->SelectObject (&m_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+CCJMenu_GAP,rect.top,rect.right,rect.bottom);
			pDC->FillRect (rect2,&m_brSelect);
			
			pDC->SelectObject (pOldPen);
			crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
		}
		else {
			CPen *pOldPen = pDC->SelectObject (&m_penBack);
			pDC->FillRect (rect,&m_brBackground);
			pDC->SelectObject (pOldPen);
			
			// draw the up edges	
			pDC->Draw3dRect (rect,m_clrBack,m_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,m_clrBack,m_clrBack);
			if(checkflag && checkmaps){
				pDC->FillRect (rect2,&m_brBackground);
				rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
					rect.top+m_iconY+4+dy);
				
				pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
				CPoint ptImage(rect.left+2,rect.top+2+dy);
				
				if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
				else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
			}
			else if(disableflag){
				if(!selectedflag){
					CBitmap bitmapstandard;
					GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
					rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
                        rect.top+m_iconY+4+dy);
					pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
					if(disable_old_style)
						DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
						(HBITMAP)(bitmapstandard),0,0,m_clrBack);
					else{
						if(hicolor_bitmaps)
							DitherBlt3(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
							bitmapstandard,m_clrBack);
						else
							DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
							bitmapstandard,0,0,m_clrBack);
					}
					bitmapstandard.DeleteObject();
				}
			}
			else if(selectedflag){
				pDC->FillRect (rect2,&m_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(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
			}
			else{
				if(state&ODS_CHECKED){
					CBrush brush;
					COLORREF col = m_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,&m_brBackground);
					rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
                        rect.top+m_iconY+4+dy);
					pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
				}
				CPoint ptImage(rect.left+2,rect.top+2+dy);
				if(bitmap)bitmap->Draw(pDC,xoffset,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);
			CMenuItemInfo info;
			info.fMask = MIIM_CHECKMARKS;
			::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
				MF_BYCOMMAND, &info);
			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
		
		x0=rect.left;y0=rect.top;
		rect.left = rect.left + m_iconX + 8 + CCJMenu_GAP; 
		
		if(!strText.IsEmpty()){
			
			CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
			
			//   Find tabs
			
			CString leftStr,rightStr;
			leftStr.Empty();rightStr.Empty();
			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(!(lpDIS->itemState & 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(m_clrBack);
					pDC->DrawText(leftStr,rectt, nFormat);
					if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
				}
			}
			pDC->SetBkMode( iOldMode );
		}
		
		m_penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	m_brBackground.DeleteObject();
}

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

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


void CCJMenu::DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
#ifdef CCJMenu_USE_MEMDC
	CCJMenuMemDC *pMemDC=NULL;
#endif
	CRect rect,rect2;
	UINT state = (((CCJMenuData*)(lpDIS->itemData))->nFlags);
	COLORREF m_newclrBack=GetSysColor(COLOR_3DFACE);
	COLORREF m_clrBack=GetSysColor(COLOR_WINDOW);
	m_clrBack=DarkenColor(m_clrBack,0.02);
	CFont m_fontMenu,*pFont=NULL;
	LOGFONT m_lf;
	if(!IsWinXPLuna())m_newclrBack=LightenColor(m_newclrBack,0.25);
	CBrush m_newbrBackground,m_brBackground;
	m_brBackground.CreateSolidBrush(m_clrBack);
	m_newbrBackground.CreateSolidBrush(m_newclrBack);
	int CCJMenu_PAD=4;
	if(xp_draw_3D_bitmaps)CCJMenu_PAD=7;
	int barwidth=m_iconX+CCJMenu_PAD;
	
	// remove the selected bit if it's grayed out
	if(lpDIS->itemState & ODS_GRAYED&&!xp_select_disabled){
		if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
#ifdef CCJMenu_USE_MEMDC
		pMemDC=new CCJMenuMemDC(pDC,&lpDIS->rcItem);
		pDC = pMemDC;
		ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
		NONCLIENTMETRICS nm;
		nm.cbSize = sizeof (NONCLIENTMETRICS);
		VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
		m_lf =  nm.lfMenuFont;
		m_fontMenu.CreateFontIndirect (&m_lf);
		pFont = pDC->SelectObject (&m_fontMenu);
#endif

	}
	
	if(state & MF_SEPARATOR){
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect (rect,&m_brBackground);
		rect2.SetRect(rect.left,rect.top,rect.left+barwidth,rect.bottom);
		rect.top+=rect.Height()>>1;
		rect.left = rect2.right+CCJMenu_PAD;
		pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
		pDC->FillRect (rect2,&m_newbrBackground);
		pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
	}
	else{
		BOOL standardflag=FALSE,selectedflag=FALSE,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 m_penBack;
		int x0,y0,dx,dy;
		int nIconNormal=-1,xoffset=-1,global_offset=-1;
		int faded_offset=1,shadow_offset=2,disabled_offset=3;
		CImageList *bitmap=NULL;
		BOOL CanDraw3D=FALSE;
		
		// set some colors
		m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
		m_brSelect.CreateSolidBrush(crSelectFill);
		
		// draw the colored rectangle portion
		
		rect.CopyRect(&lpDIS->rcItem);
		rect2=rect;
		
		// draw the up/down/focused/disabled state
		
		UINT state = lpDIS->itemState;
		CString strText;
		
		if(lpDIS->itemData != NULL){
			nIconNormal = (((CCJMenuData*)(lpDIS->itemData))->menuIconNormal);
			xoffset = (((CCJMenuData*)(lpDIS->itemData))->xoffset);
			bitmap = (((CCJMenuData*)(lpDIS->itemData))->bitmap);
			strText = ((CCJMenuData*) (lpDIS->itemData))->GetString();
			global_offset = (((CCJMenuData*)(lpDIS->itemData))->global_offset);

			if(xoffset==0&&xp_draw_3D_bitmaps&&bitmap&&bitmap->GetImageCount()>2)CanDraw3D=TRUE;

			if(nIconNormal<0&&xoffset<0&&global_offset>=0){
				xoffset=global_offset;
				nIconNormal=0;
				bitmap = &m_AllImages;
				if(xp_draw_3D_bitmaps&&CanDraw3DImageList(global_offset)){
					CanDraw3D=TRUE;
					faded_offset=global_offset+1;
					shadow_offset=global_offset+2;
					disabled_offset=global_offset+3;
				}
			}

			
			if(state&ODS_CHECKED && nIconNormal<0){
				if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
				else if(m_unselectcheck>0) checkflag=TRUE;
			}
			else if(nIconNormal != -1){
				standardflag=TRUE;
				if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
				else if(state&ODS_GRAYED) disableflag=TRUE;
			}
		}
		else{
			strText.Empty();
		}
		
		if(state&ODS_SELECTED){ // draw the down edges
			
			CPen *pOldPen = pDC->SelectObject (&m_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 (&m_penBack);
			pDC->FillRect (rect,&m_brBackground);
			pDC->FillRect (rect2,&m_newbrBackground);
			pDC->SelectObject (pOldPen);
			
			// draw the up edges
			
			pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
			pDC->Draw3dRect (rect2,m_newclrBack,m_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 && checkmaps){
				pDC->FillRect (rect2,&m_newbrBackground);
				CPoint ptImage(rect.left+dx,rect.top+dy);		
				if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
				else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
			}
			else if(disableflag){
				if(!selectedflag){
					if(CanDraw3D){
						CPoint ptImage(rect.left+dx,rect.top+dy);
						bitmap->Draw(pDC,disabled_offset,ptImage,ILD_TRANSPARENT);
					}
					else{
						CBitmap bitmapstandard;
						GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
						COLORREF transparentcol=m_newclrBack;
						if(state&ODS_SELECTED)transparentcol=crSelectFill;
						if(disable_old_style)
							DitherBlt(lpDIS->hDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
							(HBITMAP)(bitmapstandard),0,0,transparentcol);
						else
							DitherBlt2(pDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
							bitmapstandard,0,0,transparentcol);
						if(state&ODS_SELECTED)pDC->Draw3dRect (rect,crSelect,crSelect);
						bitmapstandard.DeleteObject();
					}
				}
			}
			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(bitmap){
					if(CanDraw3D&&!(state&ODS_CHECKED)){
						CPoint ptImage1(ptImage.x+1,ptImage.y+1);
						CPoint ptImage2(ptImage.x-1,ptImage.y-1);
						bitmap->Draw(pDC,shadow_offset,ptImage1,ILD_TRANSPARENT);
						bitmap->Draw(pDC,xoffset,ptImage2,ILD_TRANSPARENT);
					}
					else bitmap->Draw(pDC,xoffset,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(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
				}
				else{
					pDC->FillRect (rect2,&m_newbrBackground);
					pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
					CPoint ptImage(rect.left+dx,rect.top+dy);
					if(bitmap){
						if(CanDraw3D)
							bitmap->Draw(pDC,faded_offset,ptImage,ILD_TRANSPARENT);
						else
							bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
					}
				}
			}
		}
		if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
			CMenuItemInfo info;
			info.fMask = MIIM_CHECKMARKS;
			::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
				MF_BYCOMMAND, &info);
			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
		
		x0=rect.left;y0=rect.top;
		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,rightStr;
			leftStr.Empty();rightStr.Empty();
			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(!(lpDIS->itemState & 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 );
		}
		
		m_penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	m_brBackground.DeleteObject();
	m_newbrBackground.DeleteObject();
#ifdef CCJMenu_USE_MEMDC
	if(pFont)pDC->SelectObject (pFont); //set it to the old font
	m_fontMenu.DeleteObject();
	if(pMemDC)delete pMemDC;
#endif
}

BOOL CCJMenu::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 m_newclrBack;
	m_newclrBack=GetSysColor(COLOR_3DFACE);
	brush.CreateSolidBrush(m_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 CCJMenu::MeasureItem(LPMEASUREITEMSTRUCT)
---------------------------------------------

  Called by the framework when it wants to know what the width and height
  of our item will be.  To accomplish this we provide the width of the
  icon plus the width of the menu text, and then the height of the icon.
  
	==========================================================================
*/

void CCJMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
	UINT state = (((CCJMenuData*)(lpMIS->itemData))->nFlags);
	int CCJMenu_PAD=4;
	if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps)CCJMenu_PAD=7;
	if(state & MF_SEPARATOR){
		lpMIS->itemWidth = 0;
		int temp = GetSystemMetrics(SM_CYMENU)>>1;
		if(IsLunaMenuStyle())
			lpMIS->itemHeight = 3;
		else
			lpMIS->itemHeight = temp>(m_iconY+CCJMenu_PAD)/2 ? temp : (m_iconY+CCJMenu_PAD)/2;
	}
	else{
		CFont m_fontMenu;
		LOGFONT m_lf;
		ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
		NONCLIENTMETRICS nm;
		nm.cbSize = sizeof (NONCLIENTMETRICS);
		VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
			nm.cbSize,&nm,0)); 
		m_lf =  nm.lfMenuFont;
		m_fontMenu.CreateFontIndirect (&m_lf);
		
		// Obtain the width of the text:
		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...
		
		if (IsNewShell())
			pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
        
		//Get pointer to text SK
		const wchar_t *lpstrText = ((CCJMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
		    
		SIZE size;
		size.cx=size.cy=0;
		
		if (Win32s!=g_Shell)
			VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
			wcslen(lpstrText),&size)); //SK should also work on 95
#ifndef UNICODE //can't be UNICODE for Win32s
		else{//it's Win32suckx
			RECT rect;
			rect.left=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));
		}
#endif    
		
		CSize t = CSize(size);
		if(IsNewShell())
			pDC->SelectObject (pFont);  // Select old font in
		pWnd->ReleaseDC(pDC);  // Release the DC
		
		// Set width and height:
		
		if(IsLunaMenuStyle())lpMIS->itemWidth = m_iconX+CCJMenu_PAD+8+t.cx;
		else lpMIS->itemWidth = m_iconX + t.cx + m_iconX + CCJMenu_GAP;
		int temp = GetSystemMetrics(SM_CYMENU);
		lpMIS->itemHeight = temp>m_iconY+CCJMenu_PAD ? temp : m_iconY+CCJMenu_PAD;
		m_fontMenu.DeleteObject();
	}
}

void CCJMenu::SetIconSize (int width, int height)
{
	m_iconX = width;
	m_iconY = height;
}

BOOL CCJMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal)
{
	USES_CONVERSION;
	return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
}


BOOL CCJMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal)
{
	// Add the MF_OWNERDRAW flag if not specified:
	if(!nID){
		if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
		else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
	}
	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
	
	if(nFlags & MF_POPUP){
		m_AllSubMenus.Add((HMENU)nID);
		m_SubMenus.Add((HMENU)nID);
	}
	
	CCJMenuData *mdata = new CCJMenuData;
	m_MenuList.Add(mdata);
	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
	
	mdata->menuIconNormal = -1;
	mdata->xoffset = -1;
	
	if(nIconNormal>=0){
		CImageList bitmap;
		int xoffset=0;
		LoadFromToolBar(nID,nIconNormal,xoffset);
		if(mdata->bitmap){
			mdata->bitmap->DeleteImageList();
			mdata->bitmap=NULL;
		}
		bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(AddBitmapToImageList(&bitmap,nIconNormal)){
			mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
		}
	}
	else mdata->global_offset = GlobalImageListOffset(nID);

	mdata->nFlags = nFlags;
	mdata->nID = nID;
	BOOL returnflag=CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata);
	if(m_loadmenu)RemoveTopLevelOwnerDraw();
	return(returnflag);
}

BOOL CCJMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
                           CImageList *il,int xoffset)
{
	USES_CONVERSION;
	return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
}

BOOL CCJMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
                           CImageList *il,int xoffset)
{
	// Add the MF_OWNERDRAW flag if not specified:
	if(!nID){
		if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
		else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
	}
	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
	
	if(nFlags & MF_POPUP){
		m_AllSubMenus.Add((HMENU)nID);
		m_SubMenus.Add((HMENU)nID);
	}
	
	CCJMenuData *mdata = new CCJMenuData;
	m_MenuList.Add(mdata);
	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
	
	if(il){
		mdata->menuIconNormal = 0;
		mdata->xoffset=0;
		if(mdata->bitmap)mdata->bitmap->DeleteImageList();
		else mdata->bitmap=new(CImageList);
		ImageListDuplicate(il,xoffset,mdata->bitmap);
	}
	else{
		mdata->menuIconNormal = -1;
		mdata->xoffset = -1;
	}
	mdata->nFlags = nFlags;
	mdata->nID = nID;
	return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
}

BOOL CCJMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal)
{
	USES_CONVERSION;
	return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
}


BOOL CCJMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal)
{
	if(!(nFlags & MF_BYPOSITION)){
		int iPosition =0;
		CCJMenu* pMenu = FindMenuOption(nPosition,iPosition);
		if(pMenu){
			return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
		}
		else return(FALSE);
	}
	
	if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;

	int menustart=0;

	if(nFlags & MF_POPUP){
		if(m_loadmenu){
			menustart=GetMenuStart();
			if(nPosition<(UINT)menustart)menustart=0;
		}
		m_AllSubMenus.Add((HMENU)nID);
		m_SubMenus.InsertAt(nPosition,(HMENU)nID);
	}

	//Stephane Clog suggested adding this, believe it or not it's in the help 
	if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
	
	CCJMenuData *mdata = new CCJMenuData;
	m_MenuList.InsertAt(nPosition-menustart,mdata);
	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
	
	mdata->menuIconNormal = nIconNormal;
	mdata->xoffset=-1;
	if(nIconNormal>=0){
		CImageList bitmap;
		int xoffset=0;
		LoadFromToolBar(nID,nIconNormal,xoffset);
		if(mdata->bitmap){
			mdata->bitmap->DeleteImageList();
			mdata->bitmap=NULL;
		}
		bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(AddBitmapToImageList(&bitmap,nIconNormal)){
			mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
		}
	}
	else mdata->global_offset = GlobalImageListOffset(nID);
	mdata->nFlags = nFlags;
	mdata->nID = nID;
	BOOL returnflag=CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata);
	if(m_loadmenu)RemoveTopLevelOwnerDraw();
	return(returnflag);
}

BOOL CCJMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
                           CImageList *il,int xoffset)
{
	USES_CONVERSION;
	return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
}

BOOL CCJMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
                           CImageList *il,int xoffset)
{
	if(!(nFlags & MF_BYPOSITION)){
		int iPosition =0;
		CCJMenu* pMenu = FindMenuOption(nPosition,iPosition);
		if(pMenu){
			return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
		}
		else return(FALSE);
	}
	
	if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
	
	if(nFlags & MF_POPUP){
		m_AllSubMenus.Add((HMENU)nID);
		m_SubMenus.InsertAt(nPosition,(HMENU)nID);
	}
	
	//Stephane Clog suggested adding this, believe it or not it's in the help 
	if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
	
	CCJMenuData *mdata = new CCJMenuData;
	m_MenuList.InsertAt(nPosition,mdata);
	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
	
	mdata->menuIconNormal = -1;
	mdata->xoffset = -1;

	if(il){
		if(mdata->bitmap){
			mdata->bitmap->DeleteImageList();
			mdata->bitmap=NULL;
		}
		mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
	}
	mdata->nFlags = nFlags;
	mdata->nID = nID;
	return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
}

BOOL CCJMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
{
	USES_CONVERSION;
	return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
}

BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
{
	int nLoc;
	CCJMenuData *mdata;
	CArray<CCJMenu*,CCJMenu*>bcsubs;
	CArray<int,int&>bclocs;
	
	// Find the old CCJMenuData structure:
	CCJMenu *psubmenu = FindMenuOption(nID,nLoc);
	do{
		if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
		else{
			// Create a new CCJMenuData structure:
			mdata = new CCJMenuData;
			m_MenuList.Add(mdata);
		}
		
		ASSERT(mdata);
		if(lpstrText)
			mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
		mdata->menuIconNormal = -1;
		mdata->xoffset = -1;
		if(nIconNormal>=0){
			CImageList bitmap;
			int xoffset=0;
			LoadFromToolBar(nID,nIconNormal,xoffset);
			if(mdata->bitmap){
				mdata->bitmap->DeleteImageList();
				mdata->bitmap=NULL;
			}
			bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
			if(AddBitmapToImageList(&bitmap,nIconNormal)){
				mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
			}
		}
		else mdata->global_offset = GlobalImageListOffset(nID);
		mdata->nFlags &= ~(MF_BYPOSITION);
		mdata->nFlags |= MF_OWNERDRAW;
		mdata->nID = nID;
		bcsubs.Add(psubmenu);
		bclocs.Add(nLoc);
		if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
		else psubmenu=NULL;
	}while(psubmenu);
	return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}

BOOL CCJMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
{
	USES_CONVERSION;
	return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
}

BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
{
	int nLoc;
	CCJMenuData *mdata;
	CArray<CCJMenu*,CCJMenu*>bcsubs;
	CArray<int,int&>bclocs;
	
	// Find the old CCJMenuData structure:
	CCJMenu *psubmenu = FindMenuOption(nID,nLoc);
	do{
		if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
		else{
			// Create a new CCJMenuData structure:
			mdata = new CCJMenuData;
			m_MenuList.Add(mdata);
		}
		
		ASSERT(mdata);
		if(lpstrText)
			mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
		mdata->menuIconNormal = -1;
		mdata->xoffset = -1;
		if(il){
			if(mdata->bitmap){
				mdata->bitmap->DeleteImageList();
				mdata->bitmap=NULL;
			}
			mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
		}
		mdata->nFlags &= ~(MF_BYPOSITION);
		mdata->nFlags |= MF_OWNERDRAW;
		mdata->nID = nID;
		bcsubs.Add(psubmenu);
		bclocs.Add(nLoc);
		if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
		else psubmenu=NULL;
	}while(psubmenu);
	return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}

BOOL CCJMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
{
	USES_CONVERSION;
	return ModifyODMenuW(A2W(lpstrText),nID,bmp);
}

BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
{
	if(bmp){
		CImageList temp;
		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
		return ModifyODMenuW(lpstrText,nID,&temp,0);
	}
	return ModifyODMenuW(lpstrText,nID,NULL,0);
}

// courtesy of Warren Stevens
BOOL CCJMenu::ModifyODMenuA(const char * lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
{
	USES_CONVERSION;
	return ModifyODMenuW(A2W(lpstrText),nID,fill,border,hatchstyle,pSize);
}

BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
{
	CWnd *pWnd = AfxGetMainWnd();            // Get main window
	CDC *pDC = pWnd->GetDC();              // Get device context
	SIZE sz;
	if(!pSize){
		sz.cx = m_iconX;
		sz.cy = m_iconY;
	}
	else{
		sz.cx = pSize->cx;
		sz.cy = pSize->cy;
	}
	CSize bitmap_size(sz);
	CSize icon_size(m_iconX,m_iconY);
	CBitmap bmp;
	ColorBitmap(pDC,bmp,bitmap_size,icon_size,fill,border,hatchstyle);		
	pWnd->ReleaseDC(pDC);
	return ModifyODMenuW(lpstrText,nID,&bmp);
}


BOOL CCJMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,
                           int nIconNormal)
{
	USES_CONVERSION;
	return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC  Tech Note 059
}

BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
                           int nIconNormal)
{
	CCJMenuData *mdata;
	
	// Find the old CCJMenuData structure:
	CString junk=OptionText;
	mdata=FindMenuOption(OptionText);
	if(mdata){
		if(lpstrText)
			mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
		mdata->menuIconNormal = nIconNormal;
		mdata->xoffset=-1;
		if(nIconNormal>=0){
			mdata->xoffset=0;
			if(mdata->bitmap)mdata->bitmap->DeleteImageList();
			else mdata->bitmap=new(CImageList);
			mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
			if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
				mdata->bitmap->DeleteImageList();
				delete mdata->bitmap;
				mdata->bitmap=NULL;
				mdata->menuIconNormal = nIconNormal = -1;
				mdata->xoffset = -1;
			}
		}
		return(TRUE);
	}
	return(FALSE);
}

CCJMenuData *CCJMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
{
	CCJMenuData *mdata;
	
	mdata = new CCJMenuData;
	mdata->menuIconNormal = -1;
	mdata->xoffset=-1;
#ifdef UNICODE
	mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
#else
	mdata->SetAnsiString(string);
#endif
	mdata->nFlags = nFlags;
	mdata->nID = nID;
	
//	if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
		
	if (nFlags&MF_OWNERDRAW){
		ASSERT(!(nFlags&MF_STRING));
		ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
	}
	else if (nFlags&MF_STRING){
		ASSERT(!(nFlags&MF_OWNERDRAW));
		ModifyMenu(pos,nFlags,nID,mdata->GetString());
	}
	else{
		ASSERT(nFlags&MF_SEPARATOR);
		ModifyMenu(pos,nFlags,nID);
	}
	
	return(mdata);
};

BOOL CCJMenu::LoadToolbars(const UINT *arID,int n)
{
	ASSERT(arID);
	BOOL returnflag=TRUE;
	for(int i=0;i<n;++i){
		if(!LoadToolbar(arID[i]))returnflag=FALSE;
	}
	return(returnflag);
}

BOOL CCJMenu::LoadToolbar(UINT nToolBar)
{
	UINT nID,nStyle;
	BOOL returnflag=FALSE;
	CToolBar bar;
	int xoffset=-1,xset;
	
	CWnd* pWnd = AfxGetMainWnd();
	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
	bar.Create(pWnd);
	if(bar.LoadToolBar(nToolBar)){
		CImageList imglist;
		imglist.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(AddBitmapToImageList(&imglist,nToolBar)){
			returnflag=TRUE;
			for(int i=0;i<bar.GetCount();++i){
				nID = bar.GetItemID(i); 
				if(nID && GetMenuState(nID, MF_BYCOMMAND)
					!=0xFFFFFFFF){
					xoffset=bar.CommandToIndex(nID);
					if(xoffset>=0){
						bar.GetButtonInfo(xoffset,nID,nStyle,xset);
						if(xset>0)xoffset=xset;
					}
					ModifyODMenu(NULL,nID,&imglist,xoffset);
				}
			}
		}
	}
	return(returnflag);
}

BOOL CCJMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
{
	int xset,offset;
	UINT nStyle;
	BOOL returnflag=FALSE;
	CToolBar bar;
	
	CWnd* pWnd = AfxGetMainWnd();
	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
	bar.Create(pWnd);
	if(bar.LoadToolBar(nToolBar)){
		offset=bar.CommandToIndex(nID);
		if(offset>=0){
			bar.GetButtonInfo(offset,nID,nStyle,xset);
			if(xset>0)xoffset=xset;
			returnflag=TRUE;
		}
	}
	return(returnflag);
}

// O.S.
CCJMenuData *CCJMenu::FindMenuItem(UINT nID)
{
	CCJMenuData *pData = NULL;
	int i;
	
	for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
		if (m_MenuList[i]->nID == nID){
			pData = m_MenuList[i];
			break;
		}
	}
	if (!pData){
		int loc;
		CCJMenu *pMenu = FindMenuOption(nID, loc);
		ASSERT(pMenu != this);
		if (loc >= 0){
			return pMenu->FindMenuItem(nID);
		}
	}
	return pData;
}


CCJMenu *CCJMenu::FindAnotherMenuOption(int nId,int& nLoc,CArray<CCJMenu*,CCJMenu*>&bcsubs,
									  CArray<int,int&>&bclocs)
{
	int i,numsubs,j;
	CCJMenu *psubmenu,*pgoodmenu;
	BOOL foundflag;
	
	for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI 
		psubmenu=dynamic_cast<CCJMenu *>(GetSubMenu(i));
#else
		psubmenu=(CCJMenu *)GetSubMenu(i);
#endif
		if(psubmenu){
			pgoodmenu=psubmenu->FindAnotherMenuOption(nId,nLoc,bcsubs,bclocs);
			if(pgoodmenu)return(pgoodmenu);
		}
		else if(nId==(int)GetMenuItemID(i)){
			numsubs=bcsubs.GetSize();
			foundflag=TRUE;
			for(j=0;j<numsubs;++j){
				if(bcsubs[j]==this&&bclocs[j]==i){
					foundflag=FALSE;
					break;
				}
			}
			if(foundflag){
				nLoc=i;
				return(this);
			}
		}
	}
	nLoc = -1;
	return(NULL);
}

CCJMenu *CCJMenu::FindMenuOption(int nId,int& nLoc)
{
	int i;
	CCJMenu *psubmenu,*pgoodmenu;
	
	for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI 
		psubmenu=dynamic_cast<CCJMenu *>(GetSubMenu(i));
#else
		psubmenu=(CCJMenu *)GetSubMenu(i);
#endif
		if(psubmenu){
			pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
			if(pgoodmenu)return(pgoodmenu);
		}
		else if(nId==(int)GetMenuItemID(i)){
			nLoc=i;
			return(this);
		}
	}
	nLoc = -1;
	return(NULL);
}

CCJMenuData *CCJMenu::FindMenuOption(wchar_t *lpstrText)
{
	int i,j;
	CCJMenu *psubmenu;
	CCJMenuData *pmenulist;
	
	for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI 
		psubmenu=dynamic_cast<CCJMenu *>(GetSubMenu(i));
#else
		psubmenu=(CCJMenu *)GetSubMenu(i);
#endif
		if(psubmenu){
			pmenulist=psubmenu->FindMenuOption(lpstrText);
			if(pmenulist)return(pmenulist);
		}
		else{
			const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
			for(j=0;j<=m_MenuList.GetUpperBound();++j){     
				szWide = m_MenuList[j]->GetWideString ();
				if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
					return(m_MenuList[j]);
			}
		}
	}
	return(NULL);
}


BOOL CCJMenu::LoadMenu(HINSTANCE hInstance, int nResource)
{
	return(CCJMenu::LoadMenu(hInstance, MAKEINTRESOURCE(nResource)));
}


BOOL CCJMenu::LoadMenu(int nResource)
{
	return(CCJMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
}


BOOL CCJMenu::LoadMenu(LPCTSTR lpszResourceName)
{
	ASSERT_VALID(this);
	ASSERT(lpszResourceName != NULL);
	
	// Find the Menu Resource:
	HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
	if (NULL != hInst)
	{
		return CCJMenu::LoadMenu(hInst, lpszResourceName);
	}
	return FALSE;
}


BOOL CCJMenu::LoadMenu(HINSTANCE hInst, LPCTSTR lpszResourceName)
{
	ASSERT_VALID(this);
	ASSERT(lpszResourceName != NULL);
	
	HRSRC hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
	if (hRsrc == NULL)
	{
		hInst = NULL;
		hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
	}

	if(hRsrc == NULL)
		return FALSE;
	
	// Load the Menu Resource:
	
	HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
	if(hGlobal == NULL)return FALSE;

	// first destroy the menu if we're trying to loadmenu again
	DestroyMenu();

	// Attempt to create us as a menu...
	if(!CMenu::CreateMenu())return FALSE;
	
	// Get Item template Header, and calculate offset of MENUITEMTEMPLATES
	
	MENUITEMTEMPLATEHEADER *pTpHdr=
		(MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
	BYTE* pTp=(BYTE*)pTpHdr + 
		(sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
	
	
	// Variables needed during processing of Menu Item Templates:
	
	int j=0;
	WORD    dwFlags = 0;              // Flags of the Menu Item
	WORD    dwID  = 0;              // ID of the Menu Item
	UINT    uFlags;                  // Actual Flags.
	wchar_t *szCaption=NULL;
	int      nLen   = 0;                // Length of caption
	CTypedPtrArray<CPtrArray, CCJMenu*>  m_Stack;    // Popup menu stack
	CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
	m_Stack.Add(this);                  // Add it to this...
	m_StackEnd.Add(FALSE);
	
	do{
		// Obtain Flags and (if necessary), the ID...
		memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
		if(!(dwFlags & MF_POPUP)){
			memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
			pTp+=sizeof(WORD);
		}
		else dwID = 0;
		
		uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
		if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
			uFlags -= MF_END;
		
		// Obtain Caption (and length)
		
		nLen = 0;
		szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
		wcscpy(szCaption,(wchar_t *)pTp);
		pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
		
		// Handle popup menus first....
		
		//WideCharToMultiByte
		if(dwFlags & MF_POPUP){
			if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
			CCJMenu* pSubMenu = new CCJMenu;
			pSubMenu->m_unselectcheck=m_unselectcheck;
			pSubMenu->m_selectcheck=m_selectcheck;
			pSubMenu->checkmaps=checkmaps;
			pSubMenu->checkmapsshare=TRUE;
			pSubMenu->CreatePopupMenu();
			
			// Append it to the top of the stack:
			
			m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
				(UINT)pSubMenu->m_hMenu, -1);
			m_Stack.Add(pSubMenu);
			m_StackEnd.Add(FALSE);
		}
		else {
			m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
				dwID, -1);
			if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
			j = m_Stack.GetUpperBound();
			while(j>=0 && m_StackEnd.GetAt(j)){
				m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
				m_Stack.RemoveAt(j);
				m_StackEnd.RemoveAt(j);
				--j;
			}
		}
		
		delete[] szCaption;
	}while(m_Stack.GetUpperBound() != -1);
	
	for(int i=0;i<(int)GetMenuItemCount();++i){
		CString str=m_MenuList[i]->GetString();
		if(GetSubMenu(i)){
			m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
			ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
				(UINT)GetSubMenu(i)->m_hMenu,str);
		}
		else{
			m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
			ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
		}
	}

	m_loadmenu=TRUE;
	
	return(TRUE);
}

int CCJMenu::GetMenuStart(void)
{
	if(!m_loadmenu)return(0);

	CString name,str;
	int menuloc=-1,listloc=-1,menustart=0,i=0,j=0;
	int nummenulist=m_MenuList.GetSize();
	int nummenu=(int)GetMenuItemCount();

	while(i<nummenu&&menuloc==-1){
		GetMenuString (i, name, MF_BYPOSITION);
		if(name.GetLength()>0){
			for(j=0;j<nummenulist;++j){
				str=m_MenuList[j]->GetString();
				if(name==str){
					menuloc=i;
					listloc=j;
					break;
				}
			}
		}
		++i;
	}
	if(menuloc>=0&&listloc>=0&&menuloc>=listloc)menustart=menuloc-listloc;
	return(menustart);
}

void CCJMenu::RemoveTopLevelOwnerDraw(void)
{
	CString str;
	int i=0,j=0;
	int nummenulist=m_MenuList.GetSize(),menustart;

	menustart=GetMenuStart();
	for(i=menustart,j=0;i<(int)GetMenuItemCount();++i,++j){
		if(j<nummenulist){
			str=m_MenuList[j]->GetString();
			if(GetSubMenu(i)){
				m_MenuList[j]->nFlags=MF_POPUP|MF_BYPOSITION;
				ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
					(UINT)GetSubMenu(i)->m_hMenu,str);
			}
		}
	}

}

void CCJMenu::InsertSpaces(void)
{
	if(IsLunaMenuStyle())
		if(!xp_space_accelerators)return;
	else
		if(!original_space_accelerators)return;
	
	int i,j,numitems,maxlength;
	CString string,newstring;
	CSize t;
	CFont m_fontMenu;
	LOGFONT m_lf;
	
	ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
	NONCLIENTMETRICS nm;
	nm.cbSize = sizeof (NONCLIENTMETRICS);
	VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
	m_lf =  nm.lfMenuFont;
	m_fontMenu.CreateFontIndirect (&m_lf);
	
	CWnd *pWnd = AfxGetMainWnd();  
	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
	CDC *pDC = pWnd->GetDC();
	CFont* pFont = pDC->SelectObject (&m_fontMenu);
	
	numitems=GetMenuItemCount();
	maxlength = -1;
	for(i=0;i<numitems;++i){
		string=m_MenuList[i]->GetString();
		j=string.Find((char)9);
		newstring.Empty();
		if(j!=-1)newstring=string.Left(j);
		else newstring=string;
		newstring+=_T(" ");//SK: modified for Unicode correctness. 
		LPCTSTR lpstrText = (LPCTSTR)newstring;
		t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
		if(t.cx>maxlength)maxlength = t.cx;
	}
	for(i=0;i<numitems;++i){
		string=m_MenuList[i]->GetString();
		j=string.Find((char)9);
		if(j!=-1){
			newstring.Empty();
			newstring=string.Left(j);
			LPCTSTR lpstrText = (LPCTSTR)(newstring);
			t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
			while(t.cx<maxlength){
				newstring+=_T(' ');//SK: modified for Unicode correctness
				LPCTSTR lpstrText = (LPCTSTR)(newstring);
				t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
			}
			newstring+=string.Mid(j);
#ifdef UNICODE      
			m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
#else
			m_MenuList[i]->SetAnsiString(newstring);
#endif
		}
	}
	pDC->SelectObject (pFont);              // Select old font in
	pWnd->ReleaseDC(pDC);       // Release the DC
	m_fontMenu.DeleteObject();
}

void CCJMenu::LoadCheckmarkBitmap(int unselect, int select)
{
	if(unselect>0 && select>0){
		m_selectcheck=select;
		m_unselectcheck=unselect;
		if(checkmaps)checkmaps->DeleteImageList();
		else checkmaps=new(CImageList);
		checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
		BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
		BOOL flag2=AddBitmapToImageList(checkmaps,select);
		if(!flag1||!flag2){
			checkmaps->DeleteImageList();
			delete checkmaps;
			checkmaps=NULL;
		}
	}
}

//--------------------------------------------------------------------------
//[18.06.99 rj]
BOOL CCJMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
{
	BOOL returnflag=FALSE;
	
	if(MF_BYPOSITION&nFlags){
		UINT numMenuItems = m_MenuList.GetUpperBound();
		if(id<=numMenuItems){
			string=m_MenuList[id]->GetString();
			returnflag=TRUE;
		}
	}
	else{
		int uiLoc;
		CCJMenu* pMenu = FindMenuOption(id,uiLoc);
		if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
	}
	return(returnflag);
}


void CCJMenu::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 CCJMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color,BOOL narrowflag)
{
	int dp=0;
	CPen m_penBack;
	m_penBack.CreatePen (PS_SOLID,0,color);
	CPen *pOldPen = pDC->SelectObject (&m_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);
	m_penBack.DeleteObject();
}

CCJMenuData *CCJMenu::FindMenuList(UINT nID)
{
	for(int i=0;i<=m_MenuList.GetUpperBound();++i){
		if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
			m_MenuList[i]->syncflag=1;
			return(m_MenuList[i]);
		}
	}
	return(NULL);
}

void CCJMenu::InitializeMenuList(int value)
{
	for(int i=0;i<=m_MenuList.GetUpperBound();++i)
		m_MenuList[i]->syncflag=value;
}

void CCJMenu::DeleteMenuList(void)
{
	for(int i=0;i<=m_MenuList.GetUpperBound();++i){
		if(!m_MenuList[i]->syncflag){
			delete m_MenuList[i];
		}
	}
}

void CCJMenu::SynchronizeMenu(void)
{
	CTypedPtrArray<CPtrArray, CCJMenuData*> temp;
	CCJMenuData *mdata;
	CString string;
	UINT submenu,nID=0,state,j;
	
	InitializeMenuList(0);
	for(j=0;j<GetMenuItemCount();++j){
		mdata=NULL;
		state=GetMenuState(j,MF_BYPOSITION);
		if(state&MF_POPUP){
			submenu=(UINT)GetSubMenu(j)->m_hMenu;
			mdata=FindMenuList(submenu);
			GetMenuString(j,string,MF_BYPOSITION);
			if(!mdata)mdata=NewODMenu(j,
				(state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
			else if(string.GetLength()>0)
#ifdef UNICODE
				mdata->SetWideString(string);  //SK: modified for dynamic allocation
#else
			mdata->SetAnsiString(string);
#endif
		}
		else if(state&MF_SEPARATOR){
			mdata=FindMenuList(0);
			if(!mdata)mdata=NewODMenu(j,
				state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
			else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
		}
		else{
			nID=GetMenuItemID(j);
			mdata=FindMenuList(nID);
			GetMenuString(j,string,MF_BYPOSITION);
			if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
				nID,string);
			else{
				mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
				if(string.GetLength()>0)
#ifdef UNICODE
					mdata->SetWideString(string);//SK: modified for dynamic allocation
#else
				mdata->SetAnsiString(string);
#endif
				
				ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
			}
		}
		if(mdata)temp.Add(mdata);
	}
	DeleteMenuList();
	m_MenuList.RemoveAll();
	m_MenuList.Append(temp);
	temp.RemoveAll(); 
}

void CCJMenu::UpdateMenu(CMenu *pmenu)
{
#ifdef _CPPRTTI 
	CCJMenu *psubmenu = dynamic_cast<CCJMenu *>(pmenu);
#else
	CCJMenu *psubmenu = (CCJMenu *)pmenu;
#endif
	if(psubmenu)psubmenu->SynchronizeMenu();
}

LRESULT CCJMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
                                     CMenu *pMenu)
{
#ifdef _CPPRTTI 
	CCJMenu *pCCJMenu = dynamic_cast<CCJMenu *>(pMenu);
#else
	CCJMenu *pCCJMenu = (CCJMenu *)pMenu;
#endif
	if(pCCJMenu && nFlags&MF_POPUP){
		CString key(_T('&'),2);//SK: modified for Unicode correctness
		key.SetAt(1,(TCHAR)nChar);
		key.MakeLower();
		CString menutext;
		int menusize = (int)pCCJMenu->GetMenuItemCount();
		if(menusize!=(pCCJMenu->m_MenuList.GetUpperBound()+1))
			pCCJMenu->SynchronizeMenu();
		for(int i=0;i<menusize;++i){
			if(pCCJMenu->GetMenuText(i,menutext)){
				menutext.MakeLower();
				if(menutext.Find(key)>=0)return(MAKELRESULT(i,2));
			}
		}
	}
	return(0);
}

void CCJMenu::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, 
                        int nHeight, HBITMAP hbm, int nXSrc, int nYSrc,
						COLORREF bgcolor)
{
	ASSERT(hdcDest && hbm);
	ASSERT(nWidth > 0 && nHeight > 0);
	
	// Create a generic DC for all BitBlts
	HDC hDC = CreateCompatibleDC(hdcDest);
	ASSERT(hDC);
	
	if (hDC)
	{
		// Create a DC for the monochrome DIB section
		HDC bwDC = CreateCompatibleDC(hDC);
		ASSERT(bwDC);
		
		if (bwDC)
		{
			// Create the monochrome DIB section with a black and white palette
			struct {
				BITMAPINFOHEADER bmiHeader; 
				RGBQUAD      bmiColors[2]; 
			} RGBBWBITMAPINFO = {
				
				{    // a BITMAPINFOHEADER
					sizeof(BITMAPINFOHEADER),  // biSize 
						nWidth,         // biWidth; 
						nHeight,        // biHeight; 
						1,            // biPlanes; 
						1,            // biBitCount 
						BI_RGB,         // biCompression; 
						0,            // biSizeImage; 
						0,            // biXPelsPerMeter; 
						0,            // biYPelsPerMeter; 
						0,            // biClrUsed; 
						0            // biClrImportant; 
				},    
				{
					{ 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
					} 
			};
			VOID *pbitsBW;
			HBITMAP hbmBW = CreateDIBSection(bwDC,
				(LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
			ASSERT(hbmBW);
			
			if (hbmBW)
			{
				// Attach the monochrome DIB section and the bitmap to the DCs
				HBITMAP olddib = (HBITMAP)SelectObject(bwDC, hbmBW);
				HBITMAP hdcolddib = (HBITMAP)SelectObject(hDC, hbm);
				
				// BitBlt the bitmap into the monochrome DIB section
				BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
				
				// Paint the destination rectangle in gray
				FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
					nHeight), GetSysColorBrush(bgcolor));
				//SK: looks better on the old shell
				// BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT
				// bits in the destination DC
				// The magic ROP comes from the Charles Petzold's book
				HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
				HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
				BitBlt(hdcDest,nXDest+1,nYDest+1,nWidth,nHeight,bwDC,0,0,0xB8074A);
				
				// BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW
				// bits in the destination DC
				hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
				DeleteObject(SelectObject(hdcDest, hb));
				BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,bwDC,0,0,0xB8074A);
				DeleteObject(SelectObject(hdcDest, oldBrush));
				VERIFY(DeleteObject(SelectObject(bwDC, olddib)));
				SelectObject(hDC, hdcolddib);
			}
			
			VERIFY(DeleteDC(bwDC));
		}
		
		VERIFY(DeleteDC(hDC));
	}
}

void CCJMenu::GetFadedBitmap(CBitmap &bmp)
{
	CDC ddc;
	COLORREF bgcol,col;
	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);

	for(int i=0;i<BitMap.bmWidth;++i){
		for(int j=0;j<BitMap.bmHeight;++j){
			col=ddc.GetPixel(i,j);
			if(col!=bgcol)ddc.SetPixel(i,j,LightenColor(col,0.3));
		}
	}
	ddc.SelectObject(pddcOldBmp);
}

void CCJMenu::GetTransparentBitmap(CBitmap &bmp)
{
	CDC ddc;
	COLORREF bgcol,col,newcol;
	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=RGB(192,192,192);
	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);
	newcol=GetSysColor(COLOR_3DFACE);

	for(int i=0;i<BitMap.bmWidth;++i){
		for(int j=0;j<BitMap.bmHeight;++j){
			col=ddc.GetPixel(i,j);
			if(col==bgcol)ddc.SetPixel(i,j,newcol);
		}
	}
	ddc.SelectObject(pddcOldBmp);
}

void CCJMenu::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 CCJMenu::GetShadowBitmap(CBitmap &bmp)
{
	CDC ddc;
	COLORREF bgcol,col,shadowcol=GetSysColor(COLOR_BTNSHADOW);
	BITMAP BitMap;

	if(!IsWinXPLuna())shadowcol=LightenColor(shadowcol,0.49);
	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);

	for(int i=0;i<BitMap.bmWidth;++i){
		for(int j=0;j<BitMap.bmHeight;++j){
			col=ddc.GetPixel(i,j);
			if(col!=bgcol)ddc.SetPixel(i,j,shadowcol);
		}
	}
	ddc.SelectObject(pddcOldBmp);
}


BOOL CCJMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
{
	BOOL bReturn=FALSE;

	// O.S.
	if (m_bDynIcons){
		bmplist->Add((HICON)nResourceID);
		bReturn=TRUE;
	}
	else{
		HBITMAP hbmp=LoadSysColorBitmap(nResourceID);
		if(hbmp){
			CBitmap bmp;
			bmp.Attach(hbmp);
			if(m_bitmapBackgroundFlag){
				if(bmplist->Add(&bmp,m_bitmapBackground)>=0)bReturn=TRUE;
			}
			else{
				if(bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
			}
			bmp.Detach();
			DeleteObject(hbmp);
		}
		else{ // a hicolor bitmap
			CBitmap mybmp;
			if(mybmp.LoadBitmap(nResourceID)){
				hicolor_bitmaps=TRUE;
				GetTransparentBitmap(mybmp);
				if(m_bitmapBackgroundFlag){
					if(bmplist->Add(&mybmp,m_bitmapBackground)>=0)bReturn=TRUE;
				}
				else{
					if(bmplist->Add(&mybmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
				}
			}
		}
	}
	if(bReturn&&IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
		CWnd *pWnd = AfxGetMainWnd();            // Get main window
		if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
		CDC *pDC = pWnd->GetDC();              // Get device context
		CBitmap bmp,bmp2,bmp3;
		GetBitmapFromImageList(pDC,bmplist,0,bmp);
		GetFadedBitmap(bmp);
		bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE));
		GetBitmapFromImageList(pDC,bmplist,0,bmp2);
		GetShadowBitmap(bmp2);
		bmplist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
		GetBitmapFromImageList(pDC,bmplist,0,bmp3);
		GetDisabledBitmap(bmp3);
		bmplist->Add(&bmp3,GetSysColor(COLOR_3DFACE));
		pWnd->ReleaseDC(pDC);  // Release the DC
	}
	return(bReturn);
}

void CCJMenu::SetBitmapBackground(COLORREF color)
{
	m_bitmapBackground=color;
	m_bitmapBackgroundFlag=TRUE;
}

void CCJMenu::UnSetBitmapBackground(void)
{
	m_bitmapBackgroundFlag=FALSE;
}

// Given a toolbar, append all the options from it to this menu
// Passed a ptr to the toolbar object and the toolbar ID
// Author : Robert Edward Caldecott
void CCJMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
{
	for (int i = 0; i < pToolBar->GetCount(); i++) {
		UINT nID = pToolBar->GetItemID(i);
		// See if this toolbar option
		// appears as a command on this
		// menu or is a separator
		if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
			continue; // Item doesn't exist
		UINT nStyle;
		int nImage;
		// Get the toolbar button info
		pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
		// OK, we have the command ID of the toolbar
		// option, and the tollbar bitmap offset
		int nLoc;
		CCJMenuData* pData;
		CCJMenu *pSubMenu = FindMenuOption(nID, nLoc);
		if (pSubMenu && nLoc >= 0)pData = pSubMenu->m_MenuList[nLoc];
		else {
			// Create a new CCJMenuData structure
			pData = new CCJMenuData;
			m_MenuList.Add(pData);
		}
		// Set some default structure members
		pData->menuIconNormal = nResourceID;
		pData->nID = nID;
		pData->nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
		pData->xoffset = nImage;
		if (pData->bitmap)pData->bitmap->DeleteImageList();
		else pData->bitmap = new CImageList;
		pData->bitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
		
		if(!AddBitmapToImageList(pData->bitmap, nResourceID)){
			pData->bitmap->DeleteImageList();
			delete pData->bitmap;
			pData->bitmap=NULL;
			pData->menuIconNormal = -1;
			pData->xoffset = -1;
		}
		
		// Modify our menu
		ModifyMenu(nID,pData->nFlags,nID,(LPCTSTR)pData);
	}
}

BOOL CCJMenu::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 CCJMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck,COLORREF &colorout,BOOL selected)
{
	CBrush brushin;
	COLORREF col;
	int dx,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 CCJMenu::DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
                        int nHeight, CBitmap &bmp, int nXSrc, int nYSrc,
						COLORREF bgcolor)
{
	// create a monochrome memory DC
	CDC ddc;
	ddc.CreateCompatibleDC(0);
	CBitmap bwbmp;
	bwbmp.CreateCompatibleBitmap(&ddc, nWidth, nHeight);
	CBitmap * pddcOldBmp = ddc.SelectObject(&bwbmp);
	
	CDC dc;
	dc.CreateCompatibleDC(0);
	CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
	
	// build a mask
	ddc.PatBlt(0, 0, nWidth, nHeight, WHITENESS);
	dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
	ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCCOPY);
	dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
	ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCPAINT);
	
	// Copy the image from the toolbar into the memory DC
	// and draw it (grayed) back into the toolbar.
	dc.FillSolidRect(0,0, nWidth, nHeight, bgcolor);
	//SK: Looks better on the old shell
	dc.SetBkColor(RGB(0, 0, 0));
	dc.SetTextColor(RGB(255, 255, 255));
	CBrush brShadow, brHilight;
	brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
	brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
	CBrush * pOldBrush = dc.SelectObject(&brHilight);
	dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(nXDest+1,nYDest+1,nWidth, nHeight, &dc,0,0,SRCCOPY);
	dc.BitBlt(1,1, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
	dc.SelectObject(&brShadow);
	dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &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();
}

void CCJMenu::DitherBlt3(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
                        int nHeight, CBitmap &bmp,COLORREF bgcolor)
{
	GetDisabledBitmap(bmp,bgcolor);
	CDC dc;
	dc.CreateCompatibleDC(NULL);
	CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
	drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
	// reset DCs
	dc.SelectObject(pdcOldBmp);
	dc.DeleteDC();
}

void CCJMenu::SetDisableOldStyle(void)
{
	disable_old_style=TRUE;
}

void CCJMenu::UnSetDisableOldStyle(void)
{
	disable_old_style=FALSE;
}

BOOL CCJMenu::GetDisableOldStyle(void)
{
	return(disable_old_style);
}


WORD CCJMenu::NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
{
	if ( lpBitmap->biClrUsed != 0)
		return (WORD)lpBitmap->biClrUsed;
	
	switch (lpBitmap->biBitCount){
		case 1:
			return 2;
		case 4:
			return 16;
		case 8:
			return 256;
		default:
			return 0;
	}
	return 0;
}

HBITMAP CCJMenu::LoadSysColorBitmap(int nResourceId)
{
	HINSTANCE hInst = 
		AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
	HRSRC hRsrc = 
		::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
	if (hRsrc == NULL){
		hInst = NULL;
		hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
	}
	if (hRsrc == NULL)return NULL;

	// determine how many colors in the bitmap
	HGLOBAL hglb;
	if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
		return NULL;
	LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
	if (lpBitmap == NULL)return NULL;
	WORD numcol = NumBitmapColors(lpBitmap);
	::FreeResource(hglb);

	if(numcol!=16)return(NULL);

	return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
}

BOOL CCJMenu::RemoveMenu(UINT uiId,UINT nFlags)
{
	if(MF_BYPOSITION&nFlags){
		UINT uint = GetMenuState(uiId,MF_BYPOSITION);
		if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
			delete m_MenuList.GetAt(uiId);
			m_MenuList.RemoveAt(uiId);
		}
		else{
			CCJMenu* pSubMenu = (CCJMenu*) GetSubMenu(uiId);
			if(NULL==pSubMenu){
				UINT uiCommandId = GetMenuItemID(uiId);
				for(int i=0;i<m_MenuList.GetSize(); i++){
					if(m_MenuList[i]->nID==uiCommandId){
						delete m_MenuList.GetAt(i);
						m_MenuList.RemoveAt(i);
						break;
					}
				}
			}
			else{
				int numSubMenus = m_SubMenus.GetUpperBound();
				for(int m = numSubMenus; m >= 0; m--){
					if(m_SubMenus[m]==pSubMenu->m_hMenu){
						int numAllSubMenus = m_AllSubMenus.GetUpperBound();
						for(int n = numAllSubMenus; n>= 0; n--){
							if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
						}
						m_SubMenus.RemoveAt(m);
					}
				}
				int num = pSubMenu->GetMenuItemCount();
				for(int i=num-1;i>=0;--i)pSubMenu->RemoveMenu(i,MF_BYPOSITION);
				for(i=m_MenuList.GetUpperBound();i>=0;i--){
					if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
						delete m_MenuList.GetAt(i);
						m_MenuList.RemoveAt(i);
						break;
					}
				}
				delete pSubMenu; 
			}
		}
	}
	else{
		int iPosition =0;
		CCJMenu* pMenu = FindMenuOption(uiId,iPosition);
		// bug fix RIA 14th September 2000 
		// failed to return correct value on call to remove menu as the item was 
		// removed twice. The second time its not found 
		// so a value of 0 was being returned 
		if(pMenu) return pMenu->RemoveMenu(iPosition,MF_BYPOSITION); // added return 
	}
	return CMenu::RemoveMenu(uiId,nFlags);
}

BOOL CCJMenu::DeleteMenu(UINT uiId,UINT nFlags)
{
	if(MF_BYPOSITION&nFlags){
		UINT uint = GetMenuState(uiId,MF_BYPOSITION);
		if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
			// make sure it's a separator
			int menulistsize=m_MenuList.GetSize();	
			if(uiId<(UINT)menulistsize){
				CString str=m_MenuList[uiId]->GetString();
				if(str==""){
					delete m_MenuList.GetAt(uiId);
					m_MenuList.RemoveAt(uiId);
				}
			}
		}
		else{
			CCJMenu* pSubMenu = (CCJMenu*) GetSubMenu(uiId);
			if(NULL==pSubMenu){
				UINT uiCommandId = GetMenuItemID(uiId);
				for(int i=0;i<m_MenuList.GetSize(); i++){
					if(m_MenuList[i]->nID==uiCommandId){
						delete m_MenuList.GetAt(i);
						m_MenuList.RemoveAt(i);
						break;
					}
				}
			}
			else{
				int numSubMenus = m_SubMenus.GetUpperBound();
				for(int m = numSubMenus; m >= 0; m--){
					if(m_SubMenus[m]==pSubMenu->m_hMenu){
						int numAllSubMenus = m_AllSubMenus.GetUpperBound();
						for(int n = numAllSubMenus; n>= 0; n--){
							if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
						}
						m_SubMenus.RemoveAt(m);
					}
				}
				int num = pSubMenu->GetMenuItemCount();
				for(int i=num-1;i>=0;--i)pSubMenu->DeleteMenu(i,MF_BYPOSITION);
				for(i=m_MenuList.GetUpperBound();i>=0;i--){
					if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
						delete m_MenuList.GetAt(i);
						m_MenuList.RemoveAt(i);
						break;
					}
				}
				delete pSubMenu;
			}
		}
	}
	else{
		int iPosition =0;
		CCJMenu* pMenu = FindMenuOption(uiId,iPosition);
		if(pMenu)return pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
	}

	return(CMenu::DeleteMenu(uiId,nFlags));
}


BOOL CCJMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
{
	USES_CONVERSION;
	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
}

BOOL CCJMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
{
	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}

BOOL CCJMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
{
	USES_CONVERSION;
	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
}

BOOL CCJMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
{
	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}

BOOL CCJMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
{
	USES_CONVERSION;
	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
}

BOOL CCJMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
{
	if(bmp){
		CImageList temp;
		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
		return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,&temp,0);
	}
	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,NULL,0);
}

BOOL CCJMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
{
	USES_CONVERSION;
	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
}

BOOL CCJMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
{
	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}

BOOL CCJMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
{
	USES_CONVERSION;
	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
}

BOOL CCJMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
{
	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}

BOOL CCJMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
{
	USES_CONVERSION;
	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
}

BOOL CCJMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
{
	if(bmp){
		CImageList temp;
		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
		return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
	}
	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
}

//--------------------------------------------------------------------------
//[21.06.99 rj]
CCJMenu* CCJMenu::AppendODPopupMenuW(wchar_t *lpstrText)
{
	CCJMenu* pSubMenu = new CCJMenu;
	pSubMenu->m_unselectcheck=m_unselectcheck;
	pSubMenu->m_selectcheck=m_selectcheck;
	pSubMenu->checkmaps=checkmaps;
	pSubMenu->checkmapsshare=TRUE;
	pSubMenu->CreatePopupMenu();
	AppendODMenuW(lpstrText,MF_POPUP,(UINT)pSubMenu->m_hMenu, -1);
	return pSubMenu;
}

//--------------------------------------------------------------------------
//[21.06.99 rj]
CCJMenu* CCJMenu::AppendODPopupMenuA(LPCSTR lpstrText)
{
	USES_CONVERSION;
	return AppendODPopupMenuW(A2W(lpstrText));
}

BOOL CCJMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
{
	if (il == NULL||newlist==NULL||xoffset<0) return FALSE;
	HICON hIcon = il->ExtractIcon(xoffset);
	int cx, cy;
	ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
	newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
	newlist->Add(hIcon);
	::DestroyIcon(hIcon);
	if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
		CWnd *pWnd = AfxGetMainWnd();            // Get main window
		if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
		CDC *pDC = pWnd->GetDC();              // Get device context
		CBitmap bmp,bmp2,bmp3;
		GetBitmapFromImageList(pDC,newlist,0,bmp);
		GetFadedBitmap(bmp);
		newlist->Add(&bmp,GetSysColor(COLOR_3DFACE));
		GetBitmapFromImageList(pDC,newlist,0,bmp2);
		GetShadowBitmap(bmp2);
		newlist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
		GetBitmapFromImageList(pDC,newlist,0,bmp3);
		GetDisabledBitmap(bmp3);
		newlist->Add(&bmp3,GetSysColor(COLOR_3DFACE));
		pWnd->ReleaseDC(pDC);  // Release the DC
	}
	return TRUE;
}

// 2001-07-12, Damir Valiulin:
//          Added GetSubMenu (LPCTSTR lpszSubMenuName) function
//

CMenu* CCJMenu::GetSubMenu(int nPos)
{
	return CMenu::GetSubMenu (nPos);
}

CMenu* CCJMenu::GetSubMenu(LPCTSTR lpszSubMenuName)
{
	int num = GetMenuItemCount ();
	CString name;
	
	for (int i=0; i<num; i++)
	{
		GetMenuString (i, name, MF_BYPOSITION);
		if (name.Compare (lpszSubMenuName) == 0)
		{
			return CMenu::GetSubMenu (i);
		}
	}
	
	return NULL;
}

CCJMenu* CCJMenu::GetSubCCJMenu(char* pText)
{
	USES_CONVERSION;
	return GetSubCCJMenu(A2W(pText));
}

CCJMenu* CCJMenu::GetSubCCJMenu(wchar_t* lpszSubMenuName)
{
	CCJMenuData *mdata;
	mdata=FindMenuOption(lpszSubMenuName);
	if(mdata){
		HMENU bchmenu=(HMENU)mdata->nID;
		CMenu *ptr=FromHandle(bchmenu);
		BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( CCJMenu ));
		if(flag)return((CCJMenu *)ptr);
	}
	return NULL;
}


// Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
// before and after the popup menu can also be removed if they exist.
int CCJMenu::GetMenuPosition(char* pText)
{
	USES_CONVERSION;
	return GetMenuPosition(A2W(pText));
}

int CCJMenu::GetMenuPosition(wchar_t* pText)
{
	int i,j;
	CCJMenu* psubmenu;
	for(i=0;i<(int)(GetMenuItemCount());++i)
	{
		psubmenu=(CCJMenu *)GetSubMenu(i);
		if(!psubmenu)
		{
			const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
			for(j=0;j<=m_MenuList.GetUpperBound();++j)
			{     
				szWide = m_MenuList[j]->GetWideString ();
				if(szWide && !wcscmp(pText,szWide))//SK: modified for dynamic allocation
					return j;
			}
		}
	}
	// means no found;
	return -1;
}

int CCJMenu::RemoveMenu(char* pText, BC_Seperator sPos)
{
	USES_CONVERSION;
	return RemoveMenu(A2W(pText), sPos);
}

int CCJMenu::RemoveMenu(wchar_t* pText, BC_Seperator sPos)
{
	int nPos = GetMenuPosition(pText);
	if(nPos != -1)
	{
		RemoveMenu(nPos, MF_BYPOSITION);
	}
	if(sPos == CCJMenu_HEAD)
	{
		ASSERT(nPos - 1 >= 0);
		RemoveMenu(nPos-1, MF_BYPOSITION);
	}
	else if(sPos == CCJMenu_TAIL)
	{
		RemoveMenu(nPos-1, MF_BYPOSITION);
	}
	else if(sPos == CCJMenu_BOTH)
	{
		// remove the end first;
		RemoveMenu(nPos-1, MF_BYPOSITION);
		// remove the head;
		ASSERT(nPos - 1 >= 0);
		RemoveMenu(nPos-1, MF_BYPOSITION);
	}
	return nPos;
}

int CCJMenu::DeleteMenu(char* pText, BC_Seperator sPos)
{
	USES_CONVERSION;
	return DeleteMenu(A2W(pText), sPos);
}

int CCJMenu::DeleteMenu(wchar_t* pText, BC_Seperator sPos)
{
	int nPos = GetMenuPosition(pText);
	if(nPos != -1)
	{
		DeleteMenu(nPos, MF_BYPOSITION);
	}
	if(sPos == CCJMenu_HEAD)
	{
		ASSERT(nPos - 1 >= 0);
		DeleteMenu(nPos-1, MF_BYPOSITION);
	}
	else if(sPos == CCJMenu_TAIL)
	{
		DeleteMenu(nPos-1, MF_BYPOSITION);
	}
	else if(sPos == CCJMenu_BOTH)
	{
		// remove the end first;
		DeleteMenu(nPos-1, MF_BYPOSITION);
		// remove the head;
		ASSERT(nPos - 1 >= 0);
		DeleteMenu(nPos-1, MF_BYPOSITION);
	}
	return nPos;
}

// Larry Antram
BOOL CCJMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
{
	BOOL returnflag=FALSE;
	
	if(MF_BYPOSITION&nFlags)
	{
		UINT numMenuItems = m_MenuList.GetUpperBound();
		if(id<=numMenuItems){
#ifdef UNICODE
			m_MenuList[id]->SetWideString((LPCTSTR)string);
#else
			m_MenuList[id]->SetAnsiString(string);
#endif
			returnflag=TRUE;
		}
	}
	else{
		int uiLoc;
		CCJMenu* pMenu = FindMenuOption(id,uiLoc);
		if(NULL!=pMenu) returnflag = pMenu->SetMenuText(uiLoc,string);
	}
	return(returnflag);
}

// courtesy of Warren Stevens
void CCJMenu::ColorBitmap(CDC* pDC,CBitmap& bmp,CSize bitmap_size,CSize icon_size,COLORREF fill,COLORREF border,int hatchstyle)
{
	CDC bmpdc;
	COLORREF m_newclrBack;
	int x1=0,y1=0,x2=bitmap_size.cx,y2=bitmap_size.cy;

	if(IsWinXPLuna())m_newclrBack=GetSysColor(COLOR_3DFACE);
	else m_newclrBack=GetSysColor(COLOR_MENU);

	bmpdc.CreateCompatibleDC(pDC);

	bmp.CreateCompatibleBitmap(pDC, icon_size.cx, icon_size.cy);	
	CBitmap* pOldBitmap = bmpdc.SelectObject(&bmp);

	if(bitmap_size!=icon_size){
		CBrush background_brush;
		background_brush.CreateSolidBrush(m_newclrBack);
		CRect rect(0,0, icon_size.cx, icon_size.cy);
		bmpdc.FillRect(rect,&background_brush);
		x1 = (icon_size.cx-bitmap_size.cx)/2;
		y1 = (icon_size.cy-bitmap_size.cy)/2;
		x2 = x1+bitmap_size.cx;
		y2 = y1+bitmap_size.cy;
		background_brush.DeleteObject();
	}
	
	CPen border_pen(PS_SOLID, 1, border);
	CBrush fill_brush;
	if(hatchstyle!=-1) { fill_brush.CreateHatchBrush(hatchstyle, fill); }
	else      { fill_brush.CreateSolidBrush(fill);             }
	
	CPen*    pOldPen    = bmpdc.SelectObject(&border_pen);
	CBrush*  pOldBrush  = bmpdc.SelectObject(&fill_brush);

	bmpdc.Rectangle(x1,y1,x2,y2);

	if(NULL!=pOldBrush)  { bmpdc.SelectObject(pOldBrush);  }
	if(NULL!=pOldPen)    { bmpdc.SelectObject(pOldPen);    }
	if(NULL!=pOldBitmap) { bmpdc.SelectObject(pOldBitmap); }
}

BOOL CCJMenu::IsWindowsClassicTheme(void)
{
	TCHAR Buf[_MAX_PATH+10];
	HKEY hKey;
	DWORD size,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);
}

int CCJMenu::GlobalImageListOffset(int nID)
{
	int numcurrent=m_AllImagesID.GetSize();
	int existsloc = -1;
	for(int i=0;i<numcurrent;++i){
		if(m_AllImagesID[i]==nID){
			existsloc=i;
			break;
		}
	}
	return existsloc;
}

BOOL CCJMenu::CanDraw3DImageList(int offset)
{
	BOOL retflag=FALSE;
	int numcurrent=m_AllImagesID.GetSize();
	if(offset+1<numcurrent&&offset+2<numcurrent){
		int nID=m_AllImagesID[offset];
		if(m_AllImagesID[offset+1]==nID&&m_AllImagesID[offset+2]==nID)retflag=TRUE;
	}
	return(retflag);
}

int CCJMenu::AddToGlobalImageList(CImageList *il,int xoffset,int nID)
{
	int loc = -1;
	HIMAGELIST hImageList = m_AllImages.m_hImageList;
	if(!hImageList){
		m_AllImages.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
	}
	HICON hIcon = il->ExtractIcon(xoffset);
	if(hIcon){
		CBitmap bmp,bmp2,bmp3;
		if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
			CWnd *pWnd = AfxGetMainWnd();            // Get main window
			if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
			CDC *pDC = pWnd->GetDC();              // Get device context
			GetBitmapFromImageList(pDC,il,xoffset,bmp);
			GetFadedBitmap(bmp);
			GetBitmapFromImageList(pDC,il,xoffset,bmp2);
			GetShadowBitmap(bmp2);
			GetBitmapFromImageList(pDC,il,xoffset,bmp3);
			GetDisabledBitmap(bmp3);
			pWnd->ReleaseDC(pDC);  // Release the DC
		}
		int numcurrent=m_AllImagesID.GetSize();
		int existsloc = -1;
		for(int i=0;i<numcurrent;++i){
			if(m_AllImagesID[i]==nID){
				existsloc=i;
				break;
			}
		}
		if(existsloc>=0){
			m_AllImages.Replace(existsloc,hIcon);
			loc = existsloc;
			if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
				if(existsloc+1<numcurrent&&m_AllImagesID[existsloc+1]==nID){
					if(existsloc+2<numcurrent&&m_AllImagesID[existsloc+2]==nID){
						CImageList il2;
						il2.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
						il2.Add(&bmp,GetSysColor(COLOR_3DFACE));
						HICON hIcon2 = il2.ExtractIcon(0);
						m_AllImages.Replace(existsloc+1,hIcon2);
						il2.Add(&bmp2,GetSysColor(COLOR_3DFACE));
						HICON hIcon3 = il2.ExtractIcon(1);
						m_AllImages.Replace(existsloc+2,hIcon3);
						il2.Add(&bmp3,GetSysColor(COLOR_3DFACE));
						HICON hIcon4 = il2.ExtractIcon(2);
						m_AllImages.Replace(existsloc+3,hIcon4);
						::DestroyIcon(hIcon2);
						::DestroyIcon(hIcon3);
						::DestroyIcon(hIcon4);
					}
				}
			}
		}
		else{
			m_AllImages.Add(hIcon);
			m_AllImagesID.Add(nID);
			loc=numcurrent;
			if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
				m_AllImages.Add(&bmp,GetSysColor(COLOR_3DFACE));
				m_AllImages.Add(&bmp2,GetSysColor(COLOR_3DFACE));
				m_AllImages.Add(&bmp3,GetSysColor(COLOR_3DFACE));
				m_AllImagesID.Add(nID);
				m_AllImagesID.Add(nID);
				m_AllImagesID.Add(nID);
			}
		}
		::DestroyIcon(hIcon);
	}
	return(loc);
}

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

Anna-Jayne Metcalfe
Founder Riverblade Limited
United Kingdom United Kingdom
I haven't always written software for a living. When I graduated from Surrey University in 1989, it was with an Electronic Engineering degree, but unfortunately that never really gave me the opportunity to do anything particularly interesting (with the possible exception of designing Darth Vader's Codpiece * for the UK Army in 1990).
    * Also known as the Standard Army Bootswitch. But that's another story...
Since the opportunity arose to lead a software team developing C++ software for Avionic Test Systems in 1996, I've not looked back. More recently I've been involved in the development of subsea acoustic navigation systems, digital TV broadcast systems, port security/tracking systems, and most recently software development tools with my own company, Riverblade Ltd.
 
One of my personal specialities is IDE plug-in development. ResOrg was my first attempt at a plug-in, but my day to day work is with Visual Lint, an interactive code analysis tool environment with works within the Visual Studio and Eclipse IDEs or on build servers.
 
I love lots of things, but particularly music, photography and anything connected with history or engineering. I despise ignorant, intolerant and obstructive people - and it shows...I can be a bolshy cow if you wind me up the wrong way...Laugh | :laugh:
 
I'm currently based 15 minutes walk from the beach in Bournemouth on the south coast of England. Since I moved here I've grown to love the place - even if it is full of grockles in Summer!
Follow on   Twitter

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 10 Jan 2005
Article Copyright 2001 by Anna-Jayne Metcalfe
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid