NewMenu.cpp
上传用户:wlkj888
上传日期:2022-08-01
资源大小:806k
文件大小:121k
源码类别:

对话框与窗口

开发平台:

Visual C++

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