NewMenu.cpp
上传用户:zhanglf88
上传日期:2013-11-19
资源大小:6036k
文件大小:121k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // File    : NewMenu.cpp 
  3. // Version : 1.0
  4. // Date    : Mai 2002
  5. // Author  : Bruno Podetti
  6. // Email   : Podetti@gmx.net
  7. // Systems : VC6.0 and VC7.0 (Run under (Window 98/ME), Windows Nt 2000/XP)
  8. //
  9. // Bug Fixes and portions of code from previous version supplied by:
  10. //
  11. // Brent Corkum, Ben Ashley, Girish Bharadwaj, Jean-Edouard Lachand-Robert,
  12. // Robert Edward Caldecott, Kenny Goers, Leonardo Zide, Stefan Kuhr, 
  13. // Reiner Jung, Martin Vladic, Kim Yoo Chul, Oz Solomonovich, Tongzhe Cui, 
  14. // Stephane Clog, Warren Stevens, Damir Valiulin
  15. // 
  16. // You are free to use/modify this code but leave this header intact.
  17. // This class is public domain so you are free to use it any of your 
  18. // applications (Freeware, Shareware, Commercial). 
  19. // All I ask is that you let me know so that if you have a real winner I can
  20. // brag to my buddies that some of my code is in your app. I also wouldn't 
  21. // mind if you sent me a copy of your application since I like to play with
  22. // new stuff.
  23. //------------------------------------------------------------------------------
  24. //-----------------------------------------------------------------------//
  25. // This is a part of the GuiLib MFC Extention.  //
  26. // Modified by  :  Francisco Campos  //
  27. // (C) 2002 Francisco Campos <www.beyondata.com> All rights reserved     //
  28. // This code is provided "as is", with absolutely no warranty expressed  //
  29. // or implied. Any use is at your own risk.  //
  30. // You must obtain the author's consent before you can include this code //
  31. // in a software library.  //
  32. // If the source code in  this file is used in any application  //
  33. // then acknowledgement must be made to the author of this program  //
  34. // fcampos@tutopia.com  //
  35. //-----------------------------------------------------------------------//
  36. #include "stdafx.h"        // Standard windows header file
  37. #include "NewMenu.h"       // CNewMenu class declaration
  38. #include "GuiDrawLayer.h"
  39. #include "MenuBar.h"
  40. //#define _TRACE_MENU_
  41. #ifdef _TRACE_MENU_
  42. #include "MyTrace.h"
  43. #endif
  44. #ifdef _DEBUG
  45. #define new DEBUG_NEW
  46. #undef THIS_FILE
  47. static char THIS_FILE[] = __FILE__;
  48. #endif
  49. #ifndef ARRAY_SIZE
  50. #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
  51. #endif
  52. #ifndef IS_INTRESOURCE
  53. #define IS_INTRESOURCE(hh) (HIWORD(hh)==NULL)
  54. #endif 
  55. #define GAP 2
  56. #ifndef ODS_HOTLIGHT
  57. #define ODS_HOTLIGHT        0x0040
  58. #endif
  59. #ifndef ODS_INACTIVE
  60. #define ODS_INACTIVE        0x0080
  61. #endif
  62. #ifndef COLOR_MENUBAR
  63. #define COLOR_MENUBAR       30
  64. #endif
  65. #ifndef SPI_GETDROPSHADOW
  66. #define SPI_GETDROPSHADOW   0x1024
  67. #endif
  68. #ifndef SPI_GETFLATMENU
  69. #define SPI_GETFLATMENU     0x1022
  70. #endif
  71. extern int gbintHorz; //Horz=0, Vert=1
  72. extern CRect rcMenu; //CRect of button
  73. /////////////////////////////////////////////////////////////////////////////
  74. #include "GuiDrawLayer.h"
  75. // Helpers for casting
  76. __inline HMENU UIntToHMenu(const unsigned int ui )
  77. {
  78.   return( (HMENU)(UINT_PTR)ui );
  79. }
  80. __inline HMENU HWndToHmenu(const HWND hwnd )
  81. {
  82.   return( (HMENU)hwnd );
  83. }
  84. __inline UINT HWndToUInt(const HWND hWnd )
  85. {
  86.   return( (UINT)(UINT_PTR) hWnd);
  87. }
  88. __inline HWND UIntToHWnd(const UINT hWnd )
  89. {
  90.   return( (HWND)(UINT_PTR) hWnd);
  91. }
  92. __inline UINT HMenuToUInt(const HMENU hMenu )
  93. {
  94.   return( (UINT)(UINT_PTR) hMenu);
  95. }
  96. //static CMenuBar* pBar=CNewMenu::m_pBar;
  97. CMenuButton* pb;
  98. static void ShowLastError()
  99. {
  100.   DWORD error = GetLastError();
  101.   if(error)
  102.   {
  103.     LPVOID lpMsgBuf=NULL;
  104.     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  105.                   FORMAT_MESSAGE_FROM_SYSTEM | 
  106.                   FORMAT_MESSAGE_IGNORE_INSERTS,
  107.                   NULL,
  108.                   error,
  109.                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  110.                   (LPTSTR) &lpMsgBuf,
  111.                   0,
  112.                   NULL );
  113.     if(lpMsgBuf)
  114.     {
  115.       // Display the string.
  116.       MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("Error"), MB_OK | MB_ICONINFORMATION );
  117.       // Free the buffer.
  118.       LocalFree( lpMsgBuf );
  119.     }
  120.     else
  121.     {
  122.       CString temp;
  123.       temp.Format(_T("Error message 0x%lx not found"),error);
  124.       // Display the string.
  125.       MessageBox( NULL,temp, _T("Error"), MB_OK | MB_ICONINFORMATION );
  126.     }
  127.   }
  128. }
  129. enum Win32Type
  130. {
  131.   Win32s,
  132.   WinNT3,
  133.   Win95,
  134.   Win98,
  135.   WinME,
  136.   WinNT4,
  137.   Win2000,
  138.   WinXP
  139. };
  140. Win32Type IsShellType()
  141. {
  142.   Win32Type  ShellType;
  143.   DWORD winVer;
  144.   OSVERSIONINFO *osvi;
  145.   winVer=GetVersion();
  146.   if(winVer<0x80000000)
  147.   {/*NT */
  148.     ShellType=WinNT3;
  149.     osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
  150.     if (osvi!=NULL)
  151.     {
  152.       ZeroMemory(osvi,sizeof(OSVERSIONINFO));
  153.       osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  154.       if(!GetVersionEx(osvi))
  155.       {
  156.         ShowLastError();
  157.       }
  158.       if(osvi->dwMajorVersion==4L)
  159.       {
  160.         ShellType=WinNT4;
  161.       }
  162.       else if(osvi->dwMajorVersion==5L && osvi->dwMinorVersion==0L)
  163.       {
  164.         ShellType=Win2000;
  165.       }
  166.       else if(osvi->dwMajorVersion==5L && osvi->dwMinorVersion==1L)
  167.       {
  168.         ShellType=WinXP;
  169.       }
  170.       free(osvi);
  171.     }
  172.   }
  173.   else if (LOBYTE(LOWORD(winVer))<4)
  174.   {
  175.     ShellType=Win32s;
  176.   }
  177.   else
  178.   {
  179.     ShellType=Win95;
  180.     osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
  181.     if (osvi!=NULL)
  182.     {
  183.       memset(osvi,0,sizeof(OSVERSIONINFO));
  184.       osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  185.       GetVersionEx(osvi);
  186.       if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==10L)
  187.       {
  188.         ShellType=Win98;
  189.       }
  190.       else if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==90L)
  191.       {
  192.         ShellType=WinME;
  193.       }
  194.       free(osvi);
  195.     }
  196.   }
  197.   return ShellType;
  198. }
  199. BOOL IsShadowEnabled()
  200. {
  201.   BOOL bEnabled=FALSE;
  202.   if(SystemParametersInfo(SPI_GETDROPSHADOW,0,&bEnabled,0))
  203.   {
  204.     return bEnabled;
  205.   }
  206.   return FALSE;
  207. }
  208. COLORREF DarkenColorXP(COLORREF ColA)
  209. {
  210.   return RGB( MulDiv(GetRValue(ColA),7,10),
  211.               MulDiv(GetGValue(ColA),7,10),
  212.               MulDiv(GetBValue(ColA)+55,7,10));
  213. }
  214. // Function splits a color into its RGB components and
  215. // transforms the color using a scale 0..255
  216. COLORREF DarkenColor( long lScale, COLORREF lColor)
  217.   long R = MulDiv(GetRValue(lColor),(255-lScale),255);
  218.   long G = MulDiv(GetGValue(lColor),(255-lScale),255);
  219.   long B = MulDiv(GetBValue(lColor),(255-lScale),255);
  220.   return RGB(R, G, B); 
  221. }
  222. COLORREF MixedColor(COLORREF ColA,COLORREF ColB)
  223. {
  224.   // ( 86a + 14b ) / 100
  225.   int Red   = MulDiv(86,GetRValue(ColA),100) + MulDiv(14,GetRValue(ColB),100);
  226.   int Green = MulDiv(86,GetGValue(ColA),100) + MulDiv(14,GetGValue(ColB),100);
  227.   int Blue  = MulDiv(86,GetBValue(ColA),100) + MulDiv(14,GetBValue(ColB),100);
  228.   return RGB( Red,Green,Blue);
  229. }
  230. COLORREF MidColor(COLORREF ColA,COLORREF ColB)
  231.   // (7a + 3b)/10
  232.   int Red   = MulDiv(7,GetRValue(ColA),10) + MulDiv(3,GetRValue(ColB),10);
  233.   int Green = MulDiv(7,GetGValue(ColA),10) + MulDiv(3,GetGValue(ColB),10);
  234.   int Blue  = MulDiv(7,GetBValue(ColA),10) + MulDiv(3,GetBValue(ColB),10);
  235.   return RGB( Red,Green,Blue);
  236. }
  237. // used for function gradientfill.
  238. #pragma comment(lib,"Msimg32.lib")
  239. void DrawGradient(CDC* pDC,CRect& Rect,
  240.                   COLORREF StartColor,COLORREF EndColor, 
  241.                   BOOL bHorizontal)
  242. {
  243.   TRIVERTEX vert[2] ;
  244.   GRADIENT_RECT gRect;
  245.   vert [0].y = Rect.top;
  246.   vert [0].x = Rect.left;
  247.   vert [0].Red    = COLOR16(COLOR16(GetRValue(StartColor))<<8);
  248.   vert [0].Green  = COLOR16(COLOR16(GetGValue(StartColor))<<8);
  249.   vert [0].Blue   = COLOR16(COLOR16(GetBValue(StartColor))<<8);
  250.   vert [0].Alpha  = 0x0000;
  251.   vert [1].y = Rect.bottom;
  252.   vert [1].x = Rect.right;
  253.   vert [1].Red    = COLOR16(COLOR16(GetRValue(EndColor))<<8);
  254.   vert [1].Green  = COLOR16(COLOR16(GetGValue(EndColor))<<8);
  255.   vert [1].Blue   = COLOR16(COLOR16(GetBValue(EndColor))<<8);
  256.   vert [1].Alpha  = 0x0000;
  257.   gRect.UpperLeft  = 0;
  258.   gRect.LowerRight = 1;
  259.   if(bHorizontal)
  260.     GradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_H);
  261.   else
  262.     GradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_V);
  263. }
  264. /////////////////////////////////////////////////////////////////////////////
  265. // CMenuTheme for drawing border and the rest
  266. typedef void (CNewMenu::*pItemMeasureFkt) (LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenubar);
  267. typedef void (CNewMenu::*pItemDrawFkt) (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);
  268. typedef BOOL (CNewMenu::*pEraseBkgndFkt) (HWND hWnd, HDC hDC);
  269. typedef void (CMenuTheme::*pDrawMenuBorder)( HWND hWnd, HDC hDC, CPoint screen);
  270. class CMenuTheme
  271. {
  272. public:
  273.   CMenuTheme();
  274.   CMenuTheme(DWORD dwThemeId, 
  275.              pItemMeasureFkt pMeasureItem,
  276.              pItemDrawFkt pDrawItem,
  277.              pItemDrawFkt pDrawTitle,
  278.              DWORD dwFlags=0);
  279.   virtual ~CMenuTheme();
  280.   virtual BOOL OnInitWnd(HWND hWnd);
  281.   virtual BOOL OnUnInitWnd(HWND hWnd);
  282.   virtual BOOL DoDrawBorder();
  283.   virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC);
  284.   virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
  285.   virtual BOOL OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc);
  286.   virtual BOOL OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos);
  287.   void DrawShade( HWND hWnd, HDC hDC, CPoint screen);
  288.   void DrawSmalBorder( HWND hWnd, HDC hDC);
  289. public:
  290.   DWORD m_dwThemeId;
  291.   DWORD m_dwFlags;
  292.   pItemMeasureFkt m_pMeasureItem;
  293.   pItemDrawFkt m_pDrawItem;
  294.   pItemDrawFkt m_pDrawTitle;
  295.   CSize m_BorderTopLeft;
  296.   CSize m_BorderBottomRight;
  297. };
  298. /////////////////////////////////////////////////////////////////////////////
  299. // CMenuThemeXP for drawing border and the rest
  300. class CMenuThemeXP :public CMenuTheme
  301. {
  302. public:
  303.   CMenuThemeXP(DWORD dwThemeId, 
  304.                 pItemMeasureFkt pMeasureItem,
  305.                 pItemDrawFkt pDrawItem,
  306.                 pItemDrawFkt pDrawTitle,
  307.                 DWORD dwFlags=0);
  308.   virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC);
  309.   virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
  310.   
  311. };
  312. /////////////////////////////////////////////////////////////////////////////
  313. // CNewMenuHook important class for subclassing menus!
  314. class CNewMenuHook
  315. {
  316. public:
  317.   class CMenuHookData 
  318.   {
  319.   public:
  320.     CMenuHookData(HWND hWnd,BOOL bSpecialWnd) 
  321.       : m_dwData(bSpecialWnd),m_bDrawBorder(TRUE),m_Point(0,0)
  322.     {
  323.       // Safe actual menu
  324.       m_hMenu = CNewMenuHook::m_hLastMenu;
  325.       // Reset for the next menu
  326.       CNewMenuHook::m_hLastMenu = NULL;
  327.       // Save actual border setting etc.
  328.       m_dwStyle = GetWindowLong(hWnd, GWL_STYLE) ;
  329.       m_dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE); 
  330.     }
  331.     DWORD m_dwStyle;
  332.     DWORD m_dwExStyle;
  333.     CPoint m_Point;
  334.     DWORD m_dwData;
  335.     BOOL m_bDrawBorder;
  336.     HMENU m_hMenu;
  337.   }; 
  338. public:
  339.   CNewMenuHook();
  340.   ~CNewMenuHook();
  341. public:
  342.   static CMenuHookData* GetMenuHookData(HWND hWnd);
  343.   static BOOL AddTheme(CMenuTheme*);
  344.   static CMenuTheme* RemoveTheme(DWORD dwThemeId);
  345.   static CMenuTheme* FindTheme(DWORD dwThemeId);
  346. private:
  347.   static LRESULT CALLBACK NewMenuHook(int code, WPARAM wParam, LPARAM lParam);
  348.   static BOOL CheckSubclassing(HWND hWnd,BOOL bSpecialWnd);
  349.   static LRESULT CALLBACK SubClassMenu(HWND hWnd,  UINT uMsg, WPARAM wParam,  LPARAM lParam );
  350.   static void UnsubClassMenu(HWND hWnd);
  351.  
  352.   static BOOL SubClassMenu2(HWND hWnd,  UINT uMsg, WPARAM wParam,  LPARAM lParam, DWORD* pResult);
  353. public:
  354.   static HMENU m_hLastMenu;
  355.   static DWORD m_dwMsgPos; 
  356.   
  357. private:
  358.   static HHOOK HookOldMenuCbtFilter;
  359.   // an map of actual opened Menu and submenu
  360.   static CTypedPtrMap<CMapPtrToPtr,HWND,CMenuHookData*> m_MenuHookData;
  361.   // Stores list of all defined Themes
  362.   static CTypedPtrList<CPtrList, CMenuTheme*>* m_pRegisteredThemesList; 
  363. };
  364. //////////////////////////////////////////////////////////////////////
  365. // Construction/Destruction
  366. //////////////////////////////////////////////////////////////////////
  367. IMPLEMENT_DYNAMIC(CNewMenuItemData,CObject); 
  368. CNewMenuItemData::CNewMenuItemData()
  369. : m_nTitleFlags(0),
  370.   m_nFlags(0),
  371.   m_nID(0),
  372.   m_nSyncFlag(0),
  373.   m_nxOffset(-1),
  374.   m_pBitmap(NULL),
  375.   m_nMenuIconNormal(-1),
  376.   m_pData(NULL)
  377. {
  378. }
  379. CNewMenuItemData::~CNewMenuItemData()
  380. {
  381.   if(m_pBitmap)
  382.   {
  383.     delete m_pBitmap;
  384.     m_pBitmap = NULL;
  385.   }
  386. }
  387. LPCTSTR CNewMenuItemData::GetString()
  388. {
  389.   return m_szMenuText;
  390. }
  391.  
  392. void CNewMenuItemData::SetString(LPCTSTR szMenuText)
  393. {
  394.   m_szMenuText = szMenuText;
  395. }
  396. #if defined(_DEBUG) || defined(_AFXDLL)
  397. // Diagnostic Support
  398. void CNewMenuItemData::AssertValid() const
  399. {
  400.   CObject::AssertValid();
  401. }
  402. void CNewMenuItemData::Dump(CDumpContext& dc) const
  403. {
  404.   CObject::Dump(dc);
  405.   dc << _T("MenuItem: ") << m_szMenuText << _T("n"); 
  406. }
  407. #endif
  408. //////////////////////////////////////////////////////////////////////
  409. // Construction/Destruction
  410. //////////////////////////////////////////////////////////////////////
  411. IMPLEMENT_DYNAMIC(CNewMenu,CMenu);
  412. // Stores list of all sub-menus
  413. CTypedPtrArray<CPtrArray, HMENU> CNewMenu::m_AllSubMenus;
  414. // actual selectet menu-draw mode
  415. CMenuTheme* CNewMenu::m_pActMenuDrawing = NULL;
  416. // one instance of the hook for menu-subclassing
  417. static CNewMenuHook MyNewMenuHookInstance;
  418. // color for drawing menubar
  419. int CNewMenu::cCOLOR_MENUBAR = COLOR_MENU;
  420. // how the menu's are drawn in winXP
  421. BOOL CNewMenu::m_bSelectDisable=TRUE;
  422. static Win32Type g_Shell=IsShellType();
  423. CNewMenu::CNewMenu(HMENU hParent)
  424. : m_hParentMenu(hParent),
  425.   m_bIsPopupMenu(FALSE),
  426.   m_dwOpenMenu(NULL),
  427.   m_LastActiveMenuRect(0,0,0,0)
  428. {
  429.   // O.S. - no dynamic icons by default
  430.   m_bDynIcons = FALSE;
  431.   // Icon sizes default to 16 x 16
  432.   m_iconX = 16;
  433.   m_iconY = 15;
  434.   m_selectcheck = -1;
  435.   m_unselectcheck = -1;
  436.   checkmaps=NULL;
  437.   checkmapsshare=FALSE;
  438.   CMenuButton* m_pBar=NULL;
  439.   // set the color used for the transparent background in all bitmaps
  440.   m_bitmapBackground = CLR_DEFAULT;
  441. }
  442. CNewMenu::~CNewMenu()
  443. {
  444.   DestroyMenu();
  445. }
  446. void CNewMenu::SetLastMenuRect(HDC hDC, LPRECT pRect)
  447. {
  448.   if(!m_bIsPopupMenu)
  449.   {
  450.     HWND hWnd = WindowFromDC(hDC);
  451.     if(hWnd && pRect)
  452.     {
  453.       CRect Temp;
  454.       GetWindowRect(hWnd,Temp);
  455.       m_LastActiveMenuRect = *pRect;
  456.       m_LastActiveMenuRect.OffsetRect(Temp.TopLeft());
  457.     }
  458.   }
  459. }
  460. BOOL CNewMenu::IsNewShell ()
  461. {
  462.   return (g_Shell>=Win95);
  463. }
  464. BOOL CNewMenu::OnMeasureItem(const MSG* pMsg)
  465. {
  466.   if(pMsg->message==WM_MEASUREITEM)
  467.   {
  468.     LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)pMsg->lParam;
  469.     if(lpMIS->CtlType==ODT_MENU)
  470.     {
  471.       CMenu* pMenu=NULL;
  472.       if(::IsMenu(UIntToHMenu(lpMIS->itemID)) )
  473.       {
  474.         pMenu = CMenu::FromHandlePermanent(UIntToHMenu(lpMIS->itemID) );
  475.       }
  476.       else
  477.       {
  478.         _AFX_THREAD_STATE* pThreadState = AfxGetThreadState ();
  479.         if (pThreadState->m_hTrackingWindow == pMsg->hwnd)
  480.         {
  481.           // start from popup
  482.           pMenu = FindPopupMenuFromIDData(pThreadState->m_hTrackingMenu,lpMIS->itemID,lpMIS->itemData);
  483.         }
  484.         if(pMenu==NULL)
  485.         {
  486.           // start from menubar
  487.           pMenu = FindPopupMenuFromIDData(::GetMenu(pMsg->hwnd),lpMIS->itemID,lpMIS->itemData);
  488.           if(pMenu==NULL)
  489.           {
  490.             // finaly start from system menu.
  491.             pMenu = FindPopupMenuFromIDData(::GetSystemMenu(pMsg->hwnd,FALSE),lpMIS->itemID,lpMIS->itemData);
  492.           }
  493.         }
  494.       }
  495.       if(pMenu!=NULL)
  496.       {
  497.         pMenu->MeasureItem(lpMIS);
  498.         return TRUE;
  499.       }
  500.     }
  501.   }
  502.   return FALSE;
  503. }
  504. CMenu* CNewMenu::FindPopupMenuFromID(HMENU hMenu, UINT nID)
  505. {
  506.   // check for a valid menu-handle
  507.   if ( ::IsMenu(hMenu))
  508.   {
  509.     CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
  510.     if(pMenu)
  511.     {
  512.       return FindPopupMenuFromID(pMenu,nID);
  513.     }
  514.   }
  515.   return NULL; 
  516. }
  517. CMenu* CNewMenu::FindPopupMenuFromIDData(HMENU hMenu, UINT nID, ULONG_PTR pData)
  518. {
  519.   // check for a valid menu-handle
  520.   if ( ::IsMenu(hMenu))
  521.   {
  522.     CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
  523.     if(pMenu)
  524.     {
  525.       return FindPopupMenuFromIDData(pMenu,nID,pData);
  526.     }
  527.   }
  528.   return NULL; 
  529. }
  530. CMenu* CNewMenu::FindPopupMenuFromIDData(CMenu* pMenu, UINT nID, ULONG_PTR pData)
  531. {
  532.   ASSERT_VALID(pMenu);
  533.   // walk through all items, looking for ID match
  534.   UINT nItems = pMenu->GetMenuItemCount();
  535.   for (int iItem = 0; iItem < (int)nItems; iItem++)
  536.   {
  537.     CMenu* pPopup = pMenu->GetSubMenu(iItem);
  538.     if (pPopup != NULL)
  539.     {
  540.       // recurse to child popup
  541.       pPopup = FindPopupMenuFromIDData(pPopup, nID, pData);
  542.       // check popups on this popup
  543.       if (pPopup != NULL)
  544.         return pPopup;
  545.     }
  546.     else if (pMenu->GetMenuItemID(iItem) == nID)
  547.     { 
  548.       MENUITEMINFO MenuItemInfo;
  549.       ::ZeroMemory(&MenuItemInfo,sizeof(MenuItemInfo));
  550.       MenuItemInfo.cbSize = sizeof(MenuItemInfo);
  551.       MenuItemInfo.fMask = MIIM_DATA;
  552.       if(pMenu->GetMenuItemInfo(iItem,&MenuItemInfo,TRUE))
  553.       {
  554.         if(MenuItemInfo.dwItemData==pData)
  555.         {
  556.           // it is a normal item inside our popup
  557.           return pMenu;
  558.         }
  559.       }
  560.     }
  561.   }
  562.   // not found
  563.   return NULL;
  564. }
  565. CMenu* CNewMenu::FindPopupMenuFromID(CMenu* pMenu, UINT nID)
  566. {
  567.   ASSERT_VALID(pMenu);
  568.   // walk through all items, looking for ID match
  569.   UINT nItems = pMenu->GetMenuItemCount();
  570.   for (int iItem = 0; iItem < (int)nItems; iItem++)
  571.   {
  572.     CMenu* pPopup = pMenu->GetSubMenu(iItem);
  573.     if (pPopup != NULL)
  574.     {
  575.       // recurse to child popup
  576.       pPopup = FindPopupMenuFromID(pPopup, nID);
  577.       // check popups on this popup
  578.       if (pPopup != NULL)
  579.         return pPopup;
  580.     }
  581.     else if (pMenu->GetMenuItemID(iItem) == nID)
  582.     {
  583.       // it is a normal item inside our popup
  584.       return pMenu;
  585.     }
  586.   }
  587.   // not found
  588.   return NULL;
  589. }
  590. BOOL CNewMenu::DestroyMenu()
  591. {
  592.   // Destroy Sub menus:
  593.   int m,n;
  594.   int numAllSubMenus = (int)m_AllSubMenus.GetUpperBound();
  595.   for(n = numAllSubMenus; n>= 0; n--)
  596.   {
  597.     if(m_AllSubMenus[n]==this->m_hMenu)
  598.       m_AllSubMenus.RemoveAt(n);
  599.   }
  600.   int numSubMenus = (int)m_SubMenus.GetUpperBound();
  601.   for(m = numSubMenus; m >= 0; m--)
  602.   {
  603.     numAllSubMenus = (int)m_AllSubMenus.GetUpperBound();
  604.     for(n = numAllSubMenus; n>= 0; n--)
  605.     {
  606.       if(m_AllSubMenus[n]==m_SubMenus[m])
  607.         m_AllSubMenus.RemoveAt(n);
  608.     }
  609.     delete((CNewMenu *)FromHandle(m_SubMenus[m]));
  610.   }
  611.   m_SubMenus.RemoveAll();
  612.   // Destroy menu data
  613.   int numItems = (int)m_MenuList.GetUpperBound();
  614.   for(m = 0; m <= numItems; m++)
  615.   {
  616.     delete(m_MenuList[m]);
  617.   }
  618.   
  619.   m_MenuList.RemoveAll();
  620.   if(checkmaps&&!checkmapsshare)
  621.   {
  622.     delete checkmaps;
  623.     checkmaps=NULL;
  624.   }
  625.   // Call base-class implementation last:
  626.   return(CMenu::DestroyMenu());
  627. };
  628. int CNewMenu::GetMenuDrawMode()
  629. {
  630.   ASSERT(m_pActMenuDrawing);
  631.   return m_pActMenuDrawing->m_dwThemeId;
  632. }
  633. void CNewMenu::SetMenuDrawMode(UINT mode)
  634. {
  635.   CMenuTheme* pTheme = CNewMenuHook::FindTheme(mode);
  636.   if(pTheme)
  637.   {
  638.     m_pActMenuDrawing = pTheme;
  639.   }
  640. }
  641. HMENU CNewMenu::GetParent()
  642. {
  643.   return m_hParentMenu;
  644. }
  645. BOOL CNewMenu::IsPopup()
  646. {
  647.   return m_bIsPopupMenu;
  648. }
  649. BOOL CNewMenu::SetSelectDisableMode(BOOL mode)
  650. {
  651.   BOOL bOldMode = m_bSelectDisable;
  652.   m_bSelectDisable=mode;
  653.   return bOldMode;
  654. }
  655. BOOL CNewMenu::GetSelectDisableMode()
  656. {
  657.   return m_bSelectDisable;
  658. }
  659. void CNewMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
  660. {
  661.   ASSERT(m_pActMenuDrawing);
  662.   BOOL bIsMenuBar = IsMenuBar(UIntToHMenu(lpMIS->itemID));
  663.   ((*this).*m_pActMenuDrawing->m_pMeasureItem)(lpMIS,bIsMenuBar);
  664. }
  665. void CNewMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
  666. {
  667.   ASSERT(m_pActMenuDrawing);
  668.   
  669.   BOOL bIsMenuBar = m_hParentMenu ? FALSE: ((m_bIsPopupMenu)?FALSE:TRUE);
  670.   (this->*m_pActMenuDrawing->m_pDrawItem)(lpDIS,bIsMenuBar);
  671. }
  672. // Erase the Background of the menu
  673. BOOL CNewMenu::EraseBkgnd(HWND hWnd, HDC hDC)
  674. {
  675.   CDC* pDC = CDC::FromHandle (hDC);
  676.   CRect Rect;
  677.   //  Get the size of the menu... 
  678.   GetClientRect(hWnd, Rect );
  679.   pDC->FillSolidRect (Rect,GetSysColor(cCOLOR_MENUBAR));
  680.   return TRUE;
  681. }
  682. void CNewMenu::DrawTitle(LPDRAWITEMSTRUCT lpDIS,BOOL bIsMenuBar)
  683. {
  684.   ASSERT(m_pActMenuDrawing);
  685.   (this->*m_pActMenuDrawing->m_pDrawTitle)(lpDIS,bIsMenuBar);
  686. }
  687. void CNewMenu::DrawMenuTitle(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
  688. {
  689.   UNREFERENCED_PARAMETER(bIsMenuBar);
  690.   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  691.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  692.   ASSERT(pMenuData);
  693.   COLORREF ColA = GetSysColor(COLOR_WINDOW);
  694.   COLORREF ColB = GetSysColor(cCOLOR_MENUBAR);
  695.   
  696.   COLORREF colorMenu = MixedColor(ColA,ColB);
  697.   CRect rcClipBox;
  698.   pDC->GetClipBox(rcClipBox);
  699.   // draw the title bar
  700.   CRect rect = lpDIS->rcItem;
  701.   CPoint TextPoint;
  702.   CFont Font;
  703.   if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  704.   {
  705.     rect.top = rcClipBox.top;
  706.     rect.bottom = rcClipBox.bottom;
  707.     rect.right += GetSystemMetrics(SM_CXMENUCHECK);
  708.     Font.CreateFont(16, 0, 900, 900, FW_BOLD,
  709.                         0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
  710.                         CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  711.                         DEFAULT_PITCH,_T("Arial"));
  712.     TextPoint = CPoint(rect.left+2, rect.bottom-4);
  713.     // DrawGradient(pDC,rect,colorMenu,::GetSysColor(COLOR_ACTIVECAPTION),false);
  714.   }
  715.   else
  716.   {
  717.     Font.CreateFont(16, 0, 0, 0, FW_BOLD,
  718.                         0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
  719.                         CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  720.                         DEFAULT_PITCH,_T("Arial"));
  721.     TextPoint = CPoint(rect.left+2, rect.top);
  722.     // DrawGradient(pDC,rect,::GetSysColor(COLOR_ACTIVECAPTION),colorMenu,true);
  723.   }
  724.   if(pMenuData->m_nTitleFlags&MFT_GRADIENT)
  725.   {
  726.     if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  727.     {
  728.       DrawGradient(pDC,rect,colorMenu,::GetSysColor(COLOR_ACTIVECAPTION),false);
  729.     }
  730.     else
  731.     {
  732.       DrawGradient(pDC,rect,::GetSysColor(COLOR_ACTIVECAPTION),colorMenu,true);
  733.     }
  734.   }
  735.   else
  736.   {
  737.     if(pMenuData->m_nTitleFlags&MFT_ROUND)
  738.     {
  739.       if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  740.       {
  741.         TextPoint.y-=2;
  742.         rect.right = rect.left+21;
  743.       }
  744.       else
  745.       {
  746.         TextPoint.x+=10;
  747.       }
  748.       CBrush brush(GetSysColor(COLOR_ACTIVECAPTION));
  749.       CPen* pOldPen = (CPen*)pDC->SelectStockObject(WHITE_PEN);
  750.       CBrush* pOldBrush = pDC->SelectObject(&brush);
  751.       pDC->RoundRect(rect,CPoint(10,10));
  752.       pDC->SelectObject(pOldBrush);
  753.       pDC->SelectObject(pOldPen); 
  754.       
  755.     }
  756.     else
  757.     {
  758.       pDC->FillSolidRect(rect,GetSysColor(COLOR_ACTIVECAPTION));
  759.     }
  760.   }
  761.   if (pMenuData->m_nTitleFlags&MFT_SUNKEN)
  762.   {
  763.     pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  764.   }
  765.   CFont *pOldFont = pDC->SelectObject(&Font);
  766.   COLORREF oldColor = pDC->SetTextColor(::GetSysColor(COLOR_CAPTIONTEXT));
  767.   int OldMode = pDC->SetBkMode(TRANSPARENT);
  768.   if (pMenuData->m_nTitleFlags&MFT_CENTER)
  769.   {
  770.     SIZE size;
  771.     VERIFY(::GetTextExtentPoint32(pDC->m_hDC,pMenuData->m_szMenuText,pMenuData->m_szMenuText.GetLength(),&size));
  772.     if (pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  773.     {
  774.       TextPoint.y = rect.bottom - ((rect.Height()-size.cx)>>1);
  775.     }
  776.     else
  777.     {
  778.       TextPoint.x = rect.left + ((rect.Width()-size.cx)>>1);
  779.     }
  780.   }
  781.   pDC->TextOut(TextPoint.x,TextPoint.y, pMenuData->GetString());
  782.   if(pMenuData->m_nTitleFlags&MFT_LINE)
  783.   {
  784.     if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  785.     {
  786.       CRect rect2(rect.left+20,rect.top+5,rect.left+22,rect.bottom-5);
  787.       pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  788.       rect2.OffsetRect(3,0);
  789.       rect2.InflateRect(0,-10);
  790.       pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  791.     }
  792.     else
  793.     {
  794.       CRect rect2(rect.left+2,rect.bottom-7,rect.right-2,rect.bottom-5);
  795.       pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
  796.       rect2.OffsetRect(0,3);
  797.       rect2.InflateRect(-10,0);
  798.       pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  799.     }
  800.   }
  801.   
  802.   pDC->SetBkMode(OldMode);
  803.   pDC->SetTextColor(oldColor);  
  804.   pDC->SelectObject(pOldFont);
  805. }
  806. void CNewMenu::DrawItem_WinXP(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
  807. {
  808.   ASSERT(lpDIS != NULL);
  809.   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  810.   CRect rect;
  811.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  812.   ASSERT(pMenuData);
  813.   UINT state = pMenuData->m_nFlags;
  814.   COLORREF ColA = GetSysColor(COLOR_WINDOW);
  815.   COLORREF ColB = GetSysColor(cCOLOR_MENUBAR);
  816.   COLORREF colorMenu = MixedColor(ColA,ColB);
  817.   COLORREF colorBitmap = MixedColor(ColB,ColA);
  818.   COLORREF colorSel = MidColor(ColA,GetSysColor(COLOR_HIGHLIGHT));
  819.   CPen Pen(PS_SOLID,0,GetSysColor(COLOR_HIGHLIGHT));
  820.   if(bIsMenuBar)
  821.   {
  822. #ifdef _TRACE_MENU_
  823.     TRACE(_T("BarState: 0x%lX Menus %ldn"),lpDIS->itemState,m_dwOpenMenu);
  824. #endif
  825.     if(!m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
  826.     {
  827.       lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
  828.     }
  829.     if(!(lpDIS->itemState&ODS_HOTLIGHT))
  830.     { 
  831.       colorSel = colorBitmap;
  832.     }
  833.     colorMenu = ColB;
  834.   }
  835.   CBrush m_brBackground(colorMenu);
  836.   CBrush m_brSel(colorSel);
  837.   CBrush m_brBitmap(colorBitmap);
  838.   CRect RectL(lpDIS->rcItem);
  839.   CRect RectR(lpDIS->rcItem);
  840.   CRect RectSel(lpDIS->rcItem);
  841.   if(bIsMenuBar)
  842.   {
  843.     RectR.InflateRect (0,0,0,0);
  844.     RectSel.InflateRect (0,0,-2 -2,0);
  845.   }  
  846.   else
  847.   {
  848.     RectL.right = RectL.left + m_iconX + 8;
  849.     RectR.left  = RectL.right;
  850.     // Draw for Bitmapbackground
  851.     pDC->FillSolidRect (RectL,colorBitmap);
  852.   }
  853.   // Draw for Textbackground
  854.   pDC->FillSolidRect (RectR,colorMenu);
  855.   // Spacing for submenu only in popups
  856.   if(!bIsMenuBar)
  857.   {
  858.     RectR.left += 4;
  859.     RectR.right-= 15;
  860.   }
  861.   //  Flag for highlighted item
  862.   if(lpDIS->itemState & (ODS_HOTLIGHT|ODS_INACTIVE) )
  863.   {
  864.     lpDIS->itemState |= ODS_SELECTED;
  865.   }
  866.   if(bIsMenuBar && (lpDIS->itemState&ODS_SELECTED) )
  867.   {
  868.     if(!(lpDIS->itemState&ODS_INACTIVE) )
  869.     {
  870.       SetLastMenuRect(lpDIS->hDC,RectSel);
  871.       if(!(lpDIS->itemState&ODS_HOTLIGHT) )
  872.       { 
  873.         int X,Y;
  874.         CRect rect = RectR;
  875.         int winH = rect.Height(); 
  876.         // Simulate a shadow on right edge... 
  877.         for (X=1; X<=4 ;X++)
  878.         { 
  879.           for (Y=0; Y<4 ;Y++)
  880.           {
  881.             pDC->SetPixel(rect.right-X,Y+rect.top, ColB );
  882.           }
  883.           for (Y=4; Y<8 ;Y++)
  884.           {
  885.             pDC->SetPixel(rect.right-X,Y+rect.top,DarkenColor(3 * X * (Y - 3), ColB)) ;
  886.           }
  887.           for (Y=8; Y<=(winH-1) ;Y++)
  888.           {
  889.             pDC->SetPixel(rect.right - X, Y+rect.top, DarkenColor(15 * X, ColB) );
  890.           }
  891.         }
  892.       }
  893.     }
  894.   }
  895.   // For keyboard navigation only
  896.   BOOL bDrawSmalSelection = FALSE;
  897.   // remove the selected bit if it's grayed out
  898.   if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable)
  899.   {
  900.     if( lpDIS->itemState & ODS_SELECTED )
  901.     {
  902.       lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
  903.       DWORD MsgPos = ::GetMessagePos();
  904.       if(MsgPos==CNewMenuHook::m_dwMsgPos)
  905.       {
  906.         bDrawSmalSelection = TRUE;
  907.       }
  908.       else
  909.       {
  910.         CNewMenuHook::m_dwMsgPos = MsgPos;
  911.       }
  912.     }
  913.   }
  914.   // Draw the seperator
  915.   if(state & MF_SEPARATOR)
  916.   {
  917.     if(pMenuData->m_nTitleFlags&MFT_TITLE)
  918.     {
  919.       DrawTitle(lpDIS,bIsMenuBar);
  920.     }
  921.     else
  922.     {
  923.       // Draw only the seperator
  924.       CRect rect;
  925.       rect.top = RectR.CenterPoint().y;
  926.       rect.bottom = rect.top+1;
  927.       rect.right = lpDIS->rcItem.right+1;
  928.       rect.left = RectR.left;
  929.       pDC->FillSolidRect(rect,GetSysColor(COLOR_GRAYTEXT));
  930.     }
  931.   }
  932.   else
  933.   {
  934.     if( (lpDIS->itemState & ODS_SELECTED) && !(lpDIS->itemState&ODS_INACTIVE) )
  935.     {
  936.       // Draw the selection
  937.       CPen* pOldPen = pDC->SelectObject(&Pen);
  938.       CBrush* pOldBrush = pDC->SelectObject(&m_brSel);
  939.       pDC->Rectangle(RectSel);
  940.       pDC->SelectObject(pOldBrush);
  941.       pDC->SelectObject(pOldPen);
  942.     }
  943.     else if (bDrawSmalSelection)
  944.     {
  945.       // Draw the selection for keyboardnavigation
  946.       CPen* pOldPen = pDC->SelectObject(&Pen);
  947.       CBrush* pOldBrush = pDC->SelectObject(&m_brBackground);
  948.       pDC->Rectangle(RectSel);
  949.       pDC->SelectObject(pOldBrush);
  950.       pDC->SelectObject(pOldPen);
  951.     }
  952.     UINT state = lpDIS->itemState;
  953.     BOOL standardflag=FALSE;
  954.     BOOL selectedflag=FALSE;
  955.     BOOL disableflag=FALSE;
  956.     BOOL checkflag=FALSE;
  957.     CBrush m_brSelect;
  958.     CPen m_penBack;
  959.     CImageList* bitmap = pMenuData->m_pBitmap;
  960.     CString strText = pMenuData->GetString();
  961.     if((state&ODS_CHECKED) && (pMenuData->m_nMenuIconNormal<0))
  962.     {
  963.       if(state&ODS_SELECTED && m_selectcheck>0)
  964.       {
  965.         checkflag=TRUE;
  966.       }
  967.       else if(m_unselectcheck>0)
  968.       {
  969.         checkflag=TRUE;
  970.       }
  971.     }
  972.     else if(pMenuData->m_nMenuIconNormal != -1)
  973.     {
  974.       standardflag=TRUE;
  975.       if(state&ODS_SELECTED)
  976.       {
  977.         selectedflag=TRUE;
  978.       }
  979.       else if(state&ODS_GRAYED) 
  980.       {
  981.         disableflag=TRUE;
  982.       }
  983.     }
  984.     // draw the menutext
  985.     if(!strText.IsEmpty())
  986.     {
  987.       LOGFONT LogFontMenu;
  988.       CFont FontMenu;
  989.       NONCLIENTMETRICS nm;
  990.       ::ZeroMemory(&nm,sizeof(nm));
  991.       nm.cbSize = sizeof (nm);
  992.       VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  993.       LogFontMenu =  nm.lfMenuFont;
  994.       // Default selection?
  995.       if(state&ODS_DEFAULT)
  996.       {
  997.         // Make the font bold
  998.         LogFontMenu.lfWeight = FW_BOLD;
  999.       }
  1000.       FontMenu.CreateFontIndirect(&LogFontMenu);
  1001.       CString leftStr;
  1002.       CString rightStr;
  1003.       leftStr.Empty();
  1004.       rightStr.Empty();
  1005.       int tablocr=strText.ReverseFind(_T('t'));
  1006.       if(tablocr!=-1)
  1007.       {
  1008.         rightStr=strText.Mid(tablocr+1);
  1009.         leftStr=strText.Left(strText.Find(_T('t')));
  1010.       }
  1011.       else 
  1012.         leftStr=strText;
  1013.       // Draw the text in the correct colour:
  1014.       UINT nFormat  = DT_LEFT| DT_SINGLELINE|DT_VCENTER;
  1015.       UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  1016.       int iOldMode = pDC->SetBkMode( TRANSPARENT);
  1017.       CFont* pOldFont = pDC->SelectObject (&FontMenu);
  1018.       COLORREF OldTextColor;
  1019.       if( (lpDIS->itemState&ODS_GRAYED) || 
  1020.           (bIsMenuBar && lpDIS->itemState&ODS_INACTIVE) )
  1021.       {
  1022.         // Draw the text disabled? 
  1023.         OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  1024.       }
  1025.       else
  1026.       {
  1027.         // Draw the text normal
  1028.         OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_MENUTEXT));
  1029.       }
  1030.       if(bIsMenuBar)
  1031.       {
  1032.         pDC->DrawText(leftStr,RectSel, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  1033.       }
  1034.       else
  1035.       {
  1036.         pDC->DrawText(leftStr,RectR, nFormat);
  1037.         if(tablocr!=-1) 
  1038.           pDC->DrawText (rightStr,RectR,nFormatr);
  1039.       }
  1040.       pDC->SetTextColor(OldTextColor);
  1041.       pDC->SelectObject(pOldFont);
  1042.       pDC->SetBkMode(iOldMode);
  1043.     }
  1044.     // Draw the Bitmap or checkmarks
  1045.     if(!bIsMenuBar)
  1046.     {
  1047.       CRect rect2 = RectR;
  1048.       
  1049.       if(checkflag||standardflag||selectedflag||disableflag)
  1050.       {
  1051.         if(checkflag && checkmaps)
  1052.         {
  1053.           CPoint ptImage(RectL.left+3,RectL.top+4);
  1054.           
  1055.           if(state&ODS_SELECTED)
  1056.             checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  1057.           else 
  1058.             checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  1059.         }
  1060.         else
  1061.         {
  1062.           //CPoint ptImage(rect.left+3,rect.top+2+dy);
  1063.           HICON hDrawIcon = bitmap->ExtractIcon(0);
  1064.           int cx,cy;
  1065.           ::ImageList_GetIconSize(*bitmap, &cx, &cy);
  1066.           CSize size(cx,cy);
  1067.           CPoint ptImage(RectL.left+3,RectL.top+4);
  1068.           CBrush* pBrush = &m_brBitmap; 
  1069.           // Need to draw the checked state
  1070.           if (state&ODS_CHECKED)
  1071.           {
  1072.             CRect rect = RectL;
  1073.             rect.InflateRect (-1,-1);
  1074.             CBrush Brush;
  1075.             if(selectedflag)
  1076.               Brush.CreateSolidBrush(DarkenColorXP(colorSel));
  1077.             else
  1078.               Brush.CreateSolidBrush(DarkenColorXP(colorMenu));
  1079.             CPen* pOldPen = pDC->SelectObject(&Pen);
  1080.             CBrush* pOldBrush = pDC->SelectObject(&Brush);
  1081.             pDC->Rectangle(rect);
  1082.             pDC->SelectObject(pOldBrush);
  1083.             pDC->SelectObject(pOldPen);
  1084.           } 
  1085.           else if(selectedflag)
  1086.           {
  1087.             CBrush Brush;
  1088.             Brush.CreateSolidBrush(DarkenColorXP(colorSel));
  1089.             ptImage.x++; ptImage.y++;
  1090.             pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL | DSS_MONO, &Brush);
  1091.             ptImage.x-=2; ptImage.y-=2;
  1092.           }
  1093.           if(state & ODS_DISABLED)
  1094.             pDC->DrawState(ptImage, size, hDrawIcon, DSS_DISABLED, pBrush);
  1095.           else
  1096.             pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
  1097.         }
  1098.       }
  1099.       if(pMenuData->m_nMenuIconNormal<0 && state&ODS_CHECKED && !checkflag)
  1100.       {
  1101.         MENUITEMINFO info;
  1102.         ZeroMemory(&info,sizeof(info));
  1103.         info.cbSize = sizeof(info);
  1104.         info.fMask = MIIM_CHECKMARKS;
  1105.         ::GetMenuItemInfo(HWndToHmenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);
  1106.         if(state&ODS_CHECKED || info.hbmpUnchecked) 
  1107.         {
  1108.           CRect rect = RectL;
  1109.           rect.InflateRect (-1,-1);
  1110.           COLORREF transparentcol;
  1111.           if(state&ODS_SELECTED)
  1112.             transparentcol = DarkenColorXP(colorSel);
  1113.           else
  1114.             transparentcol = DarkenColorXP(colorMenu);
  1115.           CBrush Brush;
  1116.           Brush.CreateSolidBrush(transparentcol);
  1117.           CPen* pOldPen = pDC->SelectObject(&Pen);
  1118.           CBrush* pOldBrush = pDC->SelectObject(&Brush);
  1119.           pDC->Rectangle(rect);
  1120.           pDC->SelectObject(pOldBrush);
  1121.           pDC->SelectObject(pOldPen);
  1122.           if (state&ODS_CHECKED)
  1123.           {
  1124.             rect.InflateRect (-1,-1);
  1125.             if (!info.hbmpChecked)
  1126.             { // Checkmark
  1127.               DrawSpecialCharStyle(pDC,rect,98,state);
  1128.             }
  1129.             else
  1130.             { // Bullet
  1131.               DrawSpecialCharStyle(pDC,rect,105,state);
  1132.             }
  1133.           }
  1134.           else
  1135.           {
  1136.             CSize size = rect.Size();
  1137.             CPoint ptImage = rect.TopLeft();
  1138.             if(state & ODS_DISABLED)
  1139.               pDC->DrawState(ptImage, size, info.hbmpUnchecked, DSS_DISABLED, (HBRUSH)NULL);
  1140.             else
  1141.               pDC->DrawState(ptImage, size, info.hbmpUnchecked, DSS_NORMAL,(HBRUSH)NULL);
  1142.           }
  1143.         }
  1144.       }
  1145.       else if (lpDIS->itemID>=SC_SIZE && lpDIS->itemID<=SC_HOTKEY )
  1146.       {
  1147.         DrawSpecial_WinXP(pDC,RectL,lpDIS->itemID,state);
  1148.       }
  1149.     }
  1150.   }
  1151. }
  1152. void CNewMenu::DrawItem_SpecialStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
  1153. {
  1154.   if(!bIsMenuBar)
  1155.   {
  1156.     DrawItem_OldStyle(lpDIS,bIsMenuBar);
  1157.     return;
  1158.   }
  1159.   ASSERT(lpDIS != NULL);
  1160.   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  1161.   ASSERT(lpDIS->itemData);
  1162.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  1163.   CRect rect(lpDIS->rcItem);
  1164.   //rect.InflateRect(0,-1);
  1165.   COLORREF ColorBack;
  1166.   if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
  1167.   {
  1168.     ColorBack = GetSysColor(COLOR_HIGHLIGHT);
  1169.     SetLastMenuRect(lpDIS->hDC,rect);
  1170.   }
  1171.   else
  1172.   {
  1173.     ColorBack = GetSysColor(cCOLOR_MENUBAR);
  1174.   }
  1175.   pDC->FillSolidRect(rect,ColorBack);
  1176.   int iOldMode = pDC->SetBkMode( TRANSPARENT);
  1177.   CString strText = pMenuData->GetString();
  1178.   COLORREF crTextColor;
  1179.   if(!(lpDIS->itemState & ODS_GRAYED))
  1180.   {
  1181.     if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT)) 
  1182.       crTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
  1183.     else
  1184.       crTextColor = GetSysColor(COLOR_MENUTEXT);
  1185.   }
  1186.   else
  1187.   {
  1188.     crTextColor = GetSysColor(COLOR_GRAYTEXT);
  1189.   }
  1190.   COLORREF oldColor = pDC->SetTextColor(crTextColor);
  1191.   
  1192.   pDC->DrawText(strText,rect,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  1193.   
  1194.   pDC->SetTextColor(oldColor);
  1195.   pDC->SetBkMode( iOldMode);
  1196. }
  1197. void CNewMenu::DrawItem_OldStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
  1198. {
  1199.   ASSERT(lpDIS != NULL);
  1200.   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  1201.   CRect rect;
  1202.   ASSERT(lpDIS->itemData);
  1203.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
  1204.   UINT state = pMenuData->m_nFlags;
  1205.   CBrush m_brBackground;
  1206.   COLORREF ColorBack = bIsMenuBar?GetSysColor(cCOLOR_MENUBAR):GetSysColor(COLOR_MENU);
  1207.   m_brBackground.CreateSolidBrush(ColorBack);
  1208.   CRect RectL(lpDIS->rcItem);
  1209.   CRect RectR(lpDIS->rcItem);
  1210.   CRect RectSel(lpDIS->rcItem);
  1211.   RectL.InflateRect (-1,0,0,0);
  1212.   RectR.InflateRect (-1,0,0,0);
  1213.   RectSel.InflateRect (0,0,0,0);
  1214.   if(!bIsMenuBar)
  1215.   {
  1216.     RectL.right = RectL.left + m_iconX + 6 + GAP;
  1217.     RectR.left  = RectL.right;
  1218.     // Draw for Bitmapbackground
  1219.     pDC->FillSolidRect (RectL,ColorBack);
  1220.   }
  1221.   else
  1222.   {
  1223. #ifdef _TRACE_MENU_
  1224.     TRACE(_T("BarState: 0x%lX Menus %ldn"),lpDIS->itemState,m_dwOpenMenu);
  1225. #endif
  1226.     if(!m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
  1227.     {
  1228.       lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
  1229.     }
  1230.     RectR.InflateRect (1,0,0,0);
  1231.     RectSel.InflateRect (0,0,-5,0);
  1232.     RectSel.OffsetRect(1,-1);
  1233.     SetLastMenuRect(lpDIS->hDC,RectSel);
  1234.   }
  1235.    // For keyboard navigation only
  1236.   BOOL bDrawSmalSelection = FALSE;
  1237.   // remove the selected bit if it's grayed out
  1238.   if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable )
  1239.   {
  1240.     if(lpDIS->itemState & ODS_SELECTED)
  1241.     {
  1242.       lpDIS->itemState &= ~ODS_SELECTED;
  1243.       DWORD MsgPos = ::GetMessagePos();
  1244.       if(MsgPos==CNewMenuHook::m_dwMsgPos)
  1245.       {
  1246.         bDrawSmalSelection = TRUE;
  1247.       }
  1248.       else
  1249.       {
  1250.         CNewMenuHook::m_dwMsgPos = MsgPos;
  1251.       }
  1252.     }
  1253.   }
  1254.   if(state & MF_SEPARATOR)
  1255.   {
  1256.     if(pMenuData->m_nTitleFlags&MFT_TITLE)
  1257.     {
  1258.       DrawTitle(lpDIS,bIsMenuBar);
  1259.     }
  1260.     else
  1261.     {
  1262.       rect = lpDIS->rcItem; 
  1263.       rect.left += 1;
  1264.       pDC->FillSolidRect(rect,ColorBack);
  1265.       pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
  1266.     }
  1267.   }
  1268.   else
  1269.   {
  1270.     CRect rect2;
  1271.     BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
  1272.     BOOL checkflag=FALSE;
  1273.     CBrush m_brSelect;
  1274.     int nIconNormal=-1,xoffset=-1;
  1275.     CImageList *bitmap=NULL;
  1276.     // set some colors and the font
  1277.     m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  1278.     // draw the colored rectangle portion
  1279.     rect.CopyRect(&lpDIS->rcItem);
  1280.     rect.OffsetRect (1,1);
  1281.     rect2=rect=RectSel;
  1282.     // draw the up/down/focused/disabled state
  1283.     UINT state = lpDIS->itemState;
  1284.     CString strText;
  1285.     nIconNormal = pMenuData->m_nMenuIconNormal;
  1286.     xoffset = pMenuData->m_nxOffset;
  1287.     bitmap = pMenuData->m_pBitmap;
  1288.     strText = pMenuData->GetString();
  1289.     if( (state&ODS_CHECKED) && nIconNormal<0)
  1290.     {
  1291.       if(state&ODS_SELECTED && m_selectcheck>0)
  1292.         checkflag=TRUE;
  1293.       else if(m_unselectcheck>0) 
  1294.         checkflag=TRUE;
  1295.     }
  1296.     else if(nIconNormal != -1)
  1297.     {
  1298.       standardflag=TRUE;
  1299.       if(state&ODS_SELECTED && !(state&ODS_GRAYED))
  1300.         selectedflag=TRUE;
  1301.       else if(state&ODS_GRAYED)
  1302.         disableflag=TRUE;
  1303.     }
  1304.     if(bIsMenuBar)
  1305.     {
  1306.       //rect.InflateRect (1,0,0,0);
  1307.       rect.OffsetRect(-1,1);
  1308.       rect2=rect;
  1309.       pDC->FillSolidRect (rect,ColorBack);
  1310.     }
  1311.     else
  1312.     {
  1313.       // Draw the background
  1314.       pDC->FillSolidRect (rect,ColorBack);
  1315.     }
  1316.     // Draw the selection
  1317.     if(state&ODS_SELECTED)
  1318.     {
  1319.       // You need only Text highlight and thats what you get
  1320.       if(!bIsMenuBar)
  1321.       {
  1322.         if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
  1323.         {
  1324.           rect2.SetRect(rect.left+m_iconX+4+GAP,rect.top,rect.right,rect.bottom);
  1325.         }
  1326.         pDC->FillRect(rect2,&m_brSelect);
  1327.       }
  1328.       else
  1329.       {
  1330.         pDC->Draw3dRect(rect ,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  1331.       }
  1332.     }
  1333.     else if(bIsMenuBar && (state&ODS_HOTLIGHT) && !(state&ODS_INACTIVE))
  1334.     {
  1335.       pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
  1336.     }
  1337.     else if (bDrawSmalSelection)
  1338.     {
  1339.       pDC->DrawFocusRect(rect);
  1340.     }
  1341.     // Draw the Bitmap or checkmarks
  1342.     if(!bIsMenuBar)
  1343.     {
  1344.       CRect IconRect(rect.TopLeft(),CSize(m_iconX,m_iconY));
  1345.       IconRect.OffsetRect(GAP+1,1+((rect.Height()-m_iconY)>>2));
  1346.       CPoint ptImage = IconRect.TopLeft();
  1347.       IconRect.InflateRect(2,2);
  1348.       if(checkflag||standardflag||selectedflag||disableflag)
  1349.       {
  1350.         if(checkflag && checkmaps)
  1351.         {
  1352.           if(state&ODS_SELECTED)
  1353.             checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  1354.           else 
  1355.             checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  1356.         }
  1357.         else
  1358.         {
  1359.           // Need to draw the checked state
  1360.           if (IsNewShell())
  1361.           {
  1362.             if(state&ODS_CHECKED)
  1363.             {
  1364.               pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
  1365.             }
  1366.             else if (selectedflag)
  1367.             {
  1368.               pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
  1369.             }
  1370.           }
  1371.           if(state & ODS_DISABLED)
  1372.           {
  1373.             HICON hDrawIcon = bitmap->ExtractIcon(0);
  1374.             int cx,cy;
  1375.             ::ImageList_GetIconSize(*bitmap, &cx, &cy);
  1376.             CSize size(cx,cy);
  1377.           
  1378.             pDC->DrawState(ptImage, size, hDrawIcon, DSS_DISABLED, (HBRUSH)NULL);
  1379.           }
  1380.           else
  1381.           {
  1382.             bitmap->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  1383.           }
  1384.         }
  1385.       }
  1386.       if(pMenuData->m_nMenuIconNormal<0 && state&ODS_CHECKED && !checkflag)
  1387.       {
  1388.         MENUITEMINFO info;
  1389.         ZeroMemory(&info, sizeof(info));
  1390.         info.cbSize = sizeof(info);
  1391.         info.fMask = MIIM_CHECKMARKS;
  1392.         ::GetMenuItemInfo(HWndToHmenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);
  1393.         if(state&ODS_CHECKED || info.hbmpUnchecked) 
  1394.         {
  1395.           // Rectangle for checkmarks
  1396.           CRect rect = IconRect;
  1397.           if (state&ODS_CHECKED)
  1398.             Draw3DCheckmark(pDC, IconRect,info.hbmpChecked,state);
  1399.           else
  1400.             Draw3DCheckmark(pDC, IconRect,info.hbmpUnchecked,state);
  1401.         }
  1402.       }
  1403.       else if (lpDIS->itemID>=SC_SIZE && lpDIS->itemID<=SC_HOTKEY)
  1404.       {
  1405.         DrawSpecial_OldStyle(pDC,IconRect,lpDIS->itemID,state);
  1406.       } 
  1407.     }
  1408.     if(!strText.IsEmpty())
  1409.     {
  1410.       COLORREF crText = GetSysColor(COLOR_MENUTEXT);
  1411.       if(bIsMenuBar)
  1412.       {
  1413.         rect.left += 6;
  1414.         if(lpDIS->itemState&ODS_INACTIVE) 
  1415.           crText = GetSysColor(COLOR_GRAYTEXT);
  1416.       }
  1417.       else
  1418.       {
  1419.         if(lpDIS->itemState&ODS_SELECTED) 
  1420.           crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  1421.         rect.left += m_iconX + 12;
  1422.       }
  1423.       CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
  1424.       
  1425.       // Find tabs
  1426.       CString leftStr,rightStr;
  1427.       leftStr.Empty();rightStr.Empty();
  1428.       int tablocr=strText.ReverseFind(_T('t'));
  1429.       if(tablocr!=-1)
  1430.       {
  1431.         rightStr=strText.Mid(tablocr+1);
  1432.         leftStr=strText.Left(strText.Find(_T('t')));
  1433.         rectt.right-=m_iconX;
  1434.       }
  1435.       else
  1436.         leftStr=strText;
  1437.       int iOldMode = pDC->SetBkMode( TRANSPARENT);
  1438.       // Draw the text in the correct colour:
  1439.       UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
  1440.       UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  1441.       if(bIsMenuBar)
  1442.       {
  1443.         rectt = RectSel;
  1444.         if(state & ODS_SELECTED)
  1445.         {
  1446.           rectt.OffsetRect(1,1);
  1447.         } 
  1448.         nFormat = DT_CENTER|DT_SINGLELINE|DT_VCENTER;
  1449.       }
  1450.       if(!(lpDIS->itemState & ODS_GRAYED))
  1451.       {
  1452.         pDC->SetTextColor(crText);
  1453.         pDC->DrawText (leftStr,rectt,nFormat);
  1454.         if(tablocr!=-1)
  1455.           pDC->DrawText (rightStr,rectt,nFormatr);
  1456.       }
  1457.       else
  1458.       {
  1459.         // Draw the disabled text
  1460.         if(!(state & ODS_SELECTED))
  1461.         {
  1462.           CRect offset = rectt;
  1463.           offset.OffsetRect (1,1);
  1464.           pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
  1465.           pDC->DrawText(leftStr,&offset, nFormat);
  1466.           if(tablocr!=-1) 
  1467.             pDC->DrawText (rightStr,&offset,nFormatr);
  1468.           pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  1469.           pDC->DrawText(leftStr,rectt, nFormat);
  1470.           if(tablocr!=-1)
  1471.             pDC->DrawText(rightStr,rectt,nFormatr);
  1472.         }
  1473.         else
  1474.         {
  1475.           // And the standard Grey text:
  1476.           pDC->SetTextColor(ColorBack);
  1477.           pDC->DrawText(leftStr,rectt, nFormat);
  1478.           if(tablocr!=-1) 
  1479.             pDC->DrawText (rightStr,rectt,nFormatr);
  1480.         }
  1481.       }
  1482.       pDC->SetBkMode( iOldMode );
  1483.     }
  1484.     m_brSelect.DeleteObject();
  1485.   }
  1486.   m_brBackground.DeleteObject();
  1487. }
  1488. BOOL CNewMenu::IsMenuBar(HMENU hMenu)
  1489. {
  1490.   BOOL bIsMenuBar = ::IsMenu(hMenu);
  1491.   if(bIsMenuBar)
  1492.   {
  1493.     CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_hParentMenu));
  1494.     if (pMenu!=NULL && pMenu->m_hParentMenu!=NULL)
  1495.     {
  1496.       bIsMenuBar = FALSE;
  1497.     }
  1498.   }
  1499.   return bIsMenuBar;
  1500. }
  1501. /*
  1502. ==========================================================================
  1503. void CNewMenu::MeasureItem(LPMEASUREITEMSTRUCT)
  1504. ---------------------------------------------
  1505.   Called by the framework when it wants to know what the width and height
  1506.   of our item will be.  To accomplish this we provide the width of the
  1507.   icon plus the width of the menu text, and then the height of the icon.
  1508.   
  1509. ==========================================================================
  1510. */
  1511. void CNewMenu::MeasureItem_OldStyle( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
  1512. {
  1513.   ASSERT(lpMIS->itemData);
  1514.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);
  1515.   UINT state = pMenuData->m_nFlags;
  1516.   if(state & MF_SEPARATOR)
  1517.   {
  1518.     if(pMenuData->m_nTitleFlags&MFT_TITLE)
  1519.     {
  1520.       // DC of the desktop
  1521.       CClientDC myDC(NULL);          
  1522.       CFont font;
  1523.       font.CreatePointFont(160,_T("Arial"));
  1524.       CFont* pOldFont = myDC.SelectObject (&font);
  1525.       LPCTSTR lpstrText = pMenuData->GetString();
  1526.       SIZE size;
  1527.       VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
  1528.       // Select old font in
  1529.       myDC.SelectObject(pOldFont);  
  1530.       if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  1531.       {
  1532.         lpMIS->itemWidth = size.cy*3/4 -GetSystemMetrics(SM_CXMENUCHECK);
  1533.         // Don't make the menu higher than menuitems in it
  1534.         lpMIS->itemHeight = 0;
  1535.         if(pMenuData->m_nTitleFlags&MFT_LINE)
  1536.         {
  1537.           lpMIS->itemWidth += 6;
  1538.         }
  1539.        }
  1540.       else
  1541.       {
  1542.         lpMIS->itemWidth = size.cx*3/4;
  1543.         lpMIS->itemHeight = size.cy*3/4;
  1544.         if(pMenuData->m_nTitleFlags&MFT_LINE)
  1545.         {
  1546.           lpMIS->itemHeight += 6;
  1547.         }
  1548.       }
  1549.     }
  1550.     else
  1551.     {
  1552.       lpMIS->itemHeight = 3;
  1553.     }
  1554.   }
  1555.   else
  1556.   {
  1557.     CFont m_fontMenu;
  1558.     LOGFONT m_lf;
  1559.     ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  1560.     NONCLIENTMETRICS nm;
  1561.     nm.cbSize = sizeof (NONCLIENTMETRICS);
  1562.     VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm,0)); 
  1563.     m_lf =  nm.lfMenuFont;
  1564.     // Default selection?
  1565.     if(state&ODS_DEFAULT)
  1566.     {
  1567.       // Make the font bold
  1568.       m_lf.lfWeight = FW_BOLD;
  1569.     }
  1570.     m_fontMenu.CreateFontIndirect (&m_lf);
  1571.     
  1572.     // DC of the desktop
  1573.     CClientDC myDC(NULL);
  1574.     
  1575.     // Select menu font in...    
  1576.     CFont* pOldFont = myDC.SelectObject (&m_fontMenu);
  1577.     //Get pointer to text SK
  1578.     const LPCTSTR lpstrText = pMenuData->GetString();
  1579.     SIZE size;
  1580.     VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
  1581.     // Select old font in
  1582.     myDC.SelectObject(pOldFont);  
  1583.   
  1584.     // Set width and height:
  1585.     if(bIsMenuBar)
  1586.     {
  1587.       lpMIS->itemWidth = size.cx ;
  1588.     }
  1589.     else
  1590.     {
  1591.       lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
  1592.     }
  1593.     // Check the Key-Shortcut
  1594.     if(_tcsstr(lpstrText, _T("t")) != NULL)
  1595.       lpMIS->itemWidth += 15;
  1596.     int temp = GetSystemMetrics(SM_CYMENU);
  1597.     lpMIS->itemHeight = (temp>(m_iconY+4)) ? temp : (m_iconY+4);
  1598.     
  1599.     m_fontMenu.DeleteObject();
  1600.     // set status bar as appropriate
  1601.     UINT nItemID = (lpMIS->itemID & 0xFFF0);
  1602.     // Special case for system menu
  1603.     if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY) 
  1604.     {
  1605.       BOOL bGetNext = FALSE;
  1606.       // search the actual menu item
  1607.       for (int j=0;j<m_MenuList.GetUpperBound();++j)
  1608.       {
  1609.         CNewMenuItemData* pTemp = m_MenuList[j];
  1610.         if(pTemp==pMenuData || bGetNext==TRUE)
  1611.         {
  1612.           bGetNext = TRUE;
  1613.           pTemp = m_MenuList[j+1];
  1614.           if(pTemp->m_nID)
  1615.           {
  1616.             lpMIS->itemData = (ULONG_PTR)pTemp;
  1617.             lpMIS->itemID = pTemp->m_nID; 
  1618.             UINT nOrgWidth = lpMIS->itemWidth;
  1619.             MeasureItem_OldStyle(lpMIS,bIsMenuBar);
  1620.             // Restore old values
  1621.             lpMIS->itemData = (ULONG_PTR)pMenuData;
  1622.             lpMIS->itemID = pMenuData->m_nID;
  1623.             lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
  1624.             break;
  1625.           }
  1626.         }
  1627.       }
  1628.       lpMIS->itemHeight = temp;
  1629.     } 
  1630.   }
  1631. }
  1632. void CNewMenu::MeasureItem_WinXP( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
  1633. {
  1634.   ASSERT(lpMIS->itemData);
  1635.   CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);
  1636.   UINT state = pMenuData->m_nFlags;
  1637.   if(state & MF_SEPARATOR)
  1638.   {
  1639.     if(pMenuData->m_nTitleFlags&MFT_TITLE)
  1640.     {
  1641.       // DC of the desktop
  1642.       CClientDC myDC(NULL);
  1643.       CFont font;
  1644.       font.CreatePointFont(160,_T("Arial"));
  1645.       CFont* pOldFont = myDC.SelectObject (&font);
  1646.       LPCTSTR lpstrText = pMenuData->GetString();
  1647.       SIZE size;
  1648.       VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
  1649.       // Select old font in
  1650.       myDC.SelectObject(pOldFont);  
  1651.       if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
  1652.       {
  1653.         lpMIS->itemWidth = size.cy*3/4 -GetSystemMetrics(SM_CXMENUCHECK);
  1654.         // Don't make the menu higher than menuitems in it
  1655.         lpMIS->itemHeight = 0;
  1656.         if(pMenuData->m_nTitleFlags&MFT_LINE)
  1657.         {
  1658.           lpMIS->itemWidth += 6;
  1659.         }
  1660.       }
  1661.       else
  1662.       {
  1663.         lpMIS->itemWidth = size.cx*3/4;
  1664.         lpMIS->itemHeight = size.cy*3/4;
  1665.         if(pMenuData->m_nTitleFlags&MFT_LINE)
  1666.         {
  1667.           lpMIS->itemHeight += 6;
  1668.         }
  1669.       }
  1670.     }
  1671.     else
  1672.     {
  1673.       lpMIS->itemHeight = 3;
  1674.     }
  1675.   }
  1676.   else
  1677.   {
  1678.     CFont m_fontMenu;
  1679.     LOGFONT m_lf;
  1680.     ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  1681.     NONCLIENTMETRICS nm;
  1682.     nm.cbSize = sizeof (NONCLIENTMETRICS);
  1683.     VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm,0)); 
  1684.     m_lf =  nm.lfMenuFont;
  1685.     // Default selection?
  1686.     if(state&ODS_DEFAULT)
  1687.     {
  1688.       // Make the font bold
  1689.       m_lf.lfWeight = FW_BOLD;
  1690.     }
  1691.     m_fontMenu.CreateFontIndirect (&m_lf);
  1692.     
  1693.     // DC of the desktop
  1694.     CClientDC myDC(NULL);
  1695.     
  1696.     // Select menu font in...    
  1697.     CFont* pOldFont = myDC.SelectObject (&m_fontMenu);
  1698.     //Get pointer to text SK
  1699.     const LPCTSTR lpstrText = pMenuData->GetString();
  1700.     SIZE size;
  1701.     VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
  1702.     // Select old font in
  1703.     myDC.SelectObject(pOldFont);  
  1704.   
  1705.     // Set width and height:
  1706.     if(bIsMenuBar)
  1707.     {
  1708.       lpMIS->itemWidth = size.cx ;
  1709.     }
  1710.     else
  1711.     {
  1712.       lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
  1713.     }
  1714.     // Check the Key-Shortcut
  1715.     if(_tcsstr(lpstrText, _T("t")) != NULL)
  1716.       lpMIS->itemWidth += 15;
  1717.     int temp = GetSystemMetrics(SM_CYMENU);
  1718.     lpMIS->itemHeight = temp>m_iconY+8 ? temp : m_iconY+8;
  1719.     
  1720.     m_fontMenu.DeleteObject();
  1721.     // set status bar as appropriate
  1722.     UINT nItemID = (lpMIS->itemID & 0xFFF0);
  1723.     // Special case for system menu
  1724.     if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY) 
  1725.     {
  1726.       BOOL bGetNext = FALSE;
  1727.       // search the actual menu item
  1728.       for (int j=0;j<m_MenuList.GetUpperBound();++j)
  1729.       {
  1730.         CNewMenuItemData* pTemp = m_MenuList[j];
  1731.         if(pTemp==pMenuData || bGetNext==TRUE)
  1732.         {
  1733.           bGetNext = TRUE;
  1734.           pTemp = m_MenuList[j+1];
  1735.           if(pTemp->m_nID)
  1736.           {
  1737.             lpMIS->itemData = (ULONG_PTR)pTemp;
  1738.             lpMIS->itemID = pTemp->m_nID; 
  1739.             UINT nOrgWidth = lpMIS->itemWidth;
  1740.             MeasureItem_WinXP(lpMIS,bIsMenuBar);
  1741.             // Restore old values
  1742.             lpMIS->itemData = (ULONG_PTR)pMenuData;
  1743.             lpMIS->itemID = pMenuData->m_nID;
  1744.             lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
  1745.             break;
  1746.           }
  1747.         }
  1748.       }
  1749.       lpMIS->itemHeight = temp;
  1750.     } 
  1751.   }
  1752. }
  1753. void CNewMenu::SetIconSize (int width, int height)
  1754. {
  1755.   m_iconX = width;
  1756.   m_iconY = height;
  1757. }
  1758. BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText,UINT nFlags,UINT nID,int nIconNormal)
  1759. {
  1760.   // Add the MF_OWNERDRAW flag if not specified:
  1761.   if(!nID)
  1762.   {
  1763.     if(nFlags&MF_BYPOSITION)
  1764.       nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  1765.     else
  1766.       nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  1767.   }
  1768.   else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  1769.   
  1770.   if(nFlags & MF_POPUP)
  1771.   {
  1772.     m_AllSubMenus.Add(UIntToHMenu(nID));
  1773.     m_SubMenus.Add(UIntToHMenu(nID));
  1774.   }
  1775.   
  1776.   CNewMenuItemData *mdata = new CNewMenuItemData;
  1777.   m_MenuList.Add(mdata);
  1778.   mdata->SetString(lpstrText);
  1779.   
  1780.   mdata->m_nMenuIconNormal = nIconNormal;
  1781.   mdata->m_nxOffset=-1;
  1782.   if(nIconNormal>=0)
  1783.   {
  1784.     mdata->m_nxOffset=0;
  1785.     LoadFromToolBar(nID,nIconNormal,mdata->m_nxOffset);
  1786.     if(mdata->m_pBitmap)
  1787.       mdata->m_pBitmap->DeleteImageList();
  1788.     else
  1789.       mdata->m_pBitmap=new(CImageList);
  1790.     mdata->m_pBitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1791.     if(!AddBitmapToImageList(mdata->m_pBitmap,nIconNormal))
  1792.     {
  1793.       mdata->m_pBitmap->DeleteImageList();
  1794.       delete mdata->m_pBitmap;
  1795.       mdata->m_pBitmap=NULL;
  1796.       mdata->m_nMenuIconNormal = nIconNormal = -1;
  1797.       mdata->m_nxOffset = -1;
  1798.     }
  1799.   }
  1800.   mdata->m_nFlags = nFlags;
  1801.   mdata->m_nID = nID;
  1802.   return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
  1803. }
  1804. BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText,UINT nFlags,UINT nID,
  1805.                            CImageList *il,int xoffset)
  1806. {
  1807.   // Add the MF_OWNERDRAW flag if not specified:
  1808.   if(!nID)
  1809.   {
  1810.     if(nFlags&MF_BYPOSITION)
  1811.       nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  1812.     else 
  1813.       nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  1814.   }
  1815.   else if(!(nFlags & MF_OWNERDRAW))
  1816.     nFlags |= MF_OWNERDRAW;
  1817.   
  1818.   if(nFlags & MF_POPUP)
  1819.   {
  1820.     m_AllSubMenus.Add(UIntToHMenu(nID));
  1821.     m_SubMenus.Add(UIntToHMenu(nID));
  1822.   }
  1823.   CNewMenuItemData* mdata = new CNewMenuItemData;
  1824.   m_MenuList.Add(mdata);
  1825.   mdata->SetString(lpstrText);
  1826.   if(il)
  1827.   {
  1828.     mdata->m_nMenuIconNormal = 0;
  1829.     mdata->m_nxOffset=0;
  1830.     if(mdata->m_pBitmap)
  1831.       mdata->m_pBitmap->DeleteImageList();
  1832.     else 
  1833.       mdata->m_pBitmap=new(CImageList);
  1834.     
  1835.     ImageListDuplicate(il,xoffset,mdata->m_pBitmap);
  1836.   }
  1837.   else
  1838.   {
  1839.     mdata->m_nMenuIconNormal = -1;
  1840.     mdata->m_nxOffset = -1;
  1841.   }
  1842.   mdata->m_nFlags = nFlags;
  1843.   mdata->m_nID = nID;
  1844.   return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
  1845. }
  1846. BOOL CNewMenu::InsertODMenu(UINT nPosition,LPCTSTR lpstrText,UINT nFlags,UINT nID,
  1847.                            int nIconNormal)
  1848. {
  1849.   if(!(nFlags & MF_BYPOSITION))
  1850.   {
  1851.     int iPosition =0;
  1852.     CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
  1853.     if(pMenu)
  1854.     {
  1855.       return(pMenu->InsertODMenu(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
  1856.     }
  1857.     else 
  1858.       return(FALSE);
  1859.   }
  1860.   
  1861.   if(!nID)
  1862.     nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  1863.   else if(!(nFlags & MF_OWNERDRAW))
  1864.     nFlags |= MF_OWNERDRAW;
  1865.   
  1866.   if(nFlags & MF_POPUP)
  1867.   {
  1868.     m_AllSubMenus.Add(UIntToHMenu(nID));
  1869.     m_SubMenus.InsertAt(nPosition,UIntToHMenu(nID));
  1870.   }
  1871.   //Stephane Clog suggested adding this, believe it or not it's in the help 
  1872.   if(nPosition==(UINT)-1)
  1873.     nPosition=GetMenuItemCount();
  1874.   CNewMenuItemData *mdata = new CNewMenuItemData;
  1875.   m_MenuList.InsertAt(nPosition,mdata);
  1876.   mdata->SetString(lpstrText);
  1877.   
  1878.   mdata->m_nMenuIconNormal = nIconNormal;
  1879.   mdata->m_nxOffset=-1;
  1880.   if(nIconNormal>=0)
  1881.   {
  1882.     mdata->m_nxOffset=0;
  1883.     LoadFromToolBar(nID,nIconNormal,mdata->m_nxOffset);
  1884.     if(mdata->m_pBitmap)
  1885.       mdata->m_pBitmap->DeleteImageList();
  1886.     else
  1887.       mdata->m_pBitmap=new(CImageList);
  1888.     mdata->m_pBitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1889.     if(!AddBitmapToImageList(mdata->m_pBitmap,nIconNormal))
  1890.     {
  1891.       mdata->m_pBitmap->DeleteImageList();
  1892.       delete mdata->m_pBitmap;
  1893.       mdata->m_pBitmap=NULL;
  1894.       mdata->m_nMenuIconNormal = nIconNormal = -1;
  1895.       mdata->m_nxOffset = -1;
  1896.     }
  1897.   }
  1898.   mdata->m_nFlags = nFlags;
  1899.   mdata->m_nID = nID;
  1900.   return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
  1901. }
  1902. BOOL CNewMenu::InsertODMenu(UINT nPosition,LPCTSTR lpstrText,UINT nFlags,UINT nID,
  1903.                            CImageList *il,int xoffset)
  1904. {
  1905.   if(!(nFlags & MF_BYPOSITION))
  1906.   {
  1907.     int iPosition =0;
  1908.     CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
  1909.     if(pMenu)
  1910.     {
  1911.       return(pMenu->InsertODMenu(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
  1912.     }
  1913.     else 
  1914.       return(FALSE);
  1915.   }
  1916.   
  1917.   if(!nID)
  1918.     nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  1919.   else if(!(nFlags & MF_OWNERDRAW))
  1920.     nFlags |= MF_OWNERDRAW;
  1921.   
  1922.   if(nFlags & MF_POPUP)
  1923.   {
  1924.     m_AllSubMenus.Add(UIntToHMenu(nID));
  1925.     m_SubMenus.InsertAt(nPosition,UIntToHMenu(nID));
  1926.   }
  1927.   
  1928.   //Stephane Clog suggested adding this, believe it or not it's in the help 
  1929.   if(nPosition==(UINT)-1)
  1930.     nPosition=GetMenuItemCount();
  1931.   
  1932.   CNewMenuItemData *mdata = new CNewMenuItemData;
  1933.   m_MenuList.InsertAt(nPosition,mdata);
  1934.   mdata->SetString(lpstrText);
  1935.   if(il)
  1936.   {
  1937.     mdata->m_nMenuIconNormal = 0;
  1938.     mdata->m_nxOffset=0;
  1939.     if(mdata->m_pBitmap)
  1940.       mdata->m_pBitmap->DeleteImageList();
  1941.     else
  1942.       mdata->m_pBitmap=new(CImageList);
  1943.     ImageListDuplicate(il,xoffset,mdata->m_pBitmap);
  1944.   }
  1945.   else
  1946.   {
  1947.     mdata->m_nMenuIconNormal = -1;
  1948.     mdata->m_nxOffset = -1;
  1949.   }
  1950.   mdata->m_nFlags = nFlags;
  1951.   mdata->m_nID = nID;
  1952.   return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
  1953. }
  1954. BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText,UINT nID,int nIconNormal)
  1955. {
  1956.   int nLoc;
  1957.   CNewMenuItemData *mdata;
  1958.   CArray<CNewMenu*,CNewMenu*>newSubs;
  1959.   CArray<int,int&>newLocs;
  1960.   // Find the old CNewMenuItemData structure:
  1961.   CNewMenu *psubmenu = FindMenuOption(nID,nLoc);
  1962.   do {
  1963.     if(psubmenu && nLoc>=0)
  1964.       mdata = psubmenu->m_MenuList[nLoc];
  1965.     else
  1966.     {
  1967.       // Create a new CNewMenuItemData structure:
  1968.       mdata = new CNewMenuItemData;
  1969.       m_MenuList.Add(mdata);
  1970.     }
  1971.     ASSERT(mdata);
  1972.     if(lpstrText)
  1973.       mdata->SetString(lpstrText);
  1974.     mdata->m_nMenuIconNormal = nIconNormal;
  1975.     mdata->m_nxOffset=-1;
  1976.     if(nIconNormal>=0)
  1977.     {
  1978.       mdata->m_nxOffset=0;
  1979.       LoadFromToolBar(nID,nIconNormal,mdata->m_nxOffset);
  1980.       if(mdata->m_pBitmap)
  1981.         mdata->m_pBitmap->DeleteImageList();
  1982.       else
  1983.         mdata->m_pBitmap=new CImageList;
  1984.       mdata->m_pBitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1985.       if(!AddBitmapToImageList(mdata->m_pBitmap,nIconNormal))
  1986.       {
  1987.         mdata->m_pBitmap->DeleteImageList();
  1988.         delete mdata->m_pBitmap;
  1989.         mdata->m_pBitmap=NULL;
  1990.         mdata->m_nMenuIconNormal = nIconNormal = -1;
  1991.         mdata->m_nxOffset = -1;
  1992.       }
  1993.     }
  1994.     mdata->m_nFlags &= ~(MF_BYPOSITION);
  1995.     mdata->m_nFlags |= MF_OWNERDRAW;
  1996.     mdata->m_nID = nID;
  1997.     newSubs.Add(psubmenu);
  1998.     newLocs.Add(nLoc);
  1999.     if(psubmenu && nLoc>=0)
  2000.       psubmenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
  2001.     else 
  2002.       psubmenu=NULL;
  2003.   
  2004.   }while(psubmenu);
  2005.   return (CMenu::ModifyMenu(nID,mdata->m_nFlags,nID,(LPCTSTR)mdata));
  2006. }
  2007. BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText,UINT nID,CImageList *pil,int xoffset)
  2008. {
  2009.   int nLoc;
  2010.   CNewMenuItemData *mdata;
  2011.   CArray<CNewMenu*,CNewMenu*>newSubs;
  2012.   CArray<int,int&>newLocs;
  2013.   
  2014.   // Find the old CNewMenuItemData structure:
  2015.   CNewMenu *psubmenu = FindMenuOption(nID,nLoc);
  2016.   do {
  2017.     if(psubmenu && nLoc>=0)
  2018.     {
  2019.       mdata = psubmenu->m_MenuList[nLoc];
  2020.     }
  2021.     else
  2022.     {
  2023.       // Create a new CNewMenuItemData structure:
  2024.       mdata = new CNewMenuItemData;
  2025.       m_MenuList.Add(mdata);
  2026.     }
  2027.     ASSERT(mdata);
  2028.     if(lpstrText)
  2029.     {
  2030.       mdata->SetString(lpstrText);
  2031.     }
  2032.     if(pil)
  2033.     {
  2034.       mdata->m_nMenuIconNormal = 0;
  2035.       mdata->m_nxOffset=0;
  2036.       if(mdata->m_pBitmap)
  2037.         mdata->m_pBitmap->DeleteImageList();
  2038.       else 
  2039.         mdata->m_pBitmap=new(CImageList);
  2040.       ImageListDuplicate(pil,xoffset,mdata->m_pBitmap);
  2041.       int x=0;
  2042.       int y=0;
  2043.       if(psubmenu && ImageList_GetIconSize(pil->m_hImageList,&x,&y))
  2044.       {
  2045.         // Correct the size of the menuitem
  2046.         psubmenu->m_iconX = max(psubmenu->m_iconX,x);
  2047.         psubmenu->m_iconY = max(psubmenu->m_iconY,y);
  2048.       }
  2049.     }
  2050.     else
  2051.     {
  2052.       mdata->m_nMenuIconNormal = -1;
  2053.       mdata->m_nxOffset = -1;
  2054.     }
  2055.     mdata->m_nFlags &= ~(MF_BYPOSITION);
  2056.     mdata->m_nFlags |= MF_OWNERDRAW;
  2057.     mdata->m_nID = nID;
  2058.     newSubs.Add(psubmenu);
  2059.     newLocs.Add(nLoc);
  2060.     if(psubmenu && nLoc>=0)
  2061.       psubmenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
  2062.     else 
  2063.       psubmenu=NULL;
  2064.   } while(psubmenu);
  2065.   return (CMenu::ModifyMenu(nID,mdata->m_nFlags,nID,(LPCTSTR)mdata));
  2066. }
  2067. BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText,UINT nID,CBitmap *bmp)
  2068. {
  2069.   if (bmp)
  2070.   {
  2071.     CImageList temp;
  2072.     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2073.     
  2074.     temp.Add(bmp,GetBitmapBackground());
  2075.     return ModifyODMenu(lpstrText,nID,&temp,0);
  2076.   }
  2077.   return ModifyODMenu(lpstrText,nID,NULL,0);
  2078. }
  2079. BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle)
  2080. {
  2081.   // Get device context
  2082.   CClientDC DC(0);
  2083.   CSize bitmap_size(m_iconX,m_iconY);
  2084.   CBitmap bmp;
  2085.   ColorBitmap(&DC,bmp,bitmap_size,fill,border,hatchstyle);  
  2086.   return ModifyODMenu(lpstrText,nID,&bmp);
  2087. }
  2088. BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText,LPCTSTR OptionText, int nIconNormal)
  2089. {
  2090.   int nIndex = 0;
  2091.   CNewMenu* pOptionMenu = FindMenuOption(OptionText,nIndex);
  2092.   if(pOptionMenu!=NULL && nIndex>=0)
  2093.   {
  2094.     CNewMenuItemData* pmdata = pOptionMenu->m_MenuList[nIndex];
  2095.     if(lpstrText)
  2096.     {
  2097.       pmdata->SetString(lpstrText);
  2098.     }
  2099.     pmdata->m_nMenuIconNormal = nIconNormal;
  2100.     pmdata->m_nxOffset=-1;
  2101.     if(nIconNormal>=0)
  2102.     {
  2103.       pmdata->m_nxOffset=0;
  2104.       if(pmdata->m_pBitmap)
  2105.         pmdata->m_pBitmap->DeleteImageList();
  2106.       else
  2107.         pmdata->m_pBitmap=new(CImageList);
  2108.       if (!m_bDynIcons)
  2109.       {
  2110.         CBitmap temp;
  2111.         // Try to load the bitmap for getting dimension
  2112.         if(temp.LoadBitmap(nIconNormal))
  2113.         {
  2114.           BITMAP bitmap;
  2115.           ZeroMemory(&bitmap,sizeof(bitmap));
  2116.           if(temp.GetBitmap(&bitmap))
  2117.           {
  2118.             pOptionMenu->m_iconX = max(pOptionMenu->m_iconX,bitmap.bmWidth);
  2119.             pOptionMenu->m_iconY = max(pOptionMenu->m_iconY,bitmap.bmHeight);
  2120.           }
  2121.         }
  2122.       }
  2123.       pmdata->m_pBitmap->Create(pOptionMenu->m_iconX,pOptionMenu->m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2124.       if(!AddBitmapToImageList(pmdata->m_pBitmap,nIconNormal))
  2125.       {
  2126.         pmdata->m_pBitmap->DeleteImageList();
  2127.         delete pmdata->m_pBitmap;
  2128.         pmdata->m_pBitmap=NULL;
  2129.         pmdata->m_nMenuIconNormal = nIconNormal = -1;
  2130.         pmdata->m_nxOffset = -1;
  2131.       }
  2132.     }
  2133.     return TRUE;
  2134.   }
  2135.   return FALSE;
  2136. }
  2137. CNewMenuItemData* CNewMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,LPCTSTR string)
  2138. {
  2139.   CNewMenuItemData* mdata;
  2140.   mdata = new CNewMenuItemData;
  2141.   mdata->m_nMenuIconNormal = -1;
  2142.   mdata->m_nxOffset=-1;
  2143.   mdata->m_nFlags = nFlags;
  2144.   mdata->m_nID = nID;
  2145.   mdata->SetString (string);
  2146.   //  if(nFlags & MF_POPUP)m_AllSubMenus.Add(UIntToHMenu(nID));
  2147.   if (nFlags&MF_OWNERDRAW)
  2148.   {
  2149.     ASSERT(!(nFlags&MF_STRING));
  2150.     ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
  2151.   }
  2152.   else if (nFlags&MF_BITMAP)
  2153.   {
  2154.     ModifyMenu(pos,nFlags,nID,(CBitmap*)string);
  2155.   }
  2156.   else if (nFlags&MF_SEPARATOR)
  2157.   {
  2158.     ASSERT(nFlags&MF_SEPARATOR);
  2159.     ModifyMenu(pos,nFlags,nID);
  2160.   }
  2161.   else // (nFlags&MF_STRING)
  2162.   {
  2163.     ASSERT(!(nFlags&MF_OWNERDRAW));
  2164.     ModifyMenu(pos,nFlags,nID,mdata->GetString());
  2165.   }
  2166.   
  2167.   return(mdata);
  2168. };
  2169. BOOL CNewMenu::LoadToolBars(const UINT* arID, int n)
  2170. {
  2171.   ASSERT(arID);
  2172.   BOOL returnflag=TRUE;
  2173.   for(int i=0;i<n;++i)
  2174.   {
  2175.     if(!LoadToolBar(arID[i]))
  2176.       returnflag=FALSE;
  2177.   }
  2178.   return(returnflag);
  2179. }
  2180. struct CToolBarData
  2181. {
  2182.   WORD wVersion;
  2183.   WORD wWidth;
  2184.   WORD wHeight;
  2185.   WORD wItemCount;
  2186.   //WORD aItems[wItemCount]
  2187.   WORD* items()
  2188.     { return (WORD*)(this+1); }
  2189. };
  2190. BOOL CNewMenu::LoadToolBar(LPCTSTR lpszResourceName)
  2191. {
  2192.   ASSERT_VALID(this);
  2193.   ASSERT(lpszResourceName != NULL);
  2194.   // determine location of the bitmap in resource
  2195.   HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_TOOLBAR);
  2196.   HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);
  2197.   if (hRsrc == NULL)
  2198.     return FALSE;
  2199.   HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
  2200.   if (hGlobal == NULL)
  2201.     return FALSE;
  2202.   CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
  2203.   if (pData == NULL)
  2204.     return FALSE;
  2205.   ASSERT(pData->wVersion == 1);
  2206.   CImageList myImageList;
  2207.   myImageList.Create(pData->wWidth,pData->wHeight,ILC_COLORDDB|ILC_MASK,0,10);
  2208.   // load bitmap now that sizes are known by the toolbar control
  2209.   BOOL bResult = AddBitmapToImageList(&myImageList,(UINT)(UINT_PTR)lpszResourceName);
  2210.   
  2211.   if (bResult)
  2212.   {
  2213.     m_iconX = max(pData->wWidth,m_iconX);
  2214.     m_iconY = max(pData->wHeight,m_iconY);
  2215.     int xoffset=0;
  2216.     for (int i = 0; i < pData->wItemCount; i++)
  2217.     { 
  2218.       UINT nID = pData->items()[i];
  2219.       if (nID)
  2220.       {
  2221.         ModifyODMenu(NULL,nID,&myImageList,xoffset++);
  2222.       }
  2223.     }
  2224.   }
  2225.   UnlockResource(hGlobal);
  2226.   FreeResource(hGlobal);
  2227.   return bResult;
  2228. }
  2229. struct SToolInfo
  2230. {
  2231.   WORD wBitmapID;
  2232.   WORD wWidth;
  2233.   WORD wHeight;
  2234.   WORD* ids(){ return (WORD*)(this+1); }
  2235. };
  2236. BOOL CNewMenu::LoadToolBar(WORD* pToolInfo, COLORREF crTransparent)
  2237. {
  2238.   COLORREF oldColor = m_bitmapBackground;
  2239.   if(crTransparent!=CLR_NONE)
  2240.   { 
  2241.     oldColor = SetBitmapBackground(crTransparent);
  2242.   }  
  2243.   SToolInfo* pInfo = (SToolInfo*)pToolInfo; 
  2244.   CImageList myImageList;
  2245.   myImageList.Create(pInfo->wWidth,pInfo->wHeight,ILC_COLORDDB|ILC_MASK,0,10);
  2246.   // load bitmap now that sizes are known by the toolbar control
  2247.   BOOL bResult = AddBitmapToImageList(&myImageList,pInfo->wBitmapID);
  2248.   
  2249.   if (bResult)
  2250.   {
  2251.     WORD* pID = pInfo->ids();
  2252.     int nIndex=0;
  2253.     while(*pID)
  2254.     {
  2255.       ModifyODMenu(NULL,*pID++,&myImageList,nIndex++);
  2256.     }
  2257.   }
  2258.   SetBitmapBackground(oldColor);
  2259.   return bResult;
  2260. }
  2261. BOOL CNewMenu::LoadToolBar(UINT nToolBar)
  2262. {
  2263.   return LoadToolBar((LPCTSTR)(UINT_PTR)nToolBar);
  2264. }
  2265. BOOL CNewMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
  2266. {
  2267.   int xset,offset;
  2268.   UINT nStyle;
  2269.   BOOL returnflag=FALSE;
  2270.   CToolBar bar;
  2271.   CWnd* pWnd = AfxGetMainWnd();
  2272.   if (pWnd == NULL)
  2273.   {
  2274.     pWnd = CWnd::GetDesktopWindow();
  2275.   }
  2276.   bar.Create(pWnd);
  2277.   if(bar.LoadToolBar(nToolBar))
  2278.   {
  2279.     offset=bar.CommandToIndex(nID);
  2280.     if(offset>=0)
  2281.     {
  2282.       bar.GetButtonInfo(offset,nID,nStyle,xset);
  2283.       if(xset>0)
  2284.         xoffset=xset;
  2285.       returnflag=TRUE;
  2286.     }
  2287.   }
  2288.   return returnflag;
  2289. }
  2290. // O.S.
  2291. CNewMenuItemData* CNewMenu::FindMenuItem(UINT nID)
  2292. {
  2293.   CNewMenuItemData *pData = NULL;
  2294.   int i;
  2295.   
  2296.   for(i = 0; i <= m_MenuList.GetUpperBound(); i++)
  2297.   {
  2298.     if (m_MenuList[i]->m_nID == nID)
  2299.     {
  2300.       pData = m_MenuList[i];
  2301.       break;
  2302.     }
  2303.   }
  2304.   if (!pData)
  2305.   {
  2306.     int loc;
  2307.     CNewMenu *pMenu = FindMenuOption(nID, loc);
  2308.     ASSERT(pMenu != this);
  2309.     if (loc >= 0)
  2310.     {
  2311.       return pMenu->FindMenuItem(nID);
  2312.     }
  2313.   }
  2314.   return pData;
  2315. }
  2316. CNewMenu* CNewMenu::FindAnotherMenuOption(int nId,int& nLoc,
  2317.                                           CArray<CNewMenu*,CNewMenu*>&newSubs,
  2318.                                           CArray<int,int&>&newLocs)
  2319. {
  2320.   int i,numsubs,j;
  2321.   CNewMenu *psubmenu,*pgoodmenu;
  2322.   BOOL foundflag;
  2323.   
  2324.   for(i=0;i<(int)(GetMenuItemCount());++i)
  2325.   {
  2326.     psubmenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
  2327.     if(psubmenu)
  2328.     {
  2329.       pgoodmenu=psubmenu->FindAnotherMenuOption(nId,nLoc,newSubs,newLocs);
  2330.       if(pgoodmenu)
  2331.         return(pgoodmenu);
  2332.     }
  2333.     else if(nId==(int)GetMenuItemID(i))
  2334.     {
  2335.       numsubs = (int)newSubs.GetSize();
  2336.       foundflag=TRUE;
  2337.       for(j=0;j<numsubs;++j)
  2338.       {
  2339.         if(newSubs[j]==this&&newLocs[j]==i)
  2340.         {
  2341.           foundflag=FALSE;
  2342.           break;
  2343.         }
  2344.       }
  2345.       if(foundflag)
  2346.       {
  2347.         nLoc=i;
  2348.         return(this);
  2349.       }
  2350.     }
  2351.   }
  2352.   nLoc = -1;
  2353.   return(NULL);
  2354. }
  2355. CNewMenu* CNewMenu::FindMenuOption(int nId, int& nLoc)
  2356. {
  2357.   int i;
  2358.   CNewMenu *psubmenu,*pgoodmenu;
  2359.   
  2360.   for(i=0;i<(int)(GetMenuItemCount());++i)
  2361.   {
  2362.     psubmenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
  2363.     if(psubmenu)
  2364.     {
  2365.       pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
  2366.       if(pgoodmenu)
  2367.         return(pgoodmenu);
  2368.     }
  2369.     else if(nId==(int)GetMenuItemID(i))
  2370.     {
  2371.       nLoc=i;
  2372.       return(this);
  2373.     }
  2374.   }
  2375.   nLoc = -1;
  2376.   return NULL;
  2377. }
  2378. CNewMenu* CNewMenu::FindMenuOption(LPCTSTR lpstrText, int& nLoc)
  2379.   int i;
  2380.   // First look for all item text.
  2381.   for(i=0;i<=(int)m_MenuList.GetUpperBound();++i)
  2382.   {  
  2383.     if(m_MenuList[i]->m_szMenuText.Compare(lpstrText)==NULL)
  2384.     {
  2385.       nLoc = i;
  2386.       return this;
  2387.     }
  2388.   }
  2389.   CNewMenu* psubmenu;
  2390.   // next, look in all submenus
  2391.   for(i=0; i<(int)(GetMenuItemCount());++i)
  2392.   {
  2393.     psubmenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
  2394.     if(psubmenu)
  2395.     {
  2396.       psubmenu = psubmenu->FindMenuOption(lpstrText,nLoc);
  2397.       if(psubmenu)
  2398.       {
  2399.         return psubmenu;
  2400.       }
  2401.     }
  2402.   }
  2403.   nLoc = -1;
  2404.   return NULL;
  2405. BOOL CNewMenu::LoadMenu(HMENU hMenu)
  2406. {
  2407.   if(!::IsMenu(hMenu) || !Attach(hMenu))
  2408.   {
  2409.     return FALSE;
  2410.   } 
  2411.   for(int i=0;i<(int)(GetMenuItemCount());++i)
  2412.   { 
  2413.     HMENU hSubMenu = ::GetSubMenu(m_hMenu,i);
  2414.     if(hSubMenu)
  2415.     {
  2416.       CNewMenu* pMenu = new CNewMenu(m_hMenu);
  2417.       m_SubMenus.Add(hSubMenu);
  2418.       pMenu->LoadMenu(hSubMenu); 
  2419.     }
  2420.   }  
  2421.   SynchronizeMenu();
  2422.   return TRUE;
  2423. }
  2424. BOOL CNewMenu::LoadMenu(int nResource)
  2425. {
  2426.   return(CNewMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
  2427. }
  2428. BOOL CNewMenu::LoadMenu(LPCTSTR lpszResourceName)
  2429. {
  2430.   ASSERT_VALID(this);
  2431.   ASSERT(lpszResourceName != NULL);
  2432.   
  2433.   // Find the Menu Resource:
  2434.   HINSTANCE m_hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
  2435.   HRSRC hRsrc = ::FindResource(m_hInst,lpszResourceName,RT_MENU);
  2436.   if(hRsrc == NULL)
  2437.     return FALSE;
  2438.   
  2439.   // Load the Menu Resource:
  2440.   HGLOBAL hGlobal = LoadResource(m_hInst, hRsrc);
  2441.   if(hGlobal == NULL)
  2442.     return FALSE;
  2443.   
  2444.   // Attempt to create us as a menu...  
  2445.   if(!CMenu::CreateMenu())
  2446.     return FALSE;
  2447.   // Get Item template Header, and calculate offset of MENUITEMTEMPLATES
  2448.   MENUITEMTEMPLATEHEADER* pTpHdr= (MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
  2449.   BYTE* pTp=(BYTE*)pTpHdr +  (sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
  2450.   
  2451.   MENUITEMTEMPLATE* pTemplate = (MENUITEMTEMPLATE*)pTp;
  2452.   // Variables needed during processing of Menu Item Templates:
  2453.   
  2454.   // ID of the Menu Item
  2455.   WORD dwID  = 0;
  2456.   CString  szCaption;
  2457.   // Popup menu stack
  2458.   CTypedPtrArray<CPtrArray, CNewMenu*>  m_Stack;
  2459.   // Popup menu stack
  2460.   CArray<BOOL,BOOL>  m_StackEnd;
  2461.   // Add it to this...
  2462.   m_Stack.Add(this);
  2463.   m_StackEnd.Add(FALSE);
  2464.   
  2465.   do{
  2466.     WORD wFlags = pTemplate->mtOption; 
  2467.     // Obtain Flags and (if necessary), the ID...
  2468.     if(!(wFlags & MF_POPUP))
  2469.     {
  2470.       dwID = pTemplate->mtID;
  2471.       #ifdef UNICODE
  2472.         szCaption = pTemplate->mtString;
  2473.       #else
  2474.         szCaption.Format("%S",pTemplate->mtString);
  2475.       #endif 
  2476.           
  2477.       pTemplate = (MENUITEMTEMPLATE*)(DWORD_PTR)((DWORD)(DWORD_PTR)(pTemplate+1) +
  2478.                                       wcslen(pTemplate->mtString)*sizeof(wchar_t));
  2479.     }
  2480.     else
  2481.     {
  2482.       dwID = 0;
  2483.       #ifdef UNICODE
  2484.         szCaption = (wchar_t*)&pTemplate->mtID;
  2485.       #else
  2486.         szCaption.Format("%S",(wchar_t*)&pTemplate->mtID);
  2487.       #endif 
  2488.           
  2489.       pTemplate = (MENUITEMTEMPLATE*)(DWORD_PTR)((DWORD)(DWORD_PTR)(pTemplate+1) +
  2490.                                       wcslen(pTemplate->mtString)*sizeof(wchar_t));
  2491.     }
  2492.     // Handle popup menus first....
  2493.     if(wFlags & MF_POPUP)
  2494.     {
  2495.       if(wFlags & MF_END)
  2496.       {
  2497.         m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  2498.         wFlags &= ~MF_END;
  2499.       }
  2500.       CNewMenu* pParent = m_Stack[m_Stack.GetUpperBound()];
  2501.       CNewMenu* pSubMenu = new CNewMenu(pParent->m_hMenu);
  2502.       pSubMenu->m_unselectcheck=m_unselectcheck;
  2503.       pSubMenu->m_selectcheck=m_selectcheck;
  2504.       pSubMenu->checkmaps=checkmaps;
  2505.       pSubMenu->checkmapsshare=TRUE;
  2506.       pSubMenu->CreatePopupMenu();
  2507.       // Append it to the top of the stack:
  2508.       pParent->AppendODMenu(szCaption,wFlags,HMenuToUInt(pSubMenu->m_hMenu), -1);
  2509.       m_Stack.Add(pSubMenu);
  2510.       m_StackEnd.Add(FALSE);
  2511.     }
  2512.     else
  2513.     {
  2514.       m_Stack[m_Stack.GetUpperBound()]->AppendODMenu(szCaption,wFlags&~MF_END,dwID,-1);
  2515.       if(wFlags & MF_END)
  2516.         m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  2517.       for(int j=(int)m_Stack.GetUpperBound(); j>=0 && m_StackEnd.GetAt(j) ; --j)
  2518.       {
  2519.         m_Stack.RemoveAt(j);
  2520.         m_StackEnd.RemoveAt(j);
  2521.       }
  2522.     }
  2523.   }
  2524.   while(m_Stack.GetUpperBound() != -1);
  2525.   return(TRUE);
  2526. }
  2527. void CNewMenu::LoadCheckmarkBitmap(int unselect, int select)
  2528. {
  2529.   if(unselect>0 && select>0)
  2530.   {
  2531.     m_selectcheck=select;
  2532.     m_unselectcheck=unselect;
  2533.     if(checkmaps)
  2534.       checkmaps->DeleteImageList();
  2535.     else
  2536.       checkmaps=new(CImageList);
  2537.     checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
  2538.     BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
  2539.     BOOL flag2=AddBitmapToImageList(checkmaps,select);
  2540.     if(!flag1||!flag2)
  2541.     {
  2542.       checkmaps->DeleteImageList();
  2543.       delete checkmaps;
  2544.       checkmaps=NULL;
  2545.     }
  2546.   }
  2547. }
  2548. BOOL CNewMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
  2549. {
  2550.   BOOL returnflag=FALSE;
  2551.   if(MF_BYPOSITION&nFlags)
  2552.   {
  2553.     UINT numMenuItems = (int)m_MenuList.GetUpperBound();
  2554.     if(id<=numMenuItems)
  2555.     {
  2556.       string=m_MenuList[id]->GetString();
  2557.       returnflag=TRUE;
  2558.     }
  2559.   }
  2560.   else
  2561.   {
  2562.     int uiLoc;
  2563.     CNewMenu* pMenu = FindMenuOption(id,uiLoc);
  2564.     if(NULL!=pMenu)
  2565.     {
  2566.       returnflag = pMenu->GetMenuText(uiLoc,string);
  2567.     }
  2568.   }
  2569.   return returnflag;
  2570. }
  2571. CNewMenuItemData *CNewMenu::FindMenuList(UINT nID)
  2572. {
  2573.   for(int i=0;i<=m_MenuList.GetUpperBound();++i)
  2574.   {
  2575.     if(m_MenuList[i]->m_nID==nID && !m_MenuList[i]->m_nSyncFlag)
  2576.     {
  2577.       m_MenuList[i]->m_nSyncFlag=1;
  2578.       return(m_MenuList[i]);
  2579.     }
  2580.   }
  2581.   return(NULL);
  2582. }
  2583. void CNewMenu::InitializeMenuList(int value)
  2584. {
  2585.   for(int i=0;i<=m_MenuList.GetUpperBound();++i)
  2586.   {
  2587.     m_MenuList[i]->m_nSyncFlag=value;
  2588.   }
  2589. }
  2590. void CNewMenu::DeleteMenuList()
  2591. {
  2592.   for(int i=0;i<=m_MenuList.GetUpperBound();++i)
  2593.   {
  2594.     if(!m_MenuList[i]->m_nSyncFlag)
  2595.     {
  2596.       delete m_MenuList[i];
  2597.     }
  2598.   }
  2599. }
  2600. void CNewMenu::SynchronizeMenu()
  2601. {
  2602.   CTypedPtrArray<CPtrArray, CNewMenuItemData*> temp;
  2603.   CNewMenuItemData *mdata;
  2604.   CString string;
  2605.   UINT submenu,nID=0,state,j;
  2606.   InitializeMenuList(0);
  2607.   for(j=0;j<GetMenuItemCount();++j)
  2608.   {
  2609.     mdata=NULL;
  2610.     state=GetMenuState(j,MF_BYPOSITION);
  2611.     if(state&MF_POPUP)
  2612.     {
  2613.       submenu=HMenuToUInt(GetSubMenu(j)->m_hMenu);
  2614.       mdata=FindMenuList(submenu);
  2615.       GetMenuString(j,string,MF_BYPOSITION);
  2616.       if(!mdata)
  2617.       {
  2618.         mdata=NewODMenu(j,(state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
  2619.       }
  2620.       else if(!string.IsEmpty ())
  2621.       { 
  2622.         mdata->SetString(string);  
  2623.       }
  2624.     }
  2625.     else if(state&MF_SEPARATOR)
  2626.     {
  2627.       mdata=FindMenuList(0);
  2628.       if(!mdata)
  2629.         mdata=NewODMenu(j,state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));
  2630.       else 
  2631.         ModifyMenu(j,mdata->m_nFlags,nID,(LPCTSTR)mdata);
  2632.     }
  2633.     else
  2634.     {
  2635.       nID=GetMenuItemID(j);
  2636.       mdata=FindMenuList(nID);
  2637.       GetMenuString(j,string,MF_BYPOSITION);
  2638.       
  2639.       if(!mdata)
  2640.       {
  2641.         mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,nID,string);
  2642.       }
  2643.       else
  2644.       {
  2645.         mdata->m_nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
  2646.         if(string.GetLength()>0)
  2647.         {
  2648.           mdata->SetString(string);
  2649.         }
  2650.         ModifyMenu(j,mdata->m_nFlags,nID,(LPCTSTR)mdata);
  2651.       }
  2652.     }
  2653.     if(mdata)
  2654.       temp.Add(mdata);
  2655.   }
  2656.   DeleteMenuList();
  2657.   m_MenuList.RemoveAll();
  2658.   m_MenuList.Append(temp);
  2659.   temp.RemoveAll(); 
  2660. }
  2661. void CNewMenu::OnInitMenuPopup(HWND hWnd, CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
  2662. {
  2663.   UNREFERENCED_PARAMETER(nIndex);
  2664.   UNREFERENCED_PARAMETER(bSysMenu);
  2665. #ifdef _TRACE_MENU_
  2666.   TRACE(_T("InitMenuPopup: 0x%lx from Wnd 0x%lxn"),HMenuToUInt(pPopupMenu->m_hMenu),HWndToUInt(hWnd));
  2667. #endif
  2668.   CNewMenuHook::m_hLastMenu = pPopupMenu->m_hMenu;
  2669.   if(pPopupMenu->m_hMenu)
  2670.   {
  2671.     CNewMenu* pSubmenu = DYNAMIC_DOWNCAST(CNewMenu,pPopupMenu);
  2672.     if(pSubmenu)
  2673.     {
  2674.       pSubmenu->OnInitMenuPopup();
  2675.       HMENU hMenu = pSubmenu->GetParent();
  2676.       CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
  2677.       if(pParent)
  2678.       {
  2679.         pParent->m_dwOpenMenu += 1;
  2680.         if(pParent->m_dwOpenMenu==1 && !pParent->m_bIsPopupMenu)
  2681.         {
  2682.           // Redraw the menubar for the shade
  2683.           DrawMenuBar(hWnd);
  2684.         }
  2685.       }
  2686.     }
  2687.   }
  2688. }
  2689. BOOL CNewMenu::Replace(UINT nID,UINT nNewID)
  2690. {
  2691.   int nLoc=0;
  2692.   CNewMenu* pTempMenu = FindMenuOption(nID,nLoc);
  2693.   if(pTempMenu && nLoc >= 0)
  2694.   {
  2695.     CNewMenuItemData* pData = pTempMenu->m_MenuList[nLoc];
  2696.     UINT nFlags = pData->m_nFlags|MF_OWNERDRAW|MF_BYPOSITION;
  2697.     pData->m_nID = nNewID;
  2698.     pTempMenu->ModifyMenu(nLoc,nFlags,nNewID,(LPCTSTR)pData);
  2699.     return TRUE;
  2700.   }
  2701.   return FALSE;
  2702. }
  2703. void CNewMenu::OnInitMenuPopup()
  2704. {
  2705.   m_bIsPopupMenu = true;
  2706.   SynchronizeMenu();
  2707.   // Special purpose for windows XP with themes!!!
  2708.   Replace(SC_RESTORE,SC_RESTORE+1);
  2709.   Replace(SC_CLOSE,SC_CLOSE+1);
  2710.   Replace(SC_MINIMIZE,SC_MINIMIZE+1);
  2711. }
  2712. BOOL CNewMenu::OnUnInitPopupMenu()
  2713. {
  2714.   // Special purpose for windows XP with themes!!!
  2715.   // Restore old values otherwise you have disabled windowbuttons
  2716.   Replace(SC_RESTORE+1,SC_RESTORE);
  2717.   Replace(SC_CLOSE+1,SC_CLOSE);
  2718.   Replace(SC_MINIMIZE+1,SC_MINIMIZE);
  2719.   HMENU hMenu = GetParent();
  2720.   CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
  2721.   if(pParent)
  2722.   {
  2723.     pParent->m_dwOpenMenu -= 1;
  2724.     if(pParent->m_dwOpenMenu==NULL && !pParent->m_bIsPopupMenu)
  2725.     {
  2726.       return TRUE;
  2727.     }
  2728.   }
  2729.   return FALSE;
  2730. }
  2731. LRESULT CNewMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags, CMenu *pMenu)
  2732. {
  2733.   UNREFERENCED_PARAMETER(nFlags);
  2734.   CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,pMenu);
  2735.   if(pNewMenu)
  2736.   {
  2737.     //SK: modified for Unicode correctness
  2738.     CString key(_T('&'),2);
  2739.     key.SetAt(1,(TCHAR)nChar);
  2740.     key.MakeLower();
  2741.     CString menutext;
  2742.     int menusize = (int)pNewMenu->GetMenuItemCount();
  2743.     if(menusize!=(pNewMenu->m_MenuList.GetUpperBound()+1))
  2744.     {
  2745.       pNewMenu->SynchronizeMenu();
  2746.     }
  2747.     for(int i=0;i<menusize;++i)
  2748.     {
  2749.       if(pNewMenu->GetMenuText(i,menutext))
  2750.       {
  2751.         menutext.MakeLower();
  2752.         if(menutext.Find(key)>=0)
  2753.         {
  2754.           return(MAKELRESULT(i,2));
  2755.         }
  2756.       }
  2757.     }
  2758.   }
  2759.   return NULL;
  2760. }
  2761. BOOL CNewMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
  2762. {
  2763.   // O.S.
  2764.   if (m_bDynIcons)
  2765.   {
  2766.     bmplist->Add((HICON)(UINT_PTR)nResourceID);
  2767.     return TRUE;
  2768.   }
  2769.   CBitmap mybmp;
  2770.   HBITMAP hbmp = LoadSysColorBitmap(nResourceID);
  2771.   if(hbmp)
  2772.   {
  2773.     // Object will be destroyd by destructor of CBitmap
  2774.     mybmp.Attach(hbmp);
  2775.   }
  2776.   else
  2777.   {  
  2778.     mybmp.LoadBitmap(nResourceID);
  2779.   }
  2780.   if (mybmp.m_hObject && bmplist->Add(&mybmp,GetBitmapBackground())>=0 )
  2781.   {
  2782.     return TRUE;
  2783.   }
  2784.   return FALSE;
  2785. }
  2786. COLORREF CNewMenu::SetBitmapBackground(COLORREF newColor)
  2787. {
  2788.   COLORREF oldColor = m_bitmapBackground;
  2789.   m_bitmapBackground = newColor;
  2790.   return oldColor;
  2791. }
  2792. COLORREF CNewMenu::GetBitmapBackground()
  2793. {
  2794.   if(m_bitmapBackground==CLR_DEFAULT)
  2795.     return GetSysColor(COLOR_3DFACE);
  2796.   return m_bitmapBackground;
  2797. }
  2798. // Given a toolbar, append all the options from it to this menu
  2799. // Passed a ptr to the toolbar object and the toolbar ID
  2800. // Author : Robert Edward Caldecott
  2801. void CNewMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
  2802. {
  2803.   for (int i = 0; i < pToolBar->GetCount(); i++) 
  2804.   {
  2805.     UINT nID = pToolBar->GetItemID(i);
  2806.     // See if this toolbar option
  2807.     // appears as a command on this
  2808.     // menu or is a separator
  2809.     if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
  2810.       continue; // Item doesn't exist
  2811.     UINT nStyle;
  2812.     int nImage;
  2813.     // Get the toolbar button info
  2814.     pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
  2815.     // OK, we have the command ID of the toolbar
  2816.     // option, and the tollbar bitmap offset
  2817.     int nLoc;
  2818.     CNewMenuItemData* pData;
  2819.     CNewMenu *pSubMenu = FindMenuOption(nID, nLoc);
  2820.     if (pSubMenu && nLoc >= 0)
  2821.     {
  2822.       pData = pSubMenu->m_MenuList[nLoc];
  2823.     }
  2824.     else 
  2825.     {
  2826.       // Create a new CNewMenuItemData structure
  2827.       pData = new CNewMenuItemData;
  2828.       m_MenuList.Add(pData);
  2829.     }
  2830.     // Set some default structure members
  2831.     pData->m_nMenuIconNormal = nResourceID;
  2832.     pData->m_nID = nID;
  2833.     pData->m_nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
  2834.     pData->m_nxOffset = nImage;
  2835.     if (pData->m_pBitmap)
  2836.       pData->m_pBitmap->DeleteImageList();
  2837.     else
  2838.       pData->m_pBitmap = new CImageList;
  2839.     pData->m_pBitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
  2840.     if(!AddBitmapToImageList(pData->m_pBitmap, nResourceID))
  2841.     {
  2842.       pData->m_pBitmap->DeleteImageList();
  2843.       delete pData->m_pBitmap;
  2844.       pData->m_pBitmap=NULL;
  2845.       pData->m_nMenuIconNormal = -1;
  2846.       pData->m_nxOffset = -1;
  2847.     }    
  2848.     // Modify our menu
  2849.     ModifyMenu(nID,pData->m_nFlags,nID,(LPCTSTR)pData);
  2850.   }
  2851. }
  2852. BOOL CNewMenu::Draw3DCheckmark(CDC *pDC, const CRect& rc, HBITMAP hbmCheck, DWORD dwStyle)
  2853. {
  2854.   CRect rect(rc);
  2855.   rect.InflateRect (-1,-1);
  2856.   if (IsNewShell()) //SK: looks better on the old shell
  2857.     pDC->DrawEdge(rect, BDR_SUNKENOUTER, BF_RECT);
  2858.   rect.InflateRect (2,2);
  2859.   if (!hbmCheck)
  2860.   {
  2861.     // Checkmark
  2862.     rect.OffsetRect(1,2);
  2863.     DrawSpecialCharStyle(pDC,rect,98,dwStyle);
  2864.   }
  2865.   else
  2866.   {
  2867.     // Bullet
  2868.     DrawSpecialCharStyle(pDC,rect,105,dwStyle);
  2869.   }
  2870.   return TRUE;
  2871. }
  2872. WORD CNewMenu::NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
  2873. {
  2874.   if ( lpBitmap->biClrUsed != 0)
  2875.     return (WORD)lpBitmap->biClrUsed;
  2876.   
  2877.   switch (lpBitmap->biBitCount)
  2878.   {
  2879.   case 1:
  2880.     return 2;
  2881.   case 4:
  2882.     return 16;
  2883.   case 8:
  2884.     return 256;
  2885.   }
  2886.   return 0;
  2887. }
  2888. HBITMAP CNewMenu::LoadSysColorBitmap(int nResourceId)
  2889. {
  2890.   HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  2891.   HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  2892.   if (hRsrc == NULL)
  2893.     return NULL;
  2894.   // determine how many colors in the bitmap
  2895.   HGLOBAL hglb;
  2896.   if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
  2897.     return NULL;
  2898.   LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  2899.   if (lpBitmap == NULL)
  2900.     return NULL;
  2901.   WORD numcol = NumBitmapColors(lpBitmap);
  2902.   ::FreeResource(hglb);
  2903.   if(numcol!=16)
  2904.   {
  2905.     return(NULL);
  2906.   }
  2907.   return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
  2908. }
  2909. BOOL CNewMenu::RemoveMenu(UINT uiId,UINT nFlags)
  2910. {
  2911.   if(MF_BYPOSITION&nFlags)
  2912.   {
  2913.     UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  2914.     if(uint&MF_SEPARATOR && !(uint&MF_POPUP))
  2915.     {
  2916.       delete m_MenuList.GetAt(uiId);
  2917.       m_MenuList.RemoveAt(uiId);
  2918.     }
  2919.     else
  2920.     {
  2921.       CNewMenu* pSubMenu = (CNewMenu*) GetSubMenu(uiId);
  2922.       if(NULL==pSubMenu)
  2923.       {
  2924.         UINT uiCommandId = GetMenuItemID(uiId);
  2925.         for(int i=0;i<m_MenuList.GetSize(); i++)
  2926.         {
  2927.           if(m_MenuList[i]->m_nID==uiCommandId)
  2928.           {
  2929.             delete m_MenuList.GetAt(i);
  2930.             m_MenuList.RemoveAt(i);
  2931.             break;
  2932.           }
  2933.         }
  2934.       }
  2935.       else
  2936.       {
  2937.         int numSubMenus = (int)m_SubMenus.GetUpperBound();
  2938.         for(int m = numSubMenus; m >= 0; m--)
  2939.         {
  2940.           if(m_SubMenus[m]==pSubMenu->m_hMenu)
  2941.           {
  2942.             int numAllSubMenus = (int)m_AllSubMenus.GetUpperBound();
  2943.             for(int n = numAllSubMenus; n>= 0; n--)
  2944.             {
  2945.               if(m_AllSubMenus[n]==m_SubMenus[m])
  2946.                 m_AllSubMenus.RemoveAt(n);
  2947.             }
  2948.             m_SubMenus.RemoveAt(m);
  2949.           }
  2950.         }
  2951.         int num = pSubMenu->GetMenuItemCount();
  2952.         for(int i=num-1;i>=0;--i)
  2953.         {
  2954.           pSubMenu->RemoveMenu(i,MF_BYPOSITION);
  2955.         }
  2956.         for(i=(int)m_MenuList.GetUpperBound();i>=0;i--)
  2957.         {
  2958.           if(m_MenuList[i]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
  2959.           {
  2960.             delete m_MenuList.GetAt(i);
  2961.             m_MenuList.RemoveAt(i);
  2962.             break;
  2963.           }
  2964.         }
  2965.         delete pSubMenu;
  2966.       }
  2967.     }
  2968.   }
  2969.   else
  2970.   {
  2971.     int iPosition =0;
  2972.     CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
  2973.     if(pMenu)
  2974.     {
  2975.       return pMenu->RemoveMenu(iPosition,MF_BYPOSITION);
  2976.     }
  2977.   }
  2978.   return CMenu::RemoveMenu(uiId,nFlags);
  2979. }
  2980. BOOL CNewMenu::DeleteMenu(UINT uiId,UINT nFlags)
  2981. {
  2982.   if(MF_BYPOSITION&nFlags)
  2983.   {
  2984.     UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  2985.     if(uint&MF_SEPARATOR && !(uint&MF_POPUP))
  2986.     {
  2987.       delete m_MenuList.GetAt(uiId);
  2988.       m_MenuList.RemoveAt(uiId);
  2989.     }
  2990.     else
  2991.     {
  2992.       CNewMenu* pSubMenu = (CNewMenu*) GetSubMenu(uiId);
  2993.       if(NULL==pSubMenu)
  2994.       {
  2995.         UINT uiCommandId = GetMenuItemID(uiId);
  2996.         for(int i=0;i<m_MenuList.GetSize(); i++)
  2997.         {
  2998.           if(m_MenuList[i]->m_nID==uiCommandId)
  2999.           {
  3000.             delete m_MenuList.GetAt(i);
  3001.             m_MenuList.RemoveAt(i);
  3002.             break;
  3003.           }
  3004.         }
  3005.       }
  3006.       else
  3007.       {
  3008.         int numSubMenus = (int)m_SubMenus.GetUpperBound();
  3009.         for(int m = numSubMenus; m >= 0; m--)
  3010.         {
  3011.           if(m_SubMenus[m]==pSubMenu->m_hMenu)
  3012.           {
  3013.             int numAllSubMenus = (int)m_AllSubMenus.GetUpperBound();
  3014.             for(int n = numAllSubMenus; n>= 0; n--)
  3015.             {
  3016.               if(m_AllSubMenus[n]==m_SubMenus[m])
  3017.               {
  3018.                 m_AllSubMenus.RemoveAt(n);
  3019.               }
  3020.             }
  3021.             m_SubMenus.RemoveAt(m);
  3022.           }
  3023.         }
  3024.         int num = pSubMenu->GetMenuItemCount();
  3025.         for(int i=num-1;i>=0;--i)
  3026.         {
  3027.           pSubMenu->DeleteMenu(i,MF_BYPOSITION);
  3028.         }
  3029.         for(i=(int)m_MenuList.GetUpperBound();i>=0;i--)
  3030.         {
  3031.           if(m_MenuList[i]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
  3032.           {
  3033.             delete m_MenuList.GetAt(i);
  3034.             m_MenuList.RemoveAt(i);
  3035.             break;
  3036.           }
  3037.         }
  3038.         delete pSubMenu;
  3039.       }
  3040.     }
  3041.   }
  3042.   else
  3043.   {
  3044.     int iPosition =0;
  3045.     CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
  3046.     if(pMenu)
  3047.     {
  3048.       pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
  3049.     }
  3050.   }
  3051.   return CMenu::DeleteMenu(uiId,nFlags);
  3052. BOOL CNewMenu::AppendMenu(UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,int nIconNormal)
  3053. {
  3054.   return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  3055. }
  3056. BOOL CNewMenu::AppendMenu(UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CImageList *il,int xoffset)
  3057. {
  3058.   return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  3059. }
  3060. BOOL CNewMenu::AppendMenu(UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CBitmap *bmp)
  3061. {
  3062.   if(bmp)
  3063.   {
  3064.     CImageList temp;
  3065.     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  3066.     temp.Add(bmp,GetBitmapBackground());
  3067.     return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,&temp,0);
  3068.   }
  3069.   return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,NULL,0);
  3070. }
  3071. BOOL CNewMenu::InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,int nIconNormal)
  3072. {
  3073.   return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  3074. }
  3075. BOOL CNewMenu::InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CImageList *il,int xoffset)
  3076. {
  3077.   return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  3078. }
  3079. BOOL CNewMenu::InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem,LPCTSTR lpszNewItem,CBitmap *bmp)
  3080. {
  3081.   if(bmp)
  3082.   {
  3083.     CImageList temp;
  3084.     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  3085.     temp.Add(bmp,GetBitmapBackground());
  3086.     return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
  3087.   }
  3088.   return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
  3089. }
  3090. CNewMenu* CNewMenu::AppendODPopupMenu(LPCTSTR lpstrText)
  3091. {
  3092.   CNewMenu* pSubMenu = new CNewMenu(m_hMenu);
  3093.   pSubMenu->m_unselectcheck=m_unselectcheck;
  3094.   pSubMenu->m_selectcheck=m_selectcheck;
  3095.   pSubMenu->checkmaps=checkmaps;
  3096.   pSubMenu->checkmapsshare=TRUE;
  3097.   pSubMenu->CreatePopupMenu();
  3098.   AppendODMenu(lpstrText,MF_POPUP,HMenuToUInt(pSubMenu->m_hMenu), -1);
  3099.   return pSubMenu;
  3100. }
  3101. BOOL CNewMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
  3102. {
  3103.   if (il == NULL||newlist==NULL||xoffset<0)
  3104.     return FALSE;
  3105.   
  3106.   HICON hIcon = il->ExtractIcon(xoffset);
  3107.   int cx, cy;
  3108.   ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
  3109.   newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
  3110.   newlist->Add(hIcon);
  3111.   ::DestroyIcon(hIcon);
  3112.   return TRUE;
  3113. }
  3114. CMenu* CNewMenu::GetSubMenu(int nPos)
  3115. {
  3116.   return CMenu::GetSubMenu (nPos);
  3117. }
  3118. CMenu* CNewMenu::GetSubMenu(LPCTSTR lpszSubMenuName)
  3119. {
  3120.   int num = GetMenuItemCount ();
  3121.   CString name;
  3122.   for (int i=0; i<num; i++)
  3123.   {
  3124.     GetMenuString (i, name, MF_BYPOSITION);
  3125.     if (name.Compare (lpszSubMenuName) == 0)
  3126.     {
  3127.       return CMenu::GetSubMenu (i);
  3128.     }
  3129.   }
  3130.   return NULL;
  3131. }
  3132. // Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
  3133. // before and after the popup menu can also be removed if they exist.
  3134. int CNewMenu::GetMenuPosition(LPCTSTR pText)
  3135. {
  3136.   for(int i=0;i<(int)(GetMenuItemCount());++i)
  3137.   {
  3138.     if(!GetSubMenu(i))
  3139.     { 
  3140.       for(int j=0;j<=m_MenuList.GetUpperBound();++j)
  3141.       {  
  3142.         if(m_MenuList[j]->m_szMenuText.Compare(pText)==NULL)
  3143.           return j;
  3144.       }
  3145.     }
  3146.   }
  3147.   // means no found;
  3148.   return -1;
  3149. }
  3150. // sPos means Seperator's position, since we have no way to find the 
  3151. // seperator's position in the menu we have to specify them when we call the 
  3152. // RemoveMenu to make sure the unused seperators are removed;
  3153. // sPos  = None no seperator removal;
  3154. //       = Head  seperator in front of this menu item;
  3155. //       = Tail  seperator right after this menu item;
  3156. //       = Both  seperators at both ends;
  3157. // remove the menu item based on their text, return -1 if not found, otherwise 
  3158. // return the menu position;
  3159. int CNewMenu::RemoveMenu(LPCTSTR pText, ESeperator sPos)
  3160. {
  3161.   int nPos = GetMenuPosition(pText);
  3162.   if(nPos != -1)
  3163.   {
  3164.     switch (sPos)
  3165.     {
  3166.     case CNewMenu::NONE:
  3167.       RemoveMenu(nPos, MF_BYPOSITION);
  3168.       break;
  3169.     case CNewMenu::HEAD:
  3170.       ASSERT(nPos - 1 >= 0);
  3171.       RemoveMenu(nPos-1, MF_BYPOSITION);
  3172.       break;
  3173.     case CNewMenu::TAIL:
  3174.       RemoveMenu(nPos+1, MF_BYPOSITION);
  3175.       break;
  3176.     case CNewMenu::BOTH:
  3177.       // remove the end first;
  3178.       RemoveMenu(nPos+1, MF_BYPOSITION);
  3179.       // remove the head;
  3180.       ASSERT(nPos - 1 >= 0);
  3181.       RemoveMenu(nPos-1, MF_BYPOSITION);
  3182.       break;
  3183.     }
  3184.   }
  3185.   return nPos;
  3186. }
  3187. BOOL CNewMenu::RemoveMenuTitle()
  3188. {
  3189.   int numMenuItems = (int)m_MenuList.GetSize();
  3190.   // We need a seperator at the beginning of the menu
  3191.   if(!numMenuItems || !((m_MenuList[0]->m_nFlags)&MF_SEPARATOR) )
  3192.   {
  3193.     return FALSE;
  3194.   }
  3195.   CNewMenuItemData* pMenuData = m_MenuList[0];
  3196.   // Check for title
  3197.   if(pMenuData->m_nTitleFlags&MFT_TITLE)
  3198.   {
  3199.     if(numMenuItems>0)
  3200.     {
  3201.       CNewMenuItemData* pMenuNextData = m_MenuList[1];
  3202.       if((pMenuNextData->m_nFlags&MF_MENUBREAK))
  3203.       {
  3204.         pMenuNextData->m_nFlags &= ~MF_MENUBREAK;
  3205.         CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuNextData->m_nFlags,pMenuNextData->m_nID,(LPCTSTR)pMenuNextData);
  3206.       }
  3207.     }
  3208.     // Now remove the title
  3209.     RemoveMenu(0,MF_BYPOSITION);
  3210.     return TRUE;
  3211.   }
  3212.   return FALSE;
  3213. BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle,UINT nTitleFlags)
  3214. {
  3215.   // Check the menu integrity
  3216.   if((int)GetMenuItemCount()!=(int)m_MenuList.GetSize())
  3217.   {
  3218.     SynchronizeMenu();
  3219.   }
  3220.   int numMenuItems = (int)m_MenuList.GetSize();
  3221.   // We need a seperator at the beginning of the menu
  3222.   if(!numMenuItems || !((m_MenuList[0]->m_nFlags)&MF_SEPARATOR) )
  3223.   {
  3224.     InsertMenu(0,MF_SEPARATOR|MF_BYPOSITION);
  3225.   }
  3226.   numMenuItems = (int)m_MenuList.GetSize();
  3227.   if(numMenuItems)
  3228.   {
  3229.     CNewMenuItemData* pMenuData = m_MenuList[0];
  3230.     if(pMenuData->m_nFlags&MF_SEPARATOR)
  3231.     {
  3232.       pMenuData->SetString(pTitle);
  3233.       pMenuData->m_nTitleFlags = nTitleFlags|MFT_TITLE;
  3234.       if(numMenuItems>1)
  3235.       {
  3236.         CNewMenuItemData* pMenuData = m_MenuList[1];
  3237.         if(nTitleFlags&MFT_SIDE_TITLE)
  3238.         {
  3239.           if(!(pMenuData->m_nFlags&MF_MENUBREAK))
  3240.           {
  3241.             pMenuData->m_nFlags |= MF_MENUBREAK;
  3242.             CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
  3243.           }
  3244.         }
  3245.         else
  3246.         {
  3247.           if((pMenuData->m_nFlags&MF_MENUBREAK))
  3248.           {
  3249.             pMenuData->m_nFlags &= ~MF_MENUBREAK;
  3250.             CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
  3251.           }
  3252.         }
  3253.         return TRUE;
  3254.       }
  3255.     }
  3256.   }
  3257.   return FALSE;
  3258. }
  3259. BOOL CNewMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
  3260. {
  3261.   BOOL returnflag=FALSE;
  3262.   if(MF_BYPOSITION&nFlags)
  3263.   {
  3264.     int numMenuItems = (int)m_MenuList.GetSize();
  3265.     if(id<UINT(numMenuItems))
  3266.     {
  3267.       m_MenuList[id]->SetString(string);
  3268.       returnflag=TRUE;
  3269.     }
  3270.   }
  3271.   else
  3272.   {
  3273.     int uiLoc;
  3274.     CNewMenu* pMenu = FindMenuOption(id,uiLoc);
  3275.     if(NULL!=pMenu)
  3276.     {
  3277.       returnflag = pMenu->SetMenuText(uiLoc,string);
  3278.     }
  3279.   }
  3280.   return returnflag;
  3281. }
  3282. // courtesy of Warren Stevens
  3283. void CNewMenu::ColorBitmap(CDC* pDC,CBitmap& bmp,CSize size,COLORREF fill,COLORREF border,int hatchstyle)
  3284. {
  3285.   // Create a memory DC
  3286.   CDC MemDC;
  3287.   MemDC.CreateCompatibleDC(pDC);  
  3288.   bmp.CreateCompatibleBitmap(pDC, size.cx, size.cy);  
  3289.   CPen border_pen(PS_SOLID, 1, border);
  3290.   CBrush fill_brush;
  3291.   if(hatchstyle!=-1) 
  3292.   { 
  3293.     fill_brush.CreateHatchBrush(hatchstyle, fill); 
  3294.   }
  3295.   else 
  3296.   {
  3297.     fill_brush.CreateSolidBrush(fill);
  3298.   }
  3299.   CBitmap* pOldBitmap = MemDC.SelectObject(&bmp);
  3300.   CPen*    pOldPen    = MemDC.SelectObject(&border_pen);
  3301.   CBrush*  pOldBrush  = MemDC.SelectObject(&fill_brush);
  3302.   MemDC.Rectangle(0,0, size.cx, size.cy);
  3303.   if(NULL!=pOldBrush)  { MemDC.SelectObject(pOldBrush);  }
  3304.   if(NULL!=pOldPen)    { MemDC.SelectObject(pOldPen);    }
  3305.   if(NULL!=pOldBitmap) { MemDC.SelectObject(pOldBitmap); }
  3306. }
  3307. void CNewMenu::DrawSpecial_OldStyle(CDC* pDC, LPCRECT pRect,UINT nID, DWORD dwStyle)
  3308. {
  3309.   COLORREF oldColor;
  3310.   if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
  3311.   {
  3312.     oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  3313.   }
  3314.   else if (dwStyle&ODS_SELECTED)
  3315.   { 
  3316.     oldColor = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  3317.   }
  3318.   else
  3319.   {
  3320.     oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  3321.   }
  3322.   BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;
  3323.   switch(nID&0xfff0)
  3324.   {
  3325.   case SC_MINIMIZE:
  3326.     DrawSpecialChar(pDC,pRect,48,bBold); // Min
  3327.     break;
  3328.   case SC_MAXIMIZE:
  3329.     DrawSpecialChar(pDC,pRect,49,bBold); // Max
  3330.     break;
  3331.   case SC_CLOSE:
  3332.     DrawSpecialChar(pDC,pRect,114,bBold); // Close
  3333.     break;
  3334.   case SC_RESTORE:
  3335.     DrawSpecialChar(pDC,pRect,50,bBold); // restore
  3336.     break;
  3337.   }
  3338.   pDC->SetTextColor(oldColor);
  3339. }
  3340. void CNewMenu::DrawSpecial_WinXP(CDC* pDC, LPCRECT pRect,UINT nID, DWORD dwStyle)
  3341. {
  3342.   TCHAR cSign = 0;
  3343.   switch(nID&0xfff0)
  3344.   {
  3345.   case SC_MINIMIZE:
  3346.     cSign = 48; // Min
  3347.     break;
  3348.   case SC_MAXIMIZE:
  3349.     cSign = 49;// Max
  3350.     break;
  3351.   case SC_CLOSE:
  3352.     cSign = 114;// Close
  3353.     break;
  3354.   case SC_RESTORE:
  3355.     cSign = 50;// Restore
  3356.     break;
  3357.   }
  3358.   if(cSign)
  3359.   {
  3360.     COLORREF oldColor;
  3361.     BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;
  3362.     CRect rect(pRect);
  3363.     if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
  3364.     {
  3365.       oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  3366.     }
  3367.     else if(dwStyle&ODS_SELECTED)
  3368.     { 
  3369.       oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  3370.       DrawSpecialChar(pDC,rect,cSign,bBold);
  3371.       pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  3372.       rect.OffsetRect(-2,-2);
  3373.     }
  3374.     else
  3375.     { 
  3376.       oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  3377.     }
  3378.     DrawSpecialChar(pDC,rect,cSign,bBold);
  3379.     pDC->SetTextColor(oldColor);
  3380.   }
  3381. }
  3382. void CNewMenu::SetMBar(CMenuButton *pBar)
  3383. {
  3384. pb=pBar;
  3385. }
  3386. CRect CNewMenu::GetLastActiveMenuRect()
  3387. {
  3388.   return m_LastActiveMenuRect;
  3389. }
  3390. void CNewMenu::DrawSpecialCharStyle(CDC* pDC, LPCRECT pRect, TCHAR Sign, DWORD dwStyle)
  3391. {
  3392.   COLORREF oldColor;
  3393.   if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
  3394.   {
  3395.     oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  3396.   }
  3397.   else
  3398.   { 
  3399.     oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  3400.   }
  3401.   DrawSpecialChar(pDC,pRect,Sign,(dwStyle&ODS_DEFAULT) ? TRUE : FALSE);
  3402.   pDC->SetTextColor(oldColor);
  3403. }
  3404. void CNewMenu::DrawSpecialChar(CDC* pDC, LPCRECT pRect, TCHAR Sign, BOOL bBold)
  3405. {
  3406.   //  48 Min
  3407.   //  49 Max
  3408.   //  50 Restore
  3409.   //  98 Checkmark 
  3410.   // 105 Bullet
  3411.   // 114 Close
  3412.   CFont MyFont;
  3413.   LOGFONT logfont;
  3414.   CRect rect(pRect) ;
  3415.   rect.DeflateRect(2,2);
  3416.   logfont.lfHeight = -rect.Height();
  3417.   logfont.lfWidth = 0;
  3418.   logfont.lfEscapement = 0;
  3419.   logfont.lfOrientation = 0;
  3420.   logfont.lfWeight = (bBold) ? FW_BOLD:FW_NORMAL;
  3421.   logfont.lfItalic = FALSE;
  3422.   logfont.lfUnderline = FALSE;
  3423.   logfont.lfStrikeOut = FALSE;
  3424.   logfont.lfCharSet = DEFAULT_CHARSET;
  3425.   logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  3426.   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  3427.   logfont.lfQuality = DEFAULT_QUALITY;
  3428.   logfont.lfPitchAndFamily = DEFAULT_PITCH;
  3429.   _tcscpy(logfont.lfFaceName,_T("Marlett"));
  3430.   MyFont.CreateFontIndirect (&logfont);
  3431.   CFont* pOldFont = pDC->SelectObject (&MyFont); 
  3432.   int OldMode = pDC->SetBkMode(TRANSPARENT);  
  3433.   pDC->DrawText (&Sign,1,rect,DT_CENTER|DT_SINGLELINE);
  3434.   pDC->SetBkMode(OldMode);
  3435.   pDC->SelectObject(pOldFont);
  3436. }
  3437. //////////////////////////////////////////////////////////////////////
  3438. // Construction/Destruction
  3439. //////////////////////////////////////////////////////////////////////
  3440. CMenuTheme::CMenuTheme()
  3441.   ZeroMemory(this,sizeof(CMenuTheme));
  3442. }
  3443. CMenuTheme::CMenuTheme( DWORD dwThemeId, 
  3444.                         pItemMeasureFkt pMeasureItem,
  3445.                         pItemDrawFkt pDrawItem,
  3446.                         pItemDrawFkt pDrawTitle,
  3447.                         DWORD dwFlags)
  3448.   :m_dwThemeId(dwThemeId),
  3449.     m_dwFlags(dwFlags),
  3450.     m_pMeasureItem(pMeasureItem),
  3451.     m_pDrawItem(pDrawItem),
  3452.     m_pDrawTitle(pDrawTitle)
  3453. {
  3454.   m_BorderTopLeft = CSize(2,2);
  3455.   if(!IsShadowEnabled())
  3456.   {
  3457.     m_BorderBottomRight = CSize(5,6);
  3458.   }
  3459.   else
  3460.   {
  3461.     m_BorderBottomRight = CSize(2,2);
  3462.   }
  3463. }
  3464. CMenuTheme::~CMenuTheme()
  3465. {
  3466. }
  3467. BOOL CMenuTheme::DoDrawBorder()
  3468. {
  3469.   return (m_dwFlags&1)?TRUE:FALSE;
  3470. }
  3471. void CMenuTheme::DrawSmalBorder( HWND hWnd, HDC hDC)
  3472. {
  3473.   CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3474.   if(pData!=NULL)
  3475.   {
  3476.     if(pData->m_hMenu)
  3477.     {   
  3478.       CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pData->m_hMenu));
  3479.       if(pMenu && pMenu->GetParent())
  3480.       {
  3481.         CNewMenu* pParentMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pMenu->GetParent()));
  3482.         if(pParentMenu && !pParentMenu->IsPopup())
  3483.         {
  3484.           CRect Rect;
  3485.           // Get the size of the menu... 
  3486.           GetWindowRect(hWnd, Rect );
  3487.           Rect.OffsetRect(pData->m_Point - Rect.TopLeft());
  3488.           Rect &= pParentMenu->GetLastActiveMenuRect();
  3489.           if(!Rect.IsRectEmpty())
  3490.           {
  3491.             if(Rect.Width()>Rect.Height())
  3492.             {
  3493.               Rect.InflateRect(-1,0);
  3494.             }
  3495.             else
  3496.             {
  3497.               Rect.InflateRect(0,-1);
  3498.             }
  3499.             Rect.OffsetRect(-pData->m_Point);
  3500.             CDC* pDC = CDC::FromHandle(hDC);
  3501.             pDC->FillSolidRect(Rect,GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3502.           }
  3503.         }
  3504.       }
  3505.     }
  3506.   }
  3507. }
  3508. void CMenuTheme::DrawShade( HWND hWnd, HDC hDC,CPoint screen)
  3509.   if(IsShadowEnabled())
  3510.     return;
  3511.   // Get the size of the menu... 
  3512.   CRect Rect;
  3513.   GetWindowRect(hWnd, Rect );
  3514.   long winW = Rect.Width(); 
  3515.   long winH = Rect.Height(); 
  3516.   long xOrg = screen.x;  
  3517.   long yOrg = screen.y;
  3518.   // Get the desktop hDC... 
  3519.   HDC hDcDsk = GetWindowDC(0) ;
  3520.   
  3521.   int X,Y;
  3522.   // Simulate a shadow on right edge... 
  3523.   for (X=1; X<=4 ;X++)
  3524.   { 
  3525.     for (Y=0; Y<4 ;Y++)
  3526.     {
  3527.       SetPixel(hDC,winW-X,Y, GetPixel(hDcDsk,xOrg+winW-X,yOrg+Y) );
  3528.     }
  3529.     for (Y=4; Y<8 ;Y++)
  3530.     {
  3531.       COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
  3532.       SetPixel(hDC,winW-X,Y,DarkenColor(3 * X * (Y - 3), c)) ;
  3533.     }
  3534.     for (Y=8; Y<=(winH-5) ;Y++)
  3535.     {
  3536.       COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
  3537.       SetPixel( hDC, winW - X, Y, DarkenColor(15 * X, c) );
  3538.     }
  3539.     for (Y=(winH-4); Y<=(winH-1) ;Y++)
  3540.     {
  3541.       COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
  3542.       SetPixel( hDC, winW - X, Y, DarkenColor(3 * X * -(Y - winH), c)) ;
  3543.     }
  3544.   } 
  3545.   // Simulate a shadow on the bottom edge... 
  3546.   for(Y=1; Y<=4 ;Y++)
  3547.   {
  3548.     for(X=0; X<=3 ;X++)
  3549.     {
  3550.       SetPixel(hDC,X,winH-Y, GetPixel(hDcDsk,xOrg+X,yOrg+winH-Y)) ;
  3551.     }
  3552.     for(X=4; X<=7 ;X++)
  3553.     {
  3554.       COLORREF c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y) ;
  3555.       SetPixel( hDC, X, winH - Y, DarkenColor(3 * (X - 3) * Y, c)) ;
  3556.     }
  3557.     for(X=8; X<=(winW-5) ;X++)
  3558.     {
  3559.       COLORREF  c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y); 
  3560.       SetPixel( hDC, X, winH - Y, DarkenColor(15 * Y, c)) ;
  3561.     }
  3562.   }   
  3563.   // Release the desktop hDC... 
  3564.   ReleaseDC(0,hDcDsk);
  3565. }
  3566. BOOL CMenuTheme::OnInitWnd(HWND hWnd)
  3567. {
  3568.   if(DoDrawBorder())
  3569.   {
  3570.     CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3571.     ASSERT(pData);
  3572.     // Flag for changing styles
  3573.     pData->m_dwData |= 2;
  3574.     SetWindowLong (hWnd, GWL_STYLE, pData->m_dwStyle & (~WS_BORDER) );
  3575.     SetWindowLong (hWnd, GWL_EXSTYLE,pData->m_dwExStyle & ~(WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME));
  3576.     return TRUE;
  3577.   }
  3578.   return FALSE;
  3579. }
  3580. BOOL CMenuTheme::OnUnInitWnd(HWND hWnd)
  3581. {
  3582.   CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3583.   if(pData)
  3584.   {
  3585.     HMENU hMenu = pData->m_hMenu;
  3586.     CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
  3587.     if(pNewMenu)
  3588.     {
  3589.       if(pNewMenu->OnUnInitPopupMenu() && (pData->m_dwData&4) )
  3590.       {
  3591.         HWND hParenWnd = GetParent(hWnd);
  3592.         if(hParenWnd)
  3593.           DrawMenuBar(hParenWnd);
  3594.       }
  3595.     }
  3596.     // were windows-style changed?
  3597.     if(pData->m_dwData&2)
  3598.     {
  3599.       SetLastError(0);
  3600.       if(!(pData->m_dwData&1))
  3601.       {
  3602.         SetWindowLong (hWnd, GWL_STYLE,pData->m_dwStyle);
  3603.       }
  3604.       else
  3605.       {
  3606.         // Restore old Styles for special menu!! 
  3607.         // (Menu 0x10012!!!) special VISIBLE flag must be set
  3608.         SetWindowLong (hWnd, GWL_STYLE,pData->m_dwStyle|WS_VISIBLE);
  3609.       }
  3610.       ShowLastError();
  3611.       SetWindowLong (hWnd, GWL_EXSTYLE, pData->m_dwExStyle);
  3612.       ShowLastError();
  3613.       // Normaly when you change the style you shold call next function
  3614.       // but in this case you would lose the focus for the menu!!
  3615.       //SetWindowPos(hWnd,0,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_HIDEWINDOW);
  3616.     }
  3617.   }
  3618.   return TRUE;
  3619. }
  3620. BOOL CMenuTheme::OnEraseBkgnd(HWND hWnd, HDC hDC)
  3621. {
  3622.   //  CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3623.   //  Get the size of the menu... 
  3624.   CDC* pDC = CDC::FromHandle (hDC);
  3625.   CRect Rect;
  3626.   GetClientRect(hWnd, Rect );
  3627.   pDC->FillSolidRect (Rect,GetSysColor(COLOR_MENU));
  3628.   return TRUE;
  3629. }
  3630. BOOL CMenuTheme::OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos)
  3631. {
  3632.   UNREFERENCED_PARAMETER(hWnd);
  3633.   if(DoDrawBorder())
  3634.   {
  3635.     if(!IsShadowEnabled())
  3636.     {
  3637.       pPos->cx +=2;
  3638.       pPos->cy +=2;
  3639.     }
  3640.     else
  3641.     {
  3642.       pPos->cx -=2;
  3643.       pPos->cy -=2;
  3644.     }
  3645.     pPos->y -=1;
  3646.     return TRUE;
  3647.   }
  3648.   return FALSE;
  3649. }
  3650. BOOL CMenuTheme::OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc)
  3651. {
  3652.   UNREFERENCED_PARAMETER(hWnd);
  3653.   if(DoDrawBorder())
  3654.   {
  3655.     pCalc->rgrc->top  += m_BorderTopLeft.cy;
  3656.     pCalc->rgrc->left += m_BorderTopLeft.cx; 
  3657.     pCalc->rgrc->bottom -= m_BorderBottomRight.cy;
  3658.     pCalc->rgrc->right  -= m_BorderBottomRight.cx;
  3659.   }
  3660.   return FALSE;
  3661. }
  3662. BOOL CMenuTheme::OnDrawBorder(HWND hWnd, HDC hDC)
  3663. {
  3664.   CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3665.   if(DoDrawBorder() && pData)
  3666.   {
  3667.     CRect Rect;
  3668.     CDC* pDC = CDC::FromHandle (hDC);
  3669.     // Get the size of the menu... 
  3670.     GetWindowRect(hWnd, Rect );
  3671.     long winW = Rect.Width(); 
  3672.     long winH = Rect.Height(); 
  3673.     if(!IsShadowEnabled())
  3674.     {
  3675.       pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),GetSysColor(CNewMenu::cCOLOR_MENUBAR),GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3676.       pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
  3677.       
  3678.       DrawShade(hWnd,hDC,pData->m_Point);
  3679.     }
  3680.     else
  3681.     {
  3682.       pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),GetSysColor(CNewMenu::cCOLOR_MENUBAR),GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3683.       pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
  3684.     }
  3685.     //DrawSmalBorder(hWnd,hDC);
  3686.     return TRUE;
  3687.   }
  3688.   return FALSE;
  3689. }
  3690. CMenuThemeXP::CMenuThemeXP(DWORD dwThemeId, 
  3691.                            pItemMeasureFkt pMeasureItem,
  3692.                            pItemDrawFkt pDrawItem,
  3693.                            pItemDrawFkt pDrawTitle,
  3694.                            DWORD dwFlags)
  3695. :CMenuTheme(dwThemeId,pMeasureItem,pDrawItem,pDrawTitle,dwFlags)
  3696. {
  3697. }
  3698. BOOL CMenuThemeXP::OnDrawBorder(HWND hWnd, HDC hDC)
  3699. {
  3700.   CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3701.   if(DoDrawBorder() && pData)
  3702.   {
  3703.     CRect Rect;
  3704.     CDC* pDC = CDC::FromHandle (hDC);
  3705.     // Get the size of the menu... 
  3706.     GetWindowRect(hWnd, Rect );
  3707.     long winW = Rect.Width(); 
  3708.     long winH = Rect.Height(); 
  3709. CRect rc=Rect;
  3710.     if(!IsShadowEnabled())
  3711.     {
  3712.       pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_WINDOW));
  3713.       pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GuiDrawLayer::GetRGBColorShadow(),GuiDrawLayer::GetRGBColorShadow());
  3714.       DrawShade(hWnd,hDC,pData->m_Point);
  3715.     }
  3716.     else
  3717.     {
  3718.       pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_WINDOW));
  3719.       pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GuiDrawLayer::GetRGBColorShadow(),GuiDrawLayer::GetRGBColorShadow());
  3720.     }
  3721. pDC->Draw3dRect(CRect(CPoint(1,1),CSize(1,winH-6)),GuiDrawLayer::GetRGBColorFace(),GuiDrawLayer::GetRGBColorFace());
  3722. CRect rcDeskTop;
  3723. CWnd* pDeskTop=CWnd::FromHandle(GetDesktopWindow());
  3724. pDeskTop->GetWindowRect(rcDeskTop);
  3725. if (gbintHorz==0 )
  3726. {
  3727. if ( rcDeskTop.bottom  > Rect.bottom)
  3728. pDC->Draw3dRect(1,0,rcMenu.Width()-1,0,GetSysColor(CNewMenu::cCOLOR_MENUBAR),GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3729. }
  3730. else
  3731. {
  3732. if ( rcDeskTop.right > Rect.right)
  3733. pDC->Draw3dRect(0,1,0,rcMenu.Height()-1,GetSysColor(CNewMenu::cCOLOR_MENUBAR),GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3734. }
  3735. gbintHorz=0;
  3736. rcMenu=CRect(0,0,0,0);
  3737. DrawSmalBorder(hWnd,hDC);
  3738.     
  3739.     return TRUE;
  3740.   }
  3741.   return FALSE;
  3742. }
  3743. BOOL CMenuThemeXP::OnEraseBkgnd(HWND hWnd, HDC hDC)
  3744. {
  3745.   CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
  3746.   if(pData->m_hMenu==NULL)
  3747.   {
  3748.     return CMenuTheme::OnEraseBkgnd(hWnd,hDC);
  3749.   }
  3750.  
  3751.   //  Get the size of the menu... 
  3752.   CDC* pDC = CDC::FromHandle (hDC);
  3753.   CRect Rect;
  3754.   GetClientRect(hWnd, Rect );
  3755.   pDC->FillSolidRect (Rect,GetSysColor(CNewMenu::cCOLOR_MENUBAR));
  3756.   return TRUE;
  3757. }
  3758. //////////////////////////////////////////////////////////////////////
  3759. // Construction/Destruction
  3760. //////////////////////////////////////////////////////////////////////
  3761. const TCHAR _OldMenuProc[] = _T("OldMenuProc");
  3762. HHOOK CNewMenuHook::HookOldMenuCbtFilter = NULL;
  3763. HMENU CNewMenuHook::m_hLastMenu = NULL;
  3764. DWORD CNewMenuHook::m_dwMsgPos = 0;
  3765. CTypedPtrList<CPtrList, CMenuTheme*>* CNewMenuHook::m_pRegisteredThemesList = NULL;
  3766. CTypedPtrMap<CMapPtrToPtr,HWND,CNewMenuHook::CMenuHookData*> CNewMenuHook::m_MenuHookData;
  3767. CNewMenuHook::CNewMenuHook()
  3768.   if(IsShellType()==WinXP)
  3769.   {
  3770.     BOOL bFlatMenu = FALSE;
  3771.     if(SystemParametersInfo(SPI_GETFLATMENU,0,&bFlatMenu,0) && bFlatMenu==TRUE)
  3772.     {
  3773.       CNewMenu::cCOLOR_MENUBAR = COLOR_MENUBAR;
  3774.     }
  3775.   }
  3776.   AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL,
  3777.                           CNewMenu::MeasureItem_OldStyle,
  3778.                           CNewMenu::DrawItem_OldStyle,
  3779.                           CNewMenu::DrawMenuTitle,TRUE));
  3780.   AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER,
  3781.                           CNewMenu::MeasureItem_OldStyle,
  3782.                           CNewMenu::DrawItem_OldStyle,
  3783.                           CNewMenu::DrawMenuTitle));
  3784.   AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP,
  3785.                             CNewMenu::MeasureItem_WinXP,
  3786.                             CNewMenu::DrawItem_WinXP,
  3787.                             CNewMenu::DrawMenuTitle,TRUE));
  3788.   AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP_NOBORDER,
  3789.                             CNewMenu::MeasureItem_WinXP,
  3790.                             CNewMenu::DrawItem_WinXP,
  3791.                             CNewMenu::DrawMenuTitle));
  3792.   AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL,
  3793.                           CNewMenu::MeasureItem_OldStyle,
  3794.                           CNewMenu::DrawItem_SpecialStyle,
  3795.                           CNewMenu::DrawMenuTitle,TRUE));
  3796.   AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL_NOBORDER,
  3797.                           CNewMenu::MeasureItem_OldStyle,
  3798.                           CNewMenu::DrawItem_SpecialStyle,
  3799.                           CNewMenu::DrawMenuTitle));
  3800. //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL);
  3801. //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER);
  3802.   CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP);
  3803. //  CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP_NOBORDER);
  3804.   if (HookOldMenuCbtFilter == NULL)
  3805.   {
  3806.     HookOldMenuCbtFilter = ::SetWindowsHookEx(WH_CALLWNDPROC, NewMenuHook, NULL, ::GetCurrentThreadId());
  3807.     if (HookOldMenuCbtFilter == NULL)
  3808.     {
  3809.       ShowLastError();
  3810.       AfxThrowMemoryException();
  3811.     }
  3812.   } 
  3813. }
  3814. CNewMenuHook::~CNewMenuHook()
  3815. {
  3816.   if (HookOldMenuCbtFilter != NULL)
  3817.   {
  3818.     if(!::UnhookWindowsHookEx(HookOldMenuCbtFilter))
  3819.     {
  3820.       ShowLastError();
  3821.     }
  3822.     HookOldMenuCbtFilter = NULL;
  3823.   }
  3824.   // Destroy all registered themes.
  3825.   if( m_pRegisteredThemesList!= NULL)
  3826.   {
  3827.     while(m_pRegisteredThemesList->GetCount())
  3828.     {
  3829.       CMenuTheme* pTheme = m_pRegisteredThemesList->RemoveTail();
  3830.       delete pTheme;
  3831.     }
  3832.     delete m_pRegisteredThemesList;
  3833.     m_pRegisteredThemesList = NULL;
  3834.   }
  3835. }
  3836. BOOL CNewMenuHook::AddTheme(CMenuTheme* pTheme)
  3837. {
  3838.   if( m_pRegisteredThemesList== NULL)
  3839.   {
  3840.     m_pRegisteredThemesList = new CTypedPtrList<CPtrList, CMenuTheme*>;
  3841.   }
  3842.   if(m_pRegisteredThemesList->Find(pTheme))
  3843.   {
  3844.     return FALSE;
  3845.   }
  3846.   m_pRegisteredThemesList->AddTail(pTheme);
  3847.   return TRUE;
  3848. }
  3849. CMenuTheme* CNewMenuHook::RemoveTheme(DWORD dwThemeId)
  3850. {
  3851.   CMenuTheme* pTheme = FindTheme(dwThemeId);
  3852.   if(pTheme==NULL)
  3853.   {
  3854.     return NULL;
  3855.   }
  3856.   POSITION pos = m_pRegisteredThemesList->Find(pTheme);
  3857.   ASSERT(pos);
  3858.   if(pos)
  3859.   {
  3860.     m_pRegisteredThemesList->RemoveAt(pos);
  3861.     if(m_pRegisteredThemesList->GetCount()==NULL)
  3862.     {
  3863.       // Destroy the empty list.
  3864.       delete m_pRegisteredThemesList;
  3865.       m_pRegisteredThemesList = NULL;
  3866.     }
  3867.   }
  3868.   return pTheme; 
  3869. }
  3870. CMenuTheme* CNewMenuHook::FindTheme(DWORD dwThemeId)
  3871. {
  3872.   if(m_pRegisteredThemesList==NULL)
  3873.   {
  3874.     return NULL;
  3875.   }
  3876.   POSITION pos = m_pRegisteredThemesList->GetHeadPosition();
  3877.   while(pos)
  3878.   { 
  3879.     CMenuTheme* pTheme = m_pRegisteredThemesList->GetNext(pos);
  3880.     if(pTheme->m_dwThemeId==dwThemeId)
  3881.     {
  3882.       return pTheme;
  3883.     }    
  3884.   }
  3885.   return NULL;
  3886. }   
  3887. CNewMenuHook::CMenuHookData* CNewMenuHook::GetMenuHookData(HWND hWnd)
  3888. {
  3889.   CMenuHookData* pData=NULL;
  3890.   if(m_MenuHookData.Lookup(hWnd,pData))
  3891.   {
  3892.     return pData;
  3893.   }
  3894.   return NULL;
  3895. }
  3896. void CNewMenuHook::UnsubClassMenu(HWND hWnd)
  3897. {
  3898.   AFX_MANAGE_STATE(AfxGetModuleState());
  3899.   WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
  3900.   ASSERT(oldWndProc != NULL);  
  3901.   SetLastError(0);
  3902.   if(!SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)(DWORD_PTR)oldWndProc))
  3903.   {
  3904.     ShowLastError();
  3905.   }
  3906.   RemoveProp(hWnd, _OldMenuProc);
  3907.   GlobalDeleteAtom(GlobalFindAtom(_OldMenuProc));
  3908.   // now Clean up
  3909.   HMENU hMenu = NULL;
  3910.   // Restore old Styles for special menu!! (Menu 0x10012!!!)
  3911.   CMenuHookData* pData = GetMenuHookData(hWnd);
  3912.   if(pData)
  3913.   {
  3914.     hMenu = pData->m_hMenu;
  3915.     CNewMenu::m_pActMenuDrawing->OnUnInitWnd(hWnd);
  3916.     m_MenuHookData.RemoveKey(hWnd);
  3917.     delete pData;
  3918.   }
  3919.   
  3920. #ifdef _TRACE_MENU_
  3921.   TRACE(_T("Unsubclass Menu=0x%lX, hwnd=0x%lXn"),hMenu,hWnd);
  3922. #endif
  3923. }
  3924. LRESULT CALLBACK CNewMenuHook::SubClassMenu(HWND hWnd,      // handle to window
  3925.                                             UINT uMsg,      // message identifier
  3926.                                             WPARAM wParam,  // first message parameter
  3927.                                             LPARAM lParam   // second message parameter
  3928.                                             )
  3929. {
  3930.   AFX_MANAGE_STATE(AfxGetModuleState());
  3931.   WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
  3932.   LRESULT result = NULL;
  3933.   
  3934.   static long NestedLevel = 0;
  3935.   BOOL bCallDefault = TRUE;
  3936.   NestedLevel++;
  3937. #ifdef _TRACE_MENU_
  3938.   MSG msg = {hWnd,uMsg,wParam,lParam,0,0,0};
  3939.   TCHAR Buffer[30]; 
  3940.   wsprintf(Buffer,_T("Level %02ld"),NestedLevel);
  3941.   MyTraceMsg(Buffer,&msg);
  3942. #endif
  3943.   switch(uMsg)
  3944.   {
  3945.   case WM_NCPAINT:
  3946.     {
  3947.       CMenuHookData* pData = GetMenuHookData(hWnd);
  3948.       if(pData && pData->m_bDrawBorder)
  3949.       {
  3950.         HDC hDC;
  3951.         if(wParam!=1)
  3952.           hDC = GetDCEx(hWnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
  3953.         else
  3954.           hDC = GetWindowDC (hWnd);
  3955.         if(hDC)
  3956.         { 
  3957.   
  3958.           if(CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,hDC))
  3959.           {
  3960.             bCallDefault=FALSE;
  3961.           }
  3962.   ReleaseDC(hWnd,hDC);
  3963.         }
  3964.       }
  3965.       pData->m_bDrawBorder = TRUE;
  3966.     }
  3967.     break;
  3968.   case WM_PRINT:
  3969.     {
  3970.       CMenuHookData* pData = GetMenuHookData(hWnd);
  3971.       if(pData && CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,(HDC)wParam) )
  3972.       {
  3973.         pData->m_bDrawBorder = FALSE;
  3974.         // We need to create a bitmap for drawing
  3975.         // We can't clipp or make a offset to the DC because NT2000 (blue-screen!!)
  3976.         CRect rect;
  3977.         GetClientRect(hWnd, rect);
  3978.         CDC dc;
  3979.         CBitmap bitmap;
  3980.         CDC* pDC = CDC::FromHandle((HDC)wParam);
  3981.         dc.CreateCompatibleDC(pDC); 
  3982.         bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  3983.         CBitmap* pOldBitmap = dc.SelectObject(&bitmap);
  3984.         // might as well clip to the same rectangle
  3985.         dc.IntersectClipRect(rect);
  3986.         CSize offset = CNewMenu::m_pActMenuDrawing->m_BorderTopLeft;
  3987.         SendMessage(hWnd,WM_ERASEBKGND,(WPARAM)dc.m_hDC,0);
  3988.         SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)dc.m_hDC,lParam);
  3989.         pDC->BitBlt(offset.cx,offset.cy, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);
  3990.         dc.SelectObject(pOldBitmap);
  3991.         bCallDefault=FALSE;
  3992.       } 
  3993.     }
  3994.     break;
  3995.   case WM_ERASEBKGND:
  3996.     {
  3997.       if(CNewMenu::m_pActMenuDrawing->OnEraseBkgnd(hWnd,(HDC)wParam))
  3998.       {
  3999.         bCallDefault=FALSE; 
  4000.         result = TRUE;
  4001.       }
  4002.     }
  4003.     break;
  4004.   case WM_WINDOWPOSCHANGED:
  4005.   case WM_WINDOWPOSCHANGING:
  4006.     {
  4007.       CMenuHookData* pData=GetMenuHookData(hWnd);
  4008.       ASSERT(pData);
  4009.       LPWINDOWPOS pPos = (LPWINDOWPOS)lParam;
  4010.       // Need for windows 98
  4011.       BOOL bSetPos = pPos->x!=NULL || pPos->y!=NULL;
  4012.       if(uMsg==WM_WINDOWPOSCHANGING)
  4013.       {
  4014.         CNewMenu::m_pActMenuDrawing->OnWindowPosChanging(hWnd,pPos);
  4015.       }
  4016.       if(bSetPos)
  4017.       {
  4018.         pData->m_Point = CPoint(pPos->x,pPos->y);
  4019.       }
  4020.     }
  4021.     break;
  4022.   case WM_KEYDOWN:
  4023.     if(wParam==VK_ESCAPE)
  4024.     {
  4025.       CMenuHookData* pData = GetMenuHookData(hWnd);
  4026.       if(pData)
  4027.       {
  4028.         pData->m_dwData |= 4;
  4029.       }
  4030.     }
  4031.     m_dwMsgPos = GetMessagePos();
  4032.     break;
  4033.   case WM_NCCALCSIZE:
  4034.     {
  4035.       NCCALCSIZE_PARAMS* pCalc = (NCCALCSIZE_PARAMS*)lParam;
  4036.       if(CNewMenu::m_pActMenuDrawing->OnNcCalcSize(hWnd,pCalc))
  4037.       {
  4038.         bCallDefault=FALSE; 
  4039.       }
  4040.     }
  4041.     break;
  4042.   case WM_SHOWWINDOW:
  4043.     // Hide the window ? Test for 98 and 2000
  4044.     if(wParam==NULL)
  4045.     { 
  4046.       // Special handling for NT 2000 and WND 0x10012.
  4047.       UnsubClassMenu(hWnd);
  4048.     }
  4049.     break;
  4050.   case WM_NCDESTROY:
  4051.     UnsubClassMenu (hWnd);
  4052.     break;
  4053.   }
  4054.   if( bCallDefault )
  4055.   {
  4056.     ASSERT(oldWndProc != NULL);
  4057.     // call original wndproc for default handling
  4058.     result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  4059.   }
  4060.   NestedLevel--;
  4061.   return result;
  4062. BOOL CNewMenuHook::CheckSubclassing(HWND hWnd, BOOL bSpecialWnd)
  4063. {
  4064.   TCHAR Name[20];
  4065.   int Count = GetClassName (hWnd,Name,ARRAY_SIZE(Name));
  4066.   if(Count!=6 || _tcscmp(Name,_T("#32768"))!=0)
  4067.   {
  4068.     // does not match to menuclass
  4069.     return false;
  4070.   }
  4071.   BOOL bDoNewSubclass = FALSE;
  4072.   CMenuHookData* pData=GetMenuHookData(hWnd);
  4073.   // check if we have allready some data
  4074.   if(pData==NULL)
  4075.   {
  4076.     WNDPROC oldWndProc;
  4077.     // subclass the window with the proc which does gray backgrounds
  4078.     oldWndProc = (WNDPROC)(LONG_PTR)GetWindowLong(hWnd, GWL_WNDPROC);
  4079.     if (oldWndProc != NULL && GetProp(hWnd, _OldMenuProc) == NULL)
  4080.     {
  4081.       ASSERT(oldWndProc!=SubClassMenu);
  4082.       if(!SetProp(hWnd, _OldMenuProc, oldWndProc))
  4083.       {
  4084.         ShowLastError();
  4085.       }
  4086.       if ((WNDPROC)GetProp(hWnd, _OldMenuProc) == oldWndProc)
  4087.       {
  4088.         GlobalAddAtom(_OldMenuProc);
  4089.         CMenuHookData* pData=GetMenuHookData(hWnd);
  4090.         ASSERT(pData==NULL);
  4091.         if(pData==NULL)
  4092.         { 
  4093.           pData = new CMenuHookData(hWnd,bSpecialWnd);
  4094.           m_MenuHookData.SetAt (hWnd,pData);
  4095.           SetLastError(0);
  4096.           if(!SetWindowLong(hWnd, GWL_WNDPROC,(DWORD)(DWORD_PTR)SubClassMenu))
  4097.           {
  4098.             ShowLastError();
  4099.           }
  4100.           bDoNewSubclass = TRUE;
  4101.   #ifdef _TRACE_MENU_
  4102.           TRACE(_T("Subclass Menu=0x%lX, hwnd=0x%lXn"),pData->m_hMenu,hWnd);
  4103.   #endif 
  4104.           CNewMenu::m_pActMenuDrawing->OnInitWnd(hWnd);
  4105.         } 
  4106.       }
  4107.       else
  4108.       {
  4109.         ASSERT(0);
  4110.       }
  4111.     }
  4112.   }
  4113.   // Menu was set also assign it to this menu.
  4114.   if(m_hLastMenu)
  4115.   {
  4116.     CMenuHookData* pData = GetMenuHookData(hWnd);
  4117.     if(pData)
  4118.     {
  4119.       // Safe actual menu
  4120.       pData->m_hMenu = m_hLastMenu;
  4121.       // Reset for the next menu
  4122.       m_hLastMenu = NULL;
  4123.     }
  4124.   }
  4125.   return bDoNewSubclass;
  4126. }
  4127. LRESULT CALLBACK CNewMenuHook::NewMenuHook(int code, WPARAM wParam, LPARAM lParam)
  4128. {
  4129.   AFX_MANAGE_STATE(AfxGetModuleState());
  4130.   CWPSTRUCT* pTemp = (CWPSTRUCT*)lParam;
  4131.   if(code == HC_ACTION )
  4132.   {
  4133.     HWND hWnd = pTemp->hwnd;
  4134.     // Normal and special handling for menu 0x10012
  4135.     if(pTemp->message==WM_CREATE || pTemp->message==0x01E2)
  4136.     {
  4137.       CheckSubclassing(hWnd,pTemp->message==0x01E2);
  4138.     }
  4139.   }
  4140.   return CallNextHookEx(HookOldMenuCbtFilter, code,wParam, lParam);
  4141. }
  4142. //////////////////////////////////////////////////////////////////////
  4143. // Construction/Destruction
  4144. //////////////////////////////////////////////////////////////////////