home *** CD-ROM | disk | FTP | other *** search
/ PC Administrator / spravce.iso / TaskModule / src / ImageMenu.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-10  |  7.6 KB  |  235 lines

  1. // ImageMenu.cpp: implementation of the CImageMenu class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4.  
  5. #include "stdafx.h"
  6. #include "ImageMenu.h"
  7.  
  8. //////////////////////////////////////////////////////////////////////
  9. // Construction/Destruction
  10. //////////////////////////////////////////////////////////////////////
  11.  
  12. CImageMenu::CImageMenu()
  13. {
  14.     m_hMenu = CreatePopupMenu();
  15.     m_hInstance = GetModuleHandle(NULL);
  16.     m_hWnd = NULL;
  17.     m_wpOldWndProc = NULL;
  18.     m_szExtraSize.cx = 2;
  19.     m_szExtraSize.cy = 2;
  20.     m_szImageSize.cx = 16;
  21.     m_szImageSize.cy = 16;
  22.     m_hCurrentMenu = NULL;
  23.     m_vMenuItem.resize(0);
  24.     // init the ThunkData with the this pointer so that this can be subclassed
  25.     ThunkInit(m_Thunk, this);
  26. }
  27.  
  28. CImageMenu::~CImageMenu()
  29. {
  30.     // destroy the item data
  31.     for(int i = m_vMenuItem.size()-1;i > -1;i--)
  32.     {
  33.         m_vMenuItem[i].Cleanup();
  34.     }
  35.     m_vMenuItem.clear();
  36.     m_vMenuItem.resize(0);
  37.     // destroy the menu
  38.     DestroyMenu(m_hMenu);
  39.     if(m_wpOldWndProc)
  40.         OnDestroy();
  41. }
  42.  
  43. bool CImageMenu::Init(HWND hWnd)
  44. {// begin Init
  45.     // subclass owner's m_hParent message function
  46.     m_wpOldWndProc = (WNDPROC)::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)(void *)m_Thunk);
  47.     m_hWnd = hWnd;
  48.     return true;
  49. }// end Init
  50.  
  51. LRESULT CImageMenu::WndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
  52. {// begin WndProc
  53.     switch(nMessage)
  54.     { // begin switch
  55.     case WM_MENUSELECT:
  56.         OnMenuSelect(wParam,lParam);
  57.         break;
  58.     case WM_MEASUREITEM:
  59.         OnMeasureItem(wParam,lParam);
  60.         break;
  61.     case WM_DRAWITEM:
  62.         OnDrawItem(wParam,lParam);
  63.         break;
  64.     case WM_DESTROY:
  65.         OnDestroy();
  66.         break;
  67.     } // end switch
  68.  
  69.     // pass the message to the owner m_hWnd's WndProc function
  70.     return CallWindowProc(m_wpOldWndProc,hWnd,nMessage,wParam,lParam);
  71. }// end WndProc
  72.  
  73. LRESULT CImageMenu::OnDestroy()
  74. {// begin OnDestroy
  75.     // remove subclass of owner's m_hWnd message function
  76.     if(m_wpOldWndProc)
  77.     {
  78.         SetWindowLong(m_hWnd,GWL_WNDPROC,(long)m_wpOldWndProc);
  79.         m_wpOldWndProc = NULL;
  80.     }
  81.     return 1;
  82. }// end OnDestroy
  83.  
  84. LRESULT CImageMenu::OnMeasureItem(WPARAM wParam, LPARAM lParam)
  85. {// begin OnMeasureItem
  86.     if(wParam != 0)
  87.         return 0;    // not a menu
  88.     MEASUREITEMSTRUCT *pmisItem = (MEASUREITEMSTRUCT *)lParam;
  89.     pmisItem->itemHeight = 0;
  90.     pmisItem->itemWidth = 0;
  91.     // create a dc with the same font as the menu
  92.     HDC hWindowDC = GetWindowDC(m_hWnd);
  93.     HDC hDC = CreateCompatibleDC(hWindowDC);
  94.     ReleaseDC(m_hWnd,hDC);
  95.     NONCLIENTMETRICS ncmMetrics = {NULL};
  96.     ncmMetrics.cbSize = sizeof(NONCLIENTMETRICS);
  97.     SystemParametersInfo( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncmMetrics, 0 );
  98.     HGDIOBJ hOldFont = SelectObject(hDC,CreateFontIndirect(&(ncmMetrics.lfMenuFont)));
  99.     // get the font dimentions
  100.     SIZE szFontSize = {NULL};
  101.     GetTextExtentPoint32(hDC,m_vMenuItem[pmisItem->itemData].m_pName,lstrlen(m_vMenuItem[pmisItem->itemData].m_pName),&szFontSize);
  102.     // clean up
  103.     DeleteObject(SelectObject(hDC,hOldFont));
  104.     DeleteDC(hDC);
  105.     // add this to the final
  106.     pmisItem->itemWidth += szFontSize.cx;
  107.     pmisItem->itemHeight += szFontSize.cy;
  108.     // add on the image size
  109.     pmisItem->itemWidth += m_szImageSize.cx;
  110.     if(pmisItem->itemHeight < m_szImageSize.cy)
  111.         pmisItem->itemHeight = m_szImageSize.cy;
  112.     // add the extra space 
  113.     pmisItem->itemWidth += m_szExtraSize.cx;
  114.     pmisItem->itemHeight += m_szExtraSize.cy;
  115.     return 1;
  116. }// end OnMeasureItem
  117.  
  118. LRESULT CImageMenu::OnDrawItem(WPARAM wParam, LPARAM lParam)
  119. {// begin OnDrawItem
  120.     if(wParam != 0)
  121.         return 0;    // not a menu
  122.     DRAWITEMSTRUCT *pdisItem = (DRAWITEMSTRUCT *)lParam;
  123.     if((HMENU)pdisItem->hwndItem != m_hMenu)
  124.         return 0;
  125.     // calculate text rectangle
  126.     RECT rText = pdisItem->rcItem;
  127.     rText.left += m_szImageSize.cx+m_szExtraSize.cx*2;
  128.     // if it has the focus hilite it
  129.     UINT nColorBackground = NULL;
  130.     UINT nColorText = NULL;
  131.     if(pdisItem->itemState & ODS_SELECTED)
  132.     {// begin hilite
  133.         nColorBackground = COLOR_HIGHLIGHT;
  134.         nColorText = COLOR_HIGHLIGHTTEXT;
  135.     }// end hilite
  136.     else
  137.     {// begin draw normal
  138.         nColorBackground = COLOR_MENU;
  139.         nColorText = COLOR_MENUTEXT;
  140.     }// end draw normal
  141.     SetBkMode(pdisItem->hDC,TRANSPARENT); 
  142.     FillRect(pdisItem->hDC,&(pdisItem->rcItem),GetSysColorBrush(nColorBackground));
  143.     SetTextColor(pdisItem->hDC,GetSysColor(nColorText));
  144.  
  145.     // draw the icon
  146.     POINT ptIconPos = {NULL};
  147.     ptIconPos.x = pdisItem->rcItem.left+m_szExtraSize.cx;
  148.     ptIconPos.y = pdisItem->rcItem.top+((pdisItem->rcItem.bottom-pdisItem->rcItem.top-m_szImageSize.cy)/2);
  149.     RECT rIcon = pdisItem->rcItem;
  150.     rIcon.right = rIcon.left+m_szImageSize.cx+m_szExtraSize.cx*2;
  151.     if(pdisItem->itemState & ODS_SELECTED)
  152.         InvertRect(pdisItem->hDC,&rIcon);
  153.     DrawIconEx(pdisItem->hDC,ptIconPos.x,ptIconPos.y,m_vMenuItem[pdisItem->itemData].m_hIcon,m_szImageSize.cx,m_szImageSize.cy,0,NULL,DI_NORMAL);
  154.     if(pdisItem->itemState & ODS_SELECTED)
  155.         InvertRect(pdisItem->hDC,&rIcon);
  156.     // draw the text
  157.     UINT nTextFlags = DT_SINGLELINE|DT_VCENTER|DT_NOCLIP;
  158.     if(pdisItem->itemState & ODS_SELECTED && !(pdisItem->itemState & ODS_GRAYED))
  159.         nTextFlags |= DT_CENTER;
  160.     if(pdisItem->itemState & ODS_GRAYED)
  161.     {// begin draw disabled
  162.         if(!(pdisItem->itemState & ODS_SELECTED))
  163.         {// begin non-selected
  164.             rText.left += 1;
  165.             rText.top += 1;
  166.             SetTextColor(pdisItem->hDC,GetSysColor(COLOR_3DHILIGHT));
  167.             DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
  168.             rText.left -= 1;
  169.             rText.top -= 1;
  170.         }// end non-selected
  171.         SetTextColor(pdisItem->hDC,GetSysColor(COLOR_3DSHADOW));
  172.         DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
  173.     }// end draw disabled
  174.     else
  175.         DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
  176.     // cleanup
  177.     return 1;
  178. }// end OnDrawItem
  179.  
  180. bool CImageMenu::AppendMenu(UINT uIDNewItem,const char *pString, HICON hIcon, UINT nFlags, HANDLE hExtra)
  181. // the image is destroyed by the class so send to this function a copy
  182. {// begin AppendMenu
  183.     int nLength = lstrlen(pString);
  184.     m_vMenuItem.resize(m_vMenuItem.size()+1);
  185.     int nIndex = m_vMenuItem.size()-1;
  186.     m_vMenuItem[nIndex].m_hIcon = hIcon;
  187.     m_vMenuItem[nIndex].m_pName = new char[nLength+1];
  188.     lstrcpy(m_vMenuItem[nIndex].m_pName,pString);
  189.     // check for submenu
  190.     if(nFlags & MF_POPUP && hExtra != NULL)
  191.     {// begin add submenu
  192.         uIDNewItem = (UINT)hExtra;
  193.     }// end add submenu
  194.     return (bool)::AppendMenu(m_hMenu,MF_OWNERDRAW|nFlags,uIDNewItem,(char *)(void *)nIndex);
  195. }// end AppendMenu
  196.  
  197. bool CImageMenu::AppendMenu(UINT uIDNewItem,const char *pString, UINT idIcon)
  198. {// begin AppendMenu
  199.     return AppendMenu(uIDNewItem,pString,(HICON)LoadImage(m_hInstance,MAKEINTRESOURCE(idIcon),IMAGE_ICON,m_szImageSize.cx,m_szImageSize.cy,LR_DEFAULTCOLOR));
  200. }// end AppendMenu
  201.  
  202. int CImageMenu::TrackPopupMenu(UINT uFlags, int x, int y, HWND hOwner)
  203. {// begin TrackPopupMenu
  204.     return ::TrackPopupMenu(m_hMenu,uFlags,x,y,0,hOwner,NULL);
  205. }// end TrackPopupMenu
  206.  
  207. LRESULT CImageMenu::OnMenuSelect(WPARAM wParam,LPARAM lParam)
  208. {// begin OnMenuSelect
  209.     if(lParam)
  210.         m_hCurrentMenu = (HMENU)lParam;
  211.     return 0;
  212. }// end OnMenuSelect
  213.  
  214. HMENU CImageMenu::GetCurrentMenu()
  215. {// begin GetCurrentMenu
  216.     return m_hCurrentMenu;
  217. }// end GetCurrentMenu
  218.  
  219. HMENU CImageMenu::GetSubMenu(int nIndex)
  220. {// begin GetSubMenu
  221.     if(nIndex > m_vMenuItem.size()-1 || m_vMenuItem[nIndex].m_pimSubMenu == NULL)
  222.         return NULL;
  223.     return m_vMenuItem[nIndex].m_pimSubMenu->GetSafeHmenu();
  224. }// end GetSubMenu
  225.  
  226. HMENU CImageMenu::GetSafeHmenu()
  227. {// begin GetSafeHmenu
  228.     return m_hMenu;
  229. }// end GetSafeHmenu
  230.  
  231. int CImageMenu::GetItemCount()
  232. {// begin GetItemCount
  233.     return m_vMenuItem.size();
  234. }// end GetItemCount
  235.