如何自定义创建windows的右键弹出菜单(C++)

在进行windows编程时,很多人都会想到使用自定义的邮件弹出菜单。先上代码

实现文件:

//------------------------------------------------------------------------------
// File    : NewMenu.cpp
// Version : 1.25
// Date    : 25. June 2005
// Author  : Bruno Podetti
// Email   : [email protected]
// Web     : www.podetti.com/NewMenu
// Systems : VC6.0/7.0 and VC7.1 (Run under (Window 98/ME), Windows Nt 2000/XP)
//           for all systems it will be the best when you install the latest IE
//           it is recommended for CNewToolBar
//
// For bugreport please add following informations
// - The CNewMenu version number (Example CNewMenu 1.16)
// - Operating system Win95 / WinXP and language (English / Japanese / German etc.)
// - Installed service packs
// - Version of internet explorer (important for CNewToolBar)
// - Short description how to reproduce the bug
// - Pictures/Sample are welcome too
// - You can write in English or German to the above email-address.
// - Have my compiled examples the same effect?
//------------------------------------------------------------------------------
//
// Special
// Compiled version with visual studio V7.0/7.1 doesn't run correctly on
// WinNt 4.0 nor Windows 95. For those platforms, you have to compile it with
// visual studio V6.0.
// (It may run with 7.0/7.1, but you must be sure to have all required and newest
//  dll from the MFC installed => otherwise menu painting problems)
// Keep in mind you should have installed latest service-packs to the operating-
// system too! (And a new IE because some fixes of common components were made)
//------------------------------------------------------------------------------
//
// ToDo's
// checking GDI-Leaks, are there some more?
// Shade-Drawing, when underground is changing
// Border repainting after menu closing!!!
// Shade painting problems? On Chinese or Japanese systems?
// supporting additional bitmap in menu with ownerdrawn style
//
// 25. June 2005 (Version 1.25)
// added compatibility for new security enhancement in CRT (MFC 8.0)
//
// 16. May 2005 (Version 1.24) 
// added tranparency to menu
// added some more information for visualtudio work better with messagemaps 
// safer handling of limitted HDC's
// added new function CreateBitmapMask
// - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
//   corrected background and highlight colors for XP styles.  Read comments dated May-05-2005 below for more information
//
// 23. January 2005 (Version 1.23) - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
// added another LoadToolbar() function to map a 16 color toolbar to a 256 color bitmap
// created CNewMenuThreadHook class to be instantiated and destroyed in a thread to setup and release the menu hook
// Bruno: Now we subclass only NewMenu (Drawing border etc.)
//
// 11. September 2004 (Version 1.22)
// added helperfunction for forcing compiler to export templatefunction
// better support for Hebrew or Arabic (MFT_RIGHTORDER)
// added new support for multiple monitors
// added some more details to errorhandling of CNewMenu ShowLastError only debug
// Changed AddTheme for compatibility to VisualStudio 2005
//
// 27. June 2004 (Version 1.21)
// colorsheme for office 2003 style changed and more like real office 2003
// enabled keyboardcues in style office 2003
// Old colorscheme from office 2003 is now called STYLE_COLORFUL
//
// 1. May 2004 (Version 1.20)
// additionally drawing for menubar
// added some compatibility issue with wine
// shading window (only test)
// changed the colorscheme with more theme support
// corected the menubar detection
//
// 6. February 2004 (Version 1.19)
// Icy and standard menu: systemmenu now with symbols
// underline enabling and disabling added, thanks to Robin Leatherbarrow
// make it compatible to 64-bit windows, thanks to David Pritchard
// added accelerator support to menu, thanks to Iain Clarke
// Corrected functions names SetXpBlendig/GetXpBlendig to SetXpBlending/GetXpBlending
// removed 3d-look from office 2003 style menu (now like real office 2003 menu)
// Handling of a normal menu-item in menubar changed
//
// 30. November 2003 (Version 1.18)
// minor changes for CNewToolBar
//
// 11. September 2003 Bug Fixes or nice hints from 1.16
// Better handling of menubar brushes (never destroy) Style_XP and STYLE_XP_2003
// Drawing of menuicons on WinNt 4.0 fixed
// spelling & initializing & unused brushes fixed, thanks to John Zegers
//
// 12. July 2003 Bug Fixes or nice hints from 1.15
// Added gradient-Dockbar (CNewDockBar) for office 2003 style
// (you need to define USE_NEW_DOCK_BAR)
// fixed menu checkmarks with bitmaps (Selection-with is not correct on all styles)
// Drawing to a memory-DC minimizing flickering
// with of menu-bar-item without & now better
//
// 22. June 2003 Bug Fixes or nice hints from 1.14
// Shortkey-handling for ModifyODMenu and InsertODMenu
// Change os identifer for OS>5.0 to WinXP
// Color scheme for Office menu changed and updating menubarcolor too
// Gradientcolor for Office 2003 bar
// XP-changing settings Border Style => fixed border painting without restarting
//
// 23. April 2003 Bug Fixes or nice hints from 1.13
// Fixed the window menu with extreme width, thanks to Voy
// Fix bug about shortkey for added menu item with AppendMenu, thanks to Mehdy Bohlool(Zy)
// Measureitem for default item corrected, thanks to LordLiverpool
// New menu style office 2003, but color schema is not tested, changing of menubar color
// on win95 and WinNt is not possible
// Menubardrawing on deactivated app corrected for win95 & WinNt4.0
//
// 23. January 2003 Bug Fixes or nice hints from 1.12
// Fixed SetMenuText, thanks to Eugene Plokhov
// Easier for having an other menu font, but on your own risk ;)
// Added new function SetNewMenuBorderAllMenu for borderhandling off non CNewMenu
//
// 22. December 2002 Bug Fixes or nice hints from 1.11
// Added some new tracing stuffs
// fixed SetMenuText
// XP-Style menu more office style and better handling with less 256 color, thanks to John Zegers
// Close window button disabling under XP with theme fixed
// Menubar color with theme fixed, thanks to Luther Weeks
//
// (9. November) Bug Fixes or nice hints from 1.11b
// Some new function for bleaching bitmaps, thanks to John Zegers
// GetSubMenu(LPCTSTR) , thanks to George Menhorn
// Menu animation under Win 98 fixed
// Borderdrawing a little better also under win 98
// Added new menustyle ICY
//
// (21. August 2002) Bug Fixes or nice hints from 1.10
// Bugfix for Windows NT 4.0 System Bitmaps, thanks to Christoph Weber
//
// (30. July 2002) Bug Fixes or nice hints from 1.03
// Color of checked icons / selection marks more XP-look
// Updating images 16 color by changing systems colors
// Icon drawing with more highlighting and half transparency
// Scroller for large menu correcting (but the overlapping border is not corrected)
// Resource-problem on windows 95/98/ME?, when using too much bitmaps in menus
//  changing the kind of storing bitmaps (images list)
// Calculating the size for a menuitem (specially submenuitem) corrected.
// Recentfilelist corrected (Seperator gots a wrong ID number)
//
// (25. June 2002) Bug Fixes or nice hints from 1.02
// Adding removing menu corrected for drawing the shade in menubar
// Draw the menuborder corrected under win 98 at the bottom side
// Highlighting under 98 for menu corrected (Assert), Neville Franks
//  Works also on Windows 95
// Changing styles on XP menucolor of the bar now corrected.
//
// (18. June 2002) Bug Fixes or nice hints from 1.01
// Popup menu which has more items than will fit, better
// LoadMenu changed for better languagessuport, SnowCat
// Bordercolor & Drawing of XP-Style-Menu changed to more XP-Look
// Added some functions for setting/reading MenuItemData and MenuData
// Menubar highlighting now supported under 98/ME (NT 4.0 and 95?)
// Font for menutitle can be changed
// Bugs for popupmenu by adding submenu corrected, no autodestroy
//
// (6. June 2002) Bug Fixes or nice hints from 1.00
// Loading Icons from a resource dll expanded (LoadToolBar) Jonathan de Halleux, Belgium.
// Minimized resource leak of User and Gdi objects
// Problem of disabled windows button on 98/Me solved
// Gradient-drawing without Msimg32.dll now supported especially for win 95
// Using solid colors for drawing menu items
// GetSubMenu changed to const
// Added helper function for setting popup-flag for popup menu (centered text)
// Redraw menu bar corrected after canceling popup menu in old style menu
//
// (23. Mai 2002) Bug Fixes and portions of code from previous version supplied by:
// Brent Corkum, 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
//
// 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.
//------------------------------------------------------------------------------

#include "stdafx.h"        // Standard windows header file
#include "NewMenu.h"       // CNewMenu class declaration

// Those two following constants should be only defined for tracing.
// Normally they are commented out.
//#define _TRACE_MENU_
//#define _TRACE_MENU_LOGFILE

//#define _NEW_MENU_USER_FONT
// For using an userfont you can set the define. It does not work right in the
// systemmenu nor in the menubar. But when you like to use the new menu only in
// popups then it will work, but it is newer a good idea to set or change the
// menufont.
// I do not support this mode, you use it on your own risk. :)
#ifdef _NEW_MENU_USER_FONT
static  LOGFONT MENU_USER_FONT = {20, 0, 0, 0, FW_NORMAL,
                                  0, 0, 0, DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
                                  CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                                  DEFAULT_PITCH,_T("Comic Sans MS")};
#endif

#ifdef _TRACE_MENU_
#include "MyTrace.h"
#endif

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

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#endif

#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(hh) (HIWORD(hh)==NULL)
#endif

#define GAP 2

#ifndef COLOR_MENUBAR
#define COLOR_MENUBAR       30
#endif

#ifndef SPI_GETDROPSHADOW
#define SPI_GETDROPSHADOW   0x1024
#endif

#ifndef SPI_GETFLATMENU
#define SPI_GETFLATMENU     0x1022
#endif

#ifndef ODS_NOACCEL
#define ODS_NOACCEL         0x0100
#endif

#ifndef DT_HIDEPREFIX
#define DT_HIDEPREFIX  0x00100000
#endif

#ifndef DT_PREFIXONLY
#define DT_PREFIXONLY  0x00200000
#endif

#ifndef SPI_GETKEYBOARDCUES
#define SPI_GETKEYBOARDCUES                 0x100A
#endif

#ifndef _WIN64

#ifdef SetWindowLongPtrA
#undef SetWindowLongPtrA
#endif
inline LONG_PTR SetWindowLongPtrA( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
{
  return( ::SetWindowLongA( hWnd, nIndex, LONG( dwNewLong ) ) );
}

#ifdef SetWindowLongPtrW
#undef SetWindowLongPtrW
#endif
inline LONG_PTR SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
{
  return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
}

#ifdef GetWindowLongPtrA
#undef GetWindowLongPtrA
#endif
inline LONG_PTR GetWindowLongPtrA( HWND hWnd, int nIndex )
{
  return( ::GetWindowLongA( hWnd, nIndex ) );
}

#ifdef GetWindowLongPtrW
#undef GetWindowLongPtrW
#endif
inline LONG_PTR GetWindowLongPtrW( HWND hWnd, int nIndex )
{
  return( ::GetWindowLongW( hWnd, nIndex ) );
}

#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC        (-4)
#endif

#ifndef SetWindowLongPtr
#ifdef UNICODE
#define SetWindowLongPtr  SetWindowLongPtrW
#else
#define SetWindowLongPtr  SetWindowLongPtrA
#endif // !UNICODE
#endif //SetWindowLongPtr

#ifndef GetWindowLongPtr
#ifdef UNICODE
#define GetWindowLongPtr  GetWindowLongPtrW
#else
#define GetWindowLongPtr  GetWindowLongPtrA
#endif // !UNICODE
#endif // GetWindowLongPtr

#endif //_WIN64


// Count of menu icons normal gloomed and grayed
#define MENU_ICONS    3

BOOL bHighContrast = FALSE;
BOOL bWine = FALSE;

typedef BOOL (WINAPI* FktGradientFill)( IN HDC, IN PTRIVERTEX, IN ULONG, IN PVOID, IN ULONG, IN ULONG);
typedef BOOL (WINAPI* FktIsThemeActive)();
typedef HRESULT (WINAPI* FktSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);

FktGradientFill pGradientFill = NULL;
FktIsThemeActive pIsThemeActive = NULL;
FktSetWindowTheme pSetWindowTheme = NULL;

BOOL GUILIBDLLEXPORT IsMenuThemeActive()
{
  return pIsThemeActive?pIsThemeActive():FALSE;
}


/////////////////////////////////////////////////////////////////////////////
// Helper datatypes
class CToolBarData
{
public:
  WORD wVersion;
  WORD wWidth;
  WORD wHeight;
  WORD wItemCount;
  //WORD aItems[wItemCount]
  WORD* items()
  { return (WORD*)(this+1); }
};

class CNewMenuIconInfo
{
public:
  WORD wBitmapID;
  WORD wWidth;
  WORD wHeight;

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

// Helpers for casting
__inline HMENU UIntToHMenu(const unsigned int ui )
{
  return( (HMENU)(UINT_PTR)ui );
}

__inline HMENU HWndToHMenu(const HWND hWnd )
{
  return( (HMENU)hWnd );
}

__inline HWND HMenuToHWnd(const HMENU hMenu)
{
  return( (HWND)hMenu );
}

__inline UINT HWndToUInt(const HWND hWnd )
{
  return( (UINT)(UINT_PTR) hWnd);
}

__inline HWND UIntToHWnd(const UINT hWnd )
{
  return( (HWND)(UINT_PTR) hWnd);
}

__inline UINT HMenuToUInt(const HMENU hMenu )
{
  return( (UINT)(UINT_PTR) hMenu);
}

__inline LONG_PTR LongToPTR(const LONG value )
{
  return( LONG_PTR)value;
}

#ifdef _DEBUG
static void ShowLastError(LPCTSTR pErrorTitle=NULL)
{
  if(pErrorTitle==NULL)
{
    pErrorTitle=_T("Error from Menu");
  }
  DWORD error = GetLastError();
  if(error)
  {
    LPVOID lpMsgBuf=NULL;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
      FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS,
      NULL,
      error,
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
      (LPTSTR) &lpMsgBuf,
      0,
      NULL );
    if(lpMsgBuf)
    {
      // Display the string.
      MessageBox( NULL, (LPCTSTR)lpMsgBuf, pErrorTitle, MB_OK | MB_ICONINFORMATION );
      // Free the buffer.
      LocalFree( lpMsgBuf );
    }
    else
    {
      CString temp;
      temp.Format(_T("Error message 0x%lx not found"),error);
      // Display the string.
      MessageBox( NULL,temp, pErrorTitle, MB_OK | MB_ICONINFORMATION );
    }
  }
}
#else
#define ShowLastError(sz)
#endif


// this is a bad code! The timer 31 will be restartet, when it was used!!!!
UINT GetSafeTimerID(HWND hWnd, const UINT uiElapse)
{
  UINT nNewTimerId = NULL;
  if(IsWindow(hWnd))
  { // Try to start with TimerID 31, normaly is used 1, 10, or 100
    for(UINT nTimerId=31; nTimerId<100 && nNewTimerId==NULL; nTimerId++)
    { // Try to set a timer each uiElapse ms
      nNewTimerId = (UINT)::SetTimer(hWnd,nTimerId,uiElapse,NULL);
    }
    // Wow you have more than 69 timers!!!
    // Try to increase nTimerId<100 to nTimerId<1000;
    ASSERT(nNewTimerId);
  }
  return nNewTimerId;
}

WORD 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;
  }
  return 0;
}

int NumScreenColors()
{
  static int nColors = 0;
  if (!nColors)
  {
    // DC of the desktop
    CClientDC myDC(NULL);
    nColors = myDC.GetDeviceCaps(NUMCOLORS);
    if (nColors == -1)
    {
      nColors = 64000;
    }
  }
  return nColors;
}

HBITMAP LoadColorBitmap(LPCTSTR lpszResourceName, HMODULE hInst, int* pNumcol)
{
  if(hInst==0)
  {
    hInst = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
  }
  HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(lpszResourceName),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);
  if(pNumcol)
  {
    *pNumcol = numcol;
  }

  UnlockResource(hglb);
  FreeResource(hglb);

  return LoadBitmap(hInst,lpszResourceName);
 
}

HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent)
{
  HBITMAP hbmMask = NULL;
  BITMAP bm = {0};
  if(GetObject(hbmColour, sizeof(BITMAP), &bm))
  {
    hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
    if(hbmMask)
    {
      // Get some HDCs that are compatible with the display driver
      HDC hdcMem = CreateCompatibleDC(0);
      HDC hdcMem2 = CreateCompatibleDC(0);

      SelectObject(hdcMem, hbmColour);
      SelectObject(hdcMem2, hbmMask);

      // Set the background colour of the colour image to the colour
      // you want to be transparent.
      SetBkColor(hdcMem, crTransparent);

      // Copy the bits from the colour image to the B+W mask... everything
      // with the background colour ends up white while everythig else ends up
      // black...Just what we wanted.
      BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

      // Take our new mask and use it to turn the transparent colour in our
      // original colour image to black so the transparency effect will
      // work right.
      BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT);

      // Clean up.
      DeleteDC(hdcMem);
      DeleteDC(hdcMem2);
    }
  }
  return hbmMask;
}


COLORREF MakeGrayAlphablend(CBitmap* pBitmap, int weighting, COLORREF blendcolor)
{
  CDC myDC;
  // Create a compatible bitmap to the screen
  myDC.CreateCompatibleDC(0);
  // Select the bitmap into the DC
  CBitmap* pOldBitmap = myDC.SelectObject(pBitmap);

  BITMAP myInfo = {0};
  GetObject((HGDIOBJ)pBitmap->m_hObject,sizeof(myInfo),&myInfo);

  for (int nHIndex = 0; nHIndex < myInfo.bmHeight; nHIndex++)
  {
    for (int nWIndex = 0; nWIndex < myInfo.bmWidth; nWIndex++)
    {
      COLORREF ref = myDC.GetPixel(nWIndex,nHIndex);

      // make it gray
      DWORD nAvg =  (GetRValue(ref) + GetGValue(ref) + GetBValue(ref))/3;

      // Algorithme for alphablending
      //dest' = ((weighting * source) + ((255-weighting) * dest)) / 256
      DWORD refR = ((weighting * nAvg) + ((255-weighting) * GetRValue(blendcolor))) / 256;
      DWORD refG = ((weighting * nAvg) + ((255-weighting) * GetGValue(blendcolor))) / 256;;
      DWORD refB = ((weighting * nAvg) + ((255-weighting) * GetBValue(blendcolor))) / 256;;

      myDC.SetPixel(nWIndex,nHIndex,RGB(refR,refG,refB));
    }
  }
  COLORREF topLeftColor = myDC.GetPixel(0,0);
  myDC.SelectObject(pOldBitmap);
  return topLeftColor;
}

class CNewLoadLib
{
public:

  HMODULE m_hModule;
  void* m_pProg;

  CNewLoadLib(LPCTSTR pName,LPCSTR pProgName)
  {
    m_hModule = LoadLibrary(pName);
    m_pProg = m_hModule ? (void*)GetProcAddress (m_hModule,pProgName) : NULL;
  }

  ~CNewLoadLib()
  {
    if(m_hModule)
    {
      FreeLibrary(m_hModule);
      m_hModule = NULL;
    }
  }
};



#if(WINVER < 0x0500)

DECLARE_HANDLE(HMONITOR);

typedef struct tagMONITORINFO
{
  DWORD  cbSize;
  RECT   rcMonitor;
  RECT   rcWork;
  DWORD  dwFlags;
} MONITORINFO, *LPMONITORINFO;

BOOL GetMonitorInfo( HMONITOR hMonitor, LPMONITORINFO lpmi)
{
#ifdef UNICODE
  static CNewLoadLib menuInfo(_T("user32.dll"),"GetMonitorInfoW");
#else
  static CNewLoadLib menuInfo(_T("user32.dll"),"GetMonitorInfoA");
#endif
  if(menuInfo.m_pProg)
  {
    typedef BOOL (WINAPI* FktGetMonitorInfo)( HMONITOR,  LPMONITORINFO);
    return ((FktGetMonitorInfo)menuInfo.m_pProg)(hMonitor,lpmi);
  }
  return FALSE;
}

#define MONITOR_DEFAULTTONULL       0x00000000
#define MONITOR_DEFAULTTOPRIMARY    0x00000001
#define MONITOR_DEFAULTTONEAREST    0x00000002

#define MONITORINFOF_PRIMARY        0x00000001

HMONITOR MonitorFromWindow(
  HWND hwnd,       // handle to a window
  DWORD dwFlags    // determine return value
)
{
  static CNewLoadLib menuInfo(_T("user32.dll"),"MonitorFromWindow");
  if(menuInfo.m_pProg)
  {
    typedef HMONITOR (WINAPI* FktMonitorFromWindow)( HWND,  DWORD);
    return ((FktMonitorFromWindow)menuInfo.m_pProg)(hwnd,dwFlags);
  }
  return NULL;
}

HMONITOR MonitorFromRect(
  LPCRECT lprc,    // rectangle
  DWORD dwFlags    // determine return value
)
{
  static CNewLoadLib menuInfo(_T("user32.dll"),"MonitorFromRect");
  if(menuInfo.m_pProg)
  {
    typedef HMONITOR (WINAPI* FktMonitorFromRect)( LPCRECT,  DWORD);
    return ((FktMonitorFromRect)menuInfo.m_pProg)(lprc,dwFlags);
  }
  return NULL;
}


BOOL GetMenuInfo( HMENU hMenu, LPMENUINFO pInfo)
{
  static CNewLoadLib menuInfo(_T("user32.dll"),"GetMenuInfo");
  if(menuInfo.m_pProg)
  {
    typedef BOOL (WINAPI* FktGetMenuInfo)(HMENU, LPMENUINFO);
    return ((FktGetMenuInfo)menuInfo.m_pProg)(hMenu,pInfo);
  }
  return FALSE;
}

BOOL SetMenuInfo( HMENU hMenu, LPCMENUINFO pInfo)
{
  static CNewLoadLib menuInfo(_T("user32.dll"),"SetMenuInfo");
  if(menuInfo.m_pProg)
  {
    typedef BOOL (WINAPI* FktSetMenuInfo)(HMENU, LPCMENUINFO);
    return ((FktSetMenuInfo)menuInfo.m_pProg)(hMenu,pInfo);
  }
  return FALSE;
}

DWORD GetLayout(HDC hDC)
{
  static CNewLoadLib getLayout(_T("gdi32.dll"),"GetLayout");
  if(getLayout.m_pProg)
  {
    typedef DWORD (WINAPI* FktGetLayout)(HDC);
    return ((FktGetLayout)getLayout.m_pProg)(hDC);
  }
  return NULL;
}

DWORD SetLayout(HDC hDC, DWORD dwLayout)
{
  static CNewLoadLib setLayout(_T("gdi32.dll"),"SetLayout");
  if(setLayout.m_pProg)
  {
    typedef DWORD (WINAPI* FktSetLayout)(HDC,DWORD);
    return ((FktSetLayout)setLayout.m_pProg)(hDC,dwLayout);
  }
  return NULL;
}

#define WS_EX_LAYERED 0x00080000
#define LWA_ALPHA    2 // Use bAlpha to determine the opacity of the layer

BOOL SetLayeredWindowAttributes(HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags)
{
  static CNewLoadLib setLayout(_T("User32.dll"),"SetLayeredWindowAttributes");
  if(setLayout.m_pProg)
  {
    typedef  BOOL (WINAPI *lpfnSetLayeredWindowAttributes) (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
    return ((lpfnSetLayeredWindowAttributes)setLayout.m_pProg)(hWnd, cr, bAlpha, dwFlags);
  }
  return false;
}



#endif

void MenuDrawText(HDC hDC ,LPCTSTR lpString,int nCount,LPRECT lpRect,UINT uFormat)
{
  if(nCount==-1)
  {
    nCount = lpString?(int)_tcslen(lpString):0;
  }
  LOGFONT logfont = {0};
  if(!GetObject(GetCurrentObject(hDC, OBJ_FONT),sizeof(logfont),&logfont))
  {
    logfont.lfOrientation = 0;
  }
  size_t bufSizeTChar = nCount + 1;
  TCHAR* pBuffer = (TCHAR*)_alloca(bufSizeTChar*sizeof(TCHAR));
  _tcsncpy_s(pBuffer,bufSizeTChar,lpString,nCount);
  pBuffer[nCount] = 0;

  UINT oldAlign =  GetTextAlign(hDC);

  const int nBorder=4;
  HGDIOBJ hOldFont = NULL;
  CFont TempFont;

  TEXTMETRIC textMetric;
  if (!GetTextMetrics(hDC, &textMetric))
  {
    textMetric.tmOverhang = 0;
    textMetric.tmAscent = 0;
  }
  else if ((textMetric.tmPitchAndFamily&(TMPF_VECTOR|TMPF_TRUETYPE))==0 )
  {
    // we have a bitmapfont it is not possible to rotate
    if(logfont.lfOrientation || logfont.lfEscapement)
    {
      hOldFont = GetCurrentObject(hDC,OBJ_FONT);
      _tcscpy_s(logfont.lfFaceName,ARRAY_SIZE(logfont.lfFaceName),_T("Arial"));
      // we need a truetype font for rotation
      logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
      // the font will be destroyed at the end by destructor
      TempFont.CreateFontIndirect(&logfont);
      // we select at the end the old font
      SelectObject(hDC,TempFont);
      GetTextMetrics(hDC, &textMetric);
    }
  }

  DWORD dwLayout = GetLayout(hDC);
  if(dwLayout&LAYOUT_RTL)
  {
    SetTextAlign (hDC,TA_RIGHT|TA_TOP|TA_UPDATECP);
  }
  else
  {
    SetTextAlign (hDC,TA_LEFT|TA_TOP|TA_UPDATECP);
  }
  CPoint pos(lpRect->left,lpRect->top);

  if( (uFormat&DT_VCENTER) &&lpRect)
  {
    switch(logfont.lfOrientation%3600)
    {
    default:
    case 0:
      logfont.lfOrientation = 0;
      pos.y = (lpRect->top+lpRect->bottom-textMetric.tmHeight)/2;
      if(dwLayout&LAYOUT_RTL)
      {
        pos.x = lpRect->right - nBorder;
      }
      else
      {
        pos.x = lpRect->left + nBorder;
      }
      break;

    case 1800:
    case -1800:
      logfont.lfOrientation = 1800;
      pos.y = (lpRect->top+textMetric.tmHeight +lpRect->bottom)/2;
      if(dwLayout&LAYOUT_RTL)
      {
        pos.x = lpRect->left + nBorder;
      }
      else
      {
        pos.x = lpRect->right - nBorder;
      }
      break;

    case 900:
    case -2700:
      logfont.lfOrientation = 900;
      pos.x = (lpRect->left+lpRect->right-textMetric.tmHeight)/2;
      pos.y = lpRect->bottom - nBorder;
      if(dwLayout&LAYOUT_RTL)
      {
        pos.y = lpRect->top + nBorder;
      }
      else
      {
        pos.y = lpRect->bottom - nBorder;
      }
      break;

    case -900:
    case 2700:
      logfont.lfOrientation = 2700;
      pos.x = (lpRect->left+lpRect->right+textMetric.tmHeight)/2;
      if(dwLayout&LAYOUT_RTL)
      {
        pos.y = lpRect->bottom - nBorder;
      }
      else
      {
        pos.y = lpRect->top + nBorder;
      }
      break;
    }
  }

  CPoint oldPos;
  MoveToEx(hDC,pos.x,pos.y,&oldPos);

  while(nCount)
  {
    TCHAR *pTemp =_tcsstr(pBuffer,_T("&"));
    if(pTemp)
    {
      // we found &
      if(*(pTemp+1)==_T('&'))
      {
        // the different is in character unicode and byte works
        int nTempCount = DWORD(pTemp-pBuffer)+1;
        ExtTextOut(hDC,pos.x,pos.y,ETO_CLIPPED,lpRect,pBuffer,nTempCount,NULL);
        nCount -= nTempCount+1;
        pBuffer = pTemp+2;
      }
      else
      {
        // draw underline the different is in character unicode and byte works
        int nTempCount = DWORD(pTemp-pBuffer);
        ExtTextOut(hDC,pos.x,pos.y,ETO_CLIPPED,lpRect,pBuffer,nTempCount,NULL);
        nCount -= nTempCount+1;
        pBuffer = pTemp+1;
        if(!(uFormat&DT_HIDEPREFIX) )
        {
          CSize size;
          GetTextExtentPoint(hDC, pTemp+1, 1, &size);
          GetCurrentPositionEx(hDC,&pos);

          COLORREF oldColor = SetBkColor(hDC, GetTextColor(hDC));
          LONG cx = size.cx - textMetric.tmOverhang / 2;
          LONG nTop;
          CRect rc;
          switch(logfont.lfOrientation)
          {
          case 0:
            // Get height of text so that underline is at bottom.
            nTop = pos.y + textMetric.tmAscent + 1;
            // Draw the underline using the foreground color.
            if(dwLayout&LAYOUT_RTL)
            {
              rc.SetRect(pos.x-cx+2, nTop, pos.x+1, nTop+1);
            }
            else
            {
              rc.SetRect(pos.x, nTop, pos.x+cx, nTop+1);
            }
            ExtTextOut(hDC, pos.x, nTop, ETO_OPAQUE, &rc, _T(""), 0, NULL);
            break;

          case 1800:
            // Get height of text so that underline is at bottom.
            nTop = pos.y -(textMetric.tmAscent + 1);
            // Draw the underline using the foreground color.
            if(dwLayout&LAYOUT_RTL)
            {
              rc.SetRect(pos.x-1, nTop-1, pos.x+cx-1, nTop);
            }
            else
            {
              rc.SetRect(pos.x-cx, nTop-1, pos.x, nTop);
            }
            ExtTextOut(hDC, pos.x, nTop, ETO_OPAQUE, &rc, _T(""), 0, NULL);
            break;

          case 900:
            // draw up
            // Get height of text so that underline is at bottom.
            nTop = pos.x + (textMetric.tmAscent + 1);
            // Draw the underline using the foreground color.
            if(dwLayout&LAYOUT_RTL)
    {
              rc.SetRect(nTop-1, pos.y, nTop, pos.y+cx-2);
    }
    else
    {
              rc.SetRect(nTop, pos.y-cx, nTop+1, pos.y);
            }
            ExtTextOut(hDC, nTop, pos.y, ETO_OPAQUE, &rc, _T(""), 0, NULL);
            break;

          case 2700:
            // draw down
            // Get height of text so that underline is at bottom.
            nTop = pos.x -(textMetric.tmAscent + 1);
            // Draw the underline using the foreground color.
            if(dwLayout&LAYOUT_RTL)
            {
              rc.SetRect(nTop, pos.y-cx+1 , nTop+1, pos.y);
    }
            else
            {
              rc.SetRect(nTop-1, pos.y, nTop, pos.y+cx);
  }
            ExtTextOut(hDC, nTop, pos.y, ETO_OPAQUE, &rc, _T(""), 0, NULL);
            break;
}
          SetBkColor(hDC, oldColor);
          // corect the actual drawingpoint
          MoveToEx(hDC,pos.x,pos.y,NULL);
    }
  }
}
    else
{
      // draw the rest of the string
      ExtTextOut(hDC,pos.x,pos.y,ETO_CLIPPED,lpRect,pBuffer,nCount,NULL);
      break;
    }
  }
  // restore old point
  MoveToEx(hDC,oldPos.x,oldPos.y,NULL);
  // restore old align
  SetTextAlign(hDC,oldAlign);

  if(hOldFont!=NULL)
  {
    SelectObject(hDC,hOldFont);
  }
}


CRect GUILIBDLLEXPORT GetScreenRectFromWnd(HWND hWnd)
{
  CRect rect;
  HMONITOR hMonitor = MonitorFromWindow(hWnd,MONITOR_DEFAULTTONEAREST);
  MONITORINFO monitorinfo={0};
  monitorinfo.cbSize = sizeof(monitorinfo);
  if(hMonitor!=NULL && GetMonitorInfo(hMonitor,&monitorinfo))
  {
    rect = monitorinfo.rcWork;
  }
  else
    {
    rect.SetRect(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
    }
  return rect;
}

CRect GUILIBDLLEXPORT GetScreenRectFromRect(LPCRECT pRect)
{
  CRect rect;
  HMONITOR hMonitor = MonitorFromRect(pRect,MONITOR_DEFAULTTONEAREST);
  MONITORINFO monitorinfo={0};
  monitorinfo.cbSize = sizeof(monitorinfo);
  if(hMonitor!=NULL && GetMonitorInfo(hMonitor,&monitorinfo))
  {
    rect = monitorinfo.rcWork;
  }
  else
  {
    rect.SetRect(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
  }
  return rect;
}

 BOOL GUILIBDLLEXPORT TrackPopupMenuSpecial(CMenu *pMenu, UINT uFlags, CRect rcTBItem, CWnd *pWndCommand, BOOL bOnSide)
{
   CRect rect = GetScreenRectFromRect(rcTBItem);
   CPoint CenterPoint = rect.CenterPoint();
   CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,pMenu);

   if(bOnSide)
   {
     if(CenterPoint.xGetSafeHwnd()))
  {
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|uFlags, rcTBItem.left-1, rcTBItem.top+1,pWndCommand,NULL);
       }
       else
    {
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTALIGN|uFlags, rcTBItem.left-1, rcTBItem.top+1,pWndCommand,NULL);
       }
    }
     else
     {
       if(rcTBItem.right<=rect.left){rcTBItem.right=rect.left+1;}
       if(rcTBItem.topTrackPopupMenu(TPM_LEFTBUTTON|uFlags, rcTBItem.right-1, rcTBItem.top+1,pWndCommand,NULL);
  }
}
   else
{
     int nMenuHeight = 0;
     if(pNewMenu)
  {
       CSize size = pNewMenu->GetIconSize();
       // calculate more or less the height, seperators and titles may be wrong
       nMenuHeight = pNewMenu->GetMenuItemCount()*size.cy;
  }

     bool bMenuAbove = CenterPoint.yrect.bottom){rcTBItem.top=rect.bottom;}
       if(IsMirroredWnd(pWndCommand->GetSafeHwnd()))
{
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_BOTTOMALIGN|TPM_RIGHTALIGN|uFlags, rcTBItem.left, rcTBItem.top,pWndCommand,rcTBItem);
       }
       else
  {
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_BOTTOMALIGN|uFlags, rcTBItem.left, rcTBItem.top,pWndCommand,rcTBItem);
  }
}
     else
     {
       // top of the screen
       if(rcTBItem.leftGetSafeHwnd()))
{
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTALIGN|uFlags, rcTBItem.left, rcTBItem.bottom,pWndCommand,rcTBItem);
       }
       else
  {
        return pMenu->TrackPopupMenu(TPM_LEFTBUTTON|uFlags, rcTBItem.left, rcTBItem.bottom,pWndCommand,rcTBItem);
       }
     }
  }
}

class CNewBrushList : public CObList
{
public:
  CNewBrushList(){}
  ~CNewBrushList()
  {
    while(!IsEmpty())
    {
      delete RemoveTail();
    }
  }
};

class CNewBrush : public CBrush
{
public:
  UINT m_nMenuDrawMode;
  COLORREF m_BarColor;
  COLORREF m_BarColor2;

  CNewBrush(UINT menuDrawMode, COLORREF barColor, COLORREF barColor2):m_nMenuDrawMode(menuDrawMode),m_BarColor(barColor),m_BarColor2(barColor2)
  {
    if (g_Shell!=WinNT4 &&
        g_Shell!=Win95 &&
        (menuDrawMode==CNewMenu::STYLE_XP_2003 || menuDrawMode==CNewMenu::STYLE_COLORFUL))
    {
      // Get the desktop hDC...
      HDC hDcDsk = GetWindowDC(0);
      CDC* pDcDsk = CDC::FromHandle(hDcDsk);

      CDC clientDC;
      clientDC.CreateCompatibleDC(pDcDsk);

      CRect rect(0,0,(GetSystemMetrics(SM_CXFULLSCREEN)+16)&~7,20);

      CBitmap bitmap;
      bitmap.CreateCompatibleBitmap(pDcDsk,rect.Width(),rect.Height());
      CBitmap* pOldBitmap = clientDC.SelectObject(&bitmap);

      int nRight = rect.right;
      if(rect.right>700)
      {
        rect.right  = 700;
        DrawGradient(&clientDC,rect,barColor,barColor2,TRUE,TRUE);
        rect.left = rect.right;
        rect.right = nRight;
        clientDC.FillSolidRect(rect, barColor2);
      }
      else
      {
        DrawGradient(&clientDC,rect,barColor,barColor2,TRUE,TRUE);
      }
      clientDC.SelectObject(pOldBitmap);

      // Release the desktopdc
      ReleaseDC(0,hDcDsk);

      CreatePatternBrush(&bitmap);
    }
    else
    {
      CreateSolidBrush(barColor);
    }
  }
};

CBrush* GetMenuBarBrush()
{
  // The brushes will be destroyed at program-end => Not a memory-leak
  static CNewBrushList brushList;
  static CNewBrush* lastBrush = NULL;

  COLORREF menuBarColor;
  COLORREF menuBarColor2;  //JUS

  UINT nMenuDrawMode = CNewMenu::GetMenuDrawMode();

  switch(nMenuDrawMode)
  {
  case CNewMenu::STYLE_XP_2003 :
  case CNewMenu::STYLE_XP_2003_NOBORDER :
    {
      CNewMenu::GetMenuBarColor2003(menuBarColor, menuBarColor2);
      if (NumScreenColors()>=256 && !bHighContrast)
      {
        nMenuDrawMode = CNewMenu::STYLE_XP_2003;
      }
      else
      {
       menuBarColor = menuBarColor2 = GetSysColor(COLOR_3DFACE);
       nMenuDrawMode = CNewMenu::STYLE_XP;
      }
    }
    break;

  case CNewMenu::STYLE_COLORFUL :
  case CNewMenu::STYLE_COLORFUL_NOBORDER :
    {
      CNewMenu::GetMenuBarColor2003(menuBarColor, menuBarColor2);
      if (NumScreenColors()>=256 && !bHighContrast)
      {
        nMenuDrawMode = CNewMenu::STYLE_COLORFUL;
      }
      else
      {
        nMenuDrawMode = CNewMenu::STYLE_XP;
      }
    }
    break;

  case CNewMenu::STYLE_XP :
  case CNewMenu::STYLE_XP_NOBORDER :
    menuBarColor = menuBarColor2 = GetSysColor(COLOR_3DFACE);
    nMenuDrawMode = CNewMenu::STYLE_XP;
    break;

  default:
    return NULL;
  }

  // check if the last brush the one which we want
  if(lastBrush!=NULL &&
     lastBrush->m_nMenuDrawMode==nMenuDrawMode &&
     lastBrush->m_BarColor==menuBarColor &&
     lastBrush->m_BarColor2==menuBarColor2)
  {
    return lastBrush;
  }

  // Check if the brush is allready created
  POSITION pos = brushList.GetHeadPosition();
  while (pos)
  {
    lastBrush = (CNewBrush*)brushList.GetNext(pos);
    if(lastBrush!=NULL &&
      lastBrush->m_nMenuDrawMode==nMenuDrawMode &&
      lastBrush->m_BarColor==menuBarColor &&
      lastBrush->m_BarColor2==menuBarColor2)
    {
      return lastBrush;
    }
  }
  // create a new one and insert into the list
  brushList.AddHead(lastBrush = new CNewBrush(nMenuDrawMode,menuBarColor,menuBarColor2));
  return lastBrush;
}

void UpdateMenuBarColor(HMENU hMenu)
{
  CBrush* pBrush = GetMenuBarBrush();

  // for WindowsBlind activating it's better for not to change menubar background
  if(!pBrush /* || (pIsThemeActive && pIsThemeActive()) */ )
  {
    // menubackground hasn't been set
    return;
  }

  MENUINFO menuInfo = {0};
  menuInfo.cbSize = sizeof(menuInfo);
  menuInfo.hbrBack = *pBrush;
  menuInfo.fMask = MIM_BACKGROUND;

  // Change color only for CNewMenu and derived classes
  if(IsMenu(hMenu) && DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu))!=NULL)
  {
    SetMenuInfo(hMenu,&menuInfo);
  }

  CWinApp* pWinApp = AfxGetApp();
  // Update menu from template
  if(pWinApp)
  {
    CDocManager* pManager = pWinApp->m_pDocManager;
    if(pManager)
    {
      POSITION pos = pManager->GetFirstDocTemplatePosition();
      while(pos)
      {
        CDocTemplate* pTemplate = pManager->GetNextDocTemplate(pos);
        CMultiDocTemplate* pMultiTemplate = DYNAMIC_DOWNCAST(CMultiDocTemplate,pTemplate);
        if(pMultiTemplate)
        {
          // Change color only for CNewMenu and derived classes
          if(DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pMultiTemplate->m_hMenuShared))!=NULL)
          {
            // need for correct menubar color
            SetMenuInfo(pMultiTemplate->m_hMenuShared,&menuInfo);
          }
        }

        /*      // does not work with embeded menues
        if(pTemplate)
        {
        // Change color only for CNewMenu and derived classes
        // need for correct menubar color
        if(DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pTemplate->m_hMenuInPlace))!=NULL)
        {
        // menu & accelerator resources for in-place container
        SetMenuInfo(pTemplate->m_hMenuInPlace,&menuInfo);
        }
        if(DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pTemplate->m_hMenuEmbedding))!=NULL)
        {
        // menu & accelerator resource for server editing embedding
        SetMenuInfo(pTemplate->m_hMenuEmbedding,&menuInfo);
        }
        if(DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pTemplate->m_hMenuInPlaceServer))!=NULL)
        {
        // menu & accelerator resource for server editing in-place
        SetMenuInfo(pTemplate->m_hMenuInPlaceServer,&menuInfo);
        }
        }
        */
      }
    }
  }
}

BOOL DrawMenubarItem(CWnd* pWnd,CMenu* pMenu, UINT nItemIndex,UINT nState)
{
  CRect itemRect;
  if (nItemIndex!=UINT(-1) && GetMenuItemRect(pWnd->m_hWnd,pMenu->m_hMenu, nItemIndex, &itemRect))
  {
    MENUITEMINFO menuInfo = {0};
    menuInfo.cbSize = sizeof(menuInfo);
    menuInfo.fMask = MIIM_DATA|MIIM_TYPE|MIIM_ID;
    if(pMenu->GetMenuItemInfo(nItemIndex,&menuInfo,TRUE))
    {
      // Only ownerdrawn were allowed
      if(menuInfo.fType&MF_OWNERDRAW)
      {
        CWindowDC dc(pWnd);

        CFont fontMenu;
        LOGFONT logFontMenu;

#ifdef _NEW_MENU_USER_FONT
        logFontMenu =  MENU_USER_FONT;
#else
        NONCLIENTMETRICS nm = {0};
        nm.cbSize = sizeof (NONCLIENTMETRICS);
        VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
        logFontMenu =  nm.lfMenuFont;
#endif

        fontMenu.CreateFontIndirect (&logFontMenu);
        CFont* pOldFont = dc.SelectObject(&fontMenu);

        CRect wndRect;
        GetWindowRect(*pWnd,wndRect);
        itemRect.OffsetRect(-wndRect.TopLeft());

        // Bugfix for wine
        if(bWine)
        {
          if(!(GetWindowLongPtr(*pWnd, GWL_STYLE)&WS_THICKFRAME) )
          {
            itemRect.OffsetRect(-GetSystemMetrics(SM_CXFIXEDFRAME),
                                -(GetSystemMetrics(SM_CYMENU)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFIXEDFRAME)+1));
          }
          else
          {
            itemRect.OffsetRect(-GetSystemMetrics(SM_CXFRAME),
                                -(GetSystemMetrics(SM_CYMENU)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)+1));
          }
        }

        DRAWITEMSTRUCT drwItem = {0};
        drwItem.CtlType = ODT_MENU;
        drwItem.hwndItem = HMenuToHWnd(pMenu->m_hMenu);
        drwItem.itemID = menuInfo.wID;
        drwItem.itemData = menuInfo.dwItemData;
        drwItem.rcItem = itemRect;
        drwItem.hDC = dc.m_hDC;
        drwItem.itemState = nState;
        drwItem.itemAction = ODA_DRAWENTIRE;

        ASSERT(menuInfo.dwItemData);

        CNewMenu::m_dwLastActiveItem = (DWORD)menuInfo.dwItemData;

        CPoint windowOrg;
        SetWindowOrgEx(dc.m_hDC,0,0,&windowOrg);
        SendMessage(pWnd->GetSafeHwnd(),WM_DRAWITEM,NULL,(LPARAM)&drwItem);
        SetWindowOrgEx(dc.m_hDC,windowOrg.x,windowOrg.y,NULL);

        dc.SelectObject(pOldFont);

        return TRUE;
      }
    }
  }
  return FALSE;
}

Win32Type IsShellType()
{
  OSVERSIONINFO osvi = {0};
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

  DWORD winVer=GetVersion();
  if(winVer<0x80000000)
  {/*NT */
    if(!GetVersionEx(&osvi))
    {
      ShowLastError(_T("Error from Menu: GetVersionEx NT"));
    }
    if(osvi.dwMajorVersion==4L)
    {
      return WinNT4;
    }
    else if(osvi.dwMajorVersion==5L && osvi.dwMinorVersion==0L)
    {
      return Win2000;
    }
    // thanks to John Zegers
    else if(osvi.dwMajorVersion>=5L)// && osvi.dwMinorVersion==1L)
    {
      return WinXP;
    }
    return WinNT3;
  }
  else if (LOBYTE(LOWORD(winVer))<4)
  {
    return Win32s;
  }

  if(!GetVersionEx(&osvi))
  {
    ShowLastError(_T("Error from Menu: GetVersionEx"));
  }
  if(osvi.dwMajorVersion==4L && osvi.dwMinorVersion==10L)
  {
    return Win98;
  }
  else if(osvi.dwMajorVersion==4L && osvi.dwMinorVersion==90L)
  {
    return WinME;
  }
  return Win95;
}

BOOL IsShadowEnabled()
{
  BOOL bEnabled = FALSE;
  if(SystemParametersInfo(SPI_GETDROPSHADOW,0,&bEnabled,0))
  {
    return bEnabled;
  }
  return FALSE;
}

COLORREF DarkenColorXP(COLORREF color)
{
  return RGB( MulDiv(GetRValue(color),7,10),
    MulDiv(GetGValue(color),7,10),
    MulDiv(GetBValue(color)+55,7,10));
}

// Function splits a color into its RGB components and
// transforms the color using a scale 0..255
COLORREF DarkenColor( long lScale, COLORREF lColor)
{
  long red   = MulDiv(GetRValue(lColor),(255-lScale),255);
  long green = MulDiv(GetGValue(lColor),(255-lScale),255);
  long blue  = MulDiv(GetBValue(lColor),(255-lScale),255);

  return RGB(red, green, blue);
}

COLORREF MixedColor(COLORREF colorA,COLORREF colorB)
{
  // ( 86a + 14b ) / 100
  int red   = MulDiv(86,GetRValue(colorA),100) + MulDiv(14,GetRValue(colorB),100);
  int green = MulDiv(86,GetGValue(colorA),100) + MulDiv(14,GetGValue(colorB),100);
  int blue  = MulDiv(86,GetBValue(colorA),100) + MulDiv(14,GetBValue(colorB),100);

  return RGB( min(red,0xff),min(green,0xff), min(blue,0xff));
}

COLORREF MidColor(COLORREF colorA,COLORREF colorB)
{
  // (7a + 3b)/10
  int red   = MulDiv(7,GetRValue(colorA),10) + MulDiv(3,GetRValue(colorB),10);
  int green = MulDiv(7,GetGValue(colorA),10) + MulDiv(3,GetGValue(colorB),10);
  int blue  = MulDiv(7,GetBValue(colorA),10) + MulDiv(3,GetBValue(colorB),10);

  return RGB( min(red,0xff),min(green,0xff), min(blue,0xff));
}

COLORREF GrayColor(COLORREF crColor)
{
  int Gray  = (((int)GetRValue(crColor)) + GetGValue(crColor) + GetBValue(crColor))/3;

  return RGB( Gray,Gray,Gray);
}

BOOL IsLightColor(COLORREF crColor)
{
  return (((int)GetRValue(crColor)) + GetGValue(crColor) + GetBValue(crColor))>(3*128);
}

COLORREF GetXpHighlightColor()
{
  if(bHighContrast)
  {
    return GetSysColor(COLOR_HIGHLIGHT);
  }

  if (NumScreenColors() > 256)
  {
    // May-05-2005 - Mark P. Peterson ([email protected]) - Changed to use "MixedColor1()" instead when not using XP Theme mode.
    // It appears that using MidColor() in many non XP Themes cases returns the wrong color, this needs to be much more like the
    // highlight color as the user has selected in Windows.  If the highlight color is YELLOW, for example, and the COLOR_WINDOW
    // value is WHITE, using MidColor() the function returns a dark blue color making the menus too hard to read.
    if ((! IsMenuThemeActive()) && (IsLightColor(GetSysColor(COLOR_HIGHLIGHT))))
      return MixedColor(GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_HIGHLIGHT));
    else
      return MidColor(GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_HIGHLIGHT));
	// as released by Bruno
//    return MidColor(GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_HIGHLIGHT));
  }
  return GetSysColor(COLOR_WINDOW);
}

// Function splits a color into its RGB components and
// transforms the color using a scale 0..255
COLORREF LightenColor( long lScale, COLORREF lColor)
{
  long R = MulDiv(255-GetRValue(lColor),lScale,255)+GetRValue(lColor);
  long G = MulDiv(255-GetGValue(lColor),lScale,255)+GetGValue(lColor);
  long B = MulDiv(255-GetBValue(lColor),lScale,255)+GetBValue(lColor);

  return RGB(R, G, B);
}

COLORREF BleachColor(int Add, COLORREF color)
{
  return RGB( min (GetRValue(color)+Add, 255),
              min (GetGValue(color)+Add, 255),
              min (GetBValue(color)+Add, 255));
}

COLORREF GetAlphaBlendColor(COLORREF blendColor, COLORREF pixelColor,int weighting)
{
  if(pixelColor==CLR_NONE)
  {
    return CLR_NONE;
  }
  // Algorithme for alphablending
  //dest' = ((weighting * source) + ((255-weighting) * dest)) / 256
  DWORD refR = ((weighting * GetRValue(pixelColor)) + ((255-weighting) * GetRValue(blendColor))) / 256;
  DWORD refG = ((weighting * GetGValue(pixelColor)) + ((255-weighting) * GetGValue(blendColor))) / 256;;
  DWORD refB = ((weighting * GetBValue(pixelColor)) + ((255-weighting) * GetBValue(blendColor))) / 256;;

  return RGB(refR,refG,refB);
}


void DrawGradient(CDC* pDC,CRect& Rect,
                  COLORREF StartColor,COLORREF EndColor,
                  BOOL bHorizontal,BOOL bUseSolid)
{
  int Count = pDC->GetDeviceCaps(NUMCOLORS);
  if(Count==-1)
    bUseSolid = FALSE;

  // for running under win95 and WinNt 4.0 without loading Msimg32.dll
  if(!bUseSolid && pGradientFill )
  {
    TRIVERTEX vert[2];
    GRADIENT_RECT gRect;

    vert [0].y = Rect.top;
    vert [0].x = Rect.left;

    vert [0].Red    = COLOR16(COLOR16(GetRValue(StartColor))<<8);
    vert [0].Green  = COLOR16(COLOR16(GetGValue(StartColor))<<8);
    vert [0].Blue   = COLOR16(COLOR16(GetBValue(StartColor))<<8);
    vert [0].Alpha  = 0x0000;

    vert [1].y = Rect.bottom;
    vert [1].x = Rect.right;

    vert [1].Red    = COLOR16(COLOR16(GetRValue(EndColor))<<8);
    vert [1].Green  = COLOR16(COLOR16(GetGValue(EndColor))<<8);
    vert [1].Blue   = COLOR16(COLOR16(GetBValue(EndColor))<<8);
    vert [1].Alpha  = 0x0000;

    gRect.UpperLeft  = 0;
    gRect.LowerRight = 1;

    if(bHorizontal)
    {
      pGradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_H);
    }
    else
    {
      pGradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_V);
    }
  }
  else
  {
    BYTE StartRed   = GetRValue(StartColor);
    BYTE StartGreen = GetGValue(StartColor);
    BYTE StartBlue  = GetBValue(StartColor);

    BYTE EndRed    = GetRValue(EndColor);
    BYTE EndGreen  = GetGValue(EndColor);
    BYTE EndBlue   = GetBValue(EndColor);

    int n = (bHorizontal)?Rect.Width():Rect.Height();

    // only need for the rest, can be optimized
    {
      if(bUseSolid)
      {
        // We need a solid brush (can not be doted)
        pDC->FillSolidRect(Rect,pDC->GetNearestColor(EndColor));
      }
      else
      {
        // We need a brush (can be doted)
        CBrush TempBrush(EndColor);
        pDC->FillRect(Rect,&TempBrush);
      }
    }
    int dy = 2;
    n-=dy;
    for(int dn=0;dn<=n;dn+=dy)
    {
      BYTE ActRed   = (BYTE)(MulDiv(int(EndRed)  -StartRed,  dn,n)+StartRed);
      BYTE ActGreen = (BYTE)(MulDiv(int(EndGreen)-StartGreen,dn,n)+StartGreen);
      BYTE ActBlue  = (BYTE)(MulDiv(int(EndBlue) -StartBlue,  dn,n)+StartBlue);

      CRect TempRect;
      if(bHorizontal)
      {
        TempRect = CRect(CPoint(Rect.left+dn,Rect.top),CSize(dy,Rect.Height()));
      }
      else
      {
        TempRect = CRect(CPoint(Rect.left,Rect.top+dn),CSize(Rect.Width(),dy));
      }
      if(bUseSolid)
      {
        pDC->FillSolidRect(TempRect,pDC->GetNearestColor(RGB(ActRed,ActGreen,ActBlue)));
      }
      else
      {
        CBrush TempBrush(RGB(ActRed,ActGreen,ActBlue));
        pDC->FillRect(TempRect,&TempBrush);
      }
    }
  }
}


/////////////////////////////////////////////////////////////////////////////
// CNewMenuHook important class for subclassing menus!

class CNewMenuHook
{
  friend class CNewMenuThreadHook;
public:
  class CMenuHookData
  {
  public:
    CMenuHookData(HWND hWnd,BOOL bSpecialWnd)
      : m_dwData(bSpecialWnd),m_bDrawBorder(FALSE),m_Point(0,0),
      m_hRgn((HRGN)1),m_bDoSubclass(TRUE)
      //, m_hRightShade(NULL),m_hBottomShade(NULL),m_TimerID(0)
    {
      // Safe actual menu
      SetMenu(CNewMenuHook::m_hLastMenu);
      // Reset for the next menu
      CNewMenuHook::m_hLastMenu = NULL;

      // Save actual border setting etc.
      m_dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
      m_dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);

      //if(pSetWindowTheme)pSetWindowTheme(hWnd,L" ",L" ");
    }

    ~CMenuHookData()
    {
      if(m_hRgn!=(HRGN)1)
      {
        DeleteObject(m_hRgn);
        m_hRgn = (HRGN)1;
      }
    }

    BOOL SetMenu(HMENU hMenu)
    {
      m_hMenu = hMenu;
      if(!CNewMenu::GetNewMenuBorderAllMenu() &&
        !DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu)))
      {
        m_bDoSubclass = FALSE;
      }
      else
      {
        m_bDoSubclass = TRUE;
      }
      // When I change the backgroundcolor the borderdrawing well be wrong (scrollmenu)
      //if(IsMenu(hMenu) &&
      //    CNewMenu::GetMenuDrawMode()==CNewMenu::STYLE_XP ||
      //    CNewMenu::GetMenuDrawMode()==CNewMenu::STYLE_XP_NOBORDER )
      //{
      //  MENUINFO menuInfo;
      //  ZeroMemory(&menuInfo,sizeof(menuInfo));
      //  menuInfo.cbSize = sizeof(menuInfo);
      //  menuInfo.hbrBack = g_MenuBrush;
      //  menuInfo.fMask = MIM_BACKGROUND;
      //  ::SetMenuInfo(hMenu,&menuInfo);
      //}
      return m_bDoSubclass;
    }
    LONG_PTR m_dwStyle;
    LONG_PTR m_dwExStyle;

    CPoint m_Point;
    DWORD m_dwData; //  1=Sepcial WND, 2=Styles Changed,4=VK_ESCAPE, 8=in Print

    BOOL m_bDrawBorder;
    HMENU m_hMenu;

    CBitmap m_Screen;
    HRGN m_hRgn;

    BOOL m_bDoSubclass;

    //HWND m_hRightShade;
    //HWND m_hBottomShade;
    //UINT m_TimerID;
  };

public:
  CNewMenuHook();
  ~CNewMenuHook();

public:
  static CMenuHookData* GetMenuHookData(HWND hWnd);

  static BOOL AddTheme(CMenuTheme*);
  static CMenuTheme* RemoveTheme(DWORD dwThemeId);
  static CMenuTheme* FindTheme(DWORD dwThemeId);

private:
  static LRESULT CALLBACK NewMenuHook(int code, WPARAM wParam, LPARAM lParam);
  static BOOL CheckSubclassing(HWND hWnd,BOOL bSpecialWnd);
  static LRESULT CALLBACK SubClassMenu(HWND hWnd,  UINT uMsg, WPARAM wParam,  LPARAM lParam );
  static void UnsubClassMenu(HWND hWnd);

  static BOOL SubClassMenu2(HWND hWnd,  UINT uMsg, WPARAM wParam,  LPARAM lParam, DWORD* pResult);

public:
  static HMENU m_hLastMenu;
  static DWORD m_dwMsgPos;
  static DWORD m_bSubclassFlag;

private:
  static HMODULE m_hLibrary;
  static HMODULE m_hThemeLibrary;
  static HHOOK HookOldMenuCbtFilter;

#ifdef _TRACE_MENU_LOGFILE
  static HANDLE m_hLogFile;
#endif //_TRACE_MENU_LOGFILE

  // an map of actual opened Menu and submenu
  static CTypedPtrMap m_MenuHookData;
  // Stores list of all defined Themes
  static CTypedPtrList* m_pRegisteredThemesList;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuIconLock Helperclass for reference-counting !

class CNewMenuIconLock
{
  CNewMenuIcons* m_pIcons;

public:
  CNewMenuIconLock(CNewMenuIcons* pIcons):m_pIcons(pIcons)
  {
    m_pIcons->AddRef();
  }

  ~CNewMenuIconLock()
  {
    m_pIcons->Release();
  }
  operator CNewMenuIcons*(){return m_pIcons;}
};

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMenuIcons,CObject);

CNewMenuIcons::CNewMenuIcons()
: m_lpszResourceName(NULL),
m_hInst(NULL),
m_hBitmap(NULL),
m_nColors(0),
m_crTransparent(CLR_NONE),
m_dwRefCount(0)
{
}

CNewMenuIcons::~CNewMenuIcons()
{
  if(m_lpszResourceName && !IS_INTRESOURCE(m_lpszResourceName))
  {
    delete (LPTSTR)m_lpszResourceName;
  }
}

int CNewMenuIcons::AddRef()
{
  if(this==NULL)
    return NULL;

  return ++m_dwRefCount;
}

int CNewMenuIcons::Release()
{
  if(this==NULL)
    return NULL;

  DWORD dwCount = --m_dwRefCount;
  if(m_dwRefCount==0)
  {
    if(CNewMenu::m_pSharedMenuIcons)
    {
      POSITION pos = CNewMenu::m_pSharedMenuIcons->Find(this);
      if(pos)
      {
        CNewMenu::m_pSharedMenuIcons->RemoveAt(pos);
      }
    }
    delete this;
  }
  return dwCount;
}

#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
void CNewMenuIcons::AssertValid() const
{
  CObject::AssertValid();
}

void CNewMenuIcons::Dump(CDumpContext& dc) const
{
  CObject::Dump(dc);
  dc << _T("NewMenuIcons: ") << _T("\n");
}
#endif

BOOL CNewMenuIcons::DoMatch(LPCTSTR lpszResourceName, HMODULE hInst)
{
  if(hInst==m_hInst && lpszResourceName)
  {
    if(IS_INTRESOURCE(m_lpszResourceName))
    {
      return (lpszResourceName==m_lpszResourceName);
    }

    return (_tcscmp(lpszResourceName,m_lpszResourceName)==0);
  }
  return FALSE;
}

BOOL CNewMenuIcons::DoMatch(HBITMAP hBitmap, CSize size, UINT* pID)
{
  if(pID && m_hBitmap==hBitmap)
  {
    CSize iconSize = GetIconSize();
    if(iconSize==size)
    {
      int nCount = (int)m_IDs.GetSize();
      for(int nIndex=0 ; nIndexwBitmapID && IS_INTRESOURCE(m_lpszResourceName) &&
      ((UINT)(UINT_PTR)m_lpszResourceName)==pInfo->wBitmapID)
    {
      int nCount = (int)m_IDs.GetSize();
      WORD* pID = pInfo->ids();
      for(int nIndex=0 ; nIndexwWidth,pInfo->wHeight,MAKEINTRESOURCE(pInfo->wBitmapID)))
  {
    SetResourceName(MAKEINTRESOURCE(pInfo->wBitmapID));

    WORD* pID = pInfo->ids();
    while(*pID)
    {
      UINT nID = *(pID++);
      m_IDs.Add(nID);
      bResult = TRUE;
    }
    MakeImages();
  }
  return bResult;
}

void CNewMenuIcons::SetResourceName(LPCTSTR lpszResourceName)
{
  ASSERT_VALID(this);
  ASSERT(lpszResourceName != NULL);

  if(m_lpszResourceName && !IS_INTRESOURCE(m_lpszResourceName))
  {
    delete [](LPTSTR)m_lpszResourceName;
  }
  if( lpszResourceName && !IS_INTRESOURCE(lpszResourceName))
  {
    size_t bufSizeTchar = _tcslen(lpszResourceName)+1;
    m_lpszResourceName = new TCHAR[bufSizeTchar];
    _tcscpy_s((LPTSTR)m_lpszResourceName,bufSizeTchar,lpszResourceName);
  }
  else
  {
    m_lpszResourceName = lpszResourceName;
  }
}

BOOL CNewMenuIcons::LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst)
{
  ASSERT_VALID(this);

  SetResourceName(lpszResourceName);

  m_hInst = hInst;

  // determine location of the bitmap in resource
  if(hInst==0)
  {
    hInst = AfxFindResourceHandle(lpszResourceName, RT_TOOLBAR);
  }
  HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);

  if (hRsrc == NULL)
  { // Special purpose when you try to load it from a dll 30.05.2002
    if(AfxGetResourceHandle()!=hInst)
    {
      hInst = AfxGetResourceHandle();
      hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);
    }
    if (hRsrc == NULL)
    {
      return FALSE;
    }
  }

  HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
  if (hGlobal == NULL)
  {
    return FALSE;
  }

  CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
  if (pData == NULL)
  {
    return FALSE;
  }

  BOOL bResult = FALSE;
  ASSERT(pData->wVersion == 1);

  if(LoadBitmap(pData->wWidth,pData->wHeight,lpszResourceName,hInst))
  {
    // Remove all previous ID's
    m_IDs.RemoveAll();
    for (int i = 0; i < pData->wItemCount; i++)
    {
      UINT nID = pData->items()[i];
      if (nID)
      {
        m_IDs.Add(nID);
        bResult = TRUE;
      }
    }
  }

  UnlockResource(hGlobal);
  FreeResource(hGlobal);

  MakeImages();

  return bResult;
}

int CNewMenuIcons::AddGloomIcon(HICON hIcon, int nIndex)
{
  ICONINFO iconInfo = {0};
  if(!GetIconInfo(hIcon,&iconInfo))
  {
    return -1;
  }

  CSize size = GetIconSize();
  CDC myDC;
  myDC.CreateCompatibleDC(0);

  CBitmap bmColor;
  bmColor.Attach(iconInfo.hbmColor);
  CBitmap bmMask;
  bmMask.Attach(iconInfo.hbmMask);

  CBitmap* pOldBitmap = myDC.SelectObject(&bmColor);
  COLORREF crPixel;
  for(int i=0;iGetBitmap(&bitmap))
  {
    return -1;
  }

  if(m_IconsList.GetSafeHandle()==NULL)
  {
    m_IconsList.Create(bitmap.bmWidth,bitmap.bmHeight,ILC_COLORDDB|ILC_MASK,0,10);
  }
  else
  {
    CSize size = GetIconSize();
    // Wrong size?
    if(size.cx!=bitmap.bmWidth || size.cy!=bitmap.bmHeight)
    {
      return -1;
    }
  }
  UINT nID = 0;
  m_TranspColors.Add(crTransparent);
  m_IDs.Add(nID);
  int nIndex = m_IconsList.Add(pBitmap,crTransparent);
  HICON hIcon = m_IconsList.ExtractIcon(nIndex);
  AddGloomIcon(hIcon);
  AddGrayIcon(hIcon);
  DestroyIcon(hIcon);
  //SetBlendImage();
  return nIndex;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMenuItemData,CObject);

CNewMenuItemData::CNewMenuItemData()
: m_nTitleFlags(0),
m_nFlags(0),
m_nID(0),
m_nSyncFlag(0),
m_pData(NULL),
m_pMenuIcon(NULL),
m_nMenuIconOffset(-1)
{
}

CNewMenuItemData::~CNewMenuItemData()
{
  // it's a safe release. Do not care for NULL pointers.
  m_pMenuIcon->Release();
}

// Get the string, along with (manufactured) accelerator text.
CString CNewMenuItemData::GetString (HACCEL hAccel)
{
  if (m_nFlags & MF_POPUP )
  { // No accelerators if we're the title of a popup menu. Otherwise we get spurious accels
    hAccel = NULL;
  }

  CString s = m_szMenuText;
  int iTabIndex = s.Find ('\t');
  if (!hAccel || iTabIndex>= 0) // Got one hard coded in, or we're a popup menu
  {
    if (!hAccel && iTabIndex>= 0)
    {
      s = s.Left (iTabIndex);
    }
    return s;
  }

  // OK, we've got to go hunting through the default accelerator.
  if (hAccel == INVALID_HANDLE_VALUE)
  {
    hAccel = NULL;
    CFrameWnd *pFrame = DYNAMIC_DOWNCAST(CFrameWnd, AfxGetMainWnd ());
    // No frame. Maybe we're part of a dialog app. etc.
    if (pFrame)
    {
      hAccel = pFrame->GetDefaultAccelerator ();
    }
  }
  // No default found, or we've turned accelerators off.
  if (hAccel == NULL)
  {
    return s;
  }
  // Get the number of entries
  int nEntries = ::CopyAcceleratorTable (hAccel, NULL, 0);
  if (nEntries)
  {
    ACCEL *pAccel = (ACCEL *)_alloca(nEntries*sizeof(ACCEL));
    if (::CopyAcceleratorTable (hAccel, pAccel, nEntries))
    {
      CString sAccel;
      for (int n = 0; n < nEntries; n++)
      {
        if (pAccel [n].cmd != (WORD) m_nID)
        {
          continue;
        }
        if (!sAccel.IsEmpty ())
        {
          sAccel += _T(", ");
        }
        // Translate the accelerator into more useful code.
        if (pAccel [n].fVirt & FALT)         sAccel += _T("Alt+");
        if (pAccel [n].fVirt & FCONTROL)     sAccel += _T("Ctrl+");
        if (pAccel [n].fVirt & FSHIFT)       sAccel += _T("Shift+");
        if (pAccel [n].fVirt & FVIRTKEY)
        {
          TCHAR keyname[64];
          UINT vkey = MapVirtualKey(pAccel [n].key, 0)<<16;
          GetKeyNameText(vkey, keyname, sizeof(keyname));
          sAccel += keyname;
        }
        else
        {
          sAccel += (TCHAR)pAccel [n].key;
        }
      }
      if (!sAccel.IsEmpty ()) // We found one!
      {
        s += '\t';
        s += sAccel;
      }
    }
  }
  return s;
}

void CNewMenuItemData::SetString(LPCTSTR szMenuText)
{
  m_szMenuText = szMenuText;
}

#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
void CNewMenuItemData::AssertValid() const
{
  CObject::AssertValid();
}

void CNewMenuItemData::Dump(CDumpContext& dc) const
{
  CObject::Dump(dc);
  dc << _T("MenuItem: ") << m_szMenuText << _T("\n");
}

#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMenuItemDataTitle,CNewMenuItemData);

CNewMenuItemDataTitle::CNewMenuItemDataTitle()
: m_clrTitle(CLR_DEFAULT),
m_clrLeft(CLR_DEFAULT),
m_clrRight(CLR_DEFAULT)
{
}

CNewMenuItemDataTitle::~CNewMenuItemDataTitle()
{
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMenu,CMenu);

// actual selectet menu-draw mode
CMenuTheme* CNewMenu::m_pActMenuDrawing = NULL;
CTypedPtrList* CNewMenu::m_pSharedMenuIcons = NULL;

// Gloabal logfont for all menutitles
LOGFONT CNewMenu::m_MenuTitleFont = {16, 0, 0, 0, FW_BOLD,
0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH,_T("Arial")};


void CNewMenu::SetMenuTitleFont(CFont* pFont)
{
  ASSERT(pFont);
  pFont->GetLogFont(&m_MenuTitleFont);
}

void CNewMenu::SetMenuTitleFont(LOGFONT* pLogFont)
{
  ASSERT(pLogFont);
  m_MenuTitleFont = *pLogFont;
}

LOGFONT CNewMenu::GetMenuTitleFont()
{
  return m_MenuTitleFont;
}

DWORD CNewMenu::m_dwLastActiveItem = NULL;

// how the menu's are drawn in winXP
BOOL CNewMenu::m_bEnableXpBlending = TRUE;
BOOL CNewMenu::m_bNewMenuBorderAllMenu = TRUE;
BOOL CNewMenu::m_bSelectDisable = TRUE;
// Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
// added so the gloom value can be adjusted
// 50 is the default, may be too high, 20 is subtle
int CNewMenu::m_nGloomFactor = 50;

const Win32Type g_Shell = IsShellType();
BOOL bRemoteSession = FALSE;

// one instance of the hook for menu-subclassing
static CNewMenuHook MyNewMenuHookInstance;

CNewMenu::CNewMenu(HMENU hParent)
: m_hTempOwner(NULL),
m_hParentMenu(hParent),
m_bIsPopupMenu(TRUE),
m_dwOpenMenu(NULL),
m_LastActiveMenuRect(0,0,0,0),
m_pData(NULL),
m_hAccelToDraw((HACCEL)INVALID_HANDLE_VALUE)
{
  // O.S. - no dynamic icons by default
  m_bDynIcons = FALSE;
  // Icon sizes default to 16 x 16
  m_iconX = 16;
  m_iconY = 15;
  m_selectcheck = -1;
  m_unselectcheck = -1;
  m_checkmaps=NULL;
  m_checkmapsshare=FALSE;

  // set the color used for the transparent background in all bitmaps
  m_bitmapBackground = CLR_DEFAULT;
}

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

COLORREF CNewMenu::GetMenuColor(HMENU hMenu)
{
  if(hMenu!=NULL)
  {
    MENUINFO menuInfo={0};
    menuInfo.cbSize = sizeof(menuInfo);
    menuInfo.fMask = MIM_BACKGROUND;

    if(::GetMenuInfo(hMenu,&menuInfo) && menuInfo.hbrBack)
    {
      LOGBRUSH logBrush;
      if(GetObject(menuInfo.hbrBack,sizeof(LOGBRUSH),&logBrush))
      {
        return logBrush.lbColor;
      }
    }
  }

  if(IsShellType()==WinXP)
  {
    BOOL bFlatMenu = FALSE;
    // theme ist not checket, that must be so
    if( (SystemParametersInfo(SPI_GETFLATMENU,0,&bFlatMenu,0) && bFlatMenu==TRUE) )
    {
      return GetSysColor(COLOR_MENUBAR);
    }
  }
  return GetSysColor(COLOR_MENU);
}

COLORREF CNewMenu::GetMenuBarColorXP()
{
  // Win95 or WinNT do not support to change the menubarcolor
  if(IsShellType()==Win95 || IsShellType()==WinNT4)
  {
    return GetSysColor(COLOR_MENU);
  }
  return GetSysColor(COLOR_3DFACE);
}


HRESULT localGetCurrentThemeName( LPWSTR pszThemeFileName, int dwMaxNameChars,
                                  LPWSTR pszColorBuff,     int cchMaxColorChars,
                                  LPWSTR pszSizeBuff,      int cchMaxSizeChars)
{
  static CNewLoadLib menuInfo(_T("UxTheme.dll"),"GetCurrentThemeName");
  if(menuInfo.m_pProg)
  {
   typedef HRESULT (WINAPI* FktGetCurrentThemeName)(LPWSTR pszThemeFileName,int dwMaxNameChars, LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszSizeBuff, int cchMaxSizeChars);
    return ((FktGetCurrentThemeName)menuInfo.m_pProg)(pszThemeFileName, dwMaxNameChars, pszColorBuff, cchMaxColorChars, pszSizeBuff, cchMaxSizeChars);
  }
  return NULL;
}

HANDLE localGetWindowTheme(HWND hWnd)
{
  static CNewLoadLib menuInfo(_T("UxTheme.dll"),"GetWindowTheme");
  if(menuInfo.m_pProg)
  {
    typedef HANDLE (WINAPI* FktGetWindowTheme)(HWND hWnd);
    return ((FktGetWindowTheme)menuInfo.m_pProg)(hWnd);
  }
  return NULL;
}

HANDLE localOpenThemeData( HWND hWnd, LPCWSTR pszClassList)
{
  static CNewLoadLib menuInfo(_T("UxTheme.dll"),"OpenThemeData");
  if(menuInfo.m_pProg)
  {
    typedef HANDLE (WINAPI* FktOpenThemeData)(HWND hWnd, LPCWSTR pszClassList);
    return ((FktOpenThemeData)menuInfo.m_pProg)(hWnd,pszClassList);
  }
  return NULL;
}

HRESULT localCloseThemeData(HANDLE hTheme)
{
  static CNewLoadLib menuInfo(_T("UxTheme.dll"),"CloseThemeData");
  if(menuInfo.m_pProg)
  {
    typedef HRESULT (WINAPI* FktCloseThemeData)(HANDLE hTheme);
    return ((FktCloseThemeData)menuInfo.m_pProg)(hTheme);
  }
  return NULL;
}

HRESULT localGetThemeColor(HANDLE hTheme,
    int iPartId,
    int iStateId,
    int iColorId,
    COLORREF *pColor)
{
  static CNewLoadLib menuInfo(_T("UxTheme.dll"),"GetThemeColor");
  if(menuInfo.m_pProg)
  {
    typedef HRESULT (WINAPI* FktGetThemeColor)(HANDLE hTheme,int iPartId,int iStateId,int iColorId, COLORREF *pColor);
    return ((FktGetThemeColor)menuInfo.m_pProg)(hTheme, iPartId, iStateId, iColorId, pColor);
  }
  return S_FALSE;
}



COLORREF CNewMenu::GetMenuBarColor2003()
{
  COLORREF colorLeft,colorRight;
  GetMenuBarColor2003(colorLeft,colorRight);
  return colorLeft;
}

void CNewMenu::GetMenuBarColor2003(COLORREF& color1, COLORREF& color2, BOOL bBackgroundColor /* = TRUE */)
{
  // Win95 or WinNT do not support to change the menubarcolor
  if(IsShellType()==Win95 || IsShellType()==WinNT4)
  {
    color1 = color2 = GetSysColor(COLOR_MENU);
    return;
  }

  if(GetMenuDrawMode()==STYLE_COLORFUL_NOBORDER ||  GetMenuDrawMode()==STYLE_COLORFUL)
  {
    COLORREF colorWindow = DarkenColor(10,GetSysColor(COLOR_WINDOW));
    COLORREF colorCaption = GetSysColor(COLOR_ACTIVECAPTION);

    CClientDC myDC(NULL);
    COLORREF nearColor = myDC.GetNearestColor(MidColor(colorWindow,colorCaption));

    // some colorscheme corrections (Andreas Scher)
    if (nearColor == 15779244) //standartblau
    { //entspricht (haar-)genau office 2003
      nearColor = RGB(163,194,245);
    }
    else if (nearColor == 15132390) //standartsilber
    {
      nearColor = RGB(215,215,229);
    }
    else if (nearColor == 13425878) //olivgr
    {
      nearColor = RGB(218,218,170);
    }

    color1 = nearColor;
    color2 = LightenColor(110,color1);
    return;
  }
  else
  {
    if (IsMenuThemeActive())
    {
      COLORREF colorWindow = DarkenColor(10,GetSysColor(COLOR_WINDOW));
      COLORREF colorCaption = GetSysColor(COLOR_ACTIVECAPTION);

      //CWnd* pWnd = AfxGetMainWnd();
      //if (pWnd)
      {
        //HANDLE hTheme = localOpenThemeData(pWnd->GetSafeHwnd(),L"Window");
        // get the them from desktop window
        HANDLE hTheme = localOpenThemeData(NULL,L"Window");
        if(hTheme)
        {
          COLORREF color = CLR_NONE;
          // defined in Tmschema.h
          //    TM_PART(1, WP, CAPTION)
          //    TM_STATE(1, CS, ACTIVE)
          //    TM_PROP(204, TMT, COLOR,     COLOR)
          //for (int iColorID=0;iColorID<6000;iColorID++)
          //{
          //  if(localGetThemeColor(hTheme,1,1,iColorID,&color)==S_OK)
          //  {
          //    colorCaption = color;
          //  }
          //}

          // TM_PROP(3804, TMT, EDGELIGHTCOLOR,     COLOR)     // edge color
          // TM_PROP(3821, TMT, FILLCOLORHINT, COLOR)          // hint about fill color used (for custom controls)
          if(localGetThemeColor(hTheme,1,1,3821,&color)==S_OK && (color!=1))
          {
            colorCaption = color;
          }
          //TM_PROP(3805, TMT, EDGEHIGHLIGHTCOLOR, COLOR)     // edge color
          if(localGetThemeColor(hTheme,1,1,3805,&color)==S_OK && (color!=1))
          {
            colorWindow = color;
          }
          localCloseThemeData(hTheme);

          // left side Menubar
          switch(colorCaption)
          {
          case 0x00e55400: // blue
            color1 = RGB(163,194,245);
            break;

          case 0x00bea3a4:  // silver
            color1 = RGB(215,215,229);
            break;

          case 0x0086b8aa:  //olive green
            color1 = RGB(218,218,170);
            break;

          default:
            {
              CClientDC myDC(NULL);
              color1 = myDC.GetNearestColor(MidColor(colorWindow,colorCaption));
            }
            break;
          }

          if (bBackgroundColor)
          {
            color2 = LightenColor(110,color1);
          }
          else
          {
            color2 = LightenColor(200,color1);
            color1 = DarkenColor(20,color1);
          }
          return;
        }
      }

      CClientDC myDC(NULL);
      COLORREF nearColor = myDC.GetNearestColor(MidColor(colorWindow,colorCaption));

      // some colorscheme corrections (Andreas Sch鋜er)
      if (nearColor == 15779244) //standartblau
      { //entspricht (haar-)genau office 2003
        color1 = RGB(163,194,245);
      }
      else if (nearColor == 15132390) //standartsilber
      {
        color1 = RGB(215,215,229);
      }
      else if (nearColor == 13425878) //olivgr黱
      {
        color1 = RGB(218,218,170);
      }
      else
      {
        color1 = nearColor;
      }

      if (bBackgroundColor)
      {
        color2 = LightenColor(100,color1);
      }
      else
      {
        color2 = LightenColor(200,color1);
        color1 = DarkenColor(20,color1);
      }
    }
    else
    {
      //color1 = ::GetSysColor(COLOR_MENU);
      color1 = ::GetSysColor(COLOR_BTNFACE); // same as COLOR_3DFACE
      color2 = ::GetSysColor(COLOR_WINDOW);
      color2 =  GetAlphaBlendColor(color1,color2,220);
    }
  }
}

COLORREF CNewMenu::GetMenuBarColor(HMENU hMenu)
{
  if(hMenu!=NULL)
  {
    MENUINFO menuInfo = {0};
    menuInfo.cbSize = sizeof(menuInfo);
    menuInfo.fMask = MIM_BACKGROUND;

    if(::GetMenuInfo(hMenu,&menuInfo) && menuInfo.hbrBack)
    {
      LOGBRUSH logBrush;
      if(GetObject(menuInfo.hbrBack,sizeof(LOGBRUSH),&logBrush))
      {
        return logBrush.lbColor;
      }
    }
  }
  if(IsShellType()==WinXP)
  {
    BOOL bFlatMenu = FALSE;
    if((SystemParametersInfo(SPI_GETFLATMENU,0,&bFlatMenu,0) && bFlatMenu==TRUE) ||
      (IsMenuThemeActive()))
    {
      return GetSysColor(COLOR_MENUBAR);
    }
  }
  // May-05-2005 - Mark P. Peterson ([email protected]) - Changed to use the menubar color, I could not find why COLOR_MENU should
  // be used when not flat and no XP Theme is active.  The problem is that using this shows the wrong color in any other theme, when
  // the background color of menus is something other than the same color of the menu bar.
  return (GetMenuBarColorXP());
//  return GetSysColor(COLOR_MENU);
}

void CNewMenu::SetLastMenuRect(HDC hDC, LPRECT pRect)
{
  if(!m_bIsPopupMenu)
  {
    HWND hWnd = WindowFromDC(hDC);
    if(hWnd && pRect)
    {
      CRect Temp;
      GetWindowRect(hWnd,Temp);
      m_LastActiveMenuRect = *pRect;
      m_LastActiveMenuRect.OffsetRect(Temp.TopLeft());
#ifdef _TRACE_MENU_
      AfxTrace(_T("ActiveRect: (%ld,%ld,%ld,%ld)\n"),m_LastActiveMenuRect.left,m_LastActiveMenuRect.top,m_LastActiveMenuRect.right,m_LastActiveMenuRect.bottom);
#endif
    }
  }
}

void CNewMenu::SetLastMenuRect(LPRECT pRect)
{
  ASSERT(pRect);
  m_LastActiveMenuRect = *pRect;
}

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

BOOL CNewMenu::OnMeasureItem(const MSG* pMsg)
{
  if(pMsg->message==WM_MEASUREITEM)
  {
    LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)pMsg->lParam;
    if(lpMIS->CtlType==ODT_MENU)
    {
      CMenu* pMenu=NULL;
      if(::IsMenu(UIntToHMenu(lpMIS->itemID)) )
      {
        pMenu = CMenu::FromHandlePermanent(UIntToHMenu(lpMIS->itemID) );
      }
      else
      {
        _AFX_THREAD_STATE* pThreadState = AfxGetThreadState ();
        if (pThreadState->m_hTrackingWindow == pMsg->hwnd)
        {
          // start from popup
          pMenu = FindPopupMenuFromIDData(pThreadState->m_hTrackingMenu,lpMIS->itemID,lpMIS->itemData);
        }
        if(pMenu==NULL)
        {
          // start from menubar
          pMenu = FindPopupMenuFromIDData(::GetMenu(pMsg->hwnd),lpMIS->itemID,lpMIS->itemData);
          if(pMenu==NULL)
          {
            // finaly start from system menu.
            pMenu = FindPopupMenuFromIDData(::GetSystemMenu(pMsg->hwnd,FALSE),lpMIS->itemID,lpMIS->itemData);

#ifdef USE_NEW_MENU_BAR
            if(!pMenu)
            { // Support for new menubar
              static UINT WM_GETMENU = ::RegisterWindowMessage(_T("CNewMenuBar::WM_GETMENU"));
              pMenu = FindPopupMenuFromIDData((HMENU)::SendMessage(pMsg->hwnd,WM_GETMENU,0,0),lpMIS->itemID,lpMIS->itemData);
            }
#endif
          }
        }
      }
      if(pMenu!=NULL)
      {
#ifdef _TRACE_MENU_
        UINT oldWidth = lpMIS->itemWidth;
#endif //_TRACE_MENU_

        pMenu->MeasureItem(lpMIS);

#ifdef _TRACE_MENU_
        AfxTrace(_T("NewMenu MeasureItem: ID:0x08%X, oW:0x%X, W:0x%X, H:0x%X\n"),lpMIS->itemID,oldWidth,lpMIS->itemWidth,lpMIS->itemHeight);
#endif //_TRACE_MENU_
        return TRUE;
      }
    }
  }
  return FALSE;
}

CMenu* CNewMenu::FindPopupMenuFromID(HMENU hMenu, UINT nID)
{
  // check for a valid menu-handle
  if ( ::IsMenu(hMenu))
  {
    CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
    if(pMenu)
    {
      return FindPopupMenuFromID(pMenu,nID);
    }
  }
  return NULL;
}

CMenu* CNewMenu::FindPopupMenuFromIDData(HMENU hMenu, UINT nID, ULONG_PTR pData)
{
  // check for a valid menu-handle
  if ( ::IsMenu(hMenu))
  {
    CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
    if(pMenu)
    {
      return FindPopupMenuFromIDData(pMenu,nID,pData);
    }
  }
  return NULL;
}

CMenu* CNewMenu::FindPopupMenuFromIDData(CMenu* pMenu, UINT nID, ULONG_PTR pData)
{
  if(!pMenu || !IsMenu(pMenu->m_hMenu))
  {
    return NULL;
  }
  ASSERT_VALID(pMenu);
  // walk through all items, looking for ID match
  UINT nItems = pMenu->GetMenuItemCount();
  for (int iItem = 0; iItem < (int)nItems; iItem++)
  {
    CMenu* pPopup = pMenu->GetSubMenu(iItem);
    if (pPopup!=NULL)
    {
      // recurse to child popup
      pPopup = FindPopupMenuFromIDData(pPopup, nID, pData);
      // check popups on this popup
      if (pPopup != NULL)
      {
        return pPopup;
      }
    }
    else if (pMenu->GetMenuItemID(iItem) == nID)
    {
      MENUITEMINFO MenuItemInfo = {0};
      MenuItemInfo.cbSize = sizeof(MenuItemInfo);
      MenuItemInfo.fMask = MIIM_DATA;

      if(pMenu->GetMenuItemInfo(iItem,&MenuItemInfo,TRUE))
      {
        if(MenuItemInfo.dwItemData==pData)
        {
          // it is a normal item inside our popup
          return pMenu;
        }
      }
    }
  }
  // not found
  return NULL;
}

CMenu* CNewMenu::FindPopupMenuFromID(CMenu* pMenu, UINT nID)
{
  if(!pMenu || !IsMenu(pMenu->m_hMenu))
  {
    return NULL;
  }
  ASSERT_VALID(pMenu);
  // walk through all items, looking for ID match
  UINT nItems = pMenu->GetMenuItemCount();
  for (int iItem = 0; iItem < (int)nItems; iItem++)
  {
    CMenu* pPopup = pMenu->GetSubMenu(iItem);
    if (pPopup != NULL)
    {
      // recurse to child popup
      pPopup = FindPopupMenuFromID(pPopup, nID);
      // check popups on this popup
      if (pPopup != NULL)
      {
        return pPopup;
      }
    }
    else if (pMenu->GetMenuItemID(iItem) == nID)
    {
      // it is a normal item inside our popup
      return pMenu;
    }
  }
  // not found
  return NULL;
}

BOOL CNewMenu::DestroyMenu()
{
  // Destroy Sub menus:
  int nIndex = (int)m_SubMenus.GetSize();
  while(nIndex--)
  {
    // Destroy only if we createt it!!!!!
    CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_SubMenus[nIndex]));
    if(pMenu)
    {
      delete pMenu;
    }
  }
  m_SubMenus.RemoveAll();

  // Destroy menu data
  nIndex = (int)m_MenuItemList.GetSize();
  while(nIndex--)
  {
    delete(m_MenuItemList[nIndex]);
  }
  m_MenuItemList.RemoveAll();

  if(m_checkmaps&&!m_checkmapsshare)
  {
    delete m_checkmaps;
    m_checkmaps=NULL;
  }
  // Call base-class implementation last:
  return(CMenu::DestroyMenu());
};

UINT CNewMenu::GetMenuDrawMode()
{
  ASSERT(m_pActMenuDrawing);
  return m_pActMenuDrawing->m_dwThemeId;
}

UINT CNewMenu::SetMenuDrawMode(UINT mode)
{
#ifdef _TRACE_MENU_
  if(mode&1)
  {
    AfxTrace(_T("\nDraw menu no border\n"));
  }
  else
  {
    AfxTrace(_T("\nDraw menu with border\n"));
  }
#endif //  _TRACE_MENU_

  // under wine we disable flat menu and shade drawing
  if(bWine)
  {
    switch(mode)
    {
    case STYLE_ORIGINAL:
      mode = STYLE_ORIGINAL_NOBORDER;
      break;

    case STYLE_XP:
      mode = STYLE_XP_NOBORDER;
      break;

    case STYLE_SPECIAL:
      mode = STYLE_SPECIAL_NOBORDER;
      break;

    case STYLE_ICY:
      mode = STYLE_ICY_NOBORDER;
      break;

    case STYLE_XP_2003:
      mode = STYLE_XP_2003_NOBORDER;
      break;

    case STYLE_COLORFUL:
      mode = STYLE_COLORFUL_NOBORDER;
      break;
    }
  }

  UINT nOldMode = (UINT)STYLE_UNDEFINED;
  CMenuTheme* pTheme = CNewMenuHook::FindTheme(mode);
  if(pTheme)
  {
    if(m_pActMenuDrawing)
    {
      nOldMode = m_pActMenuDrawing->m_dwThemeId;
    }

    m_pActMenuDrawing = pTheme;
  }
  return nOldMode;
}

HMENU CNewMenu::GetParent()
{
  return m_hParentMenu;
}

BOOL CNewMenu::IsPopup()
{
  return m_bIsPopupMenu;
}

BOOL CNewMenu::SetPopup(BOOL bIsPopup)
{
  BOOL bOldFlag = m_bIsPopupMenu;
  m_bIsPopupMenu = bIsPopup;
  return bOldFlag;
}

BOOL CNewMenu::SetSelectDisableMode(BOOL mode)
{
  BOOL bOldMode = m_bSelectDisable;
  m_bSelectDisable=mode;
  return bOldMode;
}

BOOL CNewMenu::GetSelectDisableMode()
{
  return m_bSelectDisable;
}

BOOL CNewMenu::SetXpBlending(BOOL bEnable)
{
  BOOL bOldMode = m_bEnableXpBlending;
  m_bEnableXpBlending = bEnable;
  return bOldMode;
}

BOOL CNewMenu::GetXpBlending()
{
  return m_bEnableXpBlending;
}


// Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
// added SetGloomFactor() and GetGloomFactor() so that the glooming can be done in a more or less subtle way
int CNewMenu::SetGloomFactor(int nGloomFactor)
{
  int nOldGloomFactor = m_nGloomFactor;

  // set the new gloom factor
  m_nGloomFactor = nGloomFactor;

  // return the previous gloom factor
  return (nOldGloomFactor);
} // SetGloomFactor


int CNewMenu::GetGloomFactor()
{
  // return the current gloom factor
  return (m_nGloomFactor);
} // GetGloomFactor


// Function to set how default menu border were drawn
//(enable=TRUE means that all menu in the application has the same border)
BOOL CNewMenu::SetNewMenuBorderAllMenu(BOOL bEnable /* =TRUE*/)
{
  BOOL bOldMode = m_bNewMenuBorderAllMenu;
  m_bNewMenuBorderAllMenu = bEnable;
  return bOldMode;
}

BOOL CNewMenu::GetNewMenuBorderAllMenu()
{
  return m_bNewMenuBorderAllMenu;
}

void CNewMenu::OnSysColorChange()
{
  static DWORD dwLastTicks = 0;
  DWORD dwAktTicks = GetTickCount();

  // Last Update 2 sec
  if((dwAktTicks-dwLastTicks)>2000)
  {
    dwLastTicks = dwAktTicks;
    if(m_pSharedMenuIcons)
    {
      POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
      while(pos)
      {
        CNewMenuIcons* pMenuIcons = m_pSharedMenuIcons->GetNext(pos);
        pMenuIcons->OnSysColorChange();
      }
    }
  }
}

void CNewMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
  ASSERT(m_pActMenuDrawing);

  BOOL bIsMenuBar = IsMenuBar(UIntToHMenu(lpMIS->itemID));
  if(!bIsMenuBar && m_hParentMenu && !FindMenuItem(lpMIS->itemID)) //::IsMenu(UIntToHMenu(lpMIS->itemID)) )
  {
    CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_hParentMenu));
    if(pMenu)
    {
      ((*pMenu).*m_pActMenuDrawing->m_pMeasureItem)(lpMIS,bIsMenuBar);
      return;
    }
  }
  ((*this).*m_pActMenuDrawing->m_pMeasureItem)(lpMIS,bIsMenuBar);
}

void CNewMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
  ASSERT(m_pActMenuDrawing);

  BOOL bIsMenuBar = m_hParentMenu ? FALSE: ((m_bIsPopupMenu)?FALSE:TRUE);

  if(bIsMenuBar && m_dwLastActiveItem==lpDIS->itemData)
  {
    if(! (lpDIS->itemState&ODS_HOTLIGHT) )
    {
      // Mark for redraw helper for win 98
      m_dwLastActiveItem = NULL;
    }
  }

  (this->*m_pActMenuDrawing->m_pDrawItem)(lpDIS,bIsMenuBar);
}

// Erase the Background of the menu
BOOL CNewMenu::EraseBkgnd(HWND hWnd, HDC hDC)
{
  CDC* pDC = CDC::FromHandle (hDC);
  CRect Rect;
  //  Get the size of the menu...
  GetClientRect(hWnd, Rect );
  pDC->FillSolidRect (Rect,GetMenuColor());

  return TRUE;
}

void CNewMenu::DrawTitle(LPDRAWITEMSTRUCT lpDIS,BOOL bIsMenuBar)
{
  ASSERT(m_pActMenuDrawing);
  (this->*m_pActMenuDrawing->m_pDrawTitle)(lpDIS,bIsMenuBar);
}

void CNewMenu::DrawMenuTitle(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
  UNREFERENCED_PARAMETER(bIsMenuBar);

  CDC* pDC = CDC::FromHandle(lpDIS->hDC);

  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  ASSERT(pMenuData);

  COLORREF colorWindow = GetSysColor(COLOR_WINDOW);
  COLORREF colorMenuBar = GetMenuColor();

  COLORREF colorLeft = MixedColor(colorWindow,colorMenuBar);
  COLORREF colorRight = ::GetSysColor(COLOR_ACTIVECAPTION);
  COLORREF colorText = ::GetSysColor(COLOR_CAPTIONTEXT);

  CSize iconSize(0,0);
  if(pMenuData->m_nMenuIconOffset!=(-1) && pMenuData->m_pMenuIcon)
  {
    iconSize = pMenuData->m_pMenuIcon->GetIconSize();
    if(iconSize!=CSize(0,0))
    {
      iconSize += CSize(4,4);
    }
  }

  CNewMenuItemDataTitle* pItem = DYNAMIC_DOWNCAST(CNewMenuItemDataTitle,pMenuData);
  if(pItem)
  {
    if(pItem->m_clrRight!=CLR_DEFAULT)
    {
      colorRight = pItem->m_clrRight;
    }
    if(pItem->m_clrLeft!=CLR_DEFAULT)
    {
      colorLeft = pItem->m_clrLeft;
    }
    if(pItem->m_clrTitle!=CLR_DEFAULT)
    {
      colorText = pItem->m_clrTitle;
    }
  }

  CRect rcClipBox;

  HWND hWnd = ::WindowFromDC(lpDIS->hDC);
  // try to get the real size of the client window
  if(hWnd==NULL || !GetClientRect(hWnd,rcClipBox) )
  {
    // when we have menu animation the DC is a memory DC
    pDC->GetClipBox(rcClipBox);
  }

  // draw the title bar
  CRect rect = lpDIS->rcItem;
  CPoint TextPoint;

  CFont Font;
  LOGFONT MyFont = m_MenuTitleFont;
  if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  {
    rect.top = rcClipBox.top;
    rect.bottom = rcClipBox.bottom;
    rect.right += GetSystemMetrics(SM_CXMENUCHECK);
    MyFont.lfOrientation = 900;
    MyFont.lfEscapement = 900;
    TextPoint = CPoint(rect.left+2, rect.bottom-4-iconSize.cy);
  }
  else
  {
    MyFont.lfOrientation = 0;
    MyFont.lfEscapement = 0;

    TextPoint = CPoint(rect.left+2+iconSize.cx, rect.top);
  }
  Font.CreateFontIndirect(&MyFont);
  CFont *pOldFont = pDC->SelectObject(&Font);
  SIZE size = {0,0};
  VERIFY(::GetTextExtentPoint32(pDC->m_hDC,pMenuData->m_szMenuText,pMenuData->m_szMenuText.GetLength(),&size));
  COLORREF oldColor = pDC->SetTextColor(colorText);
  int OldMode = pDC->SetBkMode(TRANSPARENT);

  if(pMenuData->m_nTitleFlags&MFT_GRADIENT)
  {
    if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
    {
      DrawGradient(pDC,rect,colorLeft,colorRight,false);
    }
    else
    {
      DrawGradient(pDC,rect,colorRight,colorLeft,true);
    }
  }
  else
  {
    if(pMenuData->m_nTitleFlags&MFT_ROUND)
    {
      if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
      {
        TextPoint.y-=2;
        rect.right = rect.left+size.cy+4;
      }
      else
      {
        int maxSpace = ((rect.Width()-size.cx)/2);
        TextPoint.x+=min(maxSpace,10);
      }

      CBrush brush(colorRight);
      CPen* pOldPen = (CPen*)pDC->SelectStockObject(WHITE_PEN);
      CBrush* pOldBrush = pDC->SelectObject(&brush);

      pDC->RoundRect(rect,CPoint(10,10));
      pDC->SelectObject(pOldBrush);
      pDC->SelectObject(pOldPen);
    }
    else
    {
      pDC->FillSolidRect(rect,colorRight);
    }
  }
  if (pMenuData->m_nTitleFlags&MFT_SUNKEN)
  {
    pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  }

  if (pMenuData->m_nTitleFlags&MFT_CENTER)
  {
    if (pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
    {
      TextPoint.y = rect.bottom - ((rect.Height()-size.cx-iconSize.cy)>>1)-iconSize.cy;
    }
    else
    {
      TextPoint.x = rect.left + ((rect.Width()-size.cx-iconSize.cx)>>1)+iconSize.cx;
    }
  }

  pDC->TextOut(TextPoint.x,TextPoint.y, pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL));

  if(pMenuData->m_nMenuIconOffset!=(-1) && pMenuData->m_pMenuIcon)
  {
    CPoint ptImage = TextPoint;
    if (pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
    {
      ptImage.y += 2;
    }
    else
    {
      ptImage.x -= iconSize.cx;
      ptImage.y += 2;
    }
    // draws the icon
    HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
    pDC->DrawState(ptImage, iconSize-CSize(4,4), hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
    DestroyIcon(hDrawIcon2);
  }

  if(pMenuData->m_nTitleFlags&MFT_LINE)
  {
    if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
    {
      CRect rect2(rect.left+20,rect.top+5,rect.left+22,rect.bottom-5);
      pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
      rect2.OffsetRect(3,0);
      rect2.InflateRect(0,-10);
      pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
    }
    else
    {
      CRect rect2(rect.left+2,rect.bottom-7,rect.right-2,rect.bottom-5);
      pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
      rect2.OffsetRect(0,3);
      rect2.InflateRect(-10,0);
      pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
    }
  }
  pDC->SetBkMode(OldMode);
  pDC->SetTextColor(oldColor);
  pDC->SelectObject(pOldFont);
}

void CNewMenu::DrawItem_WinXP(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
  ASSERT(lpDIS != NULL);

  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  ASSERT(pMenuData);

  UINT nFlags = pMenuData->m_nFlags;

  CNewMemDC memDC(&lpDIS->rcItem,lpDIS->hDC);
  CDC* pDC;
  if( bIsMenuBar || (nFlags&MF_SEPARATOR) )
  { // For title and menubardrawing disable memory painting
    memDC.DoCancel();
    pDC = CDC::FromHandle(lpDIS->hDC);
  }
  else
  {
    pDC = &memDC;
  }

  COLORREF colorWindow = GetSysColor(COLOR_WINDOW);
  //  COLORREF colorMenuBar = bIsMenuBar?GetMenuBarColor(m_hMenu):GetMenuColor();
  COLORREF colorMenuBar = GetMenuBarColor(m_hMenu);
  COLORREF colorMenu = MixedColor(colorWindow,colorMenuBar);
  COLORREF colorBitmap = MixedColor(GetMenuBarColor(m_hMenu),colorWindow);
  COLORREF colorSel = GetXpHighlightColor();
  COLORREF colorBorder = GetSysColor(COLOR_HIGHLIGHT);//DarkenColor(128,colorMenuBar);

  if(bHighContrast)
  {
    colorBorder = GetSysColor(COLOR_BTNTEXT);
  }

  if (NumScreenColors() <= 256)
  {
    colorBitmap = GetSysColor(COLOR_BTNFACE);
  }

  // Better contrast when you have less than 256 colors
  if(pDC->GetNearestColor(colorMenu)==pDC->GetNearestColor(colorBitmap))
  {
    colorMenu = colorWindow;
    colorBitmap = colorMenuBar;
  }

  //CPen Pen(PS_SOLID,0,GetSysColor(COLOR_HIGHLIGHT));
  CPen Pen(PS_SOLID,0,colorBorder);

  if(bIsMenuBar)
  {
#ifdef _TRACE_MENU_
    //   AfxTrace(_T("BarState: 0x%lX Menus %ld\n"),lpDIS->itemState,m_dwOpenMenu);
#endif
    if(!IsMenu(UIntToHMenu(lpDIS->itemID)) && (lpDIS->itemState&ODS_SELECTED_OPEN))
    {
      lpDIS->itemState = (lpDIS->itemState&~(ODS_SELECTED|ODS_SELECTED_OPEN))|ODS_HOTLIGHT;
    }
    else if(!(lpDIS->itemState&ODS_SELECTED_OPEN) && !m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
    {
      lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
    }
    if(!(lpDIS->itemState&ODS_HOTLIGHT))
    {
      colorSel = colorBitmap;
    }
    colorMenu = colorMenuBar;
  }

  CBrush m_brSel(colorSel);
  CBrush m_brBitmap(colorBitmap);

  CRect RectIcon(lpDIS->rcItem);
  CRect RectText(lpDIS->rcItem);
  CRect RectSel(lpDIS->rcItem);

  if(bIsMenuBar)
  {
    RectText.InflateRect (0,0,0,0);
    if(lpDIS->itemState&ODS_DRAW_VERTICAL)
      RectSel.InflateRect (0,0,0, -4);
    else
      RectSel.InflateRect (0,0,-2 -2,0);
  }
  else
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectIcon.left = RectIcon.right - (m_iconX + 8);
      RectText.right  = RectIcon.left;
    }
    else
    {
      RectIcon.right = RectIcon.left + m_iconX + 8;
      RectText.left  = RectIcon.right;
    }
    // Draw for Bitmapbackground
    pDC->FillSolidRect (RectIcon,colorBitmap);
  }
  // Draw for Textbackground
  pDC->FillSolidRect (RectText,colorMenu);

  // Spacing for submenu only in popups
  if(!bIsMenuBar)
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectText.left += 15;
      RectText.right -= 4;
    }
    else
    {
      RectText.left += 4;
      RectText.right -= 15;
    }
  }

  //  Flag for highlighted item
  if(lpDIS->itemState & (ODS_HOTLIGHT|ODS_INACTIVE) )
  {
    lpDIS->itemState |= ODS_SELECTED;
  }

  if(bIsMenuBar && (lpDIS->itemState&ODS_SELECTED) )
  {
    if(!(lpDIS->itemState&ODS_INACTIVE) )
    {
      SetLastMenuRect(lpDIS->hDC,RectSel);
      if(!(lpDIS->itemState&ODS_HOTLIGHT) )
      {
        // Create a new pen for the special color
        Pen.DeleteObject();
        colorBorder = bHighContrast?GetSysColor(COLOR_BTNTEXT):DarkenColor(128,GetMenuBarColor());
        Pen.CreatePen(PS_SOLID,0,colorBorder);

        int X,Y;
        CRect rect = RectText;
        int winH = rect.Height();

        // Simulate a shadow on right edge...
        if (NumScreenColors() <= 256)
        {
          DWORD clr = GetSysColor(COLOR_BTNSHADOW);
          if(lpDIS->itemState&ODS_DRAW_VERTICAL)
          {
            int winW = rect.Width();
            for (Y=0; Y<=1 ;Y++)
            {
              for (X=4; X<=(winW-1) ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y,clr);
              }
            }
          }
          else
          {
            for (X=3; X<=4 ;X++)
            {
              for (Y=4; Y<=(winH-1) ;Y++)
              {
                pDC->SetPixel(rect.right - X, Y+rect.top, clr );
              }
            }
          }
        }
        else
        {
          if(lpDIS->itemState&ODS_DRAW_VERTICAL)
          {
            int winW = rect.Width();
            COLORREF barColor = pDC->GetPixel(rect.left+4,rect.bottom-4);
            for (Y=1; Y<=4 ;Y++)
            {
              for (X=0; X<4 ;X++)
              {
                if(barColor==CLR_INVALID)
                {
                  barColor = pDC->GetPixel(rect.left+X,rect.bottom-Y);
                }
                pDC->SetPixel(rect.left+X,rect.bottom-Y,colorMenuBar);
              }
              for (X=4; X<8 ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y,DarkenColor(2* 3 * Y * (X - 3), colorMenuBar));
              }
              for (X=8; X<=(winW-1) ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y, DarkenColor(2*15 * Y, colorMenuBar) );
              }
            }
          }
          else
          {
            for (X=1; X<=4 ;X++)
            {
              for (Y=0; Y<4 ;Y++)
              {
                pDC->SetPixel(rect.right-X,Y+rect.top, colorMenuBar );
              }
              for (Y=4; Y<8 ;Y++)
              {
                pDC->SetPixel(rect.right-X,Y+rect.top,DarkenColor(2* 3 * X * (Y - 3), colorMenuBar));
              }
              for (Y=8; Y<=(winH-1) ;Y++)
              {
                pDC->SetPixel(rect.right - X, Y+rect.top, DarkenColor(2*15 * X, colorMenuBar) );
              }
            }
          }
        }
      }
    }
  }
  // For keyboard navigation only
  BOOL bDrawSmallSelection = FALSE;
  // remove the selected bit if it's grayed out
  if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable)
  {
    if( lpDIS->itemState & ODS_SELECTED )
    {
      lpDIS->itemState = lpDIS->itemState & (~ODS_SELECTED);
      DWORD MsgPos = ::GetMessagePos();
      if( MsgPos==CNewMenuHook::m_dwMsgPos )
      {
        bDrawSmallSelection = TRUE;
      }
      else
      {
        CNewMenuHook::m_dwMsgPos = MsgPos;
      }
    }
  }

  // Draw the seperator
  if( nFlags & MF_SEPARATOR )
  {
    if( pMenuData->m_nTitleFlags&MFT_TITLE )
    {
      DrawTitle(lpDIS,bIsMenuBar);
    }
    else
    {
      // Draw only the seperator
      CRect rect;
      rect.top = RectText.CenterPoint().y;
      rect.bottom = rect.top+1;
      if(nFlags&MFT_RIGHTORDER)
      {
        rect.right = RectText.right;
        rect.left = lpDIS->rcItem.left;
      }
      else
      {
      rect.right = lpDIS->rcItem.right;
        rect.left = RectText.left;
      }
      pDC->FillSolidRect(rect,GetSysColor(COLOR_GRAYTEXT));
    }
  }
  else
  {
    if( (lpDIS->itemState & ODS_SELECTED) && !(lpDIS->itemState&ODS_INACTIVE) )
    {
      pDC->FillSolidRect(RectSel,colorSel);
      // Draw the selection
      CPen* pOldPen = pDC->SelectObject(&Pen);
      CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
      pDC->Rectangle(RectSel);
      pDC->SelectObject(pOldBrush);
      pDC->SelectObject(pOldPen);
    }
    else if (bDrawSmallSelection)
    {
      pDC->FillSolidRect(RectSel,colorMenu);
      // Draw the selection for keyboardnavigation
      CPen* pOldPen = pDC->SelectObject(&Pen);
      CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
      pDC->Rectangle(RectSel);
      pDC->SelectObject(pOldBrush);
      pDC->SelectObject(pOldPen);
    }

    UINT state = lpDIS->itemState;

    BOOL standardflag=FALSE;
    BOOL selectedflag=FALSE;
    BOOL disableflag=FALSE;
    BOOL checkflag=FALSE;

    CString strText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);

    if( (state&ODS_CHECKED) && (pMenuData->m_nMenuIconOffset<0) )
    {
      if(state&ODS_SELECTED && m_selectcheck>0)
      {
        checkflag=TRUE;
      }
      else if(m_unselectcheck>0)
      {
        checkflag=TRUE;
      }
    }
    else if(pMenuData->m_nMenuIconOffset != -1)
    {
      standardflag=TRUE;
      if(state&ODS_SELECTED)
      {
        selectedflag=TRUE;
      }
      else if(state&ODS_GRAYED)
      {
        disableflag=TRUE;
      }
    }

    // draw the menutext
    if(!strText.IsEmpty())
    {
      LOGFONT logFontMenu;
      CFont fontMenu;

#ifdef _NEW_MENU_USER_FONT
      logFontMenu = MENU_USER_FONT;
#else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
#endif

      // Default selection?
      if(state&ODS_DEFAULT)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }
      if(state&ODS_DRAW_VERTICAL)
      {
        // rotate font 90?
        logFontMenu.lfOrientation = -900;
        logFontMenu.lfEscapement = -900;
      }

      fontMenu.CreateFontIndirect(&logFontMenu);

      CString leftStr;
      CString 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')));
      }
      else
      {
        leftStr = strText;
      }

      // Draw the text in the correct color:
      UINT nFormat  = DT_LEFT| DT_SINGLELINE|DT_VCENTER;
      UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
      if(nFlags&MFT_RIGHTORDER)
      {
        nFormat  = DT_RIGHT| DT_SINGLELINE|DT_VCENTER|DT_RTLREADING;
        nFormatr = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
      }

      int iOldMode = pDC->SetBkMode( TRANSPARENT);
      CFont* pOldFont = pDC->SelectObject (&fontMenu);

      COLORREF OldTextColor;
      if( (lpDIS->itemState&ODS_GRAYED) ||
        (bIsMenuBar && lpDIS->itemState&ODS_INACTIVE) )
      {
        // Draw the text disabled?
        OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
      }
      else
      {
        // Draw the text normal
        if( bHighContrast && !bIsMenuBar && !(state&ODS_SELECTED) )
        {
          OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
        }
        else
        {
          OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_MENUTEXT));
        }
      }
      UINT dt_Hide = (lpDIS->itemState & ODS_NOACCEL)?DT_HIDEPREFIX:0;
      if(dt_Hide && g_Shell>=Win2000)
      {
        BOOL bMenuUnderlines = TRUE;
        if(SystemParametersInfo( SPI_GETKEYBOARDCUES,0,&bMenuUnderlines,0)==TRUE && bMenuUnderlines==TRUE)
        {
          // do not hide
          dt_Hide = 0;
        }
      }

      if(bIsMenuBar)
      {
        MenuDrawText(pDC->m_hDC,leftStr,-1,RectSel, DT_SINGLELINE|DT_VCENTER|DT_CENTER|dt_Hide);
      }
      else
      {
        pDC->DrawText(leftStr,RectText, nFormat|dt_Hide);
        if(tablocr!=-1)
        {
          pDC->DrawText (rightStr,RectText,nFormatr|dt_Hide);
        }
      }
      pDC->SetTextColor(OldTextColor);
      pDC->SelectObject(pOldFont);
      pDC->SetBkMode(iOldMode);
    }

    // Draw the bitmap or checkmarks
    if(!bIsMenuBar)
    {
      CRect rect2 = RectText;

      if(checkflag||standardflag||selectedflag||disableflag)
      {
        if(checkflag && m_checkmaps)
        {
          CPoint ptImage(RectIcon.left+3,RectIcon.top+4);

          if(state&ODS_SELECTED)
          {
            m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
          }
          else
          {
            m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
          }
        }
        else
        {
          CSize size = pMenuData->m_pMenuIcon->GetIconSize();
          HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
          //CPoint ptImage(RectIcon.left+3,RectIcon.top+ 4);
          CPoint ptImage( RectIcon.left+3, RectIcon.top + ((RectIcon.Height()-size.cy)>>1) );

          // Need to draw the checked state
          if (state&ODS_CHECKED)
          {
            CRect rect = RectIcon;
            if(nFlags&MFT_RIGHTORDER)
            {
              rect.InflateRect (-2,-1,-1,-1);
            }
            else
            {
            rect.InflateRect (-1,-1,-2,-1);
            }
            if(selectedflag)
            {
              if (NumScreenColors() > 256)
              {
                pDC->FillSolidRect(rect,MixedColor(colorSel,GetSysColor(COLOR_HIGHLIGHT)));
              }
              else
              {
                pDC->FillSolidRect(rect,colorSel); //GetSysColor(COLOR_HIGHLIGHT)
              }
            }
            else
            {
              pDC->FillSolidRect(rect,MixedColor(colorBitmap,GetSysColor(COLOR_HIGHLIGHT)));
            }

            CPen* pOldPen = pDC->SelectObject(&Pen);
            CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);

            pDC->Rectangle(rect);

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

          // Correcting of a smaler icon
          if(size.cx>1;
          }

          if(state & ODS_DISABLED)
          {
            if(m_bEnableXpBlending)
            {
              // draws the icon blended
              HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+2);
              pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
              DestroyIcon(hDrawIcon2);
            }
            else
            {
              CBrush Brush;
              Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColor(70,colorBitmap)));
              pDC->DrawState(ptImage, size, hDrawIcon, DSS_MONO, &Brush);
            }
          }
          else
          {
            if(selectedflag)
            {
              CBrush Brush;
              // Color of the shade
              Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColorXP(colorSel)));
              if(!(state & ODS_CHECKED))
              {
                ptImage.x++; ptImage.y++;
                pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL | DSS_MONO, &Brush);
                ptImage.x-=2; ptImage.y-=2;
              }
              pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
            }
            else
            {
              if(m_bEnableXpBlending)
              {
                // draws the icon blended
                HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+1);
                pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
                DestroyIcon(hDrawIcon2);
              }
              else
              {
                // draws the icon with normal color
                pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
              }
            }
          }
          DestroyIcon(hDrawIcon);
        }
      }

      if(pMenuData->m_nMenuIconOffset<0 /*&& state&ODS_CHECKED */ && !checkflag)
      {
        MENUITEMINFO info = {0};
        info.cbSize = sizeof(info);
        info.fMask = MIIM_CHECKMARKS;

        ::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);

        if(state&ODS_CHECKED || info.hbmpUnchecked)
        {
          CRect rect = RectIcon;
          if(nFlags&MFT_RIGHTORDER)
          {
            rect.InflateRect (-2,-1,-1,-1);
          }
          else
          {
          rect.InflateRect (-1,-1,-2,-1);
          }
          // draw the color behind checkmarks
          if(state&ODS_SELECTED)
          {
            if (NumScreenColors() > 256)
            {
              pDC->FillSolidRect(rect,MixedColor(colorSel,GetSysColor(COLOR_HIGHLIGHT)));
            }
            else
            {
              pDC->FillSolidRect(rect,colorSel);
            }
          }
          else
          {
            pDC->FillSolidRect(rect,MixedColor(colorBitmap,GetSysColor(COLOR_HIGHLIGHT)));
          }
          CPen* pOldPen = pDC->SelectObject(&Pen);
          CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);

          pDC->Rectangle(rect);

          pDC->SelectObject(pOldBrush);
          pDC->SelectObject(pOldPen);
          if (state&ODS_CHECKED)
          {
            CRect rect(RectIcon);
            rect.InflateRect(2,((m_iconY-RectIcon.Height())>>1)+2);

            if (!info.hbmpChecked)
            { // Checkmark
              DrawSpecialCharStyle(pDC,rect,98,state);
            }
            else if(!info.hbmpUnchecked)
            { // Bullet
              DrawSpecialCharStyle(pDC,rect,105,state);
            }
            else
            { // Draw Bitmap
              BITMAP myInfo = {0};
              GetObject((HGDIOBJ)info.hbmpChecked,sizeof(myInfo),&myInfo);
              CPoint Offset = RectIcon.TopLeft() + CPoint((RectIcon.Width()-myInfo.bmWidth)/2,(RectIcon.Height()-myInfo.bmHeight)/2);
              pDC->DrawState(Offset,CSize(0,0),info.hbmpChecked,DST_BITMAP|DSS_MONO);
            }
          }
          else if(info.hbmpUnchecked)
          {
            // Draw Bitmap
            BITMAP myInfo = {0};
            GetObject((HGDIOBJ)info.hbmpUnchecked,sizeof(myInfo),&myInfo);
            CPoint Offset = RectIcon.TopLeft() + CPoint((RectIcon.Width()-myInfo.bmWidth)/2,(RectIcon.Height()-myInfo.bmHeight)/2);
            if(state & ODS_DISABLED)
            {
              pDC->DrawState(Offset,CSize(0,0),info.hbmpUnchecked,DST_BITMAP|DSS_MONO|DSS_DISABLED);
            }
            else
            {
              pDC->DrawState(Offset,CSize(0,0),info.hbmpUnchecked,DST_BITMAP|DSS_MONO);
            }
          }
        }
        else if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
        {
          DrawSpecial_WinXP(pDC,RectIcon,lpDIS->itemID,state);
        }
      }
    }
  }
}

void CNewMenu::DrawItem_XP_2003(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
#ifdef _TRACE_MENU_
  AfxTrace(_T("BarState: 0x%lX MenuID 0x%lX\n"),lpDIS->itemState,lpDIS->itemID);
#endif
  ASSERT(lpDIS != NULL);

  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  ASSERT(pMenuData);

  UINT nFlags = pMenuData->m_nFlags;

  CNewMemDC memDC(&lpDIS->rcItem,lpDIS->hDC);
  CDC* pDC;
  if( bIsMenuBar || (nFlags&MF_SEPARATOR) )
  { // For title and menubardrawing disable memory painting
    memDC.DoCancel();
    pDC = CDC::FromHandle(lpDIS->hDC);
  }
  else
  {
    pDC = &memDC;
  }

  COLORREF colorWindow = DarkenColor(10,GetSysColor(COLOR_WINDOW));
  COLORREF colorMenuBar = bIsMenuBar?GetMenuBarColor():GetMenuColor();
  COLORREF colorMenu = MixedColor(colorWindow,colorMenuBar);
  COLORREF colorBitmap = MixedColor(GetMenuBarColor(),colorWindow);
  COLORREF colorSel = GetXpHighlightColor();
  COLORREF colorBorder = GetSysColor(COLOR_HIGHLIGHT);//DarkenColor(128,colorMenuBar);

  //COLORREF colorCaption = GetSysColor(COLOR_ACTIVECAPTION); //RGB(0,84,227);
  //COLORREF cc1 = MixedColor(colorWindow,colorCaption);
  //COLORREF cc2 = MidColor(colorWindow,colorCaption);

  COLORREF colorCheck    = RGB(255,192,111);
  COLORREF colorCheckSel = RGB(254,128,62);
  colorSel = RGB(255,238,194);
  if(!IsMenuThemeActive() &&
    GetMenuDrawMode()!=STYLE_COLORFUL_NOBORDER &&
      GetMenuDrawMode()!=STYLE_COLORFUL)
  {
    colorSel = GetXpHighlightColor();
    //colorCheck = pDC->GetNearestColor(DarkenColorXP(colorSel));
    colorCheckSel = MixedColor(colorSel,GetSysColor(COLOR_HIGHLIGHT));
    colorCheck = colorCheckSel;
  }

  colorBitmap = colorMenuBar = GetMenuBarColor2003();
  if(bHighContrast)
  {
    colorBorder = GetSysColor(COLOR_BTNTEXT);
  }

  // Better contrast when you have less than 256 colors
  if(pDC->GetNearestColor(colorMenu)==pDC->GetNearestColor(colorBitmap))
  {
    colorMenu = colorWindow;
    colorBitmap = colorMenuBar;
  }

  CPen Pen(PS_SOLID,0,colorBorder);

  if(bIsMenuBar)
  {
    if(!IsMenu(UIntToHMenu(lpDIS->itemID)) && (lpDIS->itemState&ODS_SELECTED_OPEN))
    {
      lpDIS->itemState = (lpDIS->itemState&~(ODS_SELECTED|ODS_SELECTED_OPEN))|ODS_HOTLIGHT;
    }
    else if( !(lpDIS->itemState&ODS_SELECTED_OPEN) && !m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
    {
      lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
    }
    if(!(lpDIS->itemState&ODS_HOTLIGHT))
    {
      colorSel = colorBitmap;
    }
    colorMenu = colorMenuBar;
  }

  CBrush m_brSel(colorSel);
  CBrush m_brBitmap(colorBitmap);

  CRect RectIcon(lpDIS->rcItem);
  CRect RectText(lpDIS->rcItem);
  CRect RectSel(lpDIS->rcItem);

  if(bIsMenuBar)
  {
    RectText.InflateRect (0,0,0,0);
    if(lpDIS->itemState&ODS_DRAW_VERTICAL)
    {
      RectSel.InflateRect (0,0,0, -4);
    }
    else
    {
      RectSel.InflateRect (0,0,-4,0);
    }

    if(lpDIS->itemState&ODS_SELECTED)
    {
      if(lpDIS->itemState&ODS_DRAW_VERTICAL)
        RectText.bottom -=4;
      else
        RectText.right -=4;
      if(NumScreenColors() <= 256)
      {
        pDC->FillSolidRect(RectText,colorMenu);
      }
      else
      {
        DrawGradient(pDC,RectText,colorMenu,colorBitmap,FALSE,TRUE);
      }
      if(lpDIS->itemState&ODS_DRAW_VERTICAL)
      {
        RectText.bottom +=4;
      }
      else
      {
        RectText.right +=4;
      }
    }
    else
    {
      MENUINFO menuInfo = {0};
      menuInfo.cbSize = sizeof(menuInfo);
      menuInfo.fMask = MIM_BACKGROUND;

      if(::GetMenuInfo(m_hMenu,&menuInfo) && menuInfo.hbrBack)
      {
        CBrush *pBrush = CBrush::FromHandle(menuInfo.hbrBack);
        CPoint brushOrg(0,0);

        // new support for menubar
        CControlBar* pControlBar = DYNAMIC_DOWNCAST(CControlBar,pDC->GetWindow());
        if(pControlBar)
        {
          CFrameWnd* pFrame = pControlBar->GetParentFrame();
          if(pFrame)
          {
            CRect windowRect;
            pFrame->GetWindowRect(windowRect);
            pControlBar->ScreenToClient(windowRect);
            brushOrg = windowRect.TopLeft();
          }
        }

        VERIFY(pBrush->UnrealizeObject());
        CPoint oldOrg = pDC->SetBrushOrg(brushOrg);
        pDC->FillRect(RectText,pBrush);
        pDC->SetBrushOrg(oldOrg);
      }
      else
      {
        pDC->FillSolidRect(RectText,colorMenu);
      }
      }
    }
  else
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectIcon.left = RectIcon.right - (m_iconX + 8);
      RectText.right= RectIcon.left;
      // Draw for Bitmapbackground
      DrawGradient(pDC,RectIcon,colorBitmap,colorMenu,TRUE);
  }
  else
  {
      RectIcon.right = RectIcon.left + m_iconX + 8;
      RectText.left  = RectIcon.right;
    // Draw for Bitmapbackground
      DrawGradient(pDC,RectIcon,colorMenu,colorBitmap,TRUE);
    }
    // Draw for Textbackground
    pDC->FillSolidRect(RectText,colorMenu);
  }

  // Spacing for submenu only in popups
  if(!bIsMenuBar)
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectText.left += 15;
      RectText.right -= 4;
    }
    else
    {
      RectText.left += 4;
      RectText.right -= 15;
    }
  }

  //  Flag for highlighted item
  if(lpDIS->itemState & (ODS_HOTLIGHT|ODS_INACTIVE) )
  {
    lpDIS->itemState |= ODS_SELECTED;
  }

  if(bIsMenuBar && (lpDIS->itemState&ODS_SELECTED) )
  {
    if(!(lpDIS->itemState&ODS_INACTIVE) )
    {
      SetLastMenuRect(lpDIS->hDC,RectSel);
      if(!(lpDIS->itemState&ODS_HOTLIGHT) )
      {
        // Create a new pen for the special color
        Pen.DeleteObject();
        colorBorder = bHighContrast?GetSysColor(COLOR_BTNTEXT):DarkenColor(128,GetMenuBarColor());
        Pen.CreatePen(PS_SOLID,0,colorBorder);

        int X,Y;
        CRect rect = RectText;
        int winH = rect.Height();

        // Simulate a shadow on right edge...
        if (NumScreenColors() <= 256)
        {
          DWORD clr = GetSysColor(COLOR_BTNSHADOW);
          if(lpDIS->itemState&ODS_DRAW_VERTICAL)
          {
            int winW = rect.Width();
            for (Y=0; Y<=1 ;Y++)
            {
              for (X=4; X<=(winW-1) ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y,clr);
              }
            }
          }
          else
          {
            for (X=3; X<=4 ;X++)
            {
              for (Y=4; Y<=(winH-1) ;Y++)
              {
                pDC->SetPixel(rect.right - X, Y + rect.top, clr );
              }
            }
          }
        }
        else
        {
          if(lpDIS->itemState&ODS_DRAW_VERTICAL)
          {
            int winW = rect.Width();
            COLORREF barColor = pDC->GetPixel(rect.left+4,rect.bottom-4);
            for (Y=1; Y<=4 ;Y++)
            {
              for (X=0; X<4 ;X++)
              {
                if(barColor==CLR_INVALID)
                {
                  barColor = pDC->GetPixel(rect.left+X,rect.bottom-Y);
                }
                pDC->SetPixel(rect.left+X,rect.bottom-Y,barColor);
              }
              for (X=4; X<8 ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y,DarkenColor(2* 3 * Y * (X - 3), barColor));
              }
              for (X=8; X<=(winW-1) ;X++)
              {
                pDC->SetPixel(rect.left+X,rect.bottom-Y, DarkenColor(2*15 * Y, barColor) );
              }
            }
          }
          else
          {
            COLORREF barColor = pDC->GetPixel(rect.right-1,rect.top);
            for (X=1; X<=4 ;X++)
            {
              for (Y=0; Y<4 ;Y++)
              {
                if(barColor==CLR_INVALID)
                {
                  barColor = pDC->GetPixel(rect.right-X,Y+rect.top);
                }
                pDC->SetPixel(rect.right-X,Y+rect.top, barColor );
              }
              for (Y=4; Y<8 ;Y++)
              {
                pDC->SetPixel(rect.right-X,Y+rect.top,DarkenColor(2* 3 * X * (Y - 3), barColor));
              }
              for (Y=8; Y<=(winH-1) ;Y++)
              {
                pDC->SetPixel(rect.right - X, Y+rect.top, DarkenColor(2*15 * X, barColor) );
              }
            }
          }
        }
      }
    }
  }
  // For keyboard navigation only
  BOOL bDrawSmallSelection = FALSE;
  // remove the selected bit if it's grayed out
  if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable)
  {
    if( lpDIS->itemState & ODS_SELECTED )
    {
      lpDIS->itemState = lpDIS->itemState & (~ODS_SELECTED);
      DWORD MsgPos = ::GetMessagePos();
      if( MsgPos==CNewMenuHook::m_dwMsgPos )
      {
        bDrawSmallSelection = TRUE;
      }
      else
      {
        CNewMenuHook::m_dwMsgPos = MsgPos;
      }
    }
  }

  // Draw the seperator
  if( nFlags & MFT_SEPARATOR )
  {
    if( pMenuData->m_nTitleFlags&MFT_TITLE )
    {
      DrawTitle(lpDIS,bIsMenuBar);
    }
    else
    {
      // Draw only the seperator
      CRect rect;
      rect.top = RectText.CenterPoint().y;
      rect.bottom = rect.top+1;

      if(nFlags&MFT_RIGHTORDER)
      {
        rect.right = RectText.right;
        rect.left = lpDIS->rcItem.left;
      }
      else
      {
      rect.right = lpDIS->rcItem.right;
        rect.left = RectText.left;
      }
      pDC->FillSolidRect(rect,GetSysColor(COLOR_GRAYTEXT));
    }
  }
  else
  {
    if( (lpDIS->itemState & ODS_SELECTED) && !(lpDIS->itemState&ODS_INACTIVE) )
    {
      if(bIsMenuBar)
      {
        if(NumScreenColors() <= 256)
        {
          pDC->FillSolidRect(RectSel,colorWindow);
        }
        else
        {
          DrawGradient(pDC,RectSel,colorWindow,colorSel,FALSE,TRUE);
        }
      }
      else
      {
        pDC->FillSolidRect(RectSel,colorSel);
      }
      // Draw the selection
      CPen* pOldPen = pDC->SelectObject(&Pen);
      CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
      pDC->Rectangle(RectSel);
      pDC->SelectObject(pOldBrush);
      pDC->SelectObject(pOldPen);
    }
    else if (bDrawSmallSelection)
    {
      pDC->FillSolidRect(RectSel,colorMenu);
      // Draw the selection for keyboardnavigation
      CPen* pOldPen = pDC->SelectObject(&Pen);
      CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
      pDC->Rectangle(RectSel);
      pDC->SelectObject(pOldBrush);
      pDC->SelectObject(pOldPen);
    }

    UINT state = lpDIS->itemState;

    BOOL standardflag=FALSE;
    BOOL selectedflag=FALSE;
    BOOL disableflag=FALSE;
    BOOL checkflag=FALSE;

    CString strText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);

    if( (state&ODS_CHECKED) && (pMenuData->m_nMenuIconOffset<0) )
    {
      if(state&ODS_SELECTED && m_selectcheck>0)
      {
        checkflag=TRUE;
      }
      else if(m_unselectcheck>0)
      {
        checkflag=TRUE;
      }
    }
    else if(pMenuData->m_nMenuIconOffset != -1)
    {
      standardflag = TRUE;
      if(state&ODS_SELECTED)
      {
        selectedflag=TRUE;
      }
      else if(state&ODS_GRAYED)
      {
        disableflag=TRUE;
      }
    }

    if(!strText.IsEmpty())
    {  // draw the menutext
      LOGFONT logFontMenu;
      CFont fontMenu;

#ifdef _NEW_MENU_USER_FONT
      logFontMenu = MENU_USER_FONT;
#else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu = nm.lfMenuFont;
#endif

      // Default selection?
      if(state&ODS_DEFAULT)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }
      if(state&ODS_DRAW_VERTICAL)
      {
        // rotate font 90?
        logFontMenu.lfOrientation = -900;
        logFontMenu.lfEscapement = -900;
      }

      fontMenu.CreateFontIndirect(&logFontMenu);

      CString leftStr;
      CString 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')));
      }
      else
      {
        leftStr=strText;
      }

      // Draw the text in the correct color:
      UINT nFormat  = DT_LEFT| DT_SINGLELINE|DT_VCENTER;
      UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
      if(nFlags&MFT_RIGHTORDER)
      {
        nFormat  = DT_RIGHT| DT_SINGLELINE|DT_VCENTER|DT_RTLREADING;
        nFormatr = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
      }

      int iOldMode = pDC->SetBkMode( TRANSPARENT);
      CFont* pOldFont = pDC->SelectObject (&fontMenu);

      COLORREF OldTextColor;
      if( (lpDIS->itemState&ODS_GRAYED) ||
        (bIsMenuBar && lpDIS->itemState&ODS_INACTIVE) )
      {
        // Draw the text disabled?
        if(bIsMenuBar && (NumScreenColors() <= 256) )
        {
          OldTextColor = pDC->SetTextColor(colorWindow);
        }
        else
        {
          OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
        }
      }
      else
      {
        // Draw the text normal
        if( bHighContrast && !bIsMenuBar && !(state&ODS_SELECTED) )
        {
          OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
        }
        else
        {
          OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_MENUTEXT));
        }
      }
      // Office 2003 ignors this settings
      UINT dt_Hide = 0;//(lpDIS->itemState & ODS_NOACCEL)?DT_HIDEPREFIX:0;
      if(bIsMenuBar)
      {
        MenuDrawText(pDC->m_hDC,leftStr,-1,RectSel, DT_SINGLELINE|DT_VCENTER|DT_CENTER|dt_Hide);
      }
      else
      {
        pDC->DrawText(leftStr,RectText, nFormat|dt_Hide);
        if(tablocr!=-1)
        {
          pDC->DrawText (rightStr,RectText,nFormatr|dt_Hide);
        }
      }
      pDC->SetTextColor(OldTextColor);
      pDC->SelectObject(pOldFont);
      pDC->SetBkMode(iOldMode);
    }

    // Draw the bitmap or checkmarks
    if(!bIsMenuBar)
    {
      CRect rect2 = RectText;

      if(checkflag||standardflag||selectedflag||disableflag)
      {
        if(checkflag && m_checkmaps)
        {
          CPoint ptImage(RectIcon.left+3,RectIcon.top+4);

          if(state&ODS_SELECTED)
          {
            m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
          }
          else
          {
            m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
          }
        }
        else
        {
          CSize size = pMenuData->m_pMenuIcon->GetIconSize();
          HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
          //CPoint ptImage(RectIcon.left+3,RectIcon.top+ 4);
          CPoint ptImage( RectIcon.left+3, RectIcon.top + ((RectIcon.Height()-size.cy)>>1) );

          // Need to draw the checked state
          if (state&ODS_CHECKED)
          {
            CRect rect = RectIcon;
            if(nFlags&MFT_RIGHTORDER)
            {
              rect.InflateRect (-2,-1,-1,-1);
            }
            else
            {
            rect.InflateRect (-1,-1,-2,-1);
            }
            if(selectedflag)
            {
              pDC->FillSolidRect(rect,colorCheckSel);
            }
            else
            {
              pDC->FillSolidRect(rect,colorCheck);
            }

            CPen* pOldPen = pDC->SelectObject(&Pen);
            CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);

            pDC->Rectangle(rect);

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

          // Correcting of a smaler icon
          if(size.cx>1;
          }

          if(state & ODS_DISABLED)
          {
            //if(m_bEnableXpBlending)
            {
              // draws the icon blended
              HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+2);
              pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
              DestroyIcon(hDrawIcon2);
            }
            //else
            //{
            //  CBrush Brush;
            //  Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColor(70,colorBitmap)));
            //  pDC->DrawState(ptImage, size, hDrawIcon, DSS_MONO, &Brush);
            //}
          }
          else
          {
            if(selectedflag)
            {
              //if(!(state & ODS_CHECKED))
              //{
              //  CBrush Brush;
              //  // Color of the shade
              //  Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColorXP(colorSel)));
              //  ptImage.x++; ptImage.y++;
              //  pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL | DSS_MONO, &Brush);
              //  ptImage.x-=2; ptImage.y-=2;
              //}
              pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
            }
            else
            {
              if(m_bEnableXpBlending)
              {
                // draws the icon blended
                HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+1);
                pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
                DestroyIcon(hDrawIcon2);
              }
              else
              {
                // draws the icon with normal color
                pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
                //ImageList_DrawEx(pMenuData->m_pMenuIcon->m_IconsList,pMenuData->m_nMenuIconOffset,pDC->GetSafeHdc(),ptImage.x,ptImage.y,0,0,CLR_DEFAULT,CLR_DEFAULT,ILD_NORMAL);
              }
            }
          }
          DestroyIcon(hDrawIcon);
        }
      }

      if(pMenuData->m_nMenuIconOffset<0 /*&& state&ODS_CHECKED */ && !checkflag)
      {
        MENUITEMINFO info = {0};
        info.cbSize = sizeof(info);
        info.fMask = MIIM_CHECKMARKS;

        ::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);

        if(state&ODS_CHECKED || info.hbmpUnchecked)
        {
          CRect rect = RectIcon;
          if(nFlags&MFT_RIGHTORDER)
          {
            rect.InflateRect (-2,-1,-1,-1);
          }
          else
          {
          rect.InflateRect (-1,-1,-2,-1);
          }
          // draw the color behind checkmarks
          if(state&ODS_SELECTED)
          {
            pDC->FillSolidRect(rect,colorCheckSel);
          }
          else
          {
            pDC->FillSolidRect(rect,colorCheck);
          }
          CPen* pOldPen = pDC->SelectObject(&Pen);
          CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);

          pDC->Rectangle(rect);

          pDC->SelectObject(pOldBrush);
          pDC->SelectObject(pOldPen);
          if (state&ODS_CHECKED)
          {
            CRect rect(RectIcon);
            rect.InflateRect(2,((m_iconY-RectIcon.Height())>>1)+2);

            if (!info.hbmpChecked)
            { // Checkmark
              DrawSpecialCharStyle(pDC,rect,98,state);
            }
            else if(!info.hbmpUnchecked)
            { // Bullet
              DrawSpecialCharStyle(pDC,rect,105,state);
            }
            else
            { // Draw Bitmap
              BITMAP myInfo = {0};
              GetObject((HGDIOBJ)info.hbmpChecked,sizeof(myInfo),&myInfo);
              CPoint Offset = RectIcon.TopLeft() + CPoint((RectIcon.Width()-myInfo.bmWidth)/2,(RectIcon.Height()-myInfo.bmHeight)/2);
              pDC->DrawState(Offset,CSize(0,0),info.hbmpChecked,DST_BITMAP|DSS_MONO);
            }
          }
          else
          {
            // Draw Bitmap
            BITMAP myInfo = {0};
            GetObject((HGDIOBJ)info.hbmpUnchecked,sizeof(myInfo),&myInfo);
            CPoint Offset = RectIcon.TopLeft() + CPoint((RectIcon.Width()-myInfo.bmWidth)/2,(RectIcon.Height()-myInfo.bmHeight)/2);
            if(state & ODS_DISABLED)
            {
              pDC->DrawState(Offset,CSize(0,0),info.hbmpUnchecked,DST_BITMAP|DSS_MONO|DSS_DISABLED);
            }
            else
            {
              pDC->DrawState(Offset,CSize(0,0),info.hbmpUnchecked,DST_BITMAP|DSS_MONO);
            }
          }
        }
        else if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
        {
          DrawSpecial_WinXP(pDC,RectIcon,lpDIS->itemID,state);
        }
      }
    }
  }
}

void CNewMenu::DrawItem_SpecialStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
  if(!bIsMenuBar)
  {
    DrawItem_OldStyle(lpDIS,bIsMenuBar);
    return;
  }

  ASSERT(lpDIS != NULL);
  //CNewMemDC memDC(&lpDIS->rcItem,lpDIS->hDC);
  //CDC* pDC = &memDC;
  CDC* pDC = CDC::FromHandle(lpDIS->hDC);

  ASSERT(lpDIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);

  CRect rect(lpDIS->rcItem);
  //rect.InflateRect(0,-1);

  COLORREF colorBack;
  if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
  {
    colorBack = GetSysColor(COLOR_HIGHLIGHT);
    SetLastMenuRect(lpDIS->hDC,rect);
  }
  else
  {
    colorBack = GetMenuBarColor();
  }
  pDC->FillSolidRect(rect,colorBack);

  int iOldMode = pDC->SetBkMode( TRANSPARENT);
  CString strText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
  COLORREF crTextColor;
  if(!(lpDIS->itemState & ODS_GRAYED))
  {
    if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
    {
      crTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
    }
    else
    {
      crTextColor = GetSysColor(COLOR_MENUTEXT);
    }
  }
  else
  {
    crTextColor = GetSysColor(COLOR_GRAYTEXT);
  }
  COLORREF oldColor = pDC->SetTextColor(crTextColor);

  CFont fontMenu;
  LOGFONT logFontMenu;

#ifdef _NEW_MENU_USER_FONT
  logFontMenu =  MENU_USER_FONT;
#else
  NONCLIENTMETRICS nm = {0};
  nm.cbSize = sizeof (nm);
  VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
  logFontMenu =  nm.lfMenuFont;
#endif
  if(lpDIS->itemState&ODS_DRAW_VERTICAL)
  {
    // rotate font 90?
    logFontMenu.lfOrientation = -900;
    logFontMenu.lfEscapement = -900;
  }
  fontMenu.CreateFontIndirect (&logFontMenu);

  CFont* pOldFont = pDC->SelectObject(&fontMenu);
  UINT dt_Hide = (lpDIS->itemState & ODS_NOACCEL)?DT_HIDEPREFIX:0;
  if(dt_Hide && g_Shell>=Win2000)
  {
    BOOL bMenuUnderlines = TRUE;
    if(SystemParametersInfo( SPI_GETKEYBOARDCUES,0,&bMenuUnderlines,0)==TRUE && bMenuUnderlines==TRUE)
    {
      // do not hide
      dt_Hide = 0;
    }
  }
  MenuDrawText(pDC->m_hDC,strText,-1,rect,DT_CENTER|DT_SINGLELINE|DT_VCENTER|dt_Hide);
  pDC->SelectObject(pOldFont);

  pDC->SetTextColor(oldColor);
  pDC->SetBkMode( iOldMode);
}

void CNewMenu::DrawItem_Icy(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
  ASSERT(lpDIS != NULL);
  CRect rect;

  ASSERT(lpDIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);

  UINT nFlags = pMenuData->m_nFlags;
  CNewMemDC memDC(&lpDIS->rcItem,lpDIS->hDC);
  CDC* pDC;
  if( bIsMenuBar || (nFlags&MF_SEPARATOR) )
  { // For title and menubardrawing disable memory painting
    memDC.DoCancel();
    pDC = CDC::FromHandle(lpDIS->hDC);
  }
  else
  {
    pDC = &memDC;
  }

  COLORREF colorMenu = GetMenuColor();
  COLORREF colorBack = bIsMenuBar?GetMenuBarColor():colorMenu;
  COLORREF color3DShadow = DarkenColor(60,colorMenu);
  COLORREF color3DHilight = LightenColor(60,colorMenu);
  COLORREF colorGrayText = DarkenColor(100,colorMenu);//GetSysColor(COLOR_GRAYTEXT);
  COLORREF colorHilight = GetSysColor(COLOR_HIGHLIGHT);
  COLORREF colorGrayed = bHighContrast?GetSysColor(COLOR_BTNSHADOW):pDC->GetNearestColor(DarkenColor(70,color3DShadow));

  if(bHighContrast)
  {
    color3DShadow = GetSysColor(COLOR_BTNTEXT);
    color3DHilight = GetSysColor(COLOR_BTNTEXT);
  }

  CRect RectIcon(lpDIS->rcItem);
  CRect RectText(lpDIS->rcItem);
  CRect RectSel(lpDIS->rcItem);

  RectIcon.InflateRect (-1,0,0,0);
  RectText.InflateRect (-1,0,0,0);
  RectSel.InflateRect (0,0,0,0);

  if(!bIsMenuBar)
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectIcon.left = RectIcon.right - (m_iconX + 6 + GAP);
      RectText.right  = RectIcon.left;
    }
    else
    {
      RectIcon.right = RectIcon.left + m_iconX + 6 + GAP;
      RectText.left  = RectIcon.right;
    }
  }
  else
  {
    RectText.right += 6;
    RectSel.InflateRect(0,0,-1,-1);
    RectText.InflateRect (1,-2,0,0);

    if(!IsMenu(UIntToHMenu(lpDIS->itemID)) && (lpDIS->itemState&ODS_SELECTED_OPEN))
    {
      lpDIS->itemState = (lpDIS->itemState&~(ODS_SELECTED|ODS_SELECTED_OPEN))|ODS_HOTLIGHT;
    }
    else if(!(lpDIS->itemState&ODS_SELECTED_OPEN) && !m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
    {
      lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
    }
    if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
    {
      SetLastMenuRect(lpDIS->hDC,RectSel);
    }
  }

  // For keyboard navigation only
  BOOL bDrawSmallSelection = FALSE;

  // remove the selected bit if it's grayed out
  if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable )
  {
    if(lpDIS->itemState & ODS_SELECTED)
    {
      lpDIS->itemState &= ~ODS_SELECTED;
      DWORD MsgPos = ::GetMessagePos();
      if(MsgPos==CNewMenuHook::m_dwMsgPos)
      {
        bDrawSmallSelection = TRUE;
      }
      else
      {
        CNewMenuHook::m_dwMsgPos = MsgPos;
      }
    }
  }

  if(nFlags & MF_SEPARATOR)
  {
    if(pMenuData->m_nTitleFlags&MFT_TITLE)
    {
      DrawTitle(lpDIS,bIsMenuBar);
    }
    else
    {
      rect = lpDIS->rcItem;
      //pDC->FillSolidRect(rect,colorBack);
      pDC->FillSolidRect(rect,color3DHilight);
      rect.left += 1;
      rect.right -= 1;
      pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
    }
  }
  else
  {
    CRect rect2;
    BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
    BOOL checkflag=FALSE;

    CBrush m_brSelect;
    int nIconNormal=-1;

    // set some colors and the font
    m_brSelect.CreateSolidBrush(colorHilight);
    rect2=rect=RectSel;

    // draw the up/down/focused/disabled state
    UINT state = lpDIS->itemState;

    nIconNormal = pMenuData->m_nMenuIconOffset;

    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;
      }
    }

    if(bIsMenuBar)
    {
      CRect tempRect = rect;
      tempRect.InflateRect (0,0,0,1);
      rect.OffsetRect(0,1);
      rect2=rect;

      if( bHighContrast || (state&ODS_INACTIVE) || (!(state&ODS_HOTLIGHT) && !(state&ODS_SELECTED)) )
      {
        // pDC->FillSolidRect(tempRect,colorBack);
        MENUINFO menuInfo = {0};
        menuInfo.cbSize = sizeof(menuInfo);
        menuInfo.fMask = MIM_BACKGROUND;

        if(!bHighContrast && ::GetMenuInfo(m_hMenu,&menuInfo) && menuInfo.hbrBack)
        {
          CBrush *pBrush = CBrush::FromHandle(menuInfo.hbrBack);
          VERIFY(pBrush->UnrealizeObject());
          CPoint oldOrg = pDC->SetBrushOrg(0,0);
          pDC->FillRect(tempRect,pBrush);
          pDC->SetBrushOrg(oldOrg);
        }
        else
        {
          pDC->FillSolidRect(tempRect,colorBack);
        }
      }
      else
      {
        colorBack = GetMenuColor();
        DrawGradient(pDC,tempRect,LightenColor(30,colorBack),DarkenColor(30,colorBack),false,true);
      }
    }
    else
    {
      if(bHighContrast)
      {
        pDC->FillSolidRect (rect,colorBack);
      }
      else
      {
        DrawGradient(pDC,rect,LightenColor(30,colorBack),DarkenColor(30,colorBack),false,true);
      }
    }
    // Draw the selection
    if(state&ODS_SELECTED)
    {
      // You need only Text highlight and that's what you get
      if(!bIsMenuBar)
      {
        if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
        {
          rect2 = RectText;
        }

        if(bHighContrast)
        {
          pDC->FillSolidRect (rect2,colorHilight);
        }
        else
        {
          DrawGradient(pDC,rect2,LightenColor(30,colorHilight),DarkenColor(30,colorHilight),false,true);
        }
        pDC->Draw3dRect(rect2 ,color3DShadow,color3DHilight);
      }
      else
      {
        pDC->Draw3dRect(rect2 ,color3DShadow,color3DHilight);
      }
    }
    else if(bIsMenuBar && (state&ODS_HOTLIGHT) && !(state&ODS_INACTIVE))
    {
      pDC->Draw3dRect(rect,color3DHilight,color3DShadow);
    }
    else if (bDrawSmallSelection)
    {
      pDC->DrawFocusRect(rect);
    }

    // Draw the Bitmap or checkmarks
    if(!bIsMenuBar)
    {
      CRect IconRect = RectIcon;
      // center the image
      IconRect.InflateRect(-(RectIcon.Width()-m_iconX)>>1,-(RectIcon.Height()-m_iconY)>>1);
      CPoint ptImage = IconRect.TopLeft();
      IconRect.InflateRect(2,2);

      if(checkflag||standardflag||selectedflag||disableflag)
      {
        if(checkflag && m_checkmaps)
        {
          if(state&ODS_SELECTED)
          {
            m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
          }
          else
          {
            m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
          }
        }
        else
        {
          // Need to draw the checked state
          if (IsNewShell())
          {
            if(state&ODS_CHECKED)
            {
              pDC->Draw3dRect(IconRect,color3DShadow,color3DHilight);
            }
            else if (selectedflag)
            {
              pDC->Draw3dRect(IconRect,color3DHilight,color3DShadow);
            }
          }

          CSize size = pMenuData->m_pMenuIcon->GetIconSize();
          // Correcting of a smaler icon
          if(size.cx>1;
          }
          if(size.cy>1;
          }

          HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
          if(state & ODS_DISABLED)
          {
            CBrush Brush;
            Brush.CreateSolidBrush(colorGrayed);
            pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL | DSS_MONO, (HBRUSH)Brush);
          }
          else
          {
            pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL, (HBRUSH)NULL);
          }
          DestroyIcon(hDrawIcon);
        }
      }
      if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
      {
        DrawSpecial_OldStyle(pDC,IconRect,lpDIS->itemID,state);
      }
      else if(nIconNormal<0 /*&& state&ODS_CHECKED */&& !checkflag)
      {
        MENUITEMINFO info = {0};
        info.cbSize = sizeof(info);
        info.fMask = MIIM_CHECKMARKS;

        ::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);

        Draw3DCheckmark(pDC, IconRect,info.hbmpChecked,info.hbmpUnchecked,state);
      }
    }


    CString strText;
    strText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
    if(!strText.IsEmpty())
    {
      COLORREF crText = GetSysColor(COLOR_MENUTEXT);

      if(bIsMenuBar)
      {
        rect.left += 6;
        if(lpDIS->itemState&ODS_INACTIVE)
        {
          crText = colorGrayText;
        }
      }
      else
      {
        if(lpDIS->itemState&ODS_SELECTED)
        {
          crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
        }
        rect.left += m_iconX + 12;
      }
      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->SetBkMode( TRANSPARENT);
      // Draw the text in the correct colour:
      UINT dt_Hide = (lpDIS->itemState & ODS_NOACCEL)?DT_HIDEPREFIX:0;
      if(dt_Hide && g_Shell>=Win2000)
      {
        BOOL bMenuUnderlines = TRUE;
        if(SystemParametersInfo( SPI_GETKEYBOARDCUES,0,&bMenuUnderlines,0)==TRUE && bMenuUnderlines==TRUE)
        {
          // do not hide
          dt_Hide = 0;
        }
      }

      UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      if(nFlags&MFT_RIGHTORDER)
      {
        nFormat  = DT_RIGHT| DT_SINGLELINE|DT_VCENTER|DT_RTLREADING|dt_Hide;
        nFormatr = DT_LEFT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      }

      if(bIsMenuBar)
      {
        rectt = RectSel;
        rectt.OffsetRect(-1,0);
        if(state & ODS_SELECTED)
        {
          rectt.OffsetRect(1,1);
        }
        nFormat = DT_CENTER|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      }
      else
      {
        if(nFlags&MFT_RIGHTORDER)
        {
          RectText.left += 15;
          RectText.right -= 4;
        }
        else
        {
          RectText.left += 4;
          RectText.right -= 15;
        }
      }

      CFont fontMenu;
      LOGFONT logFontMenu;

#ifdef _NEW_MENU_USER_FONT
      logFontMenu =  MENU_USER_FONT;
#else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
#endif

      // Default selection?
      if(state&ODS_DEFAULT)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }
      if(state&ODS_DRAW_VERTICAL)
      {
        // rotate font 90?
        logFontMenu.lfOrientation = -900;
        logFontMenu.lfEscapement = -900;
      }

      fontMenu.CreateFontIndirect (&logFontMenu);
      CFont* pOldFont = pDC->SelectObject(&fontMenu);

      if(!(lpDIS->itemState & ODS_GRAYED))
      {
        pDC->SetTextColor(crText);
        if(bIsMenuBar)
        {
          MenuDrawText(pDC->m_hDC,leftStr,-1,RectText,nFormat);
          if(tablocr!=-1)
          {
            MenuDrawText(pDC->m_hDC,rightStr,-1,RectText,nFormatr);
          }
        }
        else
        {
          pDC->DrawText (leftStr,RectText,nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText (rightStr,RectText,nFormatr);
          }
        }
      }
      else
      {
        // Draw the disabled text
        if(!(state & ODS_SELECTED))
        {
          CRect offset = RectText;
          offset.OffsetRect (1,1);

          pDC->SetTextColor(colorGrayed);
          pDC->DrawText(leftStr,RectText, nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText(rightStr,RectText,nFormatr);
          }
        }
        else
        {
          // And the standard Grey text:
          pDC->SetTextColor(colorBack);
          pDC->DrawText(leftStr,RectText, nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText (rightStr,RectText,nFormatr);
          }
        }
      }
      pDC->SelectObject(pOldFont);
      pDC->SetBkMode( iOldMode );
    }
    m_brSelect.DeleteObject();
  }
}

void CNewMenu::DrawItem_OldStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
  ASSERT(lpDIS != NULL);
  CRect rect;

  ASSERT(lpDIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);

  UINT nFlags = pMenuData->m_nFlags;

  CNewMemDC memDC(&lpDIS->rcItem,lpDIS->hDC);
  CDC* pDC;
  if( bIsMenuBar || (nFlags&MF_SEPARATOR) )
  { // For title and menubardrawing disable memory painting
    memDC.DoCancel();
    pDC = CDC::FromHandle(lpDIS->hDC);
  }
  else
  {
    pDC = &memDC;
  }

  COLORREF colorBack = bIsMenuBar?GetMenuBarColor():GetSysColor(COLOR_MENU);

  CRect RectIcon(lpDIS->rcItem);
  CRect RectText(lpDIS->rcItem);
  CRect RectSel(lpDIS->rcItem);

  RectIcon.InflateRect (-1,0,0,0);
  RectText.InflateRect (-1,0,0,0);
  RectSel.InflateRect (0,0,0,0);

  if(!bIsMenuBar)
  {
    if(nFlags&MFT_RIGHTORDER)
    {
      RectIcon.left = RectIcon.right - (m_iconX + 6 + GAP);
      RectText.right  = RectIcon.left;
    }
    else
    {
      RectIcon.right = RectIcon.left + m_iconX + 6 + GAP;
      RectText.left  = RectIcon.right;
    }
  }
  else
  {
    RectText.right += 6;
    RectText.InflateRect (1,0,0,0);
    RectSel.InflateRect (0,0,-2,0);
    RectSel.OffsetRect(1,-1);

#ifdef _TRACE_MENU_
    //   AfxTrace(_T("BarState: 0x%lX Menus %ld\n"),lpDIS->itemState,m_dwOpenMenu);
#endif
    if(!IsMenu(UIntToHMenu(lpDIS->itemID)) && (lpDIS->itemState&ODS_SELECTED_OPEN))
    {
      lpDIS->itemState = (lpDIS->itemState&~(ODS_SELECTED|ODS_SELECTED_OPEN))|ODS_HOTLIGHT;
    }
    else if( !(lpDIS->itemState&ODS_SELECTED_OPEN) && !m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
    {
      lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
    }

    if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
    {
      SetLastMenuRect(lpDIS->hDC,RectSel);
    }
  }

  // For keyboard navigation only
  BOOL bDrawSmallSelection = FALSE;

  // remove the selected bit if it's grayed out
  if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable )
  {
    if(lpDIS->itemState & ODS_SELECTED)
    {
      lpDIS->itemState &= ~ODS_SELECTED;
      DWORD MsgPos = ::GetMessagePos();
      if(MsgPos==CNewMenuHook::m_dwMsgPos)
      {
        bDrawSmallSelection = TRUE;
      }
      else
      {
        CNewMenuHook::m_dwMsgPos = MsgPos;
      }
    }
  }

  if(nFlags & MF_SEPARATOR)
  {
    if(pMenuData->m_nTitleFlags&MFT_TITLE)
    {
      DrawTitle(lpDIS,bIsMenuBar);
    }
    else
    {
      rect = lpDIS->rcItem;
      pDC->FillSolidRect(rect,colorBack);
      rect.left += 1;
      rect.top += 1;
      pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
    }
  }
  else
  {
    CRect rect2;
    BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
    BOOL checkflag=FALSE;

    CBrush m_brSelect;
    int nIconNormal=-1;
    //CImageList *bitmap=NULL;

    // set some colors and the font
    m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));

    // draw the colored rectangle portion
    rect2=rect=RectSel;

    // draw the up/down/focused/disabled state
    UINT state = lpDIS->itemState;

    nIconNormal = pMenuData->m_nMenuIconOffset;

    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;
      }
    }

    if(bIsMenuBar)
    {
      //rect.InflateRect (1,0,0,0);
      rect.OffsetRect(-1,1);
      rect2=rect;
      rect.right +=2;
      pDC->FillSolidRect (rect,colorBack);
      rect.right -=2;
    }
    else
    {
      // Draw the background
      pDC->FillSolidRect (rect,colorBack);
    }
    // Draw the selection
    if(state&ODS_SELECTED)
    {
      // You need only Text highlight and that's what you get
      if(!bIsMenuBar)
      {
        if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
        {
          rect2 = RectText;
        }
        pDC->FillRect(rect2,&m_brSelect);
      }
      else
      {
        pDC->Draw3dRect(rect ,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
      }
    }
    else if(bIsMenuBar && (state&ODS_HOTLIGHT) && !(state&ODS_INACTIVE))
    {
      pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
    }
    else if (bDrawSmallSelection)
    {
      pDC->DrawFocusRect(rect);
    }

    // Draw the Bitmap or checkmarks
    if(!bIsMenuBar)
    {
      CRect IconRect = RectIcon;
      // center the image
      IconRect.InflateRect(-(RectIcon.Width()-m_iconX)>>1,-(RectIcon.Height()-m_iconY)>>1);
      CPoint ptImage = IconRect.TopLeft();
      IconRect.InflateRect(2,2);

      if(checkflag||standardflag||selectedflag||disableflag)
      {
        if(checkflag && m_checkmaps)
        {
          if(state&ODS_SELECTED)
          {
            m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
          }
          else
          {
            m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
          }
        }
        else
        {
          // Need to draw the checked state
          if (IsNewShell())
          {
            if(state&ODS_CHECKED)
            {
              pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
            }
            else if (selectedflag)
            {
              pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
            }
          }

          CSize size = pMenuData->m_pMenuIcon->GetIconSize();
          // Correcting of a smaler icon
          if(size.cx>1;
          }
          if(size.cy>1;
          }

          HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
          if(state & ODS_DISABLED)
          {
            // Jan-19-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
            // opted to use blended disabled icons instead, the default is just too bad to think about using
            HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+2);
            pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
            DestroyIcon(hDrawIcon2);
//          pDC->DrawState(ptImage, size, hDrawIcon, DSS_DISABLED, (HBRUSH)NULL);
          }
          else
          {
            pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL, (HBRUSH)NULL);
          }
          DestroyIcon(hDrawIcon);
        }
      }
      if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
      {
        DrawSpecial_OldStyle(pDC,IconRect,lpDIS->itemID,state);
      }
      else if(nIconNormal<0 /*&& state&ODS_CHECKED */ && !checkflag)
      {
        MENUITEMINFO info = {0};
        info.cbSize = sizeof(info);
        info.fMask = MIIM_CHECKMARKS;

        ::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);
        Draw3DCheckmark(pDC, IconRect,info.hbmpChecked,info.hbmpUnchecked,state);
      }
    }

    CString strText;
    strText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
    if(!strText.IsEmpty())
    {
      COLORREF crText = GetSysColor(COLOR_MENUTEXT);

      if(bIsMenuBar)
      {
        if(lpDIS->itemState&ODS_INACTIVE)
          crText = GetSysColor(COLOR_GRAYTEXT);
      }
      else
      {
        if(lpDIS->itemState&ODS_SELECTED)
        {
          crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
        }
      }
      // 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')));
      }
      else
      {
        leftStr = strText;
      }

      int iOldMode = pDC->SetBkMode( TRANSPARENT);
      // Draw the text in the correct colour:
      UINT dt_Hide = (lpDIS->itemState & ODS_NOACCEL)?DT_HIDEPREFIX:0;
      if(dt_Hide && g_Shell>=Win2000)
      {
        BOOL bMenuUnderlines = TRUE;
        if(SystemParametersInfo( SPI_GETKEYBOARDCUES,0,&bMenuUnderlines,0)==TRUE && bMenuUnderlines==TRUE)
        {
          // do not hide
          dt_Hide = 0;
        }
      }
      UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      if(nFlags&MFT_RIGHTORDER)
      {
        nFormat  = DT_RIGHT| DT_SINGLELINE|DT_VCENTER|DT_RTLREADING|dt_Hide;
        nFormatr = DT_LEFT|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      }

      if(bIsMenuBar)
      {
        if(state & ODS_SELECTED)
        {
          RectText.OffsetRect(1,1);
        }
        nFormat = DT_CENTER|DT_SINGLELINE|DT_VCENTER|dt_Hide;
      }
      else
      {
        if(nFlags&MFT_RIGHTORDER)
        {
          RectText.left += 15;
          RectText.right -= 4;
        }
        else
        {
          RectText.left += 4;
          RectText.right -= 15;
        }
      }
      CFont fontMenu;
      LOGFONT logFontMenu;

#ifdef _NEW_MENU_USER_FONT
      logFontMenu =  MENU_USER_FONT;
#else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
#endif

      // Default selection?
      if(state&ODS_DEFAULT)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }
      if(state&ODS_DRAW_VERTICAL)
      {
        // rotate font 90?
        logFontMenu.lfOrientation = -900;
        logFontMenu.lfEscapement = -900;
      }

      fontMenu.CreateFontIndirect (&logFontMenu);
      CFont* pOldFont = pDC->SelectObject(&fontMenu);

      if(!(lpDIS->itemState & ODS_GRAYED))
      {
        pDC->SetTextColor(crText);
        if(bIsMenuBar)
        {
          MenuDrawText(pDC->m_hDC,leftStr,-1,RectText,nFormat);
          if(tablocr!=-1)
          {
            MenuDrawText(pDC->m_hDC,rightStr,-1,RectText,nFormatr);
          }
        }
        else
        {
          pDC->DrawText (leftStr,RectText,nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText (rightStr,RectText,nFormatr);
          }
        }
      }
      else
      {
        // Draw the disabled text
        if(!(state & ODS_SELECTED))
        {
          CRect offset = RectText;
          offset.OffsetRect (1,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,RectText, nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText(rightStr,RectText,nFormatr);
          }
        }
        else
        {
          // And the standard Grey text:
          pDC->SetTextColor(colorBack);
          pDC->DrawText(leftStr,RectText, nFormat);
          if(tablocr!=-1)
          {
            pDC->DrawText (rightStr,RectText,nFormatr);
          }
        }
      }
      pDC->SelectObject(pOldFont);
      pDC->SetBkMode( iOldMode );
    }
    m_brSelect.DeleteObject();
  }
}

BOOL CNewMenu::IsMenuBar(HMENU hMenu)
{
  BOOL bIsMenuBar = FALSE;
  if(!FindMenuItem(HMenuToUInt(hMenu)))
  {
    if(m_hParentMenu==NULL)
    {
      return m_bIsPopupMenu?FALSE:TRUE;
    }
    CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_hParentMenu));
    if (pMenu!=NULL)
    {
      return pMenu->m_bIsPopupMenu?FALSE:TRUE;
    }
  }
  else
  {
    // Test for only one item not bar
    bIsMenuBar = m_hParentMenu ? FALSE: ((m_bIsPopupMenu)?FALSE:TRUE);
  }
  return bIsMenuBar;
}

/*
==========================================================================
void CNewMenu::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 CNewMenu::MeasureItem_OldStyle( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
{
  ASSERT(lpMIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);

  UINT state = pMenuData->m_nFlags;
  if(state & MF_SEPARATOR)
  {
    if(pMenuData->m_nTitleFlags&MFT_TITLE)
    {
      SIZE size = {0,0};
      {// We need this sub-block for releasing the dc
        // DC of the desktop
        CClientDC myDC(NULL);

        CFont font;
        LOGFONT MyFont = m_MenuTitleFont;
        MyFont.lfOrientation = 0;
        MyFont.lfEscapement = 0;
        font.CreateFontIndirect(&MyFont);

        CFont* pOldFont = myDC.SelectObject (&font);
        CString lpstrText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
        VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
        // Select old font in
        myDC.SelectObject(pOldFont);
      } // We need this sub-block for releasing the dc

      CSize iconSize(0,0);
      if(pMenuData->m_nMenuIconOffset!=(-1) && pMenuData->m_pMenuIcon)
      {
        iconSize = pMenuData->m_pMenuIcon->GetIconSize();
        if(iconSize!=CSize(0,0))
        {
          iconSize += CSize(2,2);
        }
      }

      if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
      {
        if(bWine)
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx);
        }
        else
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx) - GetSystemMetrics(SM_CXMENUCHECK);
        }
        // Don't make the menu higher than menuitems in it
        lpMIS->itemHeight = 0;
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemWidth += 8;
        }
        else if(pMenuData->m_nTitleFlags&MFT_ROUND)
        {
          lpMIS->itemWidth += 4;
        }
      }
      else
      {
        lpMIS->itemWidth = size.cx + iconSize.cx;
        lpMIS->itemHeight = max(size.cy,iconSize.cy);
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemHeight += 8;
        }
      }
    }
    else
    {
      lpMIS->itemHeight = 3;
      lpMIS->itemWidth = 3;
    }
  }
  else
  {
    //Get pointer to text SK
    CString itemText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
    SIZE size = {0,0};

    {// We need this sub-block for releasing the dc
      CFont fontMenu;
      LOGFONT logFontMenu;

  #ifdef _NEW_MENU_USER_FONT
      logFontMenu =  MENU_USER_FONT;
  #else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
  #endif

      // Default selection?
      if(GetDefaultItem(0, FALSE) == pMenuData->m_nID)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }
      fontMenu.CreateFontIndirect (&logFontMenu);

      // DC of the desktop
      CClientDC myDC(NULL);
      // Select menu font in...
      CFont* pOldFont = myDC.SelectObject (&fontMenu);
      VERIFY(::GetTextExtentPoint32(myDC.m_hDC,itemText,itemText.GetLength(),&size));
      // Select old font in
      myDC.SelectObject(pOldFont);
    } // We need this sub-block for releasing the dc


    // Set width and height:
    if(bIsMenuBar)
    {
      if(itemText.Find(_T("&"))>=0)
      {
        lpMIS->itemWidth = size.cx - GetSystemMetrics(SM_CXMENUCHECK)/2;
      }
      else
      {
        lpMIS->itemWidth = size.cx;
      }
    }
    else
    {
      lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
    }

    int temp = GetSystemMetrics(SM_CYMENU);
    lpMIS->itemHeight = (temp>(m_iconY+4)) ? temp : (m_iconY+4);
    if(lpMIS->itemHeight<((UINT)size.cy) )
    {
      lpMIS->itemHeight=((UINT)size.cy);
    }

    // set status bar as appropriate
    UINT nItemID = (lpMIS->itemID & 0xFFF0);
    // Special case for system menu
    if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY)
    {
      BOOL bGetNext = FALSE;
      // search the actual menu item
      for (int j=0;jm_nID)
          {
            lpMIS->itemData = (ULONG_PTR)pTemp;
            lpMIS->itemID = pTemp->m_nID;
            UINT nOrgWidth = lpMIS->itemWidth;
            MeasureItem_OldStyle(lpMIS,bIsMenuBar);
            // Restore old values
            lpMIS->itemData = (ULONG_PTR)pMenuData;
            lpMIS->itemID = pMenuData->m_nID;
            lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
            break;
          }
        }
      }
      lpMIS->itemHeight = temp;
    }
  }
}

void CNewMenu::MeasureItem_Icy( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
{
  ASSERT(lpMIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);

  UINT state = pMenuData->m_nFlags;
  if(state & MF_SEPARATOR)
  {
    if(pMenuData->m_nTitleFlags&MFT_TITLE)
    {
      SIZE size = {0,0};
      {// We need this sub-block for releasing the dc
        // DC of the desktop
        CClientDC myDC(NULL);

        CFont font;
        LOGFONT MyFont = m_MenuTitleFont;
        MyFont.lfOrientation = 0;
        MyFont.lfEscapement = 0;
        font.CreateFontIndirect(&MyFont);

        CFont* pOldFont = myDC.SelectObject (&font);
        CString lpstrText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
        VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
        // Select old font in
        myDC.SelectObject(pOldFont);
      } // We need this sub-block for releasing the dc

      CSize iconSize(0,0);
      if(pMenuData->m_nMenuIconOffset!=(-1) && pMenuData->m_pMenuIcon)
      {
        iconSize = pMenuData->m_pMenuIcon->GetIconSize();
        if(iconSize!=CSize(0,0))
        {
          iconSize += CSize(2,2);
        }
      }

      if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
      {
        if(bWine)
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx);
        }
        else
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx) - GetSystemMetrics(SM_CXMENUCHECK);
        }
        // Don't make the menu higher than menuitems in it
        lpMIS->itemHeight = 0;
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemWidth += 8;
        }
        else if(pMenuData->m_nTitleFlags&MFT_ROUND)
        {
          lpMIS->itemWidth += 4;
        }
      }
      else
      {
        lpMIS->itemWidth = size.cx + iconSize.cx;
        lpMIS->itemHeight = max(size.cy,iconSize.cy);
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemHeight += 8;
        }
      }
    }
    else
    {
      lpMIS->itemHeight = 3;
      lpMIS->itemWidth = 3;
    }
  }
  else
  {
    //Get pointer to text SK
    CString itemText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
    SIZE size = {0,0};
    {// We need this sub-block for releasing the dc
      LOGFONT logFontMenu;
      CFont fontMenu;

  #ifdef _NEW_MENU_USER_FONT
      logFontMenu =  MENU_USER_FONT;
  #else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (nm);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
  #endif

      // Default selection?
      if(GetDefaultItem(0, FALSE) == pMenuData->m_nID)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }

      fontMenu.CreateFontIndirect (&logFontMenu);

      // DC of the desktop
      CClientDC myDC(NULL);
      // Select menu font in...
      CFont* pOldFont = myDC.SelectObject (&fontMenu);
      // Check the Key-Shortcut replacing for japanise/chinese calculating space
      itemText.Replace(_T("\t"),_T("nnn"));
      VERIFY(::GetTextExtentPoint32(myDC.m_hDC,itemText,itemText.GetLength(),&size));
      // Select old font in
      myDC.SelectObject(pOldFont);
    }// We need this sub-block for releasing the dc

    // Set width and height:
    if(bIsMenuBar)
    {
      if(itemText.Find(_T("&"))>=0)
      {
        lpMIS->itemWidth = size.cx - GetSystemMetrics(SM_CXMENUCHECK)/2;
      }
      else
      {
        lpMIS->itemWidth = size.cx;
      }
    }
    else
    {
      lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
    }

    int temp = GetSystemMetrics(SM_CYMENU);
    lpMIS->itemHeight = (temp>(m_iconY + 6)) ? temp : (m_iconY+6);
    if(lpMIS->itemHeight<((UINT)size.cy) )
    {
      lpMIS->itemHeight=((UINT)size.cy);
    }

    // set status bar as appropriate
    UINT nItemID = (lpMIS->itemID & 0xFFF0);
    // Special case for system menu
    if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY)
    {
      BOOL bGetNext = FALSE;
      // search the actual menu item
      for (int j=0;jm_nID)
          {
            lpMIS->itemData = (ULONG_PTR)pTemp;
            lpMIS->itemID = pTemp->m_nID;
            UINT nOrgWidth = lpMIS->itemWidth;
            MeasureItem_Icy(lpMIS,bIsMenuBar);
            // Restore old values
            lpMIS->itemData = (ULONG_PTR)pMenuData;
            lpMIS->itemID = pMenuData->m_nID;
            lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
            break;
          }
        }
      }
      lpMIS->itemHeight = temp;
    }
  }
}

void CNewMenu::MeasureItem_WinXP( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
{
  ASSERT(lpMIS->itemData);
  CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);

  UINT nFlag = pMenuData->m_nFlags;
  if(nFlag & MF_SEPARATOR)
  {
    if(pMenuData->m_nTitleFlags&MFT_TITLE)
    {
      SIZE size = {0,0};
      {// We need this sub-block for releasing the dc
        // DC of the desktop
        CClientDC myDC(NULL);

        CFont font;
        LOGFONT MyFont = m_MenuTitleFont;
        MyFont.lfOrientation = 0;
        MyFont.lfEscapement = 0;
        font.CreateFontIndirect(&MyFont);

        CFont* pOldFont = myDC.SelectObject (&font);
        CString lpstrText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
        VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
        // Select old font in
        myDC.SelectObject(pOldFont);
      }

      CSize iconSize(0,0);
      if(pMenuData->m_nMenuIconOffset!=(-1) && pMenuData->m_pMenuIcon)
      {
        iconSize = pMenuData->m_pMenuIcon->GetIconSize();
        if(iconSize!=CSize(0,0))
        {
          iconSize += CSize(2,2);
        }
      }

      if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
      {
        if(bWine)
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx);
        }
        else
        {
          lpMIS->itemWidth = max(size.cy,iconSize.cx) - GetSystemMetrics(SM_CXMENUCHECK);
        }
        // Don't make the menu higher than menuitems in it
        lpMIS->itemHeight = 0;
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemWidth += 8;
        }
        else if(pMenuData->m_nTitleFlags&MFT_ROUND)
        {
          lpMIS->itemWidth += 4;
        }
      }
      else
      {
        lpMIS->itemWidth = size.cx + iconSize.cx;
        lpMIS->itemHeight = max(size.cy,iconSize.cy);
        if(pMenuData->m_nTitleFlags&MFT_LINE)
        {
          lpMIS->itemHeight += 8;
        }
      }
    }
    else
    {
      lpMIS->itemHeight = 3;
      lpMIS->itemWidth = 3;
    }
  }
  else
  {
    SIZE size = {0,0};
    //Get pointer to text SK
    CString itemText = pMenuData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
    { // We need this sub-block for releasing the dc
      CFont fontMenu;
      LOGFONT logFontMenu;

  #ifdef _NEW_MENU_USER_FONT
      logFontMenu =  MENU_USER_FONT;
  #else
      NONCLIENTMETRICS nm = {0};
      nm.cbSize = sizeof (NONCLIENTMETRICS);
      VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
      logFontMenu =  nm.lfMenuFont;
  #endif

      // Default selection?
      if (GetDefaultItem(0, FALSE) == pMenuData->m_nID)
      {
        // Make the font bold
        logFontMenu.lfWeight = FW_BOLD;
      }

      fontMenu.CreateFontIndirect (&logFontMenu);

       // DC of the desktop
      CClientDC myDC(NULL);
      // Select menu font in...
      CFont* pOldFont = myDC.SelectObject (&fontMenu);
      // Check the Key-Shortcut replacing for japanise/chinese calculating space
      itemText.Replace(_T("\t"),_T("nnn"));
      VERIFY(::GetTextExtentPoint32(myDC.m_hDC,itemText,itemText.GetLength(),&size));
      // Select old font in
      myDC.SelectObject(pOldFont);
    }// We need this sub-block for releasing the dc

    int temp = GetSystemMetrics(SM_CYMENU);
    // Set width and height:
    if(bIsMenuBar)
    {
      if(itemText.Find(_T("&"))>=0)
      {
        lpMIS->itemWidth = size.cx-6; // - GetSystemMetrics(SM_CXMENUCHECK)/2;
      }
      else
      {
        lpMIS->itemWidth = size.cx;
      }
      lpMIS->itemHeight = temp >(m_iconY+2) ? temp : m_iconY+2;
    }
    else
    {
      if(nFlag&MF_POPUP)
      {
        lpMIS->itemWidth = 2 + m_iconX + 4 + size.cx + GetSystemMetrics(SM_CYMENU);
      }
      else
      {
      lpMIS->itemWidth = 2 + m_iconX +4+ size.cx + GetSystemMetrics(SM_CYMENU) / 2;
      }
      lpMIS->itemHeight = temp>m_iconY+8 ? temp : m_iconY+7;
    }

    if(lpMIS->itemHeight<((UINT)size.cy) )
    {
      lpMIS->itemHeight=((UINT)size.cy);
    }

    // set status bar as appropriate
    UINT nItemID = (lpMIS->itemID & 0xFFF0);
    // Special case for system menu
    if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY)
    {
      BOOL bGetNext = FALSE;
      // search the actual menu item
      for (int j=0;jm_nID)
          {
            lpMIS->itemData = (ULONG_PTR)pTemp;
            lpMIS->itemID = pTemp->m_nID;
            UINT nOrgWidth = lpMIS->itemWidth;
            MeasureItem_WinXP(lpMIS,bIsMenuBar);
            // Restore old values
            lpMIS->itemData = (ULONG_PTR)pMenuData;
            lpMIS->itemID = pMenuData->m_nID;
            lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
            break;
          }
        }
      }
      lpMIS->itemHeight = temp;
    }
  }
  //AfxTrace("IsMenuBar %ld, Height %2ld, width %3ld, ID 0x%08lX \r\n",int(bIsMenuBar),lpMIS->itemHeight,lpMIS->itemWidth,lpMIS->itemID);
}

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

CSize CNewMenu::GetIconSize()
{
  return CSize(m_iconX,m_iconY);
}

BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID, int nIconNormal)
{
  return CNewMenu::AppendODMenu(lpstrText,nFlags,nID,(CImageList*)NULL,nIconNormal);
}

BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
                            CBitmap* pBmp)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,pBmp));
  return AppendODMenu(lpstrText,nFlags,nID,iconLock,nIndex);
}

BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
                            CImageList* pil, int xoffset)
{
  int nIndex = 0;
  // Helper for addref and release
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,nID,pil,xoffset));
  return AppendODMenu(lpstrText,nFlags,nID,iconLock,nIndex);
}

BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
                            CNewMenuIcons* pIcons, int nIndex)
{
  // 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)
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
    if(pSubMenu)
    {
      pSubMenu->m_hParentMenu = m_hMenu;
    }
  }

  CNewMenuItemData* pItemData = new CNewMenuItemData;
  m_MenuItemList.Add(pItemData);
  pItemData->SetString(lpstrText);

  pIcons->AddRef();
  pItemData->m_pMenuIcon->Release();
  pItemData->m_pMenuIcon = pIcons;
  pItemData->m_nFlags = nFlags;
  pItemData->m_nID = nID;

  if(pIcons && nIndex>=0)
  {
    pItemData->m_nMenuIconOffset = nIndex;
    CSize size = pIcons->GetIconSize();
    m_iconX = max(m_iconX,size.cx);
    m_iconY = max(m_iconY,size.cy);
  }
  else
  {
    pItemData->m_nMenuIconOffset = -1;
  }

  // for having automated shortcut handling, thank to Mehdy Bohlool
  if (CMenu::AppendMenu(nFlags&~MF_OWNERDRAW, nID, pItemData->m_szMenuText))
  {
    return CMenu::ModifyMenu( CMenu::GetMenuItemCount()-1, MF_BYPOSITION| nFlags, nID, (LPCTSTR)pItemData );
  }
  return FALSE;
}

BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
                            int nIconNormal)
{
  int nIndex = -1;
  CNewMenuIcons* pIcons=NULL;

  if(nIconNormal>=0)
  {
    if(LoadFromToolBar(nID,nIconNormal,nIndex))
    {
      // the nIconNormal is a toolbar
      pIcons = GetToolbarIcons(nIconNormal);
      if(pIcons)
      {
        nIndex = pIcons->FindIndex(nID);
      }
    }
    else
    {
      // the nIconNormal is a bitmap
      pIcons = GetMenuIcon(nIndex,nIconNormal);
    }
  }

  CNewMenuIconLock iconLock(pIcons);
  return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}

BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID, CBitmap* pBmp)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,pBmp));
  return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}

BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID, CImageList *pil, int xoffset)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,nID,pil,xoffset));
  return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}

BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
                            CNewMenuIcons* pIcons, int nIndex)
{
  if(!(nFlags & MF_BYPOSITION))
  {
    int iPosition =0;
    CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
    if(pMenu)
    {
      return(pMenu->InsertODMenu(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,pIcons,nIndex));
    }
    else
    {
      return(FALSE);
    }
  }

  if(!nID)
  {
    nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  }
  else if(!(nFlags & MF_OWNERDRAW))
  {
    nFlags |= MF_OWNERDRAW;
  }

  if(nFlags & MF_POPUP)
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
    if(pSubMenu)
    {
      pSubMenu->m_hParentMenu = m_hMenu;
    }
  }

  //Stephane Clog suggested adding this, believe it or not it's in the help
  if(nPosition==(UINT)-1)
  {
    nPosition = GetMenuItemCount();
  }

  CNewMenuItemData *pItemData = new CNewMenuItemData;
  m_MenuItemList.InsertAt(nPosition,pItemData);
  pItemData->SetString(lpstrText);

  pIcons->AddRef();
  pItemData->m_pMenuIcon->Release();
  pItemData->m_pMenuIcon = pIcons;
  pItemData->m_nFlags = nFlags;
  pItemData->m_nID = nID;

  if(pIcons && nIndex>=0)
  {
    pItemData->m_nMenuIconOffset = nIndex;
    CSize size = pIcons->GetIconSize();
    m_iconX = max(m_iconX,size.cx);
    m_iconY = max(m_iconY,size.cy);
  }
  else
  {
    pItemData->m_nMenuIconOffset = -1;
  }
  // for having automated shortcut handling, thank to Mehdy Bohlool
  if (CMenu::InsertMenu(nPosition,nFlags&~MF_OWNERDRAW,nID,pItemData->m_szMenuText))
  {
    return CMenu::ModifyMenu(nPosition, MF_BYPOSITION| nFlags, nID, (LPCTSTR)pItemData );
  }
  return FALSE;
}

// Same as ModifyMenu but replacement for CNewMenu
BOOL CNewMenu::ModifyODMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem,LPCTSTR lpszNewItem)
{
  if(!(nFlags & MF_BYPOSITION))
  {
    int iPosition =0;
    CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
    if(pMenu)
    {
      return(pMenu->ModifyODMenu(iPosition,nFlags|MF_BYPOSITION,nIDNewItem,lpszNewItem));
    }
    else
    {
      return(FALSE);
    }
  }
  UINT nMenuID = GetMenuItemID(nPosition);
  if(nMenuID==(UINT)-1)
  {
    nMenuID = HMenuToUInt(::GetSubMenu(m_hMenu,nPosition));
  }
  CNewMenuItemData* pItemData = FindMenuItem(nMenuID);
  BOOL bRet = CMenu::ModifyMenu(nPosition, nFlags, nIDNewItem,lpszNewItem);
  if(pItemData)
  {
    pItemData->m_nID = nIDNewItem;
    GetMenuString(nPosition,pItemData->m_szMenuText,MF_BYPOSITION);
    CMenu::ModifyMenu(nPosition, nFlags|MF_OWNERDRAW, nIDNewItem,(LPCTSTR)pItemData);
  }
  if(bRet && (nFlags & MF_POPUP) )
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nIDNewItem)));
    if(pSubMenu)
    {
      pSubMenu->m_hParentMenu = m_hMenu;
    }
  }
  return bRet;
}

BOOL CNewMenu::ModifyODMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp)
{
  if(!(nFlags & MF_BYPOSITION))
  {
    int iPosition =0;
    CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
    if(pMenu)
    {
      return(pMenu->ModifyODMenu(iPosition,nFlags|MF_BYPOSITION,nIDNewItem,pBmp));
    }
    else
    {
      return(FALSE);
    }
  }
  UINT nMenuID = GetMenuItemID(nPosition);
  if(nMenuID==(UINT)-1)
  {
    nMenuID = HMenuToUInt(::GetSubMenu(m_hMenu,nPosition));
  }
  CNewMenuItemData* pItemData = FindMenuItem(nMenuID);
  BOOL bRet = CMenu::ModifyMenu(nPosition, nFlags, nIDNewItem,pBmp);
  if(pItemData)
  {
    pItemData->m_nID = nIDNewItem;
    pItemData->m_szMenuText.Empty();
    CMenu::ModifyMenu(nPosition, nFlags|MF_OWNERDRAW, nIDNewItem,(LPCTSTR)pItemData);
  }
  if(bRet && (nFlags & MF_POPUP) )
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nIDNewItem)));
    if(pSubMenu)
    {
      pSubMenu->m_hParentMenu = m_hMenu;
    }
  }
  return bRet;
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, int nIconNormal)
{
  int nLoc;
  CNewMenuItemData* pItemData;
  CArraynewSubs;
  CArraynewLocs;

  BOOL bModifyOK = TRUE;

  // Find the old CNewMenuItemData structure:
  CNewMenu* pSubMenu = FindMenuOption(nID,nLoc);
  do {
    if(pSubMenu && nLoc>=0)
    {
      pItemData = pSubMenu->m_MenuItemList[nLoc];
    }
    else
    {
      // Create a new CNewMenuItemData structure:
      pItemData = new CNewMenuItemData;
      m_MenuItemList.Add(pItemData);
    }

    BOOL bTextChanged = FALSE;
    ASSERT(pItemData);
    if(lpstrText && pItemData->m_szMenuText.Compare(lpstrText)!=NULL)
    {
      bTextChanged = TRUE;
      pItemData->SetString(lpstrText);
    }

    pItemData->m_nMenuIconOffset=-1;
    if(nIconNormal>=0)
    {
      int nxOffset = -1;
      CNewMenuIcons* pIcons=NULL;
      if(LoadFromToolBar(nID,nIconNormal,nxOffset))
      {
        // the nIconNormal is a toolbar
        pIcons = GetToolbarIcons(nIconNormal);
        if(pIcons)
        {
          pItemData->m_nMenuIconOffset = pIcons->FindIndex(nID);
        }
      }
      else
      {
        // the nIconNormal is a bitmap
        pIcons = GetMenuIcon(pItemData->m_nMenuIconOffset,nIconNormal);
      }
      pIcons->AddRef();
      pItemData->m_pMenuIcon->Release();
      pItemData->m_pMenuIcon = pIcons;
      if(pIcons)
      {
        CSize size = pIcons->GetIconSize();
        pSubMenu->m_iconX = max(pSubMenu->m_iconX,size.cx);
        pSubMenu->m_iconY = max(pSubMenu->m_iconY,size.cy);
      }
    }
    pItemData->m_nFlags &= ~(MF_BYPOSITION);
    pItemData->m_nFlags |= MF_OWNERDRAW;
    pItemData->m_nID = nID;

    // for having automated shortcut handling
    if(pSubMenu && bTextChanged)
    {
      if(pSubMenu->ModifyMenu(nLoc, MF_BYPOSITION|(pItemData->m_nFlags&~MF_OWNERDRAW), nID,pItemData->m_szMenuText) )
      {
        if(!pSubMenu->ModifyMenu(nLoc, MF_BYPOSITION|pItemData->m_nFlags, nID,(LPCTSTR)pItemData))
        {
          bModifyOK = FALSE;
        }
      }
      else
      {
        bModifyOK = FALSE;
      }
    }

    newSubs.Add(pSubMenu);
    newLocs.Add(nLoc);

    if(pSubMenu && nLoc>=0)
    {
      pSubMenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
    }
    else
    {
      pSubMenu = NULL;
    }
  }while(pSubMenu);

  return (CMenu::ModifyMenu(nID,pItemData->m_nFlags,nID,(LPCTSTR)pItemData)) && bModifyOK;
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CImageList *pil, int xoffset)
{
  int nIndex = 0;
  CNewMenuIcons* pIcons = GetMenuIcon(nIndex,nID,pil,xoffset);
  pIcons->AddRef();

  BOOL bResult = ModifyODMenu(lpstrText,nID,pIcons,nIndex);

  pIcons->Release();

  return bResult;
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CNewMenuIcons* pIcons, int xoffset)
{
  ASSERT(pIcons);
  int nLoc;
  CNewMenuItemData *pItemData;
  CArraynewSubs;
  CArraynewLocs;
  BOOL bModifyOK = TRUE;

  // Find the old CNewMenuItemData structure:
  CNewMenu *pSubMenu = FindMenuOption(nID,nLoc);
  do {
    if(pSubMenu && nLoc>=0)
    {
      pItemData = pSubMenu->m_MenuItemList[nLoc];
    }
    else
    {
      // Create a new CNewMenuItemData structure:
      pItemData = new CNewMenuItemData;
      m_MenuItemList.Add(pItemData);
    }

    BOOL bTextChanged = FALSE;
    ASSERT(pItemData);
    if(lpstrText && pItemData->m_szMenuText.Compare(lpstrText)!=NULL)
    {
      bTextChanged = TRUE;
      pItemData->SetString(lpstrText);
    }

    if(pIcons)
    {
      pIcons->AddRef();
      pItemData->m_pMenuIcon->Release();
      pItemData->m_pMenuIcon = pIcons;

      pItemData->m_nMenuIconOffset = xoffset;

      int x=0;
      int y=0;
      if(pSubMenu && pIcons->GetIconSize(&x,&y))
      {
        // Correct the size of the menuitem
        pSubMenu->m_iconX = max(pSubMenu->m_iconX,x);
        pSubMenu->m_iconY = max(pSubMenu->m_iconY,y);
      }
    }
    else
    {
      pItemData->m_nMenuIconOffset = -1;
    }
    pItemData->m_nFlags &= ~(MF_BYPOSITION);
    pItemData->m_nFlags |= MF_OWNERDRAW;
    pItemData->m_nID = nID;

    // for having automated shortcut handling
    if(pSubMenu && bTextChanged)
    {
      if(pSubMenu->ModifyMenu(nLoc, MF_BYPOSITION|(pItemData->m_nFlags&~MF_OWNERDRAW), nID,pItemData->m_szMenuText) )
      {
        if(!pSubMenu->ModifyMenu(nLoc, MF_BYPOSITION|pItemData->m_nFlags, nID,(LPCTSTR)pItemData))
        {
          bModifyOK = FALSE;
        }
      }
      else
      {
        bModifyOK = FALSE;
      }
    }

    newSubs.Add(pSubMenu);
    newLocs.Add(nLoc);
    if(pSubMenu && nLoc>=0)
    {
      pSubMenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
    }
    else
    {
      pSubMenu = NULL;
    }
  } while(pSubMenu);

  return (CMenu::ModifyMenu(nID,pItemData->m_nFlags,nID,(LPCTSTR)pItemData)) && bModifyOK;
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CBitmap* bmp)
{
  if (bmp)
  {
    CImageList temp;
    temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);

    temp.Add(bmp,GetBitmapBackground());

    return ModifyODMenu(lpstrText,nID,&temp,0);
  }
  return ModifyODMenu(lpstrText,nID,(CImageList*)NULL,0);
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, COLORREF fill, COLORREF border, int hatchstyle)
{
  // Get device context
  CSize bitmap_size(m_iconX,m_iconY);
  CBitmap bmp;
  {
    CClientDC DC(0);
    ColorBitmap(&DC,bmp,bitmap_size,fill,border,hatchstyle);
  }
  return ModifyODMenu(lpstrText,nID,&bmp);
}

BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, LPCTSTR OptionText, int nIconNormal)
{
  int nIndex = 0;
  CNewMenu* pOptionMenu = FindMenuOption(OptionText,nIndex);

  if(pOptionMenu!=NULL && nIndex>=0)
  {
    CNewMenuItemData* pItemData = pOptionMenu->m_MenuItemList[nIndex];

    BOOL bTextChanged = FALSE;
    ASSERT(pItemData);
    if(lpstrText && pItemData->m_szMenuText.Compare(lpstrText)!=NULL)
    {
      bTextChanged = TRUE;
      pItemData->SetString(lpstrText);
    }

    pItemData->m_nMenuIconOffset = nIconNormal;
    if(nIconNormal>=0)
    {
      CNewMenuIcons* pIcons = GetMenuIcon(pItemData->m_nMenuIconOffset,nIconNormal);
      pIcons->AddRef();
      pItemData->m_pMenuIcon->Release();
      pItemData->m_pMenuIcon = pIcons;

      CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,pItemData->m_pMenuIcon);
      if(pMenuIcon)
      {
        CSize size = pMenuIcon->GetIconSize();
        pOptionMenu->m_iconX = max(pOptionMenu->m_iconX,size.cx);
        pOptionMenu->m_iconY = max(pOptionMenu->m_iconY,size.cy);
      }
    }

    // for having automated shortcut handling
    if(pOptionMenu && bTextChanged)
    {
      if(!pOptionMenu->ModifyMenu(nIndex, MF_BYPOSITION|(pItemData->m_nFlags&~MF_OWNERDRAW), pItemData->m_nID,pItemData->m_szMenuText) ||
        !pOptionMenu->ModifyMenu(nIndex, MF_BYPOSITION|pItemData->m_nFlags, pItemData->m_nID,(LPCTSTR)pItemData))
      {
        return FALSE;
      }
    }
    return TRUE;
  }
  return FALSE;
}

CNewMenuItemData* CNewMenu::NewODMenu(UINT pos, UINT nFlags, UINT nID, LPCTSTR string)
{
  CNewMenuItemData* pItemData;

  pItemData = new CNewMenuItemData;
  pItemData->m_nFlags = nFlags;
  pItemData->m_nID = nID;
  if(!(nFlags&MF_BITMAP))
  {
  pItemData->SetString (string);
  }

  if(nFlags & MF_POPUP)
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
    if(pSubMenu)
    {
      pSubMenu->m_hParentMenu = m_hMenu;
    }
  }

  BOOL bModified = FALSE;
  if (nFlags&MF_OWNERDRAW)
  {
    bModified = ModifyMenu(pos,nFlags,nID,(LPCTSTR)pItemData);
  }
  else if (nFlags&MF_BITMAP)
  {
    bModified = ModifyMenu(pos,nFlags,nID,(CBitmap*)string);
  }
  else if (nFlags&MF_SEPARATOR)
  {
    ASSERT(nFlags&MF_SEPARATOR);
    bModified = ModifyMenu(pos,nFlags,nID);
  }
  else // (nFlags&MF_STRING)
  {
    ASSERT(!(nFlags&MF_OWNERDRAW));
    bModified = ModifyMenu(pos,nFlags,nID,pItemData->GetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL));
  }
  if(!bModified)
  {
    ShowLastError(_T("Error from Menu: ModifyMenu"));
  }
  return(pItemData);
};

BOOL CNewMenu::LoadToolBars(const UINT* arID, int n, HMODULE hInst)
{
  ASSERT(arID);
  BOOL returnflag = TRUE;
  for(int i=0;im_IDs.GetSize();
  while(nCount--)
  {
    ModifyODMenu(NULL,pMenuIcons->m_IDs[nCount],pMenuIcons,nCount*MENU_ICONS);
  }
  return pMenuIcons->m_dwRefCount;
}

CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, UINT nID, CImageList *pil, int xoffset)
{
  if(pil==NULL || xoffset<0)
  {
    nIndex=-1;
    return NULL;
  }

  HICON hIcon = pil->ExtractIcon(xoffset);

  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
      if(pMenuIcon)
      {
        nIndex = pMenuIcon->Add(hIcon,nID);
        if(nIndex!=-1)
        {
          DestroyIcon(hIcon);
          return pMenuIcon;
        }
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
  pMenuIcon->m_crTransparent = m_bitmapBackground;
  nIndex = pMenuIcon->Add(hIcon,nID);
  DestroyIcon(hIcon);
  if(nIndex!=-1)
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    return pMenuIcon;
  }
  delete pMenuIcon;
  return NULL;
}

CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, int nID)
{
  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
      if(pMenuIcon)
      {
        if(m_bDynIcons)
        {
          nIndex = pMenuIcon->Add((HICON)(INT_PTR)nID);
        }
        else
        {
          nIndex = pMenuIcon->Add(nID,m_bitmapBackground);
        }
        if(nIndex!= -1)
        {
          return pMenuIcon;
        }
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
  pMenuIcon->m_crTransparent = m_bitmapBackground;
  nIndex = pMenuIcon->Add(nID,m_bitmapBackground);
  if(nIndex!=-1)
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    return pMenuIcon;
  }
  delete pMenuIcon;
  return NULL;
}

CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, CBitmap* pBmp)
{
  if(pBmp==NULL)
  {
    nIndex=-1;
    return NULL;
  }

  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
      if(pMenuIcon)
      {
        nIndex = pMenuIcon->Add(pBmp,m_bitmapBackground);
        if(nIndex!=-1)
        {
          return pMenuIcon;
        }
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
  pMenuIcon->m_crTransparent = m_bitmapBackground;
  nIndex = pMenuIcon->Add(pBmp,m_bitmapBackground);
  if(nIndex!=-1)
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    return pMenuIcon;
  }
  delete pMenuIcon;
  return NULL;
}


CNewMenuIcons* CNewMenu::GetToolbarIcons(UINT nToolBar, HMODULE hInst)
{
  ASSERT_VALID(this);
  ASSERT(nToolBar != NULL);

  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuIcons* pMenuIcon = m_pSharedMenuIcons->GetNext(pos);
      if(pMenuIcon->DoMatch(MAKEINTRESOURCE(nToolBar),hInst))
      {
        return pMenuIcon;
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuIcons* pMenuIcon = new CNewMenuIcons();
  pMenuIcon->m_crTransparent = m_bitmapBackground;
  if(pMenuIcon->LoadToolBar(MAKEINTRESOURCE(nToolBar),hInst))
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    return pMenuIcon;
  }
  delete pMenuIcon;
  return NULL;
}


BOOL CNewMenu::LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst)
{
  CNewMenuIcons* pMenuIcon = GetToolbarIcons((UINT)(UINT_PTR)lpszResourceName,hInst);
  if(pMenuIcon)
  {
    SetMenuIcons(pMenuIcon);
    return TRUE;
  }
  return FALSE;
}

BOOL CNewMenu::LoadToolBar(HBITMAP hBitmap, CSize size, UINT* pID, COLORREF crTransparent)
{
  ASSERT_VALID(this);
  ASSERT(pID);

  if(crTransparent==CLR_NONE)
  {
    crTransparent = m_bitmapBackground;
  }
  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuIcons* pMenuIcon = m_pSharedMenuIcons->GetNext(pos);
      if(pMenuIcon->DoMatch(hBitmap,size,pID))
      {
        SetMenuIcons(pMenuIcon);
        return TRUE;
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuIcons* pMenuIcon = new CNewMenuIcons();
  if(pMenuIcon->LoadToolBar(hBitmap,size,pID,crTransparent))
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    SetMenuIcons(pMenuIcon);
    return TRUE;
  }
  delete pMenuIcon;
  return FALSE;
}

BOOL CNewMenu::LoadToolBar(WORD* pToolInfo, COLORREF crTransparent)
{
  ASSERT_VALID(this);
  ASSERT(pToolInfo);

  if(crTransparent==CLR_NONE)
  {
    crTransparent = m_bitmapBackground;
  }

  if(m_pSharedMenuIcons!=NULL)
  {
    POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
    while(pos)
    {
      CNewMenuIcons* pMenuIcon = m_pSharedMenuIcons->GetNext(pos);
      if(pMenuIcon->DoMatch(pToolInfo,crTransparent))
      {
        SetMenuIcons(pMenuIcon);
        return TRUE;
      }
    }
  }
  else
  {
    m_pSharedMenuIcons = new CTypedPtrList;
  }
  CNewMenuIcons* pMenuIcon = new CNewMenuIcons();
  if(pMenuIcon->LoadToolBar(pToolInfo,crTransparent))
  {
    m_pSharedMenuIcons->AddTail(pMenuIcon);
    SetMenuIcons(pMenuIcon);
    return TRUE;
  }
  delete pMenuIcon;
  return FALSE;
}


// Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
// added this function as a helper to LoadToolBar(WORD* pToolInfo, COLORREF crTransparent), the purpose of this function
// is to easily load a high color toolbar to the menu, instead of creating and maintaining a command map.  this function
// simply reads an existing 16 bit toolbar, and builds the word map based on that toolbar, using the 256 color bitmap.
BOOL CNewMenu::LoadToolBar(UINT n16ToolBarID, UINT n256BitmapID, COLORREF transparentColor, HMODULE hInst)
{
  BOOL bRet = FALSE;
  // determine location of the bitmap in resource
  if(hInst==0)
  {
    hInst = AfxFindResourceHandle(MAKEINTRESOURCE(n16ToolBarID), RT_TOOLBAR);
  }
  HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(n16ToolBarID), RT_TOOLBAR);

  if (hRsrc == NULL)
  { // Special purpose when you try to load it from a dll 30.05.2002
    if(AfxGetResourceHandle()!=hInst)
    {
      hInst = AfxGetResourceHandle();
      hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(n16ToolBarID), RT_TOOLBAR);
    }
    if (hRsrc == NULL)
    {
      return FALSE;
    }
  }

  HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
  if (hGlobal)
  {
    CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
    if (pData)
    {
      int nSize = sizeof(WORD)*(pData->wItemCount+4);
      // no need for delete
      WORD* pToolId = (WORD*)_alloca(nSize);
      // sets also the last entry to zero
      ZeroMemory(pToolId,nSize);

      pToolId[0] = (WORD)n256BitmapID;
      pToolId[1] = pData->wWidth;
      pToolId[2] = pData->wHeight;

      WORD* pTemp = pToolId+3;
      for (int nIndex = 0; nIndex < pData->wItemCount; nIndex++)
      { // not a seperator?
        if( (pData->items()[nIndex]) )
        {
          *pTemp++ = pData->items()[nIndex];
        }
      }
      // load the toolbar images into the menu
      bRet = LoadToolBar(pToolId, transparentColor);
      UnlockResource(hGlobal);
    }
    FreeResource(hGlobal);
  }
  // return TRUE for success, FALSE for failure
  return (bRet);
} // LoadHiColor


BOOL CNewMenu::LoadToolBar(UINT nToolBar, HMODULE hInst)
{
  return LoadToolBar((LPCTSTR)(UINT_PTR)nToolBar,hInst);
}

BOOL CNewMenu::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.
CNewMenuItemData* CNewMenu::FindMenuItem(UINT nID)
{
  CNewMenuItemData *pData = NULL;
  int i;

  for(i = 0; i < m_MenuItemList.GetSize(); i++)
  {
    if (m_MenuItemList[i]->m_nID == nID)
    {
      pData = m_MenuItemList[i];
      break;
    }
  }
  if (!pData)
  {
    int loc;
    CNewMenu *pMenu = FindMenuOption(nID, loc);
    ASSERT(pMenu != this);
    if (loc >= 0)
    {
      return pMenu->FindMenuItem(nID);
    }
  }
  return pData;
}


CNewMenu* CNewMenu::FindAnotherMenuOption(int nId, int& nLoc,
                                          CArray&newSubs,
                                          CArray&newLocs)
{
  int i,numsubs,j;
  CNewMenu *pSubMenu,*pgoodmenu;
  BOOL foundflag;

  for(i=0;i<(int)(GetMenuItemCount());++i)
  {
    pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
    if(pSubMenu)
    {
      pgoodmenu = pSubMenu->FindAnotherMenuOption(nId,nLoc,newSubs,newLocs);
      if(pgoodmenu)
      {
        return pgoodmenu;
      }
    }
    else if(nId==(int)GetMenuItemID(i))
    {
      numsubs = (int)newSubs.GetSize();
      foundflag = TRUE;
      for(j=0;jFindMenuOption(nId,nLoc);
      if(pgoodmenu)
      {
        return pgoodmenu;
      }
    }
    else if(nId==(int)GetMenuItemID(i))
    {
      nLoc = i;
      return(this);
    }
  }
  nLoc = -1;
  return NULL;
}

CNewMenu* CNewMenu::FindMenuOption(LPCTSTR lpstrText, int& nLoc)
{
  int i;
  // First look for all item text.
  for(i=0;i<(int)m_MenuItemList.GetSize();++i)
  {
    if(m_MenuItemList[i]->m_szMenuText.Compare(lpstrText)==NULL)
    {
      nLoc = i;
      return this;
    }
  }
  CNewMenu* pSubMenu;
  // next, look in all submenus
  for(i=0; i<(int)(GetMenuItemCount());++i)
  {
    pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
    if(pSubMenu)
    {
      pSubMenu = pSubMenu->FindMenuOption(lpstrText,nLoc);
      if(pSubMenu)
      {
        return pSubMenu;
      }
    }
  }
  nLoc = -1;
  return NULL;
}

BOOL CNewMenu::LoadMenu(HMENU hMenu)
{
  if(!::IsMenu(hMenu) || !Attach(hMenu))
  {
    return FALSE;
  }
  m_bIsPopupMenu = FALSE;
  for(int i=0;i<(int)(GetMenuItemCount());++i)
  {
    HMENU hSubMenu = ::GetSubMenu(m_hMenu,i);
    if(hSubMenu)
    {
      CNewMenu* pMenu = new CNewMenu(m_hMenu);
      m_SubMenus.Add(hSubMenu);
      pMenu->LoadMenu(hSubMenu);
      pMenu->m_bIsPopupMenu = TRUE;
    }
  }
  SynchronizeMenu();
  return TRUE;
}

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

BOOL CNewMenu::LoadMenu(LPCTSTR lpszResourceName)
{
  ASSERT(this);
  HMENU hMenu = ::LoadMenu(AfxFindResourceHandle(lpszResourceName,RT_MENU), lpszResourceName);
  #ifdef _DEBUG
  ShowLastError(_T("Error from Menu: LoadMenu"));
  #endif
  return LoadMenu(hMenu);
}

BOOL CNewMenu::SetItemData(UINT uiId, DWORD_PTR dwItemData, BOOL fByPos)
{
  MENUITEMINFO MenuItemInfo = {0};
  MenuItemInfo.cbSize = sizeof(MenuItemInfo);
  MenuItemInfo.fMask = MIIM_DATA;
  if(::GetMenuItemInfo(m_hMenu,uiId,fByPos,&MenuItemInfo))
  {
    CNewMenuItemData* pItem = CheckMenuItemData(MenuItemInfo.dwItemData);
    if(pItem)
    {
      pItem->m_pData = (void*)dwItemData;
      return TRUE;
    }
  }
  return FALSE;
}

BOOL CNewMenu::SetItemDataPtr(UINT uiId, void* pItemData, BOOL fByPos )
{
  return SetItemData(uiId, (DWORD_PTR) pItemData, fByPos);
}

DWORD_PTR CNewMenu::GetItemData(UINT uiId, BOOL fByPos) const
{
  MENUITEMINFO MenuItemInfo = {0};
  MenuItemInfo.cbSize = sizeof(MenuItemInfo);
  MenuItemInfo.fMask = MIIM_DATA;
  if(::GetMenuItemInfo(m_hMenu,uiId,fByPos,&MenuItemInfo))
  {
    CNewMenuItemData* pItem = CheckMenuItemData(MenuItemInfo.dwItemData);
    if(pItem)
    {
      return (DWORD_PTR)pItem->m_pData;
    }
  }
  return DWORD_PTR(-1);
}

void* CNewMenu::GetItemDataPtr(UINT uiId, BOOL fByPos) const
{
  return (void*)GetItemData(uiId,fByPos);
}

BOOL CNewMenu::SetMenuData(DWORD_PTR dwMenuData)
{
  m_pData = (void*)dwMenuData;
  return TRUE;
}

BOOL CNewMenu::SetMenuDataPtr(void* pMenuData)
{
  m_pData = (void*)pMenuData;
  return TRUE;
}

DWORD_PTR CNewMenu::GetMenuData() const
{
  return (DWORD_PTR)m_pData;
}

void* CNewMenu::GetMenuDataPtr() const
{
  return m_pData;
}

BOOL  CNewMenu::m_bDrawAccelerators = TRUE;

BOOL  CNewMenu::SetAcceleratorsDraw (BOOL bDraw)
{
  BOOL bOld = m_bDrawAccelerators;
  m_bDrawAccelerators = bDraw;
  return bOld;
}
BOOL  CNewMenu::GetAcceleratorsDraw ()
{
  return m_bDrawAccelerators;
}

BYTE CNewMenu::m_bAlpha = 255;

BYTE CNewMenu::SetAlpha(BYTE bAlpha)
{
  BYTE oldAlpha = m_bAlpha;
  m_bAlpha = bAlpha;
  return oldAlpha;
}

BYTE CNewMenu::GetAlpha()
{
  return m_bAlpha;
}

// INVALID_HANDLE_VALUE = Draw default frame's accel. NULL = Off
HACCEL  CNewMenu::SetAccelerator (HACCEL hAccel)
{
  HACCEL hOld = m_hAccelToDraw;
  m_hAccelToDraw = hAccel;
  return hOld;
}
HACCEL  CNewMenu::GetAccelerator ()
{
  return m_hAccelToDraw;
}

void CNewMenu::LoadCheckmarkBitmap(int unselect, int select)
{
  if(unselect>0 && select>0)
  {
    m_selectcheck = select;
    m_unselectcheck = unselect;
    if(m_checkmaps)
    {
      m_checkmaps->DeleteImageList();
    }
    else
    {
      m_checkmaps = new CImageList();
    }

    m_checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
    BOOL flag1 = AddBitmapToImageList(m_checkmaps,unselect);
    BOOL flag2 = AddBitmapToImageList(m_checkmaps,select);

    if(!flag1||!flag2)
    {
      m_checkmaps->DeleteImageList();
      delete m_checkmaps;
      m_checkmaps = NULL;
    }
  }
}

BOOL CNewMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
{
  if(MF_BYPOSITION&nFlags)
  {
    UINT numMenuItems = (int)m_MenuItemList.GetSize();
    if(idGetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
      return TRUE;
    }
  }
  else
  {
    int uiLoc;
    CNewMenu* pMenu = FindMenuOption(id,uiLoc);
    if(NULL!=pMenu)
    {
      return pMenu->GetMenuText(uiLoc,string);
    }
  }
  return FALSE;
}

CNewMenuItemData* CNewMenu::CheckMenuItemData(ULONG_PTR nItemData) const
{
  for(int i=0;im_nID==nID && !pMenuItem->m_nSyncFlag)
    {
      pMenuItem->m_nSyncFlag = 1;
      return pMenuItem;
    }
  }
  return NULL;
}

void CNewMenu::InitializeMenuList(int value)
{
  for(int i=0;im_nSyncFlag = value;
  }
}

void CNewMenu::DeleteMenuList()
{
  for(int i=0;im_nSyncFlag)
    {
      delete m_MenuItemList[i];
    }
  }
}

void CNewMenu::SynchronizeMenu()
{
  CTypedPtrArray temp;
  CNewMenuItemData *pItemData;
  CString string;
  UINT submenu,state,j;

  InitializeMenuList(0);
  for(j=0;j=SC_SIZE && nID<=SC_HOTKEY)
        // we do not support bitmap in menu because the OS handle it not right with
        // ownerdrawn style so let show the default one
        {
        pItemData = new CNewMenuItemData;
        pItemData->m_nFlags = state;
        pItemData->m_nID = nID;
      }
        //else
        //{
        //  // sets the handle of the bitmap
        //  pItemData = NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,nID,menuInfo.dwTypeData);
        //}
      }
    }
    else if(state&MF_POPUP)
    {
      HMENU hSubMenu = GetSubMenu(j)->m_hMenu;
      submenu = HMenuToUInt(hSubMenu);
      pItemData = FindMenuList(submenu);
      GetMenuString(j,string,MF_BYPOSITION);

      if(!pItemData)
      {
        state &= ~(MF_USECHECKBITMAPS|MF_SEPARATOR);
        pItemData = NewODMenu(j,state|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
      }
      else if(!string.IsEmpty ())
      {
        pItemData->SetString(string);
      }

      CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hSubMenu));
      if(pSubMenu && pSubMenu->m_hParentMenu!=m_hMenu)
      { // Sets again the parent to this one
        pSubMenu->m_hParentMenu = m_hMenu;
      }
    }
    else if(state&MF_SEPARATOR)
    {
      pItemData = FindMenuList(0);
      if(!pItemData)
      {
        pItemData = NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,0,_T(""));
      }
      else
      {
        pItemData->m_nFlags = state|MF_BYPOSITION|MF_OWNERDRAW;
        ModifyMenu(j,pItemData->m_nFlags,0,(LPCTSTR)pItemData);
      }
    }
    else
    {
      UINT nID = GetMenuItemID(j);
      pItemData = FindMenuList(nID);
      GetMenuString(j,string,MF_BYPOSITION);

      if(!pItemData)
      {
        pItemData = NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,nID,string);
      }
      else
      {
        pItemData->m_nFlags = state|MF_BYPOSITION|MF_OWNERDRAW;
        if(string.GetLength()>0)
        {
          pItemData->SetString(string);
        }
        ModifyMenu(j,pItemData->m_nFlags,nID,(LPCTSTR)pItemData);
      }
    }
    if(pItemData)
    {
      temp.Add(pItemData);
    }
  }
  DeleteMenuList();
  m_MenuItemList.RemoveAll();
  m_MenuItemList.Append(temp);
  temp.RemoveAll();
}

void CNewMenu::OnInitMenuPopup(HWND hWnd, CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
  UNREFERENCED_PARAMETER(nIndex);
  UNREFERENCED_PARAMETER(bSysMenu);

#ifdef _TRACE_MENU_
  AfxTrace(_T("InitMenuPopup: 0x%lx from Wnd 0x%lx\n"),HMenuToUInt(pPopupMenu->m_hMenu),HWndToUInt(hWnd));
#endif
  CNewMenuHook::m_hLastMenu = pPopupMenu->m_hMenu;

  if(IsMenu(pPopupMenu->m_hMenu))
  {
    CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,pPopupMenu);
    if(pSubMenu)
    {
      pSubMenu->m_hTempOwner = hWnd;
      pSubMenu->OnInitMenuPopup();
      HMENU hMenu = pSubMenu->GetParent();
      CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
      if(pParent)
      {
        pParent->m_dwOpenMenu += 1;
        if(pParent->m_dwOpenMenu==1 && !pParent->m_bIsPopupMenu)
        {
          // Redraw the menubar for the shade
          CRect rect = pParent->GetLastActiveMenuRect();
          if(!rect.IsRectEmpty())
          {
            rect.InflateRect(0,0,10,10);
            CPoint Point(0,0);
            ClientToScreen(hWnd,&Point);
            rect.OffsetRect(-Point);
            RedrawWindow(hWnd,rect,0,RDW_FRAME|RDW_INVALIDATE);
          }
        }
      }
    }
  }
}

BOOL CNewMenu::Replace(UINT nID, UINT nNewID)
{
  int nLoc=0;
  CNewMenu* pTempMenu = FindMenuOption(nID,nLoc);
  if(pTempMenu && nLoc >= 0)
  {
#ifdef _TRACE_MENU_
    AfxTrace(_T("Replace MenuID 0x%X => 0x%X\n"),nID,nNewID);
#endif
    CNewMenuItemData* pData = pTempMenu->m_MenuItemList[nLoc];
    UINT nFlags = pData->m_nFlags|MF_OWNERDRAW|MF_BYPOSITION;
    pData->m_nID = nNewID;
    return pTempMenu->ModifyMenu(nLoc,nFlags,nNewID,(LPCTSTR)pData);
  }
  return FALSE;
}

void CNewMenu::OnInitMenuPopup()
{
  m_bIsPopupMenu = true;
  SynchronizeMenu();
  // Special purpose for windows XP with themes!!!
  if(g_Shell==WinXP)
  {
    Replace(SC_RESTORE,SC_RESTORE+1);
    Replace(SC_CLOSE,SC_CLOSE+1);
    Replace(SC_MINIMIZE,SC_MINIMIZE+1);
  }
}

BOOL CNewMenu::OnUnInitPopupMenu()
{
#ifdef _TRACE_MENU_
  AfxTrace(_T("UnInitMenuPopup: 0x%lx\n"),HMenuToUInt(m_hMenu));
#endif
  if(g_Shell==WinXP)
  {
    // Special purpose for windows XP with themes!!!
    // Restore old values otherwise you have disabled windowbuttons
    Replace(SC_MINIMIZE+1,SC_MINIMIZE);
    Replace(SC_RESTORE+1,SC_RESTORE);
    if(Replace(SC_CLOSE+1,SC_CLOSE))
    {
      //EnableMenuItem(SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
      SetWindowPos(m_hTempOwner,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
    }
    //Replace(SC_RESTORE+1,SC_RESTORE);
    //Replace(SC_MINIMIZE+1,SC_MINIMIZE);
  }

  HMENU hMenu = GetParent();
  CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
  if(pParent)
  {
    pParent->m_dwOpenMenu -= 1;
    if(pParent->m_dwOpenMenu>=NULL && !pParent->m_bIsPopupMenu)
    {
      pParent->m_dwOpenMenu = 0;
      // Redraw the menubar for the shade
      CRect rect = pParent->GetLastActiveMenuRect();
      if(!rect.IsRectEmpty())
      {
        rect.InflateRect(0,0,10,10);
        CPoint Point(0,0);
        ClientToScreen(m_hTempOwner,&Point);
        rect.OffsetRect(-Point);
        RedrawWindow(m_hTempOwner,rect,0,RDW_FRAME|RDW_INVALIDATE);
      }
      return TRUE;
    }
  }
  return FALSE;
}

LRESULT CNewMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags, CMenu* pMenu)
{
  UNREFERENCED_PARAMETER(nFlags);

  CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,pMenu);
  if(pNewMenu)
  {
    //SK: modified for Unicode correctness
    CString key(_T('&'),2);
    key.SetAt(1,(TCHAR)nChar);
    key.MakeLower();
    CString menutext;
    int menusize = (int)pNewMenu->GetMenuItemCount();
    if(menusize!=(pNewMenu->m_MenuItemList.GetSize()))
    {
      pNewMenu->SynchronizeMenu();
    }
    for(int i=0;iGetMenuText(i,menutext))
      {
        menutext.MakeLower();
        if(menutext.Find(key)>=0)
        {
          return(MAKELRESULT(i,2));
        }
      }
    }
  }
  return NULL;
}

BOOL CNewMenu::AddBitmapToImageList(CImageList* bmplist,UINT nResourceID)
{
  // O.S.
  if (m_bDynIcons)
  {
    bmplist->Add((HICON)(UINT_PTR)nResourceID);
    return TRUE;
  }

  CBitmap mybmp;
  HBITMAP hbmp = LoadSysColorBitmap(nResourceID);
  if(hbmp)
  {
    // Object will be destroyd by destructor of CBitmap
    mybmp.Attach(hbmp);
  }
  else
  {
    mybmp.LoadBitmap(nResourceID);
  }

  if (mybmp.m_hObject && bmplist->Add(&mybmp,GetBitmapBackground())>=0 )
  {
    return TRUE;
  }

  return FALSE;
}

COLORREF CNewMenu::SetBitmapBackground(COLORREF newColor)
{
  COLORREF oldColor = m_bitmapBackground;
  m_bitmapBackground = newColor;
  return oldColor;
}

COLORREF CNewMenu::GetBitmapBackground()
{
  if(m_bitmapBackground==CLR_DEFAULT)
    return GetSysColor(COLOR_3DFACE);

  return m_bitmapBackground;
}

BOOL CNewMenu::Draw3DCheckmark(CDC *pDC, CRect rect, HBITMAP hbmpChecked, HBITMAP hbmpUnchecked, DWORD dwState)
{
  if(dwState&ODS_CHECKED || hbmpUnchecked)
  {
    rect.InflateRect(-1,-1);

    if (IsNewShell()) //SK: looks better on the old shell
    {
      pDC->DrawEdge(rect, BDR_SUNKENOUTER, BF_RECT);
    }

    rect.InflateRect (2,2);
    if(dwState&ODS_CHECKED)
    {
      if (!hbmpChecked)
      { // Checkmark
        rect.OffsetRect(1,2);
        DrawSpecialCharStyle(pDC,rect,98,dwState);
      }
      else if(!hbmpUnchecked)
      { // Bullet
        DrawSpecialCharStyle(pDC,rect,105,dwState);
      }
      else
      {
        // Draw Bitmap
        BITMAP myInfo = {0};
        GetObject((HGDIOBJ)hbmpChecked,sizeof(myInfo),&myInfo);
        CPoint Offset = rect.TopLeft() + CPoint((rect.Width()-myInfo.bmWidth)/2,(rect.Height()-myInfo.bmHeight)/2);
        pDC->DrawState(Offset,CSize(0,0),hbmpChecked,DST_BITMAP|DSS_MONO);
      }
    }
    else
    {
      // Draw Bitmap
      BITMAP myInfo = {0};
      GetObject((HGDIOBJ)hbmpUnchecked,sizeof(myInfo),&myInfo);
      CPoint Offset = rect.TopLeft() + CPoint((rect.Width()-myInfo.bmWidth)/2,(rect.Height()-myInfo.bmHeight)/2);
      if(dwState & ODS_DISABLED)
      {
        pDC->DrawState(Offset,CSize(0,0),hbmpUnchecked,DST_BITMAP|DSS_MONO|DSS_DISABLED);
      }
      else
      {
        pDC->DrawState(Offset,CSize(0,0),hbmpUnchecked,DST_BITMAP|DSS_MONO);
      }
    }
    return TRUE;
  }
  return FALSE;
}

HBITMAP CNewMenu::LoadSysColorBitmap(int nResourceId)
{
  HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  HRSRC 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);
}

// sPos means Seperator's position, since we have no way to find the
// seperator's position in the menu we have to specify them when we call the
// RemoveMenu to make sure the unused seperators are removed;
// sPos  = None no seperator removal;
//       = Head  seperator in front of this menu item;
//       = Tail  seperator right after this menu item;
//       = Both  seperators at both ends;
// remove the menu item based on their text, return -1 if not found, otherwise
// return the menu position;
int CNewMenu::RemoveMenu(LPCTSTR pText, ESeperator sPos)
{
  int nPos = GetMenuPosition(pText);
  if(nPos != -1)
  {
    switch (sPos)
    {
    case CNewMenu::NONE:
      RemoveMenu(nPos, MF_BYPOSITION);
      break;

    case CNewMenu::HEAD:
      ASSERT(nPos - 1 >= 0);
      RemoveMenu(nPos-1, MF_BYPOSITION);
      break;

    case CNewMenu::TAIL:
      RemoveMenu(nPos+1, MF_BYPOSITION);
      break;

    case CNewMenu::BOTH:
      // remove the end first;
      RemoveMenu(nPos+1, MF_BYPOSITION);
      // remove the head;
      ASSERT(nPos - 1 >= 0);
      RemoveMenu(nPos-1, MF_BYPOSITION);
      break;
    }
  }
  return nPos;
}

BOOL CNewMenu::RemoveMenu(UINT uiId, UINT nFlags)
{
  if(MF_BYPOSITION&nFlags)
  {
    UINT nItemState = GetMenuState(uiId,MF_BYPOSITION);
    if((nItemState&MF_SEPARATOR) && !(nItemState&MF_POPUP))
    {
      CNewMenuItemData* pData =  m_MenuItemList.GetAt(uiId);
      m_MenuItemList.RemoveAt(uiId);
      delete pData;
    }
    else
    {
      CMenu* pSubMenu = GetSubMenu(uiId);
      if(NULL==pSubMenu)
      {
        UINT uiCommandId = GetMenuItemID(uiId);
        for(int i=0;im_nID==uiCommandId)
          {
            CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
            m_MenuItemList.RemoveAt(i);
            delete pData;
            break;
          }
        }
      }
      else
      {
        // Only remove the menu.
        int numSubMenus = (int)m_SubMenus.GetSize();
        while(numSubMenus--)
        {
          if(m_SubMenus[numSubMenus]==pSubMenu->m_hMenu)
          {
            m_SubMenus.RemoveAt(numSubMenus);
          }
        }
        numSubMenus = (int)m_MenuItemList.GetSize();
        while(numSubMenus--)
        {
          if(m_MenuItemList[numSubMenus]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
          {
            CNewMenuItemData* pData = m_MenuItemList.GetAt(numSubMenus);
            m_MenuItemList.RemoveAt(numSubMenus);
            delete pData;
            break;
          }
        }
        // Don't delete it's only remove
        //delete pSubMenu;
      }
    }
  }
  else
  {
    int iPosition =0;
    CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
    if(pMenu)
    {
      return pMenu->RemoveMenu(iPosition,MF_BYPOSITION);
    }
  }
  return CMenu::RemoveMenu(uiId,nFlags);
}

BOOL CNewMenu::DeleteMenu(UINT uiId, UINT nFlags)
{
  if(MF_BYPOSITION&nFlags)
  {
    UINT nItemState = GetMenuState(uiId,MF_BYPOSITION);
    if( (nItemState&MF_SEPARATOR) && !(nItemState&MF_POPUP))
    {
      CNewMenuItemData* pData = m_MenuItemList.GetAt(uiId);
      m_MenuItemList.RemoveAt(uiId);
      delete pData;
    }
    else
    {
      CMenu* pSubMenu = GetSubMenu(uiId);
      if(NULL==pSubMenu)
      {
        UINT uiCommandId = GetMenuItemID(uiId);
        for(int i=0;im_nID==uiCommandId)
          {
            CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
            m_MenuItemList.RemoveAt(i);
            delete pData;
          }
        }
      }
      else
      {
        BOOL bCanDelete = FALSE;
        int numSubMenus = (int)m_SubMenus.GetSize();
        while(numSubMenus--)
        {
          if(m_SubMenus[numSubMenus]==pSubMenu->m_hMenu)
          {
            m_SubMenus.RemoveAt(numSubMenus);
            bCanDelete = TRUE;
          }
        }

        numSubMenus = (int)m_MenuItemList.GetSize();
        while(numSubMenus--)
        {
          if(m_MenuItemList[numSubMenus]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
          {
            CNewMenuItemData* pData = m_MenuItemList.GetAt(numSubMenus);
            m_MenuItemList.RemoveAt(numSubMenus);
            delete pData;
            break;
          }
        }
        // Did we created the menu
        if(bCanDelete)
        { // Oh yes so we can destroy it
          delete pSubMenu;
        }
      }
    }
  }
  else
  {
    int iPosition =0;
    CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
    if(pMenu)
    {
      return pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
    }
  }
  return CMenu::DeleteMenu(uiId,nFlags);
}

BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, int nIconNormal)
{
  return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}

BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CImageList* il, int xoffset)
{
  return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}

BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CBitmap* bmp)
{
  return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,bmp);
}

BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, int nIconNormal)
{
  return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}

BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CImageList* il, int xoffset)
{
  return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}

BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CBitmap* bmp)
{
  return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,bmp);
}

CNewMenu* CNewMenu::AppendODPopupMenu(LPCTSTR lpstrText)
{
  CNewMenu* pSubMenu = new CNewMenu(m_hMenu);
  pSubMenu->m_unselectcheck=m_unselectcheck;
  pSubMenu->m_selectcheck=m_selectcheck;
  pSubMenu->m_checkmaps=m_checkmaps;
  pSubMenu->m_checkmapsshare=TRUE;
  pSubMenu->CreatePopupMenu();
  if(AppendODMenu(lpstrText,MF_POPUP,HMenuToUInt(pSubMenu->m_hMenu), -1))
  {
    m_SubMenus.Add(pSubMenu->m_hMenu);
    return pSubMenu;
  }
  delete pSubMenu;
  return NULL;
}

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

CMenu* CNewMenu::GetSubMenu(LPCTSTR lpszSubMenuName) const
{
  int num = GetMenuItemCount ();
  CString name;
  MENUITEMINFO info = {0};

  for (int i=0; iGetString(m_bDrawAccelerators ? m_hAccelToDraw : NULL);
      }
    }

    if (name.Compare (lpszSubMenuName) == 0)
    {
      return CMenu::GetSubMenu (i);
    }
  }
  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 CNewMenu::GetMenuPosition(LPCTSTR pText)
{
  for(int i=0;i<(int)(GetMenuItemCount());++i)
  {
    if(!GetSubMenu(i))
    {
      for(int j=0;jm_szMenuText.Compare(pText)==NULL)
        {
          return j;
        }
      }
    }
  }
  // means no found;
  return -1;
}

BOOL CNewMenu::RemoveMenuTitle()
{
  int numMenuItems = (int)m_MenuItemList.GetSize();

  // We need a seperator at the beginning of the menu
  if(!numMenuItems || !((m_MenuItemList[0]->m_nFlags)&MF_SEPARATOR) )
  {
    return FALSE;
  }
  CNewMenuItemData* pMenuData = m_MenuItemList[0];
  // Check for title
  if(pMenuData->m_nTitleFlags&MFT_TITLE)
  {
    if(numMenuItems>0)
    {
      CNewMenuItemData* pMenuNextData = m_MenuItemList[1];
      if((pMenuNextData->m_nFlags&MF_MENUBREAK))
      {
        pMenuNextData->m_nFlags &= ~MF_MENUBREAK;
        CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuNextData->m_nFlags,pMenuNextData->m_nID,(LPCTSTR)pMenuNextData);
      }
    }
    // Now remove the title
    RemoveMenu(0,MF_BYPOSITION);
    return TRUE;
  }
  return FALSE;
}

BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, int nIconNormal)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,nIconNormal));
  return SetMenuTitle(pTitle,nTitleFlags,iconLock,nIndex);
}

BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CBitmap* pBmp)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,pBmp));
  return SetMenuTitle(pTitle,nTitleFlags,iconLock,nIndex);
}

BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CImageList *pil, int xoffset)
{
  int nIndex = -1;
  CNewMenuIconLock iconLock(GetMenuIcon(nIndex,0,pil,xoffset));
  return SetMenuTitle(pTitle,nTitleFlags,iconLock,nIndex);
}

BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CNewMenuIcons* pIcons, int nIndex)
{
  // Check if menu is valid
  if(!::IsMenu(m_hMenu))
  {
    return FALSE;
  }
  // Check the menu integrity
  if((int)GetMenuItemCount()!=(int)m_MenuItemList.GetSize())
  {
    SynchronizeMenu();
  }
  int numMenuItems = (int)m_MenuItemList.GetSize();
  // We need a seperator at the beginning of the menu
  if(!numMenuItems || !((m_MenuItemList[0]->m_nFlags)&MF_SEPARATOR) )
  {
    // We add the special menu item for title
    CNewMenuItemData *pItemData = new CNewMenuItemDataTitle;
    m_MenuItemList.InsertAt(0,pItemData);
    pItemData->SetString(pTitle);
    pItemData->m_nFlags = MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW;

    VERIFY(CMenu::InsertMenu(0,MF_SEPARATOR|MF_BYPOSITION,0,pItemData->m_szMenuText));
    VERIFY(CMenu::ModifyMenu(0, MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW, 0, (LPCTSTR)pItemData ));

    //InsertMenu(0,MF_SEPARATOR|MF_BYPOSITION);
  }

  numMenuItems = (int)m_MenuItemList.GetSize();
  if(numMenuItems)
  {
    CNewMenuItemData* pMenuData = m_MenuItemList[0];
    if(pMenuData->m_nFlags&MF_SEPARATOR)
    {
      pIcons->AddRef();
      pMenuData->m_pMenuIcon->Release();
      pMenuData->m_pMenuIcon = pIcons;
      if(pIcons && nIndex>=0)
      {
        pMenuData->m_nMenuIconOffset = nIndex;
        //CSize size = pIcons->GetIconSize();
        //m_iconX = max(m_iconX,size.cx);
        //m_iconY = max(m_iconY,size.cy);
      }
      else
      {
        pMenuData->m_nMenuIconOffset = -1;
      }
      pMenuData->SetString(pTitle);
      pMenuData->m_nTitleFlags = nTitleFlags|MFT_TITLE;

      if(numMenuItems>1)
      {
        CNewMenuItemData* pMenuData = m_MenuItemList[1];

        if(nTitleFlags&MFT_SIDE_TITLE)
        {
          if(!(pMenuData->m_nFlags&MF_MENUBREAK))
          {
            pMenuData->m_nFlags |= MF_MENUBREAK;
            CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
          }
        }
        else
        {
          if((pMenuData->m_nFlags&MF_MENUBREAK))
          {
            pMenuData->m_nFlags &= ~MF_MENUBREAK;
            CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
          }
        }
        return TRUE;
      }
    }
  }
  return FALSE;
}

CNewMenuItemDataTitle* CNewMenu::GetMemuItemDataTitle()
{
  // Check if menu is valid
  if(!this || !::IsMenu(m_hMenu))
  {
    return NULL;
  }
  // Check the menu integrity
  if((int)GetMenuItemCount()!=(int)m_MenuItemList.GetSize())
  {
    SynchronizeMenu();
  }

  if(m_MenuItemList.GetSize()>0)
  {
    return DYNAMIC_DOWNCAST(CNewMenuItemDataTitle,m_MenuItemList[0]);
  }
  return NULL;
}


BOOL CNewMenu::SetMenuTitleColor(COLORREF clrTitle, COLORREF clrLeft, COLORREF clrRight)
{
  CNewMenuItemDataTitle* pItem = GetMemuItemDataTitle();
  if(pItem)
  {
    pItem->m_clrTitle = clrTitle;
    pItem->m_clrLeft = clrLeft;
    pItem->m_clrRight = clrRight;
    return TRUE;
  }
  return FALSE;
}

BOOL CNewMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
{
  if(MF_BYPOSITION&nFlags)
  {
    int numMenuItems = (int)m_MenuItemList.GetSize();
    if(idSetString(string);

      if(CMenu::ModifyMenu(id,MF_BYPOSITION|MF_STRING | nState, pItemData->m_nID, string))
      {
        return ModifyMenu(id,MF_BYPOSITION | MF_OWNERDRAW,pItemData->m_nID,(LPCTSTR)pItemData);
      }
    }
  }
  else
  {
    int uiLoc;
    CNewMenu* pMenu = FindMenuOption(id,uiLoc);
    if(NULL!=pMenu)
    {
      return pMenu->SetMenuText(uiLoc,string);
    }
  }
  return FALSE;
}

// courtesy of Warren Stevens
void CNewMenu::ColorBitmap(CDC* pDC, CBitmap& bmp, CSize size, COLORREF fill, COLORREF border, int hatchstyle)
{
  // Create a memory DC
  CDC MemDC;
  MemDC.CreateCompatibleDC(pDC);
  bmp.CreateCompatibleBitmap(pDC, size.cx, size.cy);
  CPen border_pen(PS_SOLID, 1, border);

  CBrush fill_brush;
  if(hatchstyle!=-1)
  {
    fill_brush.CreateHatchBrush(hatchstyle, fill);
  }
  else
  {
    fill_brush.CreateSolidBrush(fill);
  }

  CBitmap* pOldBitmap = MemDC.SelectObject(&bmp);
  CPen*    pOldPen    = MemDC.SelectObject(&border_pen);
  CBrush*  pOldBrush  = MemDC.SelectObject(&fill_brush);

  MemDC.Rectangle(0,0, size.cx, size.cy);

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

void CNewMenu::DrawSpecial_OldStyle(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle)
{
  COLORREF oldColor;
  if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
  {
    oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  }
  else if (dwStyle&ODS_SELECTED)
  {
    oldColor = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  }
  else
  {
    oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  }
  BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;

  switch(nID&0xfff0)
  {
  case SC_MINIMIZE:
    DrawSpecialChar(pDC,pRect,48,bBold); // Min
    break;
  case SC_MAXIMIZE:
    DrawSpecialChar(pDC,pRect,49,bBold); // Max
    break;
  case SC_CLOSE:
    DrawSpecialChar(pDC,pRect,114,bBold); // Close
    break;
  case SC_RESTORE:
    DrawSpecialChar(pDC,pRect,50,bBold); // restore
    break;
  }
  pDC->SetTextColor(oldColor);
}

void CNewMenu::DrawSpecial_WinXP(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle)
{
  TCHAR cSign = 0;
  switch(nID&0xfff0)
  {
  case SC_MINIMIZE:
    cSign = 48; // Min
    break;
  case SC_MAXIMIZE:
    cSign = 49;// Max
    break;
  case SC_CLOSE:
    cSign = 114;// Close
    break;
  case SC_RESTORE:
    cSign = 50;// Restore
    break;
  }
  if(cSign)
  {
    COLORREF oldColor;
    BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;
    CRect rect(pRect);
    rect.InflateRect(0,(m_iconY-rect.Height())>>1);


    if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
    {
      oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
    }
    else if(dwStyle&ODS_SELECTED)
    {
      oldColor = pDC->SetTextColor(DarkenColorXP(GetXpHighlightColor()));
      rect.OffsetRect(1,1);
      DrawSpecialChar(pDC,rect,cSign,bBold);
      pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
      rect.OffsetRect(-2,-2);
    }
    else
    {
      oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
    }
    DrawSpecialChar(pDC,rect,cSign,bBold);

    pDC->SetTextColor(oldColor);
  }
}

CRect CNewMenu::GetLastActiveMenuRect()
{
  return m_LastActiveMenuRect;
}

void CNewMenu::DrawSpecialCharStyle(CDC* pDC, LPCRECT pRect, TCHAR Sign, DWORD dwStyle)
{
  COLORREF oldColor;
  if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
  {
    oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  }
  else
  {
    oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  }

  DrawSpecialChar(pDC,pRect,Sign,(dwStyle&ODS_DEFAULT) ? TRUE : FALSE);

  pDC->SetTextColor(oldColor);
}

void CNewMenu::DrawSpecialChar(CDC* pDC, LPCRECT pRect, TCHAR Sign, BOOL bBold)
{
  //  48 Min
  //  49 Max
  //  50 Restore
  //  98 Checkmark
  // 105 Bullet
  // 114 Close

  CFont MyFont;
  LOGFONT logfont;

  CRect rect(pRect);
  rect.DeflateRect(2,2);

  logfont.lfHeight = -rect.Height();
  logfont.lfWidth = 0;
  logfont.lfEscapement = 0;
  logfont.lfOrientation = 0;
  logfont.lfWeight = (bBold) ? FW_BOLD:FW_NORMAL;
  logfont.lfItalic = FALSE;
  logfont.lfUnderline = FALSE;
  logfont.lfStrikeOut = FALSE;
  logfont.lfCharSet = DEFAULT_CHARSET;
  logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  logfont.lfQuality = DEFAULT_QUALITY;
  logfont.lfPitchAndFamily = DEFAULT_PITCH;

  _tcscpy_s(logfont.lfFaceName,ARRAY_SIZE(logfont.lfFaceName),_T("Marlett"));

  MyFont.CreateFontIndirect (&logfont);

  CFont* pOldFont = pDC->SelectObject (&MyFont);
  int OldMode = pDC->SetBkMode(TRANSPARENT);

  pDC->DrawText (&Sign,1,rect,DT_CENTER|DT_SINGLELINE);

  pDC->SetBkMode(OldMode);
  pDC->SelectObject(pOldFont);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMenuTheme::CMenuTheme()
: m_dwThemeId(0),
m_dwFlags(0),
m_pMeasureItem(NULL),
m_pDrawItem(NULL),
m_pDrawTitle(NULL),
m_BorderTopLeft(0,0),
m_BorderBottomRight(0,0)
{
}

CMenuTheme::CMenuTheme( DWORD dwThemeId,
                       pItemMeasureFkt pMeasureItem,
                       pItemDrawFkt pDrawItem,
                       pItemDrawFkt pDrawTitle,
                       DWORD dwFlags)
                       :m_dwThemeId(dwThemeId),
                       m_dwFlags(dwFlags),
                       m_pMeasureItem(pMeasureItem),
                       m_pDrawItem(pDrawItem),
                       m_pDrawTitle(pDrawTitle)
{
  UpdateSysColors();
  UpdateSysMetrics();
}

CMenuTheme::~CMenuTheme()
{
}

void CMenuTheme::DrawFrame(CDC* pDC, CRect rectOuter, CRect rectInner, COLORREF crBorder)
{
  CRect Temp;
  rectInner.right -= 1;
  // Border top
  Temp.SetRect(rectOuter.TopLeft(),CPoint(rectOuter.right,rectInner.top));
  pDC->FillSolidRect(Temp,crBorder);
  // Border bottom
  Temp.SetRect(CPoint(rectOuter.left,rectInner.bottom),rectOuter.BottomRight());
  pDC->FillSolidRect(Temp,crBorder);

  // Border left
  Temp.SetRect(rectOuter.TopLeft(),CPoint(rectInner.left,rectOuter.bottom));
  pDC->FillSolidRect(Temp,crBorder);
  // Border right
  Temp.SetRect(CPoint(rectInner.right,rectOuter.top),rectOuter.BottomRight());
  pDC->FillSolidRect(Temp,crBorder);
}

BOOL CMenuTheme::DoDrawBorder()
{
  return (m_dwFlags&1)?TRUE:FALSE;
}

void CMenuTheme::DrawSmalBorder( HWND hWnd, HDC hDC)
{
  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  if(pData!=NULL)
  {
    if(pData->m_hMenu)
    {
      CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pData->m_hMenu));
      if(pMenu && pMenu->GetParent())
      {
        CNewMenu* pParentMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pMenu->GetParent()));
        if(pParentMenu && !pParentMenu->IsPopup())
        {
          CRect Rect;
          // Get the size of the menu...
          GetWindowRect(hWnd, Rect );
          Rect.OffsetRect(pData->m_Point - Rect.TopLeft());
          Rect &= pParentMenu->GetLastActiveMenuRect();
          if(!Rect.IsRectEmpty())
          {
            if(Rect.Width()>Rect.Height())
            {
              Rect.InflateRect(-1,0);
            }
            else
            {
              Rect.InflateRect(0,-1);
            }
            Rect.OffsetRect(-pData->m_Point);
            CDC* pDC = CDC::FromHandle(hDC);

            COLORREF colorSmalBorder;
            if (NumScreenColors() > 256)
            {
              colorSmalBorder = MixedColor(CNewMenu::GetMenuBarColor(),GetSysColor(COLOR_WINDOW));
            }
            else
            {
              colorSmalBorder = GetSysColor(COLOR_BTNFACE);
            }
            pDC->FillSolidRect(Rect,colorSmalBorder);
          }
        }
      }
    }
  }
}

void CMenuTheme::DrawShade( HWND hWnd, HDC hDC, CPoint screen)
{
  if(IsShadowEnabled())
    return;

  // Get the size of the menu...
  CRect Rect;
  GetWindowRect(hWnd, Rect );

  long winW = Rect.Width();
  long winH = Rect.Height();
  long xOrg = screen.x;
  long yOrg = screen.y;

  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);

  CDC* pDC = CDC::FromHandle(hDC);
  CDC memDC;
  memDC.CreateCompatibleDC(pDC);
  CBitmap* pOldBitmap = memDC.SelectObject(&pData->m_Screen);

  HDC hDcDsk = memDC.m_hDC;
  xOrg = 0;
  yOrg = 0;

  //// Get the desktop hDC...
  //HDC hDcDsk = GetWindowDC(0);

  int X,Y;
  // Simulate a shadow on right edge...
  if (NumScreenColors() <= 256)
  {
    DWORD rgb = ::GetSysColor(COLOR_BTNSHADOW);
    BitBlt(hDC,winW-2,0,    2,winH,hDcDsk,xOrg+winW-2,0,SRCCOPY);
    BitBlt(hDC,0,winH-2,winW,2,hDcDsk,0,yOrg+winH-2,SRCCOPY);
    for (X=3; X<=4 ;X++)
    {
      for (Y=0; Y<4 ;Y++)
      {
        SetPixel(hDC,winW-X,Y,GetPixel(hDcDsk,xOrg+winW-X,yOrg+Y));
      }
      for (Y=4; Y<8 ;Y++)
      {
        SetPixel(hDC,winW-X,Y,rgb);
      }
      for (Y=8; Y<=(winH-5) ;Y++)
      {
        SetPixel( hDC, winW - X, Y, rgb);
      }
      for (Y=(winH-4); Y<=(winH-3) ;Y++)
      {
        SetPixel( hDC, winW - X, Y, rgb);
      }
    }
    // Simulate a shadow on the bottom edge...
    for(Y=3; Y<=4 ;Y++)
    {
      for(X=0; X<=3 ;X++)
      {
        SetPixel(hDC,X,winH-Y, GetPixel(hDcDsk,xOrg+X,yOrg+winH-Y));
      }
      for(X=4; X<=7 ;X++)
      {
        SetPixel( hDC, X, winH - Y, rgb);
      }
      for(X=8; X<=(winW-5) ;X++)
      {
        SetPixel( hDC, X, winH - Y, rgb);
      }
    }
  }
  else
  {
    for (X=1; X<=4 ;X++)
    {
      for (Y=0; Y<4 ;Y++)
      {
        SetPixel(hDC,winW-X,Y, GetPixel(hDcDsk,xOrg+winW-X,yOrg+Y) );
      }
      for (Y=4; Y<8 ;Y++)
      {
        COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y);
        SetPixel(hDC,winW-X,Y,DarkenColor(2* 3 * X * (Y - 3), c));
      }
      for (Y=8; Y<=(winH-5) ;Y++)
      {
        COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y);
        SetPixel( hDC, winW - X, Y, DarkenColor(2* 15 * X, c) );
      }
      for (Y=(winH-4); Y<=(winH-1) ;Y++)
      {
        COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y);
        SetPixel( hDC, winW - X, Y, DarkenColor(2* 3 * X * -(Y - winH), c));
      }
    }

    // Simulate a shadow on the bottom edge...
    for(Y=1; Y<=4 ;Y++)
    {
      for(X=0; X<=3 ;X++)
      {
        SetPixel(hDC,X,winH-Y, GetPixel(hDcDsk,xOrg+X,yOrg+winH-Y));
      }
      for(X=4; X<=7 ;X++)
      {
        COLORREF c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y);
        SetPixel( hDC, X, winH - Y, DarkenColor(2*3 * (X - 3) * Y, c));
      }
      for(X=8; X<=(winW-5) ;X++)
      {
        COLORREF  c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y);
        SetPixel( hDC, X, winH - Y, DarkenColor(2* 15 * Y, c));
      }
    }
  }

  memDC.SelectObject(pOldBitmap);

  //// Release the desktop hDC...
  //ReleaseDC(0,hDcDsk);
}

#define CX_GRIPPER  3
#define CY_GRIPPER  3
#define CX_BORDER_GRIPPER 2
#define CY_BORDER_GRIPPER 2

void CMenuTheme::UpdateSysColors()
{
	clrBtnFace = ::GetSysColor(COLOR_BTNFACE);
	clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);
	clrBtnHilite = ::GetSysColor(COLOR_BTNHIGHLIGHT);
	clrBtnText = ::GetSysColor(COLOR_BTNTEXT);
	clrWindowFrame = ::GetSysColor(COLOR_WINDOWFRAME);
}

void CMenuTheme::UpdateSysMetrics()
{
  m_BorderTopLeft = CSize(2,2);
  if(!IsShadowEnabled())
  {
    m_BorderBottomRight = CSize(5,6);
  }
  else
  {
    m_BorderBottomRight = CSize(2,2);
  }
}

void CMenuTheme::GetBarColor(COLORREF &clrUpperColor, COLORREF &clrMediumColor, COLORREF &clrBottomColor, COLORREF &clrDarkLine)
{
  if(IsMenuThemeActive())
  {
    COLORREF menuColor = CNewMenu::GetMenuBarColor2003();
    // corrections from Andreas Sch鋜er
    switch(menuColor)
    {
    case RGB(163,194,245)://blau
      {
        clrUpperColor = RGB(221,236,254);
        clrMediumColor = RGB(196, 219,249);
        clrBottomColor = RGB(129,169,226);
        clrDarkLine = RGB(59,97,156);
        break;
      }
    case RGB(215,215,229)://silber
      {
        clrUpperColor = RGB(243,244,250);
        clrMediumColor = RGB(225,226,236);
        clrBottomColor = RGB(153,151,181);
        clrDarkLine = RGB(124,124,148);
        break;
      }
    case RGB(218,218,170)://olivgr
      {
        clrUpperColor = RGB(244,247,222);
        clrMediumColor = RGB(209,222,172);
        clrBottomColor = RGB(183,198,145);
        clrDarkLine = RGB(96,128,88);
        break;
      }
    default:
      {
        clrUpperColor = LightenColor(140,menuColor);
        clrMediumColor = LightenColor(115,menuColor);
        clrBottomColor = DarkenColor(40,menuColor);
        clrDarkLine = DarkenColor(110,menuColor);
        break;
      }
    }
  }
  else
  {
    COLORREF menuColor, menuColor2;
    CNewMenu::GetMenuBarColor2003(menuColor, menuColor2, FALSE);
    clrUpperColor = menuColor2;
    clrBottomColor = menuColor;
    clrMediumColor = GetAlphaBlendColor(clrBottomColor, clrUpperColor,100);
    clrDarkLine = DarkenColor(50,clrBottomColor);
  }
}

void CMenuTheme::PaintCorner(CDC *pDC, LPCRECT pRect, COLORREF color)
{
  pDC->SetPixel(pRect->left+1,pRect->top  ,color);
  pDC->SetPixel(pRect->left+0,pRect->top  ,color);
  pDC->SetPixel(pRect->left+0,pRect->top+1,color);

  pDC->SetPixel(pRect->left+0,pRect->bottom  ,color);
  pDC->SetPixel(pRect->left+0,pRect->bottom-1,color);
  pDC->SetPixel(pRect->left+1,pRect->bottom  ,color);

  pDC->SetPixel(pRect->right-1,pRect->top  ,color);
  pDC->SetPixel(pRect->right  ,pRect->top  ,color);
  pDC->SetPixel(pRect->right  ,pRect->top+1,color);

  pDC->SetPixel(pRect->right-1,pRect->bottom  ,color);
  pDC->SetPixel(pRect->right  ,pRect->bottom  ,color);
  pDC->SetPixel(pRect->right  ,pRect->bottom-1,color);
}


void CMenuTheme::DrawGripper(CDC* pDC, const CRect& rect, DWORD dwStyle, 	
                             int m_cxLeftBorder, int m_cxRightBorder,
                             int m_cyTopBorder, int m_cyBottomBorder)
{
  // only draw the gripper if not floating and gripper is specified
  if ((dwStyle & (CBRS_GRIPPER|CBRS_FLOATING)) == CBRS_GRIPPER)
  {
    // draw the gripper in the border
    switch (CNewMenu::GetMenuDrawMode())
    {
    case CNewMenu::STYLE_XP:
    case CNewMenu::STYLE_XP_NOBORDER:
      {
        COLORREF col = DarkenColorXP(CNewMenu::GetMenuBarColorXP());
        CPen pen(PS_SOLID,0,col);
        CPen* pOld = pDC->SelectObject(&pen);
        if (dwStyle & CBRS_ORIENT_HORZ)
        {
          for (int n=rect.top+m_cyTopBorder+2*CY_BORDER_GRIPPER;nMoveTo(rect.left+CX_BORDER_GRIPPER+2,n);
            pDC->LineTo(rect.left+CX_BORDER_GRIPPER+CX_GRIPPER+2,n);
          }
        }
        else
        {
          for (int n=rect.top+m_cxLeftBorder+2*CX_BORDER_GRIPPER;nMoveTo(n,rect.top+CY_BORDER_GRIPPER+2);
            pDC->LineTo(n,rect.top+CY_BORDER_GRIPPER+CY_GRIPPER+2);
          }
        }
        pDC->SelectObject(pOld);
      }
      break;

    case CNewMenu::STYLE_ICY:
    case CNewMenu::STYLE_ICY_NOBORDER:
      {
        COLORREF color = DarkenColor(100,CNewMenu::GetMenuColor());
        if (dwStyle & CBRS_ORIENT_HORZ)
        {
          for (int n=rect.top+m_cyTopBorder+2*CY_BORDER_GRIPPER;nFillSolidRect(rect.left+CX_BORDER_GRIPPER+2+m_cxLeftBorder,n  +1,2,2,color);
          }
        }
        else
        {
          for (int n=rect.top+m_cxLeftBorder+2*CX_BORDER_GRIPPER;nFillSolidRect(n,  rect.top+CY_BORDER_GRIPPER+2+m_cxLeftBorder,2,2,color);
          }
        }
      }
      break;

    case CNewMenu::STYLE_XP_2003_NOBORDER:
    case CNewMenu::STYLE_XP_2003:
    case CNewMenu::STYLE_COLORFUL_NOBORDER:
    case CNewMenu::STYLE_COLORFUL:
      {
        COLORREF clrUpperColor, clrMediumColor, clrBottomColor, clrDarkLine;
        CNewMenu::GetActualMenuTheme()->GetBarColor(clrUpperColor,clrMediumColor,clrBottomColor,clrDarkLine);

        COLORREF color1 = GetSysColor(COLOR_WINDOW);
        //COLORREF color2 = DarkenColor(40,MidColor(GetSysColor(COLOR_BTNFACE),color1));

        if (dwStyle & CBRS_ORIENT_HORZ)
        {
          for (int n=rect.top+m_cyTopBorder+2*CY_BORDER_GRIPPER;nFillSolidRect(rect.left+CX_BORDER_GRIPPER+3+m_cxLeftBorder,n+1+1,2,2,color1);
            pDC->FillSolidRect(rect.left+CX_BORDER_GRIPPER+2+m_cxLeftBorder,n  +1,2,2,clrDarkLine);
          }
        }
        else
        {
          for (int n=rect.top+m_cxLeftBorder+2*CX_BORDER_GRIPPER;nFillSolidRect(n+1,rect.top+CY_BORDER_GRIPPER+3+m_cxLeftBorder,2,2,color1);
            pDC->FillSolidRect(n,  rect.top+CY_BORDER_GRIPPER+2+m_cxLeftBorder,2,2,clrDarkLine);
          }
        }
      }
      break;

    default:
      {
        //BPO late this can be eliminated (cached?)
	      clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);
	      clrBtnHilite = ::GetSysColor(COLOR_BTNHIGHLIGHT);

        CRect temp = rect;
        //temp.left+=2;
        if (dwStyle & CBRS_ORIENT_HORZ)
        {
          pDC->Draw3dRect(rect.left+CX_BORDER_GRIPPER+m_cxLeftBorder,
                          rect.top+m_cyTopBorder,
                          CX_GRIPPER, rect.Height()-m_cyTopBorder-m_cyBottomBorder,
                          clrBtnHilite, clrBtnShadow);
        }
        else
        {
          temp.top+=2;
          pDC->Draw3dRect(rect.left+m_cyTopBorder,
                          rect.top+CY_BORDER_GRIPPER,
                          rect.Width()-m_cyTopBorder-m_cyBottomBorder, CY_GRIPPER,
                          clrBtnHilite, clrBtnShadow);
        }
      }
      break;
    }
  }
}

void CMenuTheme::DrawCorner(CDC* pDC, LPCRECT pRect, DWORD dwStyle)
{
  if ((dwStyle & (CBRS_GRIPPER|CBRS_FLOATING)) == CBRS_GRIPPER)
  {
    // draw the gripper in the border
    switch (CNewMenu::GetMenuDrawMode())
    {
    case CNewMenu::STYLE_ICY:
    case CNewMenu::STYLE_ICY_NOBORDER:
      {
        // make round corners
        COLORREF color = GetSysColor(COLOR_3DLIGHT);
        PaintCorner(pDC,pRect,color);
      }
      break;

    case CNewMenu::STYLE_XP_2003_NOBORDER:
    case CNewMenu::STYLE_XP_2003:
    case CNewMenu::STYLE_COLORFUL_NOBORDER:
    case CNewMenu::STYLE_COLORFUL:
      {
        // make round corners
        COLORREF color = CNewMenu::GetMenuBarColor2003();
        PaintCorner(pDC,pRect,color);
      }
      break;
    }
  }
}

void SetWindowShade(HWND hWndMenu, CNewMenuHook::CMenuHookData* pData );

#define CMS_MENUFADE            175
#define MENU_TIMER_ID 0x1234

BOOL CMenuTheme::OnInitWnd(HWND hWnd)
{
  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  ASSERT(pData);
  if( pData->m_bDoSubclass)
  {
    if(!DoDrawBorder())
    {
      if(g_Shell>=Win2000 && CNewMenu::GetAlpha()!=255)
      {
        // Flag for changing styles
        pData->m_dwData |= 2;
        SetWindowLongPtr (hWnd, GWL_EXSTYLE,(pData->m_dwExStyle| WS_EX_LAYERED));
        SetLayeredWindowAttributes(hWnd, 0, CNewMenu::GetAlpha(), LWA_ALPHA);
        pData->m_dwData |= 4;
        SetTimer(hWnd,MENU_TIMER_ID,50,NULL);
      }
    }
    else
    {
      // Flag for changing styles
      pData->m_dwData |= 2;

      SetWindowLongPtr (hWnd, GWL_STYLE, pData->m_dwStyle & (~WS_BORDER) );

      if(g_Shell>=Win2000 && CNewMenu::GetAlpha()!=255)
      {
        SetWindowLongPtr (hWnd, GWL_EXSTYLE,(pData->m_dwExStyle| WS_EX_LAYERED) & ~(WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME));
        SetLayeredWindowAttributes(hWnd, 0, CNewMenu::GetAlpha(), LWA_ALPHA);
        pData->m_dwData |= 4;
        SetTimer(hWnd,MENU_TIMER_ID,50,NULL);
        //RedrawWindow(hWnd,NULL,NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);  
      }
      else
      {
        SetWindowLongPtr (hWnd, GWL_EXSTYLE,pData->m_dwExStyle & ~(WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME));
      }

      //if(!IsShadowEnabled())
      //{
      //  BOOL bAnimate = FALSE;
      //  if(SystemParametersInfo(SPI_GETMENUANIMATION,0,&bAnimate,0) && bAnimate==TRUE)
      //  {
      //    // All menuanimation should be terminated after 200 ms
      //    pData->m_TimerID = GetSafeTimerID(hWnd,200);
      //  }
      //  else
      //  {
      //    pData->m_TimerID = GetSafeTimerID(hWnd,500);
      //    //SetWindowShade(hWnd, pData);
      //  }
      //}

      return TRUE;
    }
  }
  return FALSE;
}

BOOL CMenuTheme::OnUnInitWnd(HWND hWnd)
{
  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  if(pData)
  {
    if(pData->m_dwData&4)
    {
      KillTimer(hWnd,MENU_TIMER_ID);
      pData->m_dwData &= ~4;
    }
    HMENU hMenu = pData->m_hMenu;
    if(IsMenu(hMenu))
    {
      CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));

      if(pNewMenu)
      {
        // Redraw menubar on place.
        pNewMenu->OnUnInitPopupMenu();
      }
    }

    //// Destroy object and window for shading support
    //if(pData->m_TimerID)
    //{
    //  KillTimer(hWnd,pData->m_TimerID);
    //  pData->m_TimerID = NULL;
    //}
    //if(pData->m_hRightShade)
    //{
    //  DestroyWindow(pData->m_hRightShade);
    //  pData->m_hRightShade = NULL;
    //}
    //if(pData->m_hBottomShade)
    //{
    //  DestroyWindow(pData->m_hBottomShade);
    //  pData->m_hBottomShade = NULL;
    //}

    // were windows-style changed?
    if(pData->m_dwData&2)
    {
      SetLastError(0);
      if(!(pData->m_dwData&1))
      {
        SetWindowLongPtr (hWnd, GWL_STYLE,pData->m_dwStyle);
        ShowLastError(_T("Error from Menu: SetWindowLongPtr I"));
      }
      else
      {
        // Restore old Styles for special menu!!
        // (Menu 0x10012!!!) special VISIBLE flag must be set
        SetWindowLongPtr (hWnd, GWL_STYLE,pData->m_dwStyle|WS_VISIBLE);
        ShowLastError(_T("Error from Menu: SetWindowLongPtr I, Special"));
      }

      SetWindowLongPtr (hWnd, GWL_EXSTYLE, pData->m_dwExStyle);
      ShowLastError(_T("Error from Menu: SetWindowLongPtr II"));
      // Normaly when you change the style you shold call next function
      // but in this case you would lose the focus for the menu!!
      //SetWindowPos(hWnd,0,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_HIDEWINDOW);
    }
  }
  return TRUE;
}

BOOL CMenuTheme::OnEraseBkgnd(HWND hWnd, HDC hDC)
{
  //  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);

  //  Get the size of the menu...
  CDC* pDC = CDC::FromHandle (hDC);
  CRect Rect;
  GetClientRect(hWnd, Rect );
  if(DoDrawBorder())
  {
    Rect.InflateRect(+2,0,-1,0);
  }
  else
  {
    Rect.InflateRect(+2,0,0,0);
  }

  pDC->FillSolidRect (Rect,CNewMenu::GetMenuColor(0));//GetSysColor(COLOR_MENU));

  return TRUE;
}

BOOL CMenuTheme::OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos)
{
  UNREFERENCED_PARAMETER(hWnd);

  if(DoDrawBorder())
  {
#ifdef _TRACE_MENU_
    AfxTrace(_T("WindowPosChanging hwnd=0x%lX, (%ld,%ld)(%ld,%ld)\n"),hWnd,pPos->x,pPos->y,pPos->cx,pPos->cy);
#endif

    if(!IsShadowEnabled())
    {
      pPos->cx +=2;
      pPos->cy +=2;
    }
    else
    {
      pPos->cx -=2;
      pPos->cy -=2;
    }
    pPos->y -=1;

#ifdef _TRACE_MENU_
    AfxTrace(_T("WindowPosChanged  hwnd=0x%lX, (%ld,%ld)(%ld,%ld)\n"),hWnd,pPos->x,pPos->y,pPos->cx,pPos->cy);
#endif

    return TRUE;
  }
  return FALSE;
}

BOOL CMenuTheme::OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc)
{
  UNREFERENCED_PARAMETER(hWnd);

  if(DoDrawBorder())
  {
#ifdef _TRACE_MENU_
    AfxTrace(_T("OnNcCalcSize 0 hwnd=0x%lX, (top=%ld,bottom=%ld,left=%ld,right=%ld)\n"),hWnd,pCalc->rgrc->top,pCalc->rgrc->bottom,pCalc->rgrc->left,pCalc->rgrc->right);
#endif

    int cx=0,cy=0;
    if(!IsShadowEnabled())
    {
      cx = 5;
      cy = 6;
    }
    else
    {
      cx = 1;
      cy = 2;
    }

    pCalc->rgrc->top  += m_BorderTopLeft.cy;
    pCalc->rgrc->left += m_BorderTopLeft.cx;
    pCalc->rgrc->bottom -= cy;
    pCalc->rgrc->right  -= cx;

#ifdef _TRACE_MENU_
    AfxTrace(_T("OnNcCalcSize 0 hwnd=0x%lX, (top=%ld,bottom=%ld,left=%ld,right=%ld)\n"),hWnd,pCalc->rgrc->top,pCalc->rgrc->bottom,pCalc->rgrc->left,pCalc->rgrc->right);
    AfxTrace(_T("OnNcCalcSize 2 hwnd=0x%lX, (top=%ld,bottom=%ld,left=%ld,right=%ld)\n"),hWnd,pCalc->rgrc[2].top,pCalc->rgrc[2].bottom,pCalc->rgrc[2].left,pCalc->rgrc[2].right);
#endif

    //WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
    //LRESULT result = NULL;
    //BOOL bCallDefault = TRUE;
    //result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);

    //return true;
  }
  return FALSE;
}

BOOL CMenuTheme::OnCalcFrameRect(HWND hWnd,LPRECT pRect)
{
  if(GetWindowRect(hWnd,pRect))
  {
    if(DoDrawBorder())
    {
      pRect->top += 2;
      pRect->left += 2;
      if(!IsShadowEnabled())
      {
        pRect->bottom -= 7;
        pRect->right -= 7;
      }
      else
      {
        pRect->bottom -= 3;
        pRect->right -= 3;
      }
    }
    return TRUE;
  }
  return FALSE;
}

void* CMenuTheme::SetScreenBitmap(HWND hWnd, HDC hDC)
{
  UNREFERENCED_PARAMETER(hDC);

  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  if(pData->m_Screen.m_hObject==NULL)
  {
    // Get the desktop hDC...
    HDC hDcDsk = GetWindowDC(0);
    CDC* pDcDsk = CDC::FromHandle(hDcDsk);

    CDC dc;
    dc.CreateCompatibleDC(pDcDsk);

    CRect rect;
    GetWindowRect(hWnd,rect);
    pData->m_Screen.CreateCompatibleBitmap(pDcDsk,rect.Width()+10,rect.Height()+10);
    CBitmap* pOldBitmap = dc.SelectObject(&pData->m_Screen);
    dc.BitBlt(0,0,rect.Width()+10,rect.Height()+10,pDcDsk,pData->m_Point.x,pData->m_Point.y,SRCCOPY);

    dc.SelectObject(pOldBitmap);
    // Release the desktop hDC...
    ReleaseDC(0,hDcDsk);
  }
  return pData;
}

BOOL CMenuTheme::OnDrawBorder(HWND hWnd, HDC hDC, BOOL bOnlyBorder)
{
  CNewMenuHook::CMenuHookData* pData = (CNewMenuHook::CMenuHookData*)SetScreenBitmap(hWnd,hDC);
  if(DoDrawBorder() && pData)
  {
    CRect rect;
    CRect client;
    CDC* pDC = CDC::FromHandle (hDC);

    // Get the size of the menu...
    GetWindowRect(hWnd, rect );
    GetClientRect(hWnd, client);
    CPoint offset(0,0);
    ClientToScreen(hWnd,&offset);
    client.OffsetRect(offset-rect.TopLeft());

    long winW = rect.Width();
    long winH = rect.Height();

    if(!IsShadowEnabled())
    {
      if(!bOnlyBorder)
      {
        DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-6,winH-6)),client,CNewMenu::GetMenuColor());
      }
      if(bHighContrast)
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GetSysColor(COLOR_BTNTEXT ),GetSysColor(COLOR_BTNTEXT ));
      }
      else
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
        DrawShade(hWnd,hDC,pData->m_Point);
      }
    }
    else
    {
      if(!bOnlyBorder)
      {
        DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-2,winH-2)),client,CNewMenu::GetMenuColor());
        //pDC->FillSolidRect(winW-2,2,2,winH-2,RGB(0,0,255));
      }

      if(bHighContrast)
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GetSysColor(COLOR_BTNTEXT ),GetSysColor(COLOR_BTNTEXT ));
      }
      else
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
      }
    }
    //DrawSmalBorder(hWnd,hDC);
    return TRUE;
  }
  return FALSE;
}

CMenuThemeXP::CMenuThemeXP(DWORD dwThemeId,
                           pItemMeasureFkt pMeasureItem,
                           pItemDrawFkt pDrawItem,
                           pItemDrawFkt pDrawTitle,
                           DWORD dwFlags)
                           :CMenuTheme(dwThemeId,pMeasureItem,pDrawItem,pDrawTitle,dwFlags)
{
}

BOOL CMenuThemeXP::OnDrawBorder(HWND hWnd, HDC hDC, BOOL bOnlyBorder)
{
  CNewMenuHook::CMenuHookData* pData = (CNewMenuHook::CMenuHookData*)SetScreenBitmap(hWnd,hDC);
  if(DoDrawBorder() && pData)
  {
    UINT nMenuDrawMode = CNewMenu::GetMenuDrawMode();
  
    CRect rect;
    CRect client;
    CDC* pDC = CDC::FromHandle (hDC);

    // Get the size of the menu...
    GetWindowRect(hWnd, rect );
    GetClientRect(hWnd,client);
    CPoint offset(0,0);
    ClientToScreen(hWnd,&offset);
    client.OffsetRect(offset-rect.TopLeft());

    long winW = rect.Width();
    long winH = rect.Height();

    // Same Color as in DrawItem_WinXP
    COLORREF crMenuBar = CNewMenu::GetMenuColor(pData->m_hMenu);
    COLORREF crWindow = GetSysColor(COLOR_WINDOW);
    COLORREF crThinBorder = MixedColor(crWindow,crMenuBar);
    COLORREF clrBorder = DarkenColor(128,crMenuBar);
    COLORREF colorBitmap;

    if (NumScreenColors() > 256)
    {
      colorBitmap = MixedColor(crMenuBar,crWindow);
    }
    else
    {
      colorBitmap = GetSysColor(COLOR_BTNFACE);
    }

    // Better contrast when you have less than 256 colors
    if(pDC->GetNearestColor(crThinBorder)==pDC->GetNearestColor(colorBitmap))
    {
      crThinBorder = crWindow;
      colorBitmap = crMenuBar;
    }

    if(!IsShadowEnabled())
    {
      if(!bOnlyBorder)
      {
        DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-6,winH-6)),client,crThinBorder);
      }

      if(bHighContrast)
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GetSysColor(COLOR_BTNTEXT),GetSysColor(COLOR_BTNTEXT));
      }
      else
      {
        pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),crThinBorder,crThinBorder);
        pDC->FillSolidRect(1,2,1,winH-8,colorBitmap);
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),clrBorder,clrBorder);

        DrawShade(hWnd,pDC->m_hDC,pData->m_Point);
      }
    }
    else
    {
      if(!bOnlyBorder)
      {
        DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-2,winH-2)),client,crThinBorder);
      }

      if(bHighContrast)
      {
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GetSysColor(COLOR_BTNTEXT ),GetSysColor(COLOR_BTNTEXT ));
      }
      else
      {
        pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),crThinBorder,crThinBorder);
        if(nMenuDrawMode==CNewMenu::STYLE_XP_2003 || nMenuDrawMode==CNewMenu::STYLE_XP_2003_NOBORDER)
        {
          pDC->FillSolidRect(1,2,1,winH-4,crWindow);
        }
        else
        {
          pDC->FillSolidRect(1,2,1,winH-4,colorBitmap);
        }
        pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),clrBorder,clrBorder);
      }
    }
    DrawSmalBorder(hWnd,pDC->m_hDC);

    return TRUE;
  }
  return FALSE;
}

BOOL CMenuThemeXP::OnEraseBkgnd(HWND hWnd, HDC hDC)
{
  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  if(pData->m_hMenu==NULL)
  {
    return CMenuTheme::OnEraseBkgnd(hWnd,hDC);
  }
  //  Get the size of the menu...
  CDC* pDC = CDC::FromHandle (hDC);
  CRect Rect;
  GetClientRect(hWnd, Rect );
  if(DoDrawBorder())
  {
    Rect.InflateRect(+2,0,-1,0);
  }
  else
  {
    Rect.InflateRect(+2,0,0,0);
  }

  //BPO!!!!!!!!!!  fehler Zeichnet auch in den rand hinein 2
  //pDC->FillSolidRect (Rect,CNewMenu::GetMenuColor());
  pDC->FillSolidRect (Rect,CNewMenu::GetMenuBarColor(pData->m_hMenu));

  return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMenuTheme2003 for drawing border and the rest

CMenuTheme2003::CMenuTheme2003( DWORD dwThemeId,
                                pItemMeasureFkt pMeasureItem,
                                pItemDrawFkt pDrawItem,
                                pItemDrawFkt pDrawTitle,
                                DWORD dwFlags)
 : CMenuThemeXP(dwThemeId,pMeasureItem,pDrawItem,pDrawTitle,dwFlags)
{
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

const TCHAR _OldMenuProc[] = _T("OldMenuProc");

HMODULE CNewMenuHook::m_hLibrary = NULL;
HMODULE CNewMenuHook::m_hThemeLibrary = NULL;
HHOOK CNewMenuHook::HookOldMenuCbtFilter = NULL;
HMENU CNewMenuHook::m_hLastMenu = NULL;
DWORD CNewMenuHook::m_dwMsgPos = 0;
DWORD CNewMenuHook::m_bSubclassFlag = 0;

#ifdef _TRACE_MENU_LOGFILE
HANDLE CNewMenuHook::m_hLogFile = INVALID_HANDLE_VALUE;
#endif //_TRACE_MENU_LOGFILE


CTypedPtrList* CNewMenuHook::m_pRegisteredThemesList = NULL;

CTypedPtrMap CNewMenuHook::m_MenuHookData;

#ifndef SM_REMOTESESSION
#define SM_REMOTESESSION     0x1000
#endif

CNewMenuHook::CNewMenuHook()
{
  if(g_Shell>=Win2000 && GetSystemMetrics(SM_REMOTESESSION))
  {
    bRemoteSession=TRUE;
  }

  { // Detecting wine because we have some issue
    HMODULE hModule = GetModuleHandle(_T("kernel32.dll"));
    bWine = hModule && GetProcAddress(hModule,"wine_get_unix_file_name");
//    if(Wine)
//    {
//      MessageBox(NULL,_T("We are running under wine!!"),_T("wine detected"),MB_OK);
//    }
  }


  HIGHCONTRAST highcontrast = {0};
  highcontrast.cbSize = sizeof(highcontrast);
  if(SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(highcontrast),&highcontrast,0) )
  {
    bHighContrast = ((highcontrast.dwFlags&HCF_HIGHCONTRASTON)!=0);
  }

#ifdef _TRACE_MENU_LOGFILE
  m_hLogFile = CreateFile(_T("c:\\NewMenuLog.txt"), GENERIC_WRITE, FILE_SHARE_WRITE,
    NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if(m_hLogFile!=INVALID_HANDLE_VALUE)
  {
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, m_hLogFile);

    _RPT0(_CRT_WARN,_T("file message\n"));
  }
#endif // _TRACE_MENU_LOGFILE

  // Try to load theme library from XP
  m_hThemeLibrary = LoadLibrary(_T("uxtheme.dll"));
  if(m_hThemeLibrary)
  {
    pIsThemeActive = (FktIsThemeActive)GetProcAddress(m_hThemeLibrary,"IsThemeActive");
    pSetWindowTheme = (FktSetWindowTheme)GetProcAddress(m_hThemeLibrary,"SetWindowTheme");
  }
  else
  {
    pIsThemeActive = NULL;
  }

  // Try to load the library for gradient drawing
  m_hLibrary = LoadLibrary(_T("Msimg32.dll"));

  // Don't use the gradientfill under Win98 because it is buggy!!!
  if(g_Shell!=Win98 && m_hLibrary)
  {
    pGradientFill = (FktGradientFill)GetProcAddress(m_hLibrary,"GradientFill");
  }
  else
  {
    pGradientFill = NULL;
  }

  AddTheme(new CMenuTheme(CNewMenu::STYLE_ICY,
    &CNewMenu::MeasureItem_Icy,
    &CNewMenu::DrawItem_Icy,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuTheme(CNewMenu::STYLE_ICY_NOBORDER,
    &CNewMenu::MeasureItem_Icy,
    &CNewMenu::DrawItem_Icy,
    &CNewMenu::DrawMenuTitle));

  AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL,
    &CNewMenu::MeasureItem_OldStyle,
    &CNewMenu::DrawItem_OldStyle,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER,
    &CNewMenu::MeasureItem_OldStyle,
    &CNewMenu::DrawItem_OldStyle,
    &CNewMenu::DrawMenuTitle));

  AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_WinXP,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP_NOBORDER,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_WinXP,
    &CNewMenu::DrawMenuTitle));

  AddTheme(new CMenuTheme2003(CNewMenu::STYLE_XP_2003,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_XP_2003,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuTheme2003(CNewMenu::STYLE_XP_2003_NOBORDER,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_XP_2003,
    &CNewMenu::DrawMenuTitle));

  AddTheme(new CMenuThemeXP(CNewMenu::STYLE_COLORFUL,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_XP_2003,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuThemeXP(CNewMenu::STYLE_COLORFUL_NOBORDER,
    &CNewMenu::MeasureItem_WinXP,
    &CNewMenu::DrawItem_XP_2003,
    &CNewMenu::DrawMenuTitle));

  AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL,
    &CNewMenu::MeasureItem_OldStyle,
    &CNewMenu::DrawItem_SpecialStyle,
    &CNewMenu::DrawMenuTitle,TRUE));

  AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL_NOBORDER,
    &CNewMenu::MeasureItem_OldStyle,
    &CNewMenu::DrawItem_SpecialStyle,
    &CNewMenu::DrawMenuTitle));

  //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL);
  //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER);
  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP);
  //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP_NOBORDER);

  if (HookOldMenuCbtFilter == NULL)
  {
    HookOldMenuCbtFilter = ::SetWindowsHookEx(WH_CALLWNDPROC, NewMenuHook, NULL, ::GetCurrentThreadId());
    if (HookOldMenuCbtFilter == NULL)
    {
      ShowLastError(_T("Error from Menu: SetWindowsHookEx"));
      AfxThrowMemoryException();
    }
  }
}

CNewMenuHook::~CNewMenuHook()
{
  if (HookOldMenuCbtFilter != NULL)
  {
    if(!::UnhookWindowsHookEx(HookOldMenuCbtFilter))
    {
      ShowLastError(_T("Error from Menu: UnhookWindowsHookEx"));
    }
    HookOldMenuCbtFilter = NULL;
  }
  // Destroy all registered themes.
  if( m_pRegisteredThemesList!= NULL)
  {
    while(m_pRegisteredThemesList->GetCount())
    {
      CMenuTheme* pTheme = m_pRegisteredThemesList->RemoveTail();
      delete pTheme;
    }
    delete m_pRegisteredThemesList;
    m_pRegisteredThemesList = NULL;
  }

  pIsThemeActive = NULL;
  FreeLibrary(m_hThemeLibrary);

  pGradientFill = NULL;
  FreeLibrary(m_hLibrary);

  // Cleanup for shared menu icons
  if(CNewMenu::m_pSharedMenuIcons)
  {
    delete CNewMenu::m_pSharedMenuIcons;
    CNewMenu::m_pSharedMenuIcons = NULL;
  }

#ifdef _TRACE_MENU_LOGFILE
  if(m_hLogFile!=INVALID_HANDLE_VALUE)
  {
    CloseHandle(m_hLogFile);
    m_hLogFile = INVALID_HANDLE_VALUE;
  }
#endif
}

BOOL CNewMenuHook::AddTheme(CMenuTheme* pTheme)
{
  if( m_pRegisteredThemesList== NULL)
  {
    m_pRegisteredThemesList = new CTypedPtrList;
  }
  if(m_pRegisteredThemesList->Find(pTheme))
  {
    return FALSE;
  }
  m_pRegisteredThemesList->AddTail(pTheme);
  return TRUE;
}

CMenuTheme* CNewMenuHook::RemoveTheme(DWORD dwThemeId)
{
  CMenuTheme* pTheme = FindTheme(dwThemeId);
  if(pTheme==NULL)
  {
    return NULL;
  }
  POSITION pos = m_pRegisteredThemesList->Find(pTheme);
  ASSERT(pos);
  if(pos)
  {
    m_pRegisteredThemesList->RemoveAt(pos);
    if(m_pRegisteredThemesList->GetCount()==NULL)
    {
      // Destroy the empty list.
      delete m_pRegisteredThemesList;
      m_pRegisteredThemesList = NULL;
    }
  }
  return pTheme;
}

CMenuTheme* CNewMenuHook::FindTheme(DWORD dwThemeId)
{
  if(m_pRegisteredThemesList==NULL)
  {
    return NULL;
  }

  POSITION pos = m_pRegisteredThemesList->GetHeadPosition();
  while(pos)
  {
    CMenuTheme* pTheme = m_pRegisteredThemesList->GetNext(pos);
    if(pTheme->m_dwThemeId==dwThemeId)
    {
      return pTheme;
    }
  }
  return NULL;
}

CNewMenuHook::CMenuHookData* CNewMenuHook::GetMenuHookData(HWND hWnd)
{
  CMenuHookData* pData=NULL;
  if(m_MenuHookData.Lookup(hWnd,pData))
  {
    return pData;
  }
  return NULL;
}

void CNewMenuHook::UnsubClassMenu(HWND hWnd)
{
  AFX_MANAGE_STATE(AfxGetModuleState());

  WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
  ASSERT(oldWndProc != NULL);

  SetLastError(0);
  if(!SetWindowLongPtr(hWnd, GWLP_WNDPROC, (INT_PTR)oldWndProc))
  {
    ShowLastError(_T("Error from Menu: SetWindowLongPtr III"));
  }
  RemoveProp(hWnd, _OldMenuProc);
  GlobalDeleteAtom(GlobalFindAtom(_OldMenuProc));

  // now Clean up
  HMENU hMenu = NULL;
  // Restore old Styles for special menu!! (Menu 0x10012!!!)
  CMenuHookData* pData = GetMenuHookData(hWnd);
  if(pData)
  {
    hMenu = pData->m_hMenu;
    CNewMenu::m_pActMenuDrawing->OnUnInitWnd(hWnd);

    m_MenuHookData.RemoveKey(hWnd);

    delete pData;
  }

#ifdef _TRACE_MENU_
  AfxTrace(_T("Unsubclass Menu=0x%lX, hwnd=0x%lX\n"),hMenu,hWnd);
#endif
}

LRESULT CALLBACK CNewMenuHook::SubClassMenu(HWND hWnd,      // handle to window
                                            UINT uMsg,      // message identifier
                                            WPARAM wParam,  // first message parameter
                                            LPARAM lParam)  // second message parameter
{
  AFX_MANAGE_STATE(AfxGetModuleState());

  WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
  LRESULT result = NULL;
  BOOL bCallDefault = TRUE;


#ifdef _TRACE_MENU_
  static long NestedLevel = 0;
  NestedLevel++;
  MSG msg = {hWnd,uMsg,wParam,lParam,0,0,0};
  TCHAR Buffer[30];
  wsprintf(Buffer,_T("Level %02ld"),NestedLevel);
  MyTraceMsg(Buffer,&msg);
#endif

  CMenuHookData* pData = GetMenuHookData(hWnd);
  if(NULL == pData)
  {
    return ::CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  }
  ASSERT(pData);

  switch(uMsg)
  {
  case WM_NCPAINT:
    ASSERT(pData);

    if(pData->m_bDoSubclass)
    {
#ifdef _TRACE_MENU_
      AfxTrace(_T("WM_NCPAINT (0x%x) 0x%X, 0x%X\n"),hWnd,wParam,lParam);
#endif
      if(!pData->m_bDrawBorder)
      {
        if(pData->m_hRgn!=(HRGN)wParam)
        {
          if(pData->m_hRgn!=(HRGN)1)
          {
            DeleteObject(pData->m_hRgn);
            pData->m_hRgn=(HRGN)1;
          }
          if(wParam!=1)
          {
            CRgn dest;
            dest.CreateRectRgn( 0, 0, 1, 1);
            dest.CopyRgn(CRgn::FromHandle((HRGN)wParam));
            pData->m_hRgn = (HRGN)dest.Detach();
          }
        }
      }

      if(pData->m_dwData&8)
      {
        // do not call default!!!
        bCallDefault=FALSE;
      }

      if(pData->m_bDrawBorder &&  CNewMenu::m_pActMenuDrawing->DoDrawBorder())
      {
        //HDC hDC = GetWindowDC(hWnd);
        HDC hDC;
        //if(wParam!=1)
        //  hDC = GetDCEx(hWnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
        //else
        hDC = GetWindowDC (hWnd);

#ifdef _TRACE_MENU_
        if(wParam!=1)
        {
          DWORD dwCount = GetRegionData((HRGN)wParam,0,0);
          RGNDATA* pRegionData = (RGNDATA*)_alloca(dwCount);
          GetRegionData((HRGN)wParam,dwCount,pRegionData);

          TRACE(_T("WM_NCPAINT (0x%x) region %ld "),hWnd,pRegionData->rdh.nCount);
          CRect* pRect = (CRect*)pRegionData->Buffer;
          for(DWORD n=0; nrdh.nCount; n++)
          {
            TRACE( _T("(%ld,%ld,%ld,%ld)"),pRect[n].left,pRect[n].top,pRect[n].right,pRect[n].bottom);
          }
          TRACE(_T("\r\n"));
        }
#endif //  _TRACE_MENU_

        if(hDC)
        {
          if(CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,hDC))
          {
            CRect rect;
            if(CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rect))
            {
              CRgn rgn;
              rect.InflateRect(-1,-1);
              rgn.CreateRectRgnIndirect(rect);
              // do we need a combination of the regions?
              //if(wParam!=1)
              //{
              //  rgn.CombineRgn(&rgn,CRgn::FromHandle((HRGN)wParam),RGN_AND);
              //}
              ASSERT(oldWndProc);

              bCallDefault=FALSE;
              result = CallWindowProc(oldWndProc, hWnd, uMsg, (WPARAM)rgn.m_hObject, lParam);
              //result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
              // Redraw the border and shade
              CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,hDC,true);
            }
          }
          ReleaseDC(hWnd,hDC);
        }
      }
      if(CNewMenu::m_pActMenuDrawing->DoDrawBorder() && bCallDefault)
      {
        // Save the background
        HDC hDC = GetWindowDC (hWnd);
        CNewMenu::m_pActMenuDrawing->SetScreenBitmap(hWnd,hDC);
        ReleaseDC(hWnd,hDC);
      }
    }

    break;

  case WM_PRINT:
    if(pData && pData->m_bDoSubclass)
    {
      if(CNewMenu::m_pActMenuDrawing->DoDrawBorder())
      {
        // Mark for WM_PRINT
        pData->m_dwData |= 8;

        //      pData->m_bDrawBorder = FALSE;
        // We need to create a bitmap for drawing
        // We can't clipp or make a offset to the DC because NT2000 (blue-screen!!)
        CRect rect;
        GetWindowRect(hWnd, rect);
        CDC dc;
        CBitmap bitmap;

        CDC* pDC = CDC::FromHandle((HDC)wParam);
        dc.CreateCompatibleDC(pDC);

        bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
        CBitmap* pOldBitmap = dc.SelectObject(&bitmap);

        // new
        //       dc.FillSolidRect(0,0,rect.Width(), rect.Height(),CNewMenu::GetMenuBarColor(pData->m_hMenu));

        CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,dc.m_hDC);

        CRect rectClient;
        if(CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rectClient))
        {
          // might as well clip to the same rectangle
          CRect clipRect = rectClient;
          clipRect.OffsetRect(rectClient.TopLeft()-rect.TopLeft());
          clipRect.InflateRect(-1,-1);
          dc.IntersectClipRect(clipRect);
          result = CallWindowProc(oldWndProc, hWnd, uMsg, (WPARAM)dc.m_hDC, lParam&~PRF_CLIENT);

          pDC->BitBlt(0,0, rect.Width(), rect.Height(), &dc,0,0, SRCCOPY);

          GetClientRect(hWnd,clipRect);
          SelectClipRgn(dc.m_hDC,NULL);
          dc.IntersectClipRect(clipRect);

          SendMessage(hWnd,WM_ERASEBKGND,(WPARAM)dc.m_hDC,0);
          SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)dc.m_hDC,lParam);

          CPoint wndOffset(0,0);
          ClientToScreen(hWnd,&wndOffset);
          wndOffset -= rect.TopLeft();
          pDC->BitBlt(wndOffset.x,wndOffset.y, clipRect.Width()-1, clipRect.Height(), &dc, 0, 0, SRCCOPY);
          //pDC->BitBlt(wndOffset.x,wndOffset.y, clipRect.Width(), clipRect.Height(), &dc, 0, 0, SRCCOPY);
        }
        //
        dc.SelectObject(pOldBitmap);
        bCallDefault=FALSE;

        // Clear for WM_PRINT
        pData->m_dwData &= ~8;
      }
    }
    break;

  case WM_ERASEBKGND:
    ASSERT(pData);
    if(pData->m_bDoSubclass)
    {
      if(CNewMenu::m_pActMenuDrawing->DoDrawBorder())
      {
        if(!(pData->m_dwData&8) && !pData->m_bDrawBorder )
        {
          pData->m_bDrawBorder = true;
          //SendMessage(hWnd,WM_NCPAINT,(WPARAM)pData->m_hRgn,0);
          SendMessage(hWnd,WM_NCPAINT,(WPARAM)1,0);
        }
      }

      if(CNewMenu::m_pActMenuDrawing->OnEraseBkgnd(hWnd,(HDC)wParam))
      {
        bCallDefault=FALSE;
        result = TRUE;
      }
    }
    break;

  case WM_WINDOWPOSCHANGED:
  case WM_WINDOWPOSCHANGING:
    {
      ASSERT(pData);

      LPWINDOWPOS pPos = (LPWINDOWPOS)lParam;
      if(uMsg==WM_WINDOWPOSCHANGING)
      {
        CNewMenu::m_pActMenuDrawing->OnWindowPosChanging(hWnd,pPos);
      }
      if(!(pPos->flags&SWP_NOMOVE) )
      {
        if(pData->m_Point==CPoint(0,0))
        {
          pData->m_Point = CPoint(pPos->x,pPos->y);
        }
        else if(pData->m_Point!=CPoint(pPos->x,pPos->y))
        {
          /*          CRect rect(0,0,0,0);
          if(!GetWindowRect(hWnd,rect))
          {
          AfxTrace(_T("Error get rect\n"));
          }
          #ifdef _TRACE_MENU_

          DWORD dwPos =GetMessagePos();
          AfxTrace(_T("Rect pos (%ld/%ld), dimensions [%ld,%ld], Delta(%ld/%ld),MPos %lx\n"),
          pData->m_Point.x,pData->m_Point.y,rect.Width(),rect.Height(),
          pData->m_Point.x-pPos->x,pData->m_Point.y-pPos->y,dwPos);
          #endif
          */
          if(!(pPos->flags&SWP_NOSIZE))
          {
            UnsubClassMenu(hWnd);
          }
          else
          {
            pData->m_Point=CPoint(pPos->x,pPos->y);
            pData->m_Screen.DeleteObject();
          }
        }
      }
    }
    break;

  case WM_KEYDOWN:
    if(wParam==VK_ESCAPE)
    {
      if(pData)
      {
        pData->m_dwData |= 4;
      }
    }
    m_dwMsgPos = GetMessagePos();
    break;

  case WM_NCCALCSIZE:
    if(pData->m_bDoSubclass)
    {
      NCCALCSIZE_PARAMS* pCalc = (NCCALCSIZE_PARAMS*)lParam;
      if(CNewMenu::m_pActMenuDrawing->OnNcCalcSize(hWnd,pCalc))
      {
        bCallDefault=FALSE;
      }
    }
    break;

  case WM_SHOWWINDOW:
    // Hide the window ? Test for 98 and 2000
    if(wParam==NULL)
    {
      // Special handling for NT 2000 and WND 0x10012.
      UnsubClassMenu(hWnd);
    }
    break;

  case WM_NCDESTROY:
    UnsubClassMenu (hWnd);
    break;

  case WM_TIMER:
    if(wParam==MENU_TIMER_ID)
    {
      if(g_Shell>=Win2000)
      {
        LONG_PTR dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
        if( !(dwExStyle&WS_EX_LAYERED) )
        {
          SetWindowLongPtr (hWnd, GWL_EXSTYLE,dwExStyle| WS_EX_LAYERED);
          SetLayeredWindowAttributes(hWnd, 0, CNewMenu::GetAlpha(), LWA_ALPHA);
          pData->m_dwData &= ~4;
          KillTimer(hWnd,MENU_TIMER_ID);
        }
      }
    }
    break;

    //  if(pData->m_TimerID && pData->m_TimerID==wParam)
    //  {
    //    bCallDefault = FALSE;
    //    KillTimer(hWnd,pData->m_TimerID);
    //    pData->m_TimerID = NULL;
    //    result = 0;
    //    // Create shade windows
    //    SetWindowShade(hWnd, pData);
    //  }
    //  break;

    //default:
    //  {
    //    static const UINT WBHook = RegisterWindowMessage(_T("WBHook"));
    //    if (uMsg==WBHook)
    //    {
    //      bCallDefault = false;
    //    }
    //  }
    //  break;
  }

  if( bCallDefault )
  {
    ASSERT(oldWndProc != NULL);
    // call original wndproc for default handling
    result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  }

#ifdef _TRACE_MENU_
  NestedLevel--;
#endif

  return result;
}

BOOL CNewMenuHook::CheckSubclassing(HWND hWnd, BOOL bSpecialWnd)
{
  TCHAR Name[20];
  int Count = GetClassName (hWnd,Name,ARRAY_SIZE(Name));
  // Check for the menu-class
  if(Count!=6 || _tcscmp(Name,_T("#32768"))!=0)
  {
    // does not match to menuclass
    return false;
  }
  BOOL bDoNewSubclass = FALSE;
  CMenuHookData* pData=GetMenuHookData(hWnd);
  // check if we have allready some data
  if(pData==NULL)
  {

    // a way for get the menu-handle not documented
    if(!m_hLastMenu)
    {
      // WinNt 4.0 will crash in submenu
      m_hLastMenu = (HMENU)SendMessage(hWnd,0x01E1,0,0);
    }
    CMenu *pMenu = CMenu::FromHandlePermanent(m_hLastMenu);
    // now we support only new menu
    if( !DYNAMIC_DOWNCAST(CNewMenu,pMenu) )
    {
      return false;
    }

    WNDPROC oldWndProc;
    // subclass the window with the proc which does gray backgrounds
    oldWndProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
    if (oldWndProc != NULL && GetProp(hWnd, _OldMenuProc) == NULL)
    {
      ASSERT(oldWndProc!=SubClassMenu);

      if(!SetProp(hWnd, _OldMenuProc, oldWndProc))
      {
        ShowLastError(_T("Error from Menu: SetProp"));
      }
      if ((WNDPROC)GetProp(hWnd, _OldMenuProc) == oldWndProc)
      {
        GlobalAddAtom(_OldMenuProc);

        CMenuHookData* pData=GetMenuHookData(hWnd);
        ASSERT(pData==NULL);
        if(pData==NULL)
        {
          pData = new CMenuHookData(hWnd,bSpecialWnd);
          m_MenuHookData.SetAt (hWnd,pData);

          SetLastError(0);
          if(!SetWindowLongPtr(hWnd, GWLP_WNDPROC,(INT_PTR)SubClassMenu))
          {
            ShowLastError(_T("Error from Menu: SetWindowLongPtr IV"));
          }
          bDoNewSubclass = TRUE;
#ifdef _TRACE_MENU_
          //SendMessage(hWnd,0x01E1,0,0) a way for get the menu-handle
          AfxTrace(_T("Subclass Menu=0x%lX, hwnd=0x%lX\n"),pData->m_hMenu,hWnd);
#endif
          CNewMenu::m_pActMenuDrawing->OnInitWnd(hWnd);
        }
      }
      else
      {
        ASSERT(0);
      }
    }
  }

  // Menu was set also assign it to this menu.
  if(m_hLastMenu)
  {
    CMenuHookData* pData = GetMenuHookData(hWnd);
    if(pData)
    {
      // Safe actual menu
      pData->SetMenu(m_hLastMenu);
      // Reset for the next menu
      m_hLastMenu = NULL;
      //
      CNewMenu::m_pActMenuDrawing->OnInitWnd(hWnd);
    }
  }
  return bDoNewSubclass;
}

/////////////////////////////////////////////////////////////////////////////
// CNewMenuThreadHook class used to hook for threads
// Jan-17-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/

CNewMenuThreadHook::CNewMenuThreadHook()
{
  // set the hook handler for this thread
  m_hHookOldMenuCbtFilter = ::SetWindowsHookEx(WH_CALLWNDPROC, CNewMenuHook::NewMenuHook, NULL, ::GetCurrentThreadId());
} // CNewMenuThreadHook


CNewMenuThreadHook::~CNewMenuThreadHook()
{
  // reset the hook handler
  if (m_hHookOldMenuCbtFilter)
  {
    ::UnhookWindowsHookEx(m_hHookOldMenuCbtFilter);
  }
  // clear the handle
  m_hHookOldMenuCbtFilter = NULL;
} // ~CNewMenuThreadHook


/////////////////////////////////////////////////////////////////////////////
// CNewMenuTempHandler class used to add NewMenu to system dialog
class CNewMenuTempHandler : public CObject
{
  CNewMenu m_SystemNewMenu;
  WNDPROC m_oldWndProc;
  HWND m_hWnd;

public:
  CNewMenuTempHandler(HWND hWnd)
  {
    m_hWnd = hWnd;
    VERIFY(SetProp(hWnd,_T("CNewMenuTempHandler"),this));
    // Subclass the dialog control.
    m_oldWndProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(INT_PTR)TempSubclass);
  }

  ~CNewMenuTempHandler()
  {
    SetWindowLongPtr(m_hWnd, GWLP_WNDPROC,(INT_PTR)m_oldWndProc);
    VERIFY(RemoveProp(m_hWnd,_T("CNewMenuTempHandler")));
  }

  LRESULT Default(UINT uMsg, WPARAM wParam, LPARAM lParam )
  {
    // call original wndproc for default handling
    return CallWindowProc(m_oldWndProc, m_hWnd, uMsg, wParam, lParam);
  }

  LRESULT OnCmd(UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
    MSG msg = {m_hWnd,uMsg,wParam,lParam,0,0,0};
    switch(uMsg)
    {
    case WM_DRAWITEM:
      {
        if(m_SystemNewMenu.m_hMenu)
        {
          DRAWITEMSTRUCT* lpDrawItemStruct = (DRAWITEMSTRUCT*)lParam;
          if (lpDrawItemStruct->CtlType == ODT_MENU)
          {
            CMenu* pMenu = CMenu::FromHandlePermanent((HMENU)lpDrawItemStruct->hwndItem);
            if (DYNAMIC_DOWNCAST(CNewMenu,pMenu))
            {
              pMenu->DrawItem(lpDrawItemStruct);
              return true; // eat it
            }
          }
        }
        return Default(uMsg, wParam, lParam);
      }

    case WM_MEASUREITEM:
      if(CNewMenu::OnMeasureItem(&msg))
      {
        return TRUE;
      }
      break;

    case WM_MENUCHAR:
      {
        CMenu* pMenu = CMenu::FromHandle(UIntToHMenu((UINT)lParam));;
        LRESULT lresult;
        if( DYNAMIC_DOWNCAST(CNewMenu,pMenu) )
          lresult=CNewMenu::FindKeyboardShortcut(LOWORD(wParam), HIWORD(wParam),pMenu );
        else
          lresult=Default(uMsg, wParam, lParam);
        return lresult;
      }
      break;

    case WM_INITMENUPOPUP:
      {
        CMenu* pMenu = CMenu::FromHandle(UIntToHMenu((UINT)wParam));
        LRESULT result = Default(uMsg, wParam, lParam);
        CNewMenu::OnInitMenuPopup(m_hWnd, pMenu, LOWORD(lParam), HIWORD(lParam));
        return result;
      }

    case WM_INITDIALOG:
      if(CNewMenuHook::m_bSubclassFlag&NEW_MENU_DIALOG_SYSTEM_MENU)
      {
        LRESULT bRetval = Default(uMsg, wParam, lParam);
        VERIFY(m_SystemNewMenu.m_hMenu==0);

        HMENU hMenu = ::GetSystemMenu(m_hWnd,FALSE);
        if(IsMenu(hMenu))
        {
          CMenu* pMenu = CMenu::FromHandlePermanent(hMenu);
          // Only attach to CNewMenu once
          if (DYNAMIC_DOWNCAST(CNewMenu,pMenu)==NULL )
          {
            m_SystemNewMenu.Attach(hMenu);
          }
        }
        return bRetval;
      }
      break;

    case WM_DESTROY:
      LRESULT result = Default(uMsg, wParam, lParam);
      delete this;
      return result;
    }

    return Default(uMsg, wParam, lParam);
  }

  // Subclass procedure
  static LRESULT APIENTRY TempSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
    AFX_MANAGE_STATE(AfxGetModuleState());

    CNewMenuTempHandler* pTemp = (CNewMenuTempHandler*)GetProp(hwnd,_T("CNewMenuTempHandler"));
    ASSERT(pTemp);
    return pTemp->OnCmd(uMsg, wParam, lParam);
  }

};

LRESULT CALLBACK CNewMenuHook::NewMenuHook(int code, WPARAM wParam, LPARAM lParam)
{
  AFX_MANAGE_STATE(AfxGetModuleState());

  CWPSTRUCT* pTemp = (CWPSTRUCT*)lParam;
  if(code == HC_ACTION )
  {
    HWND hWnd = pTemp->hwnd;

#ifdef _TRACE_MENU_
    static HWND acthMenu = NULL;
    static HWND acthWnd = NULL;

    // Check if we need to find out the window
    if (hWnd && hWnd!=acthWnd && hWnd!=acthMenu)
    {
      TCHAR Name[20];
      int Count = GetClassName (hWnd,Name,ARRAY_SIZE(Name));
      // Check for the menu-class
      if(Count!=6 || _tcscmp(Name,_T("#32768"))!=0)
      {
        // does not match to menuclass
        acthWnd = hWnd;
      }
      else
      {
        acthMenu = hWnd;
        // AfxTrace(_T("Found new menu HWND: 0x%08X\n"),acthMenu);
      }
    }
    // Trace all menu msg
    if(acthMenu==hWnd && acthMenu)
    {
      MSG msg = {hWnd,pTemp->message,pTemp->wParam,pTemp->lParam,0,0,0};
      MyTraceMsg(_T(" Menu   "),&msg);
    }
#endif

    // Normal and special handling for menu 0x10012
    if(pTemp->message==WM_CREATE || pTemp->message==0x01E2)
    {
      if(!CheckSubclassing(hWnd,pTemp->message==0x01E2))
      {
        if( (m_bSubclassFlag&NEW_MENU_DIALOG_SUBCLASS) && pTemp->message==WM_CREATE)
        {
          TCHAR Name[20];
          int Count = GetClassName (hWnd,Name,ARRAY_SIZE(Name));
          // Check for the Dialog-class
          if(Count==6 && _tcscmp(Name,_T("#32770"))==0 )
          {
            // Only first dialog
            // m_bSubclassFlag &= ~NEW_MENU_DIALOG_SUBCLASS;
            // Freed by WM_DESTROY
            new CNewMenuTempHandler(hWnd);
          }
        }
      }
    }
  }
  return CallNextHookEx(HookOldMenuCbtFilter, code,wParam, lParam);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewDialog,CDialog)

BEGIN_MESSAGE_MAP(CNewDialog, CNewFrame)
  //{{AFX_MSG_MAP(CNewDialog)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  ON_WM_INITMENUPOPUP()
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

CNewDialog::CNewDialog()
{
}

CNewDialog::CNewDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
  ASSERT(IS_INTRESOURCE(lpszTemplateName) || AfxIsValidString(lpszTemplateName));

  m_pParentWnd = pParentWnd;
  m_lpszTemplateName = lpszTemplateName;
  if (IS_INTRESOURCE(m_lpszTemplateName))
    m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);
}

CNewDialog::CNewDialog(UINT nIDTemplate, CWnd* pParentWnd)
{
  m_pParentWnd = pParentWnd;
  m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);
  m_nIDHelp = nIDTemplate;
}

BOOL CNewDialog::OnInitDialog()
{
  BOOL bRetval = CDialog::OnInitDialog();

  HMENU hMenu = m_SystemNewMenu.Detach();
  HMENU hSysMenu = ::GetSystemMenu(m_hWnd,FALSE);
  if(hMenu!=hSysMenu)
  {
    if(IsMenu(hMenu))
    {
      if(!::DestroyMenu(hMenu))
      {
        ShowLastError(_T("Error from Menu: DestroyMenu"));
      }
    }
  }
  m_SystemNewMenu.Attach(hSysMenu);
  m_DefaultNewMenu.LoadMenu(::GetMenu(m_hWnd));

  if(IsMenu(m_DefaultNewMenu.m_hMenu))
  {
    UpdateMenuBarColor(m_DefaultNewMenu);
  }

  return bRetval;
}

extern void AFXAPI AfxCancelModes(HWND hWndRcvr);

// Most of the code is copied from the MFC code from CFrameWnd::OnInitMenuPopup
void CNewDialog::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
  AfxCancelModes(m_hWnd);

  // don't support system menu
  if (!bSysMenu)
  {
    ASSERT(pMenu != NULL);
    // check the enabled state of various menu items

    CCmdUI state;
    state.m_pMenu = pMenu;
    ASSERT(state.m_pOther == NULL);
    ASSERT(state.m_pParentMenu == NULL);

    // determine if menu is popup in top-level menu and set m_pOther to
    //  it if so (m_pParentMenu == NULL indicates that it is secondary popup)
    HMENU hParentMenu;
    if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
    {
      state.m_pParentMenu = pMenu;    // parent == child for tracking popup
    }
    else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
    {
      CWnd* pParent = GetTopLevelParent();
      // child windows don't have menus -- need to go to the top!
      if (pParent != NULL &&
        (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
      {
        int nIndexMax = ::GetMenuItemCount(hParentMenu);
        for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
        {
          if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
          {
            // when popup is found, m_pParentMenu is containing menu
            state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
            break;
          }
        }
      }
    }

    state.m_nIndexMax = pMenu->GetMenuItemCount();
    for (state.m_nIndex = 0; state.m_nIndexGetMenuItemID(state.m_nIndex);
      if (state.m_nID == 0)
        continue; // menu separator or invalid cmd - ignore it

      ASSERT(state.m_pOther == NULL);
      ASSERT(state.m_pMenu != NULL);
      if (state.m_nID == (UINT)-1)
      {
        // possibly a popup menu, route to first item of that popup
        state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
        if (state.m_pSubMenu == NULL ||
          (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
          state.m_nID == (UINT)-1)
        {
          continue;       // first item of popup can't be routed to
        }
        state.DoUpdate(this, FALSE);    // popups are never auto disabled
      }
      else
      {
        // normal menu item
        // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
        //    set and command is _not_ a system command.
        state.m_pSubMenu = NULL;
        state.DoUpdate(this, state.m_nID < 0xF000);
      }

      // adjust for menu deletions and additions
      UINT nCount = pMenu->GetMenuItemCount();
      if (nCount < state.m_nIndexMax)
      {
        state.m_nIndex -= (state.m_nIndexMax - nCount);
        while (state.m_nIndex < nCount &&
          pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
        {
          state.m_nIndex++;
        }
      }
      state.m_nIndexMax = nCount;
    }
  }
  // Do the work for update
  CNewFrame::OnInitMenuPopup(pMenu,nIndex,bSysMenu);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CNewMiniFrameWnd,CMiniFrameWnd)
BEGIN_MESSAGE_MAP(CNewMiniFrameWnd, CNewFrame)
  //{{AFX_MSG_MAP(CNewMiniFrameWnd)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNCREATE(CNewMDIChildWnd,CMDIChildWnd)
BEGIN_MESSAGE_MAP(CNewMDIChildWnd, CNewFrame)
  //{{AFX_MSG_MAP(CNewMDIChildWnd)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNCREATE(CNewMiniDockFrameWnd,CMiniDockFrameWnd);
BEGIN_MESSAGE_MAP(CNewMiniDockFrameWnd, CNewFrame)
  //{{AFX_MSG_MAP(CNewMiniDockFrameWnd)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CNewFrameWnd,CFrameWnd)

BEGIN_MESSAGE_MAP(CNewFrameWnd, CNewFrame)
  //{{AFX_MSG_MAP(CNewFrameWnd)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

#if _MFC_VER < 0x0700

#include <../src/afximpl.h>

BOOL CNewFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
                             CWnd* pParentWnd, CCreateContext* pContext)
{
  // only do this once
  ASSERT_VALID_IDR(nIDResource);
  ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

  m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)

  CString strFullString;
  if (strFullString.LoadString(nIDResource))
    AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string

  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

  // attempt to create the window
  LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
  LPCTSTR lpszTitle = m_strTitle;
  if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
    pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
  {
    return FALSE;   // will self destruct on failure normally
  }

  // save the default menu handle
  ASSERT(m_hWnd != NULL);
  m_hMenuDefault = ::GetMenu(m_hWnd);

  // load accelerator resource
  LoadAccelTable(MAKEINTRESOURCE(nIDResource));

  if (pContext == NULL)   // send initial update
    SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

  return TRUE;
}
#endif

BOOL CNewFrameWnd::Create(LPCTSTR lpszClassName,
                          LPCTSTR lpszWindowName,
                          DWORD dwStyle,
                          const RECT& rect,
                          CWnd* pParentWnd,
                          LPCTSTR lpszMenuName,
                          DWORD dwExStyle,
                          CCreateContext* pContext)
{
  if (lpszMenuName != NULL)
  {
    m_DefaultNewMenu.LoadMenu(lpszMenuName);
    // load in a menu that will get destroyed when window gets destroyed
    if (m_DefaultNewMenu.m_hMenu == NULL)
    {
#if _MFC_VER < 0x0700
      TRACE0("Warning: failed to load menu for CNewFrameWnd.\n");
#else
      TRACE(traceAppMsg, 0, "Warning: failed to load menu for CNewFrameWnd.\n");
#endif
      PostNcDestroy();            // perhaps delete the C++ object
      return FALSE;
    }
  }
  m_strTitle = lpszWindowName;    // save title for later

  if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
    pParentWnd->GetSafeHwnd(), m_DefaultNewMenu.m_hMenu, (LPVOID)pContext))
  {
#if _MFC_VER < 0x0700
    TRACE0("Warning: failed to create CNewFrameWnd.\n");
#else
    TRACE(traceAppMsg, 0, "Warning: failed to create CNewFrameWnd.\n");
#endif

    return FALSE;
  }

  UpdateMenuBarColor(m_DefaultNewMenu);

  return TRUE;
}

#ifdef USE_NEW_DOCK_BAR

//Bug in compiler??

#ifdef _AFXDLL
// control bar docking
// dwDockBarMap
const DWORD CFrameWnd::dwDockBarMap[4][2] =
{
  { AFX_IDW_DOCKBAR_TOP,      CBRS_TOP    },
  { AFX_IDW_DOCKBAR_BOTTOM,   CBRS_BOTTOM },
  { AFX_IDW_DOCKBAR_LEFT,     CBRS_LEFT   },
  { AFX_IDW_DOCKBAR_RIGHT,    CBRS_RIGHT  },
};
#endif

// dock bars will be created in the order specified by dwDockBarMap
// this also controls which gets priority during layout
// this order can be changed by calling EnableDocking repetitively
// with the exact order of priority
void CNewFrameWnd::EnableDocking(DWORD dwDockStyle)
{
  // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);

  m_pFloatingFrameClass = RUNTIME_CLASS(CNewMiniDockFrameWnd);
  for (int i = 0; i < 4; i++)
  {
    if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)
    {
      CDockBar* pDock = (CDockBar*)GetControlBar(dwDockBarMap[i][0]);
      if (pDock == NULL)
      {
        pDock = new CNewDockBar;
        if (!pDock->Create(this,
          WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
          dwDockBarMap[i][1], dwDockBarMap[i][0]))
        {
          AfxThrowResourceException();
        }
      }
    }
  }
}
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMDIFrameWnd,CMDIFrameWnd)

BEGIN_MESSAGE_MAP(CNewMDIFrameWnd, CNewFrame)
  //{{AFX_MSG_MAP(CNewMDIFrameWnd)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CNewMDIFrameWnd::ShowMenu(BOOL bShow)
{
  // Gets the actual menu
  HMENU hMenu = ::GetMenu(m_hWnd);
  if(bShow)
  {
    if(m_hShowMenu)
    {
      ::SetMenu(m_hWnd, m_hShowMenu);
      DrawMenuBar();
      m_hShowMenu = NULL;
      return FALSE;
    }
    return TRUE;
  }
  else
  {
    m_hShowMenu = hMenu;
    if(m_hShowMenu)
    {
      ::SetMenu(m_hWnd, NULL);
      DrawMenuBar();
      return TRUE;
    }
    return FALSE;
  }
}



#if _MFC_VER < 0x0700

BOOL CNewMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
                                CWnd* pParentWnd, CCreateContext* pContext)
{
  // only do this once
  ASSERT_VALID_IDR(nIDResource);
  ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

  m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)

  CString strFullString;
  if (strFullString.LoadString(nIDResource))
    AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string

  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

  // attempt to create the window
  LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
  LPCTSTR lpszTitle = m_strTitle;
  if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
    pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
  {
    return FALSE;   // will self destruct on failure normally
  }

  // save the default menu handle
  ASSERT(m_hWnd != NULL);
  m_hMenuDefault = ::GetMenu(m_hWnd);

  // load accelerator resource
  LoadAccelTable(MAKEINTRESOURCE(nIDResource));

  if (pContext == NULL)   // send initial update
    SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

  // save menu to use when no active MDI child window is present
  ASSERT(m_hWnd != NULL);
  m_hMenuDefault = ::GetMenu(m_hWnd);
  if (m_hMenuDefault == NULL)
    TRACE0("Warning: CMDIFrameWnd without a default menu.\n");
  return TRUE;
}
#endif

BOOL CNewMDIFrameWnd::Create( LPCTSTR lpszClassName,
                             LPCTSTR lpszWindowName,
                             DWORD dwStyle,
                             const RECT& rect,
                             CWnd* pParentWnd,
                             LPCTSTR lpszMenuName,
                             DWORD dwExStyle,
                             CCreateContext* pContext)
{
  if (lpszMenuName != NULL)
  {
    m_DefaultNewMenu.LoadMenu(lpszMenuName);
    // load in a menu that will get destroyed when window gets destroyed
    if (m_DefaultNewMenu.m_hMenu == NULL)
    {
#if _MFC_VER < 0x0700
      TRACE0("Warning: failed to load menu for CNewMDIFrameWnd.\n");
#else
      TRACE(traceAppMsg, 0, "Warning: failed to load menu for CNewMDIFrameWnd.\n");
#endif
      PostNcDestroy();            // perhaps delete the C++ object
      return FALSE;
    }
  }

  m_strTitle = lpszWindowName;    // save title for later

  if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
    pParentWnd->GetSafeHwnd(), m_DefaultNewMenu.m_hMenu, (LPVOID)pContext))
  {
#if _MFC_VER < 0x0700
    TRACE0("Warning: failed to create CNewMDIFrameWnd.\n");
#else
    TRACE(traceAppMsg, 0, "Warning: failed to create CNewMDIFrameWnd.\n");
#endif

    return FALSE;
  }

  UpdateMenuBarColor(m_DefaultNewMenu);

  return TRUE;
}

#ifdef USE_NEW_DOCK_BAR

// dock bars will be created in the order specified by dwDockBarMap
// this also controls which gets priority during layout
// this order can be changed by calling EnableDocking repetitively
// with the exact order of priority
void CNewMDIFrameWnd::EnableDocking(DWORD dwDockStyle)
{
  // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);

  m_pFloatingFrameClass = RUNTIME_CLASS(CNewMiniDockFrameWnd);
  for (int i = 0; i < 4; i++)
  {
    if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)
    {
      CDockBar* pDock = (CDockBar*)GetControlBar(dwDockBarMap[i][0]);
      if (pDock == NULL)
      {
        pDock = new CNewDockBar;
        if (!pDock->Create(this,
          WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
          dwDockBarMap[i][1], dwDockBarMap[i][0]))
        {
          AfxThrowResourceException();
        }
      }
    }
  }
}
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CNewMultiDocTemplate,CMultiDocTemplate)

CNewMultiDocTemplate::CNewMultiDocTemplate(UINT nIDResource,
                                           CRuntimeClass* pDocClass,
                                           CRuntimeClass* pFrameClass,
                                           CRuntimeClass* pViewClass)
                                           : CMultiDocTemplate(nIDResource,pDocClass,pFrameClass,pViewClass)
{
  if (m_nIDResource != 0 && m_hMenuShared)
  {
    // Attach the menu.
    m_NewMenuShared.LoadMenu(m_hMenuShared);
    // Try to load icons to the toolbar.
    m_NewMenuShared.LoadToolBar(m_nIDResource);
  }
}

CNewMultiDocTemplate::~CNewMultiDocTemplate()
{
  // Let only the CNewMenu to destroy the menu.
  if(m_hMenuShared==m_NewMenuShared.m_hMenu)
  {
    m_hMenuShared = NULL;
  }
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNewMenuHelper::CNewMenuHelper(DWORD dwFlags)
{
  m_dwOldFlags = CNewMenuHook::m_bSubclassFlag;
  CNewMenuHook::m_bSubclassFlag = dwFlags;

  m_OldMenuDrawStyle = CNewMenu::GetMenuDrawMode();
  if(CNewMenuHook::m_bSubclassFlag&NEW_MENU_DEFAULT_BORDER)
  {
    CNewMenu::SetMenuDrawMode(m_OldMenuDrawStyle|1);
  }
}

CNewMenuHelper::CNewMenuHelper(CNewMenu::EDrawStyle setTempStyle)
{
  m_dwOldFlags = CNewMenuHook::m_bSubclassFlag;
  m_OldMenuDrawStyle = CNewMenu::SetMenuDrawMode(setTempStyle);
}

CNewMenuHelper::~CNewMenuHelper()
{
  // Restore the old border style
  CNewMenu::SetMenuDrawMode(m_OldMenuDrawStyle);
  CNewMenuHook::m_bSubclassFlag = m_dwOldFlags;
}


// CNewDockBar

IMPLEMENT_DYNCREATE(CNewDockBar, CDockBar)

CNewDockBar::CNewDockBar(BOOL bFloating):CDockBar(bFloating)
{
}

CNewDockBar::~CNewDockBar()
{
}

BEGIN_MESSAGE_MAP(CNewDockBar, CDockBar)
  //{{AFX_MSG_MAP(CNewDockBar)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //    DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG_MAP
  ON_WM_ERASEBKGND()
  ON_WM_NCPAINT()
END_MESSAGE_MAP()


// CNewDockBar diagnostics

#if defined(_DEBUG) || defined(_AFXDLL)
void CNewDockBar::AssertValid() const
{
  CDockBar::AssertValid();
}

void CNewDockBar::Dump(CDumpContext& dc) const
{
  CDockBar::Dump(dc);
}
#endif //_DEBUG


// CNewDockBar message handlers
void CNewDockBar::EraseNonClient()
{
  // get window DC that is clipped to the non-client area
  CWindowDC dc(this);
  CRect rectClient;
  GetClientRect(rectClient);
  CRect rectWindow;
  GetWindowRect(rectWindow);
  ScreenToClient(rectWindow);
  rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
  dc.ExcludeClipRect(rectClient);

  // draw borders in non-client area
  rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

  //DrawBorders(&dc, rectWindow);

  // erase parts not drawn
  dc.IntersectClipRect(rectWindow);
  SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);

  // draw gripper in non-client area
  DrawGripper(&dc, rectWindow);
}

BOOL CNewDockBar::OnEraseBkgnd(CDC* pDC)
{
  MENUINFO menuInfo = {0};
  menuInfo.cbSize = sizeof(menuInfo);
  menuInfo.fMask = MIM_BACKGROUND;

  //if(::GetMenuInfo(::GetMenu(::GetParent(m_hWnd)),&menuInfo) && menuInfo.hbrBack)
  CBrush *pBrush = GetMenuBarBrush();
  if(pBrush)
  {
    CRect rectA;
    CRect rectB;
    GetWindowRect(rectA);
    ::GetWindowRect(::GetParent(m_hWnd),rectB);

    // need for win95/98/me
    VERIFY(pBrush->UnrealizeObject());
    CPoint oldOrg = pDC->SetBrushOrg(-(rectA.left-rectB.left),0);
    CRect rect;
    pDC->GetClipBox(rect);
    pDC->FillRect(rect,pBrush);
    pDC->SetBrushOrg(oldOrg);
    return true;
  }
  else
  {
    // do default drawing
    return CDockBar::OnEraseBkgnd(pDC);
  }
}

void CNewDockBar::OnNcPaint()
{
  // Do not call CDockBar::OnNcPaint() for painting messages
  EraseNonClient();
}

DWORD CNewDockBar::RecalcDelayShow(AFX_SIZEPARENTPARAMS* lpLayout)
{
  DWORD result = CDockBar::RecalcDelayShow(lpLayout);

#ifdef USE_NEW_MENU_BAR

  // we want to have the menubar on its own row or column and align to border
  int nCount = (int)m_arrBars.GetSize();
  for(int nPos=0;nPosGetWindowRect(rect);
      ScreenToClient(rect);
      if(pBar->m_dwStyle&CBRS_ORIENT_HORZ)
      {
        if(rect.left>0)
        {
          pBar->SetWindowPos(NULL,-5,rect.top,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_FRAMECHANGED);
        }
      }
      else
      {
        if(rect.top>0)
        {
          pBar->SetWindowPos(NULL,rect.left,-5,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_FRAMECHANGED);
        }
      }

      if((nPos+1)hwnd != hWnd)
        SetWindowPos (hWnd, HWND_TOP, 0, 0, 0, 0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
    }
    break;

  case WM_SHOWWINDOW:
    {
      result = DefWindowProc(hWnd, message, wParam, lParam);
      //if(wParam)
      //{
      //  // window is show
      //  //InvalidateRect(hWnd,NULL,FALSE);
      //  SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOACTIVATE);
      //}
      //else
      //{
      //  // window disappear
      //  InvalidateRect(hWnd,NULL,FALSE);
      //}
    }
    break;

  case WM_CREATE:
    {
      LPCREATESTRUCT pCreate = (LPCREATESTRUCT)lParam;
      ASSERT(pCreate);
      //CRect rect;
      //GetWindowRect(pCreate->hwndParent,rect);
      result = DefWindowProc(hWnd, message, wParam, lParam);
      SShadeInfo *pShadeInfo = (SShadeInfo*)pCreate->lpCreateParams;
      ASSERT(pShadeInfo);
      if(pShadeInfo->bSideShade)
      {
        SetWindowPos(hWnd,HWND_TOPMOST,
          pShadeInfo->parentRect.left+5,pShadeInfo->parentRect.bottom,
          pShadeInfo->parentRect.Width(),5,
          SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER);
      }
      else
      {
        SetWindowPos(hWnd,HWND_TOPMOST,
          pShadeInfo->parentRect.right,pShadeInfo->parentRect.top+5,
          5,pShadeInfo->parentRect.Height()-5,
          SWP_SHOWWINDOW|SWP_NOACTIVATE);
      }
      //GetSafeTimerID(hWnd,200);
    }
    break;

  default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return result;
}


//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
BOOL ShadeRegisterClass()
{
  WNDCLASS wndcls;

  wndcls.style         = CS_HREDRAW | CS_VREDRAW;
  wndcls.lpfnWndProc   = (WNDPROC)ShadeWndProc;
  wndcls.cbClsExtra    = 0;
  wndcls.cbWndExtra    = 0;
  wndcls.hInstance     = AfxGetInstanceHandle();
  wndcls.hIcon         = (HICON)NULL;
  wndcls.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wndcls.hbrBackground = (HBRUSH)NULL;
  wndcls.lpszMenuName  = (LPCTSTR)NULL;
  wndcls.lpszClassName = szShadeWindowClass;

  return AfxRegisterClass(&wndcls);
}

void SetWindowShade(HWND hWndParent,LPRECT pRect)
{
  ShadeRegisterClass();

  SShadeInfo shadeInfo;

  shadeInfo.hParent = hWndParent;
  if(pRect!=NULL)
  {
    shadeInfo.parentRect = *pRect;
  }
  else
  {
    GetWindowRect(hWndParent,&shadeInfo.parentRect);
  }

  shadeInfo.bSideShade = true;
  HWND hWnd = CreateWindowEx(WS_EX_TRANSPARENT|WS_EX_TOPMOST ,
    szShadeWindowClass,
    NULL,
    WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
    CW_USEDEFAULT, 0,
    CW_USEDEFAULT, 0,
    hWndParent, (HMENU)0,
    AfxGetInstanceHandle(),
    &shadeInfo);

  shadeInfo.bSideShade = false;
  hWnd = CreateWindowEx( WS_EX_TRANSPARENT|WS_EX_TOPMOST ,
    szShadeWindowClass,
    NULL,
    WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
    CW_USEDEFAULT, 0,
    CW_USEDEFAULT, 0,
    hWndParent, (HMENU)0,
    AfxGetInstanceHandle(),
    &shadeInfo);
}

//void SetWindowShade(HWND hWndMenu, CNewMenuHook::CMenuHookData* pData )
//{
//  if(pData==NULL || pData->m_hRightShade!=NULL || pData->m_hBottomShade)
//  {
//    return;
//  }
//
//  ShadeRegisterClass();
//
//  HWND hWndParent = AfxGetMainWnd()->GetSafeHwnd();
//  SShadeInfo shadeInfo;
//  shadeInfo.hParent = hWndMenu;
//  GetWindowRect(hWndMenu,&shadeInfo.parentRect);
//
//  shadeInfo.bSideShade = true;
//
//  pData->m_hRightShade = CreateWindowEx(WS_EX_TRANSPARENT|WS_EX_TOPMOST ,
//                                        szShadeWindowClass,
//                                        NULL,
//                                        WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
//                                        CW_USEDEFAULT, 0,
//                                        CW_USEDEFAULT, 0,
//                                        hWndParent, (HMENU)0,
//                                        AfxGetInstanceHandle(),
//                                        &shadeInfo);
//
//  shadeInfo.bSideShade = false;
//  pData->m_hBottomShade = CreateWindowEx( WS_EX_TRANSPARENT|WS_EX_TOPMOST ,
//                                          szShadeWindowClass,
//                                          NULL,
//                                          WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
//                                          CW_USEDEFAULT, 0,
//                                          CW_USEDEFAULT, 0,
//                                          hWndParent, (HMENU)0,
//                                          AfxGetInstanceHandle(),
//                                          &shadeInfo);
//}


#ifdef _AFXDLL

static void ForceVectorDelete()
{
  // this function is only need for exporting all template
  // functions

  // never called
  ASSERT(FALSE);

  new CNewFrameWnd[2];

  new CNewMDIChildWnd[2];
  new CNewMDIFrameWnd[2];

  new CNewDialog[2];

  new CNewMiniDockFrameWnd[2];
  new CNewMiniFrameWnd[2];
}

void (*_ForceVectorDelete)() = &ForceVectorDelete;

#endif

头文件:

//------------------------------------------------------------------------------
// File    : NewMenu.h 
// Version : 1.25
// Date    : 25. June 2005
// Author  : Bruno Podetti
// Email   : [email protected]
// Web     : www.podetti.com/NewMenu 
// Systems : VC6.0/7.0 and VC7.1 (Run under (Window 98/ME), Windows Nt 2000/XP)
//           for all systems it will be the best when you install the latest IE
//           it is recommended for CNewToolBar
//
// 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.
//------------------------------------------------------------------------------
#ifndef __CNewMenu_H_
#define __CNewMenu_H_

// new constant for having the same color in the toolbar, you can define this
// also in the projekt definition
//#define USE_NEW_DOCK_BAR

// for using my CNewMenu in the GuiToolkit see
// http://www.codeproject.com/library/guitoolkit.asp
// you need to #define _GUILIB_   in the ExtLib.h  and include this file
// the constant for exporting importing these classes can be changed in the 
// next release GUILIBDLLEXPORT!!!

#ifdef NEW_MENU_DLL
  #ifdef NEW_MENU_DLL_EXPORT
    #define GUILIBDLLEXPORT __declspec(dllexport)
  #else
    #define GUILIBDLLEXPORT __declspec(dllimport)

#if _MSC_VER >= 1300
    // older compiler have a bug. static template member were not exported corectly
    // so we need this
    #define _GUILIB_
#endif

  #endif
#endif

#ifndef GUILIBDLLEXPORT
#define GUILIBDLLEXPORT
#endif

#pragma warning(push)
#pragma warning(disable : 4211)

#include 
#include 

// Flagdefinitions 
#define MFT_TITLE       0x0001
#define MFT_TOP_TITLE   0x0000
#define MFT_SIDE_TITLE  0x0002
#define MFT_GRADIENT    0x0004
#define MFT_SUNKEN      0x0008
#define MFT_LINE        0x0010
#define MFT_ROUND       0x0020
#define MFT_CENTER      0x0040

// Typedefinition for compatibility to MFC 7.0
#ifndef DWORD_PTR
typedef DWORD DWORD_PTR, *PDWORD_PTR;
#endif

#ifndef ULONG_PTR
typedef unsigned long ULONG_PTR, *PULONG_PTR;
#endif

#ifndef LONG_PTR
typedef long LONG_PTR, *PLONG_PTR;
#endif

// Additional flagdefinition for highlighting
#ifndef ODS_HOTLIGHT
#define ODS_HOTLIGHT        0x0040
#endif

#ifndef ODS_INACTIVE
#define ODS_INACTIVE        0x0080
#endif

// Typedefinition for old compatibility lesser than MFC 8.0
#if _MFC_VER < 0x0800  
#define _tcscpy_s(strDestination,sizeInTchar,strSource )  _tcscpy(strDestination,strSource)
#define _tcsncpy_s(strDestination,sizeInTchar,strSource,sizeCopyInTchar) _tcsncpy(strDestination,strSource,sizeCopyInTchar)
#endif


// new define menustyles
#define ODS_SELECTED_OPEN   0x0800
#define ODS_RIGHTJUSTIFY    0x1000
#define ODS_WRAP            0x2000
#define ODS_HIDDEN          0x4000
#define ODS_DRAW_VERTICAL   0x8000


/////////////////////////////////////////////////////////////////////////////
// Constans for detecting OS-Type
enum Win32Type
{
  Win32s,
  WinNT3,
  Win95,
  Win98,
  WinME,
  WinNT4,
  Win2000,
  WinXP
};

Win32Type GUILIBDLLEXPORT IsShellType();

extern const Win32Type GUILIBDLLEXPORT g_Shell;
extern BOOL GUILIBDLLEXPORT bRemoteSession;
BOOL GUILIBDLLEXPORT IsMenuThemeActive();

/////////////////////////////////////////////////////////////////////////////
// Support for getting menuinfo without runtime-error

#if(WINVER < 0x0500)

#define MNS_NOCHECK         0x80000000
#define MNS_MODELESS        0x40000000
#define MNS_DRAGDROP        0x20000000
#define MNS_AUTODISMISS     0x10000000
#define MNS_NOTIFYBYPOS     0x08000000
#define MNS_CHECKORBMP      0x04000000

#define MIM_MAXHEIGHT               0x00000001
#define MIM_BACKGROUND              0x00000002
#define MIM_HELPID                  0x00000004
#define MIM_MENUDATA                0x00000008
#define MIM_STYLE                   0x00000010
#define MIM_APPLYTOSUBMENUS         0x80000000


typedef struct tagMENUINFO
{
  DWORD   cbSize;
  DWORD   fMask;
  DWORD   dwStyle;
  UINT    cyMax;
  HBRUSH  hbrBack;
  DWORD   dwContextHelpID;
  ULONG_PTR dwMenuData;
}   MENUINFO, FAR *LPMENUINFO;
typedef MENUINFO CONST FAR *LPCMENUINFO;

BOOL GUILIBDLLEXPORT GetMenuInfo( HMENU hMenu, LPMENUINFO pInfo);
BOOL GUILIBDLLEXPORT SetMenuInfo( HMENU hMenu, LPCMENUINFO pInfo);

#define WS_EX_LAYOUTRTL         0x00400000L // Right to left mirroring

#define LAYOUT_RTL              0x00000001  // Right to left

DWORD GUILIBDLLEXPORT GetLayout(HDC hDC);
DWORD GUILIBDLLEXPORT SetLayout(HDC hDC, DWORD dwLayout);

#endif

inline bool IsMirroredHdc(HDC hDC)
{
  return (GetLayout(hDC)&LAYOUT_RTL)?true:false;
}

inline bool IsMirroredWnd(HWND hWnd)
{
  return (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)?true:false;
}

CRect GUILIBDLLEXPORT GetScreenRectFromWnd(HWND hWnd);
CRect GUILIBDLLEXPORT GetScreenRectFromRect(LPCRECT pRect);
BOOL GUILIBDLLEXPORT TrackPopupMenuSpecial(CMenu *pMenu, UINT uFlags, CRect rcTBItem, CWnd* pWndCommand, BOOL bOnSide);

/////////////////////////////////////////////////////////////////////////////
// Forwarddeclaration and global function for menu drawing
void GUILIBDLLEXPORT DrawGradient(CDC* pDC,CRect& Rect,
                                  COLORREF StartColor,COLORREF EndColor, 
                                  BOOL bHorizontal,BOOL bUseSolid=FALSE);

void GUILIBDLLEXPORT MenuDrawText(HDC hDC ,LPCTSTR lpString,int nCount,LPRECT lpRect,UINT uFormat);


COLORREF GUILIBDLLEXPORT DarkenColorXP(COLORREF color);
COLORREF GUILIBDLLEXPORT DarkenColor( long lScale, COLORREF lColor);

COLORREF GUILIBDLLEXPORT MixedColor(COLORREF colorA,COLORREF colorB);
COLORREF GUILIBDLLEXPORT MidColor(COLORREF colorA,COLORREF colorB);

COLORREF GUILIBDLLEXPORT LightenColor( long lScale, COLORREF lColor);

COLORREF GUILIBDLLEXPORT BleachColor(int Add, COLORREF color);
COLORREF GUILIBDLLEXPORT GetAlphaBlendColor(COLORREF blendColor, COLORREF pixelColor,int weighting);

COLORREF GUILIBDLLEXPORT GetXpHighlightColor();
COLORREF GUILIBDLLEXPORT GrayColor(COLORREF crColor); 

/////////////////////////////////////////////////////////////////////////////
// Global helperfunctions
UINT GUILIBDLLEXPORT GetSafeTimerID(HWND hWnd, const UINT uiElapse);

BOOL GUILIBDLLEXPORT DrawMenubarItem(CWnd* pWnd,CMenu* pMenu, UINT nItemIndex,UINT nState);
void GUILIBDLLEXPORT UpdateMenuBarColor(HMENU hMenu=NULL);
CBrush GUILIBDLLEXPORT *GetMenuBarBrush();

int GUILIBDLLEXPORT NumScreenColors();
WORD GUILIBDLLEXPORT NumBitmapColors(LPBITMAPINFOHEADER lpBitmap);
HBITMAP GUILIBDLLEXPORT LoadColorBitmap(LPCTSTR lpszResourceName, HMODULE hInst, int* pNumcol=NULL);

COLORREF GUILIBDLLEXPORT MakeGrayAlphablend(CBitmap* pBitmap, int weighting, COLORREF blendcolor);
HBITMAP GUILIBDLLEXPORT CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent);

/////////////////////////////////////////////////////////////////////////////
// Forwarddeclaration for drawing purpose
class CNewMenu;
class CMenuTheme;
class CNewDockBar;

/////////////////////////////////////////////////////////////////////////////
// CMenuTheme for drawing border and the rest

typedef void (CNewMenu::*pItemMeasureFkt) (LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenubar);
typedef void (CNewMenu::*pItemDrawFkt) (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);
typedef BOOL (CNewMenu::*pEraseBkgndFkt) (HWND hWnd, HDC hDC);

typedef void (CMenuTheme::*pDrawMenuBorder)( HWND hWnd, HDC hDC, CPoint screen);

class GUILIBDLLEXPORT CMenuTheme
{
public:
  CMenuTheme();

  CMenuTheme(DWORD dwThemeId,
    pItemMeasureFkt pMeasureItem,
    pItemDrawFkt pDrawItem,
    pItemDrawFkt pDrawTitle,
    DWORD dwFlags=0);

  virtual ~CMenuTheme();
  virtual BOOL OnInitWnd(HWND hWnd);
  virtual BOOL OnUnInitWnd(HWND hWnd);

  virtual BOOL DoDrawBorder();

  virtual void UpdateSysColors();
  virtual void UpdateSysMetrics();

  virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC, BOOL bOnlyBorder=FALSE);
  virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
  virtual BOOL OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc);
  virtual BOOL OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos);
  virtual BOOL OnCalcFrameRect(HWND hWnd,LPRECT pRect);

  virtual void DrawGripper( CDC* pDC, const CRect& rect, DWORD dwStyle, 	
                            int m_cxLeftBorder, int m_cxRightBorder,
                            int m_cyTopBorder, int m_cyBottomBorder);

  virtual void DrawCorner ( CDC* pDC, LPCRECT pRect, DWORD dwStyle);

  void PaintCorner(CDC *pDC, LPCRECT pRect, COLORREF color);

  virtual void GetBarColor(COLORREF &clrUpperColor, COLORREF &clrMediumColor, COLORREF &clrBottomColor, COLORREF &clrDarkLine);

  void DrawShade( HWND hWnd, HDC hDC, CPoint screen);
  void DrawSmalBorder( HWND hWnd, HDC hDC);
  void DrawFrame(CDC* pDC, CRect rectOuter, CRect rectInner, COLORREF crBorder);

  void* SetScreenBitmap(HWND hWnd, HDC hDC);

public:
  DWORD m_dwThemeId;
  DWORD m_dwFlags;

  pItemMeasureFkt m_pMeasureItem;
  pItemDrawFkt m_pDrawItem;
  pItemDrawFkt m_pDrawTitle;

  CSize m_BorderTopLeft;
  CSize m_BorderBottomRight;

	// color values of system colors used for CToolBar
	COLORREF clrBtnFace, clrBtnShadow, clrBtnHilite;
	COLORREF clrBtnText, clrWindowFrame;
};

/////////////////////////////////////////////////////////////////////////////
// CMenuThemeXP for drawing border and the rest

class GUILIBDLLEXPORT CMenuThemeXP :public CMenuTheme
{
public:
  CMenuThemeXP(DWORD dwThemeId,
    pItemMeasureFkt pMeasureItem,
    pItemDrawFkt pDrawItem,
    pItemDrawFkt pDrawTitle,
    DWORD dwFlags=0);

  virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC, BOOL bOnlyBorder=FALSE);
  virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
};

/////////////////////////////////////////////////////////////////////////////
// CMenuTheme2003 for drawing border and the rest
class GUILIBDLLEXPORT CMenuTheme2003 :public CMenuThemeXP
{
public:
  CMenuTheme2003(DWORD dwThemeId,
    pItemMeasureFkt pMeasureItem,
    pItemDrawFkt pDrawItem,
    pItemDrawFkt pDrawTitle,
    DWORD dwFlags=0);
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuIcons menu icons for drawing

class GUILIBDLLEXPORT CNewMenuIcons : public CObject
{
  DECLARE_DYNCREATE(CNewMenuIcons)

public:
  CNewMenuIcons();
  virtual ~CNewMenuIcons();

public:
  BOOL GetIconSize(int* cx, int* cy);
  CSize GetIconSize();

  virtual int FindIndex(UINT nID);
  virtual void OnSysColorChange();

  virtual BOOL LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst);
  virtual BOOL LoadToolBar(WORD* pToolInfo, COLORREF crTransparent=CLR_NONE);
  virtual BOOL LoadToolBar(HBITMAP hBitmap, CSize size, UINT* pID, COLORREF crTransparent=CLR_NONE);

  virtual BOOL DoMatch(LPCTSTR lpszResourceName, HMODULE hInst);
  virtual BOOL DoMatch(WORD* pToolInfo, COLORREF crTransparent=CLR_NONE);
  virtual BOOL DoMatch(HBITMAP hBitmap, CSize size, UINT* pID);

  virtual BOOL LoadBitmap(int nWidth, int nHeight, LPCTSTR lpszResourceName, HMODULE hInst=NULL);

  //  virtual BOOL SetBlendImage();
  virtual int AddGloomIcon(HICON hIcon, int nIndex=-1);
  virtual int AddGrayIcon(HICON hIcon, int nIndex=-1);
  virtual BOOL MakeImages();

  void SetResourceName(LPCTSTR lpszResourceName);

  int AddRef();
  int Release();

#if defined(_DEBUG) || defined(_AFXDLL)
  // Diagnostic Support
  virtual void AssertValid() const;
  virtual void Dump(CDumpContext& dc) const;
#endif

public:
  LPCTSTR m_lpszResourceName;
  HMODULE m_hInst;
  HBITMAP m_hBitmap;
  int m_nColors;
  COLORREF m_crTransparent;

  CImageList m_IconsList;

  CArray m_IDs;
  DWORD m_dwRefCount;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuBitmaps menu icons for drawing
class GUILIBDLLEXPORT CNewMenuBitmaps : public CNewMenuIcons
{
  DECLARE_DYNCREATE(CNewMenuBitmaps)

public:
  CNewMenuBitmaps();
  virtual ~CNewMenuBitmaps();

public:
  int Add(UINT nID, COLORREF crTransparent=CLR_NONE);
  int Add(HICON hIcon, UINT nID=0);
  int Add(CBitmap* pBitmap, COLORREF crTransparent=CLR_NONE);

  virtual void OnSysColorChange();

  CArray m_TranspColors;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuItemData menu item data for drawing

class GUILIBDLLEXPORT CNewMenuItemData : public CObject
{
  DECLARE_DYNCREATE(CNewMenuItemData)

public:
  CNewMenuItemData();
  virtual ~CNewMenuItemData();

public:
  // get the item text, 
  // hAccel=INVALID_HANDLE_VALUE = gets the default from the frame
  // hAccel=NULL disable accelerator support
  virtual CString GetString(HACCEL hAccel=NULL);
  virtual void SetString(LPCTSTR szMenuText);

#if defined(_DEBUG) || defined(_AFXDLL)
  // Diagnostic Support
  virtual void AssertValid() const;
  virtual void Dump(CDumpContext& dc) const;
#endif

public:
  CString m_szMenuText;

  UINT m_nTitleFlags;
  UINT m_nFlags;
  UINT m_nID;
  UINT m_nSyncFlag;

  CNewMenuIcons* m_pMenuIcon;
  int m_nMenuIconOffset;

  void* m_pData;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuItemDataTitle menu item data for drawing menu Title

class GUILIBDLLEXPORT CNewMenuItemDataTitle : public CNewMenuItemData
{
  DECLARE_DYNCREATE(CNewMenuItemDataTitle)

public:
  CNewMenuItemDataTitle();
  virtual ~CNewMenuItemDataTitle();

public:
  COLORREF m_clrTitle;
  COLORREF m_clrLeft;
  COLORREF m_clrRight;

  CFont m_Font;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenu the new menu class

class GUILIBDLLEXPORT CNewMenu : public CMenu
{
  friend class CNewMenuHook;
  friend class CNewMenuIcons;

  DECLARE_DYNCREATE(CNewMenu)

public:
  // how the menu's are drawn, either original or XP style
  typedef enum 
  { 
    STYLE_ORIGINAL=0,
    STYLE_ORIGINAL_NOBORDER=1,

    STYLE_XP=2,
    STYLE_XP_NOBORDER=3,

    STYLE_SPECIAL=4,
    STYLE_SPECIAL_NOBORDER=5,

    STYLE_ICY=6,
    STYLE_ICY_NOBORDER=7,

    STYLE_XP_2003=8,
    STYLE_XP_2003_NOBORDER=9,

    STYLE_COLORFUL=10,
    STYLE_COLORFUL_NOBORDER=11,

    STYLE_LAST = 11,

    STYLE_UNDEFINED = -1

  } EDrawStyle;

  // how seperators are handled when removing a menu (Tongzhe Cui)
  typedef enum {NONE, HEAD, TAIL, BOTH} ESeperator;

public:
  CNewMenu(HMENU hParent=0); 
  virtual ~CNewMenu();

  // Functions for loading and applying bitmaps to menus (see example application)
  virtual BOOL LoadMenu(HMENU hMenu);
  virtual BOOL LoadMenu(LPCTSTR lpszResourceName);
  virtual BOOL LoadMenu(int nResource);

  BOOL LoadToolBar(HBITMAP hBitmap, CSize size, UINT* pID, COLORREF crTransparent=CLR_NONE);
  BOOL LoadToolBar(WORD* pIconInfo, COLORREF crTransparent=CLR_NONE);
  BOOL LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst = NULL);
  BOOL LoadToolBar(UINT nToolBar, HMODULE hInst = NULL);
  BOOL LoadToolBars(const UINT *arID,int n, HMODULE hInst = NULL);
  // Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
  BOOL LoadToolBar(UINT n16ToolBarID, UINT n256BitmapID, COLORREF transparentColor, HMODULE hInst = NULL);

  BOOL LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset);
  BOOL AddBitmapToImageList(CImageList *list,UINT nResourceID);

  static HBITMAP LoadSysColorBitmap(int nResourceId);
  // custom check mark bitmaps
  void LoadCheckmarkBitmap(int unselect, int select); 

  // functions for appending a menu option, use the AppendMenu call
  BOOL AppendMenu(UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL,int nIconNormal=-1);
  BOOL AppendMenu(UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CImageList *il,int xoffset);
  BOOL AppendMenu(UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CBitmap *bmp);

  BOOL AppendODMenu(LPCTSTR lpstrText, UINT nFlags = MF_OWNERDRAW, UINT nID = 0, int nIconNormal = -1);  
  BOOL AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID, CBitmap* pbmp);
  BOOL AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID, CImageList *il, int xoffset);
  BOOL AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID, CNewMenuIcons* pIcons, int nIndex);

  // for appending a popup menu (see example application)
  CNewMenu* AppendODPopupMenu(LPCTSTR lpstrText);

  // functions for inserting a menu option, use the InsertMenu call (see above define)
  BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL,int nIconNormal=-1);
  BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CImageList *il,int xoffset);
  BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CBitmap *bmp);

  BOOL InsertODMenu(UINT nPosition,LPCTSTR lpstrText, UINT nFlags = MF_OWNERDRAW,UINT nID = 0,int nIconNormal = -1);  
  BOOL InsertODMenu(UINT nPosition,LPCTSTR lpstrText, UINT nFlags, UINT nID, CBitmap* pBmp);
  BOOL InsertODMenu(UINT nPosition,LPCTSTR lpstrText, UINT nFlags, UINT nID, CImageList *il,int xoffset);
  BOOL InsertODMenu(UINT nPosition,LPCTSTR lpstrText, UINT nFlags, UINT nID, CNewMenuIcons* pIcons, int nIndex);

  // Same as ModifyMenu but replacement for CNewMenu
  BOOL ModifyODMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem = 0,LPCTSTR lpszNewItem = NULL);
  BOOL ModifyODMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp);

  // functions for modifying a menu option, use the ModifyODMenu call (see above define)
  BOOL ModifyODMenu(LPCTSTR lpstrText, UINT nID=0, int nIconNormal=-1);
  BOOL ModifyODMenu(LPCTSTR lpstrText, UINT nID, CImageList *il, int xoffset);
  BOOL ModifyODMenu(LPCTSTR lpstrText, UINT nID, CNewMenuIcons* pIcons, int nIndex);

  BOOL ModifyODMenu(LPCTSTR lpstrText,UINT nID,CBitmap *bmp);
  BOOL ModifyODMenu(LPCTSTR lpstrText,LPCTSTR OptionText,int nIconNormal);
  // use this method for adding a solid/hatched colored square beside a menu option
  // courtesy of Warren Stevens
  BOOL ModifyODMenu(LPCTSTR lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle=-1);

  // for deleting and removing menu options
  BOOL  DeleteMenu(UINT uiId,UINT nFlags);
  BOOL  RemoveMenu(UINT uiId,UINT nFlags);
  int RemoveMenu(LPCTSTR pText, ESeperator sPos=CNewMenu::NONE);

  // function for retrieving and setting a menu options text (use this function
  // because it is ownerdrawn)
  BOOL GetMenuText(UINT id,CString &string,UINT nFlags = MF_BYPOSITION);
  BOOL SetMenuText(UINT id,CString string, UINT nFlags = MF_BYPOSITION);

  // Getting a submenu from it's name or position
  CMenu* GetSubMenu (LPCTSTR lpszSubMenuName) const;
  CMenu* GetSubMenu (int nPos) const;
  int GetMenuPosition(LPCTSTR pText);

  // Destoying
  virtual BOOL DestroyMenu();

  // Drawing: 
  // Draw an item
  virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
  // Measure an item  
  virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMIS);
  // Draw title of the menu
  virtual void DrawTitle(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar);
  // Erase the Background of the menu
  virtual BOOL EraseBkgnd(HWND hWnd, HDC hDC);

  static COLORREF GetMenuBarColor2003();
  static void GetMenuBarColor2003(COLORREF& color1, COLORREF& color2, BOOL bBackgroundColor = TRUE);
  static COLORREF GetMenuBarColorXP();
  static COLORREF GetMenuBarColor(HMENU hMenu=NULL);
  static COLORREF GetMenuColor(HMENU hMenu=NULL);

  static void SetMenuTitleFont(CFont* pFont);
  static void SetMenuTitleFont(LOGFONT* pLogFont);
  static LOGFONT GetMenuTitleFont();

  // Menutitle function
  BOOL SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags=MFT_TOP_TITLE, int nIconNormal = -1);
  BOOL SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CBitmap* pBmp);
  BOOL SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CImageList *pil, int xoffset);
  BOOL SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags, CNewMenuIcons* pIcons, int nIndex);

  BOOL SetMenuTitleColor(COLORREF clrTitle=CLR_DEFAULT, COLORREF clrLeft=CLR_DEFAULT, COLORREF clrRight=CLR_DEFAULT);

  BOOL RemoveMenuTitle();

  // Function to set how menu is drawn, either original or XP style
  static UINT GetMenuDrawMode();
  static UINT SetMenuDrawMode(UINT mode);

  static CMenuTheme* GetActualMenuTheme(){ return m_pActMenuDrawing;}

  // Function to set how disabled items are drawn 
  //(mode=FALSE means they are not drawn selected)
  static BOOL SetSelectDisableMode(BOOL mode);
  static BOOL GetSelectDisableMode();

  // Function to set how icons were drawn in normal mode 
  //(enable=TRUE means they are drawn blended)
  static BOOL SetXpBlending(BOOL bEnable=TRUE);
  static BOOL GetXpBlending();

  // Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
  // added SetGloomFactor() and GetGloomFactor() so that the glooming can be done in a more or less subtle way
  static int SetGloomFactor(int nGloomFactor);
  static int GetGloomFactor();

  // Function to set how default menu border were drawn
  //(enable=TRUE means that all menu in the application has the same border)
  static BOOL SetNewMenuBorderAllMenu(BOOL bEnable=TRUE);
  static BOOL GetNewMenuBorderAllMenu();

  static void OnSysColorChange();

  // Static functions used for handling menu's in the mainframe
  static LRESULT FindKeyboardShortcut(UINT nChar,UINT nFlags,CMenu *pMenu);
  static BOOL OnMeasureItem(const MSG* pMsg);
  static void OnInitMenuPopup(HWND hWnd, CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);

  // Helperfunction to find the menu to the item
  static CMenu* FindPopupMenuFromID(CMenu* pMenu, UINT nID);
  static CMenu* FindPopupMenuFromID(HMENU hMenu, UINT nID);

  static CMenu* FindPopupMenuFromIDData(CMenu* pMenu, UINT nID, ULONG_PTR pData);
  static CMenu* FindPopupMenuFromIDData(HMENU hMenu, UINT nID, ULONG_PTR pData);

  virtual void OnInitMenuPopup();
  virtual BOOL OnUnInitPopupMenu();

  // Customizing:
  // Set icon size
  void SetIconSize(int width, int height);
  CSize GetIconSize();

  // set the color in the bitmaps that is the background transparent color
  COLORREF SetBitmapBackground(COLORREF newColor);
  COLORREF GetBitmapBackground(); 

  // Return the last itemrect from a menubaritem.
  CRect GetLastActiveMenuRect();
  void SetLastMenuRect(HDC hDC, LPRECT pRect);
  void SetLastMenuRect(LPRECT pRect);

  HMENU GetParent();
  BOOL IsPopup();
  BOOL SetPopup(BOOL bIsPopup=TRUE);

  BOOL SetItemData(UINT uiId, DWORD_PTR dwItemData, BOOL fByPos = FALSE);
  BOOL SetItemDataPtr(UINT uiId, void* pItemData, BOOL fByPos = FALSE);

  DWORD_PTR GetItemData(UINT uiId, BOOL fByPos = FALSE) const;
  void* GetItemDataPtr(UINT uiId, BOOL fByPos = FALSE) const;

  BOOL SetMenuData(DWORD_PTR dwMenuData);
  BOOL SetMenuDataPtr(void* pMenuData);

  DWORD_PTR GetMenuData() const;
  void* GetMenuDataPtr() const;

  // enable or disable the global accelerator drawing
  static BOOL SetAcceleratorsDraw (BOOL bDraw);
  static BOOL GetAcceleratorsDraw ();

  // Set Alphablending of the menu only win2000 /XP/2003
  // When bAlpha is 255, the window is opaque
  static BYTE SetAlpha(BYTE bAlpha);
  static BYTE GetAlpha();

  // INVALID_HANDLE_VALUE = Draw default frame's accel. NULL = Off
  HACCEL SetAccelerator (HACCEL hAccel);
  HACCEL GetAccelerator ();

  // can set icons from a global saved icons-list
  DWORD SetMenuIcons(CNewMenuIcons* pMenuIcons);

  // Miscellaneous Protected Member functions
protected:
  CNewMenuIcons* GetMenuIcon(int &nIndex, UINT nID, CImageList *pil, int xoffset);
  CNewMenuIcons* GetMenuIcon(int &nIndex, int nID);
  CNewMenuIcons* GetMenuIcon(int &nIndex, CBitmap* pBmp);

  CNewMenuIcons* GetToolbarIcons(UINT nToolBar, HMODULE hInst=NULL);

  BOOL Replace(UINT nID, UINT nNewID);

  static BOOL IsNewShell();
  BOOL IsMenuBar(HMENU hMenu=NULL);

  CNewMenuItemData* FindMenuItem(UINT nID);
  CNewMenu* FindMenuOption(int nId, int& nLoc);
  CNewMenu* FindMenuOption(LPCTSTR lpstrText, int& nLoc);

  CNewMenu* FindAnotherMenuOption(int nId, int& nLoc, CArray&newSubs, CArray&newLocs);

  CNewMenuItemData* NewODMenu(UINT pos, UINT nFlags, UINT nID, LPCTSTR string);
  CNewMenuItemDataTitle* GetMemuItemDataTitle();

  void SynchronizeMenu();
  void InitializeMenuList(int value);
  void DeleteMenuList();

  CNewMenuItemData* FindMenuList(UINT nID);
  CNewMenuItemData* CheckMenuItemData(ULONG_PTR nItemData) const;

  void DrawSpecial_OldStyle(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle);
  void DrawSpecial_WinXP(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle);

  void DrawSpecialCharStyle(CDC* pDC, LPCRECT pRect, TCHAR Sign, DWORD dwStyle);
  void DrawSpecialChar(CDC* pDC, LPCRECT pRect, TCHAR Sign, BOOL bBold);

  void DrawMenuTitle(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar);

  // Measure an item
  void MeasureItem_OldStyle( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar); 
  void DrawItem_OldStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);

  void MeasureItem_Icy( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar); 
  void DrawItem_Icy (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);
  BOOL Draw3DCheckmark(CDC* dc, CRect rc, HBITMAP hbmpChecked, HBITMAP hbmpUnchecked, DWORD dwState);

  void MeasureItem_WinXP( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar); 
  void DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar);

  void DrawItem_XP_2003 (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar);

  void DrawItem_SpecialStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);

  //  BOOL ImageListDuplicate(CImageList* il,int xoffset,CImageList* newlist);
  void ColorBitmap(CDC* pDC, CBitmap& bmp, CSize size, COLORREF fill, COLORREF border, int hatchstyle=-1);


  // Member Variables
public:
  static DWORD m_dwLastActiveItem;

protected: 
  // Stores list of menu items
  CTypedPtrArray m_MenuItemList;   
  // When loading an owner-drawn menu using a Resource, CNewMenu must keep track of
  // the popup menu's that it creates. Warning, this list *MUST* be destroyed
  // last item first :)
  // Stores list of sub-menus
  CTypedPtrArray  m_SubMenus;

  static BOOL m_bEnableXpBlending;
  static BOOL m_bNewMenuBorderAllMenu;
  static BOOL m_bSelectDisable;
  // Jan-12-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/
  // added gloom factor
  static int m_nGloomFactor;
  static CMenuTheme* m_pActMenuDrawing;
  static LOGFONT m_MenuTitleFont;
  static CTypedPtrList* m_pSharedMenuIcons;
  static BOOL m_bDrawAccelerators;
  static BYTE m_bAlpha;

  int m_iconX;
  int m_iconY;

  HWND m_hTempOwner;

  COLORREF m_bitmapBackground;

  CImageList* m_checkmaps;
  BOOL m_checkmapsshare;

  int m_selectcheck;
  int m_unselectcheck;

  BOOL m_bDynIcons;

  HMENU m_hParentMenu;

  BOOL m_bIsPopupMenu;

  CRect m_LastActiveMenuRect;

  DWORD m_dwOpenMenu;

  void* m_pData;

  HACCEL  m_hAccelToDraw;
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuThreadHook class for hooking in a new thread
// Jan-17-2005 - Mark P. Peterson - [email protected] - http://www.RhinoSoft.com/

class GUILIBDLLEXPORT CNewMenuThreadHook
{
// Initialization
public:
  CNewMenuThreadHook();
  virtual ~CNewMenuThreadHook();

// Attributes
private:
  HHOOK m_hHookOldMenuCbtFilter;
};

/////////////////////////////////////////////////////////////////////////////
// CNewFrame<> template for easy using of the new menu

template
class GUILIBDLLEXPORT CNewFrame : public baseClass
{
  typedef CNewFrame MyNewFrame;
public:
  CNewMenu m_DefaultNewMenu;
  CNewMenu m_SystemNewMenu;

public:

  CNewFrame()
  {
    m_bInMenuLoop = FALSE;
    m_TimerID = NULL;
    m_menubarItemIndex = UINT(-1);
  }

  // control bar docking
  void EnableDocking(DWORD dwDockStyle)
  {
    baseClass::EnableDocking(dwDockStyle);
    // Owerite registering for floating frame
    m_pFloatingFrameClass = RUNTIME_CLASS(CNewMiniDockFrameWnd);
  }

private:
  static const AFX_MSGMAP_ENTRY _messageEntries[];

protected: 
  static const AFX_MSGMAP messageMap;

  BOOL m_bInMenuLoop;
  UINT m_TimerID;
  UINT m_menubarItemIndex;


#if _MFC_VER < 0x0700 
  static const AFX_MSGMAP* PASCAL _GetBaseMessageMap()
  { 
    return &baseClass::messageMap; 
  };
#else
  static const AFX_MSGMAP* PASCAL GetThisMessageMap()
  {
    return &CNewFrame::messageMap; 
  }
#endif

  virtual const AFX_MSGMAP* GetMessageMap() const 
  {
    return &CNewFrame::messageMap; 
  }
	//{{AFX_MSG(CNewFrame)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG

  static const AFX_MSGMAP_ENTRY* GetMessageEntries()
  {
#if _MFC_VER >= 0x0800  
    typedef MyNewFrame ThisClass;
#endif
    static const AFX_MSGMAP_ENTRY Entries[] =
    {
        ON_WM_MEASUREITEM()
        ON_WM_MENUCHAR()
        ON_WM_INITMENUPOPUP()
        ON_WM_ENTERMENULOOP()
        ON_WM_EXITMENULOOP() 
        ON_WM_TIMER()
        ON_WM_CREATE()
        ON_WM_NCHITTEST()
        ON_WM_DESTROY()
        ON_WM_SYSCOLORCHANGE()
#ifdef USE_NEW_DOCK_BAR
        ON_WM_NCPAINT()
        ON_WM_PAINT()
        ON_WM_ACTIVATEAPP()
        ON_WM_ACTIVATE()
#endif //USE_NEW_DOCK_BAR
      {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
    }; 
    return Entries;
  }

  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)
  {
    if (baseClass::OnCreate(lpCreateStruct) == -1)
      return -1;

    if(m_SystemNewMenu.m_hMenu)
    {
      ::DestroyMenu(m_SystemNewMenu.Detach());
    }
    m_SystemNewMenu.Attach(::GetSystemMenu(m_hWnd,FALSE));
    return 0;
  }

  afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
  {
    baseClass::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
    CNewMenu::OnInitMenuPopup(m_hWnd,pPopupMenu, nIndex, bSysMenu);
  }

  afx_msg void OnSysColorChange() 
  {
    baseClass::OnSysColorChange();
    CNewMenu::OnSysColorChange();
    UpdateMenuBarColor(m_DefaultNewMenu);
  }

  afx_msg void OnEnterMenuLoop(BOOL bIsTrackPopupMenu)
  {
    m_bInMenuLoop = TRUE;
    if(m_TimerID!=NULL)
    {
      KillTimer(m_TimerID);
      m_TimerID = NULL;
    }
    if (m_menubarItemIndex!=UINT(-1))
    {
      DrawMenubarItem(this,GetMenu(),m_menubarItemIndex,NULL);
      m_menubarItemIndex=UINT(-1);
    }
    baseClass::OnEnterMenuLoop(bIsTrackPopupMenu);
  }

  afx_msg void OnExitMenuLoop(BOOL bIsTrackPopupMenu)
  {
    m_bInMenuLoop = FALSE;
    baseClass::OnExitMenuLoop(bIsTrackPopupMenu);
  }

  afx_msg void OnTimer(UINT_PTR nIDEvent)
  {
    baseClass::OnTimer(nIDEvent);
    if(m_TimerID==nIDEvent)
    {   
      CPoint pt;
      GetCursorPos(&pt);
      SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));
    }
  }

  afx_msg void OnDestroy()
  {
    if(m_TimerID!=NULL)
    {
      KillTimer(m_TimerID);
      m_TimerID = NULL;
    }
    baseClass::OnDestroy();
  }

 #if _MFC_VER < 0x0800  
  afx_msg UINT OnNcHitTest(CPoint point)
  {
    UINT nHitCode = baseClass::OnNcHitTest(point);
#else
  afx_msg LRESULT OnNcHitTest(CPoint point)
  {
    UINT nHitCode = (UINT)baseClass::OnNcHitTest(point);
#endif
    // Test Win95/98/me and Win NT 4.0
    if(g_Shellm_hMenu, point);

          if ( nItemIndex!=(UINT)-1 )
          {
            if(m_menubarItemIndex!=nItemIndex)
            { 
              // Clear the old Item
              DrawMenubarItem(this,pNewMenu,m_menubarItemIndex,nStatus);

              // Draw the hotlight item.
              if(DrawMenubarItem(this,pNewMenu,nItemIndex,nHotlightStatus))
              {
                // Set a new Timer
                if(m_TimerID==NULL)
                {
                  m_TimerID=GetSafeTimerID(m_hWnd,100);
                }
                m_menubarItemIndex = nItemIndex;
              }
              else
              {
                m_menubarItemIndex = UINT(-1);
              }
            }
            else
            {
              // Draw the hotlight item again.
              if(CNewMenu::m_dwLastActiveItem==NULL && 
                DrawMenubarItem(this,pNewMenu,nItemIndex,nHotlightStatus))
              {
                // Set a new Timer
                if(m_TimerID==NULL)
                {
                  m_TimerID=GetSafeTimerID(m_hWnd,100);
                }
                m_menubarItemIndex = nItemIndex;
              }
            }
            return nHitCode;
          }
        }
      }

      if (m_menubarItemIndex!=UINT(-1))
      {
        DrawMenubarItem(this,pNewMenu,m_menubarItemIndex,nStatus);
        m_menubarItemIndex=UINT(-1);
      }
      if(m_TimerID!=NULL)
      {
        KillTimer(m_TimerID);
        m_TimerID=NULL;
      }
    }
    return nHitCode;
  }

  afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMIS) 
  {
    if(!CNewMenu::OnMeasureItem(GetCurrentMessage()))
    {
      CMenu* pMenu;
      _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
      if (pThreadState && pThreadState->m_hTrackingWindow == m_hWnd)
      {
        // start from popup
        pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
      }
      else
      {
        // start from menubar
        pMenu = GetMenu();
      }
      if(pMenu)
      {
        baseClass::OnMeasureItem(nIDCtl, lpMIS);
      }
    } 
  }

  afx_msg LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) 
  {
    LRESULT lresult;
    if( DYNAMIC_DOWNCAST(CNewMenu,pMenu) )
      lresult=CNewMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
    else
      lresult=baseClass::OnMenuChar(nChar, nFlags, pMenu);

    return lresult;
  }

#ifdef USE_NEW_DOCK_BAR
  afx_msg void OnNcPaint()
  {
    baseClass::OnNcPaint();
    DrawSmallBorder();
  }

  afx_msg void OnPaint()
  {
    baseClass::OnPaint();
    DrawSmallBorder();
  }

#if _MFC_VER < 0x0700 
  afx_msg void OnActivateApp(BOOL bActive, HTASK hTask)
  {
    baseClass::OnActivateApp(bActive, hTask);
    DrawSmallBorder();
  }
#else
  afx_msg void OnActivateApp(BOOL bActive, DWORD dwThreadID)
  {
    baseClass::OnActivateApp(bActive, dwThreadID);
    DrawSmallBorder();
  }
#endif

  afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized )
  {
    baseClass::OnActivate(nState,pWndOther, bMinimized );
    DrawSmallBorder();
  }

  void DrawSmallBorder()
  {
    // To eliminate small border between menu and client rect
    MENUINFO menuInfo = {0};
    menuInfo.cbSize = sizeof(menuInfo);
    menuInfo.fMask = MIM_BACKGROUND;
    if(::GetMenuInfo(::GetMenu(m_hWnd),&menuInfo) && menuInfo.hbrBack)
    {
      CDC* pDC = GetWindowDC(); 
      CRect clientRect;
      GetClientRect(clientRect);
      ClientToScreen(clientRect);
      CRect windowRect;
      GetWindowRect(windowRect);
      CRect rect(clientRect.left-windowRect.left,clientRect.top-windowRect.top-1,clientRect.right-windowRect.left,clientRect.top-windowRect.top);

      CBrush *pBrush = CBrush::FromHandle(menuInfo.hbrBack);
      // need for win95/98/me
      VERIFY(pBrush->UnrealizeObject());
      CPoint oldOrg = pDC->SetBrushOrg(0,0);
      pDC->FillRect(rect,pBrush);
      pDC->SetBrushOrg(oldOrg);
      // must be called
      ReleaseDC(pDC);
    }
  }
#endif
};

/////////////////////////////////////////////////////////////////////////////
// CNewMiniDockFrameWnd for docking toolbars with new menu

class GUILIBDLLEXPORT CNewMiniDockFrameWnd: public CNewFrame 
{
  DECLARE_DYNCREATE(CNewMiniDockFrameWnd) 
  DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CNewDialog for dialog implementation

class GUILIBDLLEXPORT CNewDialog : public CNewFrame
{
  DECLARE_DYNAMIC(CNewDialog);

public:
  CNewDialog();
  CNewDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
  CNewDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);

  // Overridables (special message map entries)
  virtual BOOL OnInitDialog();

protected:
  // Generated message map functions
  //{{AFX_MSG(CNewDialog)
  afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
  //}}AFX_MSG

  DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CNewMiniFrameWnd for menu to documents

class GUILIBDLLEXPORT CNewMiniFrameWnd : public CNewFrame
{
  DECLARE_DYNCREATE(CNewMiniFrameWnd)
	//{{AFX_MSG(CNewMiniFrameWnd)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CNewMDIChildWnd for menu to documents

class GUILIBDLLEXPORT CNewMDIChildWnd : public CNewFrame
{
  DECLARE_DYNCREATE(CNewMDIChildWnd)
	//{{AFX_MSG(CNewMDIChildWnd)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CNewFrameWnd for menu to documents

class GUILIBDLLEXPORT CNewFrameWnd : public CNewFrame
{
  DECLARE_DYNCREATE(CNewFrameWnd)

public:
#if _MFC_VER < 0x0700 
  // dynamic creation - load frame and associated resources
  virtual BOOL LoadFrame(UINT nIDResource,
    DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
    CWnd* pParentWnd = NULL,
    CCreateContext* pContext = NULL);
#endif

  // under MFC 7.0 the next function is virtual so we don't neet to owerwrite
  // loadframe
  BOOL Create(LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName,
    DWORD dwStyle = WS_OVERLAPPEDWINDOW,
    const RECT& rect = rectDefault,
    CWnd* pParentWnd = NULL,        // != NULL for popups
    LPCTSTR lpszMenuName = NULL,
    DWORD dwExStyle = 0,
    CCreateContext* pContext = NULL);

#ifdef USE_NEW_DOCK_BAR
  // control bar docking
  void EnableDocking(DWORD dwDockStyle);
#endif
	//{{AFX_MSG(CNewFrameWnd)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CNewMDIFrameWnd for menu to documents

class GUILIBDLLEXPORT CNewMDIFrameWnd : public CNewFrame
{
  DECLARE_DYNCREATE(CNewMDIFrameWnd);
  HMENU m_hShowMenu;

public: 
  CNewMDIFrameWnd():m_hShowMenu(NULL){};

  BOOL ShowMenu(BOOL bShow);

#if _MFC_VER < 0x0700 
  // dynamic creation - load frame and associated resources
  virtual BOOL LoadFrame(UINT nIDResource,
    DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
    CWnd* pParentWnd = NULL,
    CCreateContext* pContext = NULL);
#endif
  // under MFC 7.0 the next function is virtual so we don't neet to owerwrite
  // loadframe
  BOOL Create(LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName,
    DWORD dwStyle = WS_OVERLAPPEDWINDOW,
    const RECT& rect = rectDefault,
    CWnd* pParentWnd = NULL,        // != NULL for popups
    LPCTSTR lpszMenuName = NULL,
    DWORD dwExStyle = 0,
    CCreateContext* pContext = NULL);

#ifdef USE_NEW_DOCK_BAR
  // control bar docking
  void EnableDocking(DWORD dwDockStyle);
#endif

	//{{AFX_MSG(CNewMDIFrameWnd)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};


/////////////////////////////////////////////////////////////////////////////
// CNewMultiDocTemplate for menu to documents

class GUILIBDLLEXPORT CNewMultiDocTemplate: public CMultiDocTemplate
{
  DECLARE_DYNAMIC(CNewMultiDocTemplate)

public:
  CNewMenu m_NewMenuShared;

  // Constructors
public:
  CNewMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
    CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass);

  ~CNewMultiDocTemplate();
};


/////////////////////////////////////////////////////////////////////////////
// CNewMemDC helperclass for drawing off screen 

class GUILIBDLLEXPORT CNewMemDC: public CDC
{
  CRect m_rect;
  CBitmap* m_pOldBitmap;
  CBitmap  m_memBitmap;
  BOOL m_bCancel;

  HDC m_hDcOriginal;

public:
  CNewMemDC(LPCRECT pRect, HDC hdc):m_rect(pRect),m_bCancel(FALSE),m_hDcOriginal(hdc)
  {
    CDC *pOrgDC = CDC::FromHandle(m_hDcOriginal);
    CreateCompatibleDC(pOrgDC);

    m_memBitmap.CreateCompatibleBitmap (pOrgDC,m_rect.Width (),m_rect.Height());
    m_pOldBitmap = SelectObject (&m_memBitmap);
    SetWindowOrg(m_rect.left, m_rect.top);
  }

  // Abborting to copy image from memory dc to client
  void DoCancel(){m_bCancel=TRUE;}

  ~CNewMemDC()
  {
    if(!m_bCancel)
    {
      CDC *pOrgDC = CDC::FromHandle(m_hDcOriginal);
      pOrgDC->BitBlt (m_rect.left,m_rect.top,m_rect.Width (),m_rect.Height (),this,m_rect.left,m_rect.top,SRCCOPY);
    }
    SelectObject (m_pOldBitmap);
  }
};

/////////////////////////////////////////////////////////////////////////////
// CNewMenuHelper for enabling / disabling menu border, replacing system menu.

#define  NEW_MENU_DIALOG_SUBCLASS     1
#define  NEW_MENU_DIALOG_SYSTEM_MENU  2
#define  NEW_MENU_DEFAULT_BORDER      4
#define  NEW_MENU_CHANGE_MENU_STYLE   8

class GUILIBDLLEXPORT CNewMenuHelper
{
private:
  DWORD m_dwOldFlags;
  int m_OldMenuDrawStyle;

public: 
  CNewMenuHelper(DWORD dwFlags);
  CNewMenuHelper(CNewMenu::EDrawStyle setTempStyle);

  ~CNewMenuHelper();
};

/////////////////////////////////////////////////////////////////////////////
// CNewDockBar support for office2003 colors.
class GUILIBDLLEXPORT CNewDockBar : public CDockBar
{
  DECLARE_DYNCREATE(CNewDockBar)
public:
  CNewDockBar(BOOL bFloating = FALSE);   // TRUE if attached to CMiniDockFrameWnd
  virtual ~CNewDockBar();

#if defined(_DEBUG) || defined(_AFXDLL)
  virtual void AssertValid() const;
  virtual void Dump(CDumpContext& dc) const;
#endif

public:

  virtual DWORD RecalcDelayShow(AFX_SIZEPARENTPARAMS* lpLayout);
  void EraseNonClient();

  afx_msg BOOL OnEraseBkgnd(CDC* pDC);
  afx_msg void OnNcPaint();

protected:
	//{{AFX_MSG(CNewDockBar)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

#ifndef _GUILIB_
  #ifdef _AFXDLL
    #if _MFC_VER < 0x0700 
      template
      const AFX_MSGMAP CNewFrame::messageMap = { &CNewFrame::_GetBaseMessageMap, GetMessageEntries()};
    #else
      template
      const AFX_MSGMAP CNewFrame::messageMap = { &baseClass::GetThisMessageMap, GetMessageEntries()};
    #endif
  #else
    #if _MFC_VER < 0x0800 
      template
      const AFX_MSGMAP CNewFrame::messageMap = { &baseClass::messageMap, GetMessageEntries()};
    #else
      template
      const AFX_MSGMAP CNewFrame::messageMap = { &baseClass::GetThisMessageMap, GetMessageEntries()};
    #endif
  #endif // _AFXDLL
#endif // _GUILIB_


#pragma warning(pop)

#endif // __CNewMenu_H_



然后在需要创建邮件菜单的时候调用以下代码(示例)

CNewMenu menu;
 menu.CreatePopupMenu();

menu.InsertMenu(index,MF_BYPOSITION,msgBaseNumber,expand[LanguageID],&m_setImage,19);//参数需根据自己的项目进行更改
menu.SetMenuTitle(logText[LanguageID],MFT_GRADIENT|MFT_SIDE_TITLE|MFT_LINE);    //设置菜单的名字
  menu.TrackPopupMenu(TPM_LEFTALIGN,point.x ,point.y,this);  //设置弹出菜单的位置

 

你可能感兴趣的:(如何自定义创建windows的右键弹出菜单(C++))