home *** CD-ROM | disk | FTP | other *** search
- // ImageMenu.cpp: implementation of the CImageMenu class.
- //
- //////////////////////////////////////////////////////////////////////
-
- #include "stdafx.h"
- #include "ImageMenu.h"
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
- CImageMenu::CImageMenu()
- {
- m_hMenu = CreatePopupMenu();
- m_hInstance = GetModuleHandle(NULL);
- m_hWnd = NULL;
- m_wpOldWndProc = NULL;
- m_szExtraSize.cx = 2;
- m_szExtraSize.cy = 2;
- m_szImageSize.cx = 16;
- m_szImageSize.cy = 16;
- m_hCurrentMenu = NULL;
- m_vMenuItem.resize(0);
- // init the ThunkData with the this pointer so that this can be subclassed
- ThunkInit(m_Thunk, this);
- }
-
- CImageMenu::~CImageMenu()
- {
- // destroy the item data
- for(int i = m_vMenuItem.size()-1;i > -1;i--)
- {
- m_vMenuItem[i].Cleanup();
- }
- m_vMenuItem.clear();
- m_vMenuItem.resize(0);
- // destroy the menu
- DestroyMenu(m_hMenu);
- if(m_wpOldWndProc)
- OnDestroy();
- }
-
- bool CImageMenu::Init(HWND hWnd)
- {// begin Init
- // subclass owner's m_hParent message function
- m_wpOldWndProc = (WNDPROC)::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)(void *)m_Thunk);
- m_hWnd = hWnd;
- return true;
- }// end Init
-
- LRESULT CImageMenu::WndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
- {// begin WndProc
- switch(nMessage)
- { // begin switch
- case WM_MENUSELECT:
- OnMenuSelect(wParam,lParam);
- break;
- case WM_MEASUREITEM:
- OnMeasureItem(wParam,lParam);
- break;
- case WM_DRAWITEM:
- OnDrawItem(wParam,lParam);
- break;
- case WM_DESTROY:
- OnDestroy();
- break;
- } // end switch
-
- // pass the message to the owner m_hWnd's WndProc function
- return CallWindowProc(m_wpOldWndProc,hWnd,nMessage,wParam,lParam);
- }// end WndProc
-
- LRESULT CImageMenu::OnDestroy()
- {// begin OnDestroy
- // remove subclass of owner's m_hWnd message function
- if(m_wpOldWndProc)
- {
- SetWindowLong(m_hWnd,GWL_WNDPROC,(long)m_wpOldWndProc);
- m_wpOldWndProc = NULL;
- }
- return 1;
- }// end OnDestroy
-
- LRESULT CImageMenu::OnMeasureItem(WPARAM wParam, LPARAM lParam)
- {// begin OnMeasureItem
- if(wParam != 0)
- return 0; // not a menu
- MEASUREITEMSTRUCT *pmisItem = (MEASUREITEMSTRUCT *)lParam;
- pmisItem->itemHeight = 0;
- pmisItem->itemWidth = 0;
- // create a dc with the same font as the menu
- HDC hWindowDC = GetWindowDC(m_hWnd);
- HDC hDC = CreateCompatibleDC(hWindowDC);
- ReleaseDC(m_hWnd,hDC);
- NONCLIENTMETRICS ncmMetrics = {NULL};
- ncmMetrics.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfo( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncmMetrics, 0 );
- HGDIOBJ hOldFont = SelectObject(hDC,CreateFontIndirect(&(ncmMetrics.lfMenuFont)));
- // get the font dimentions
- SIZE szFontSize = {NULL};
- GetTextExtentPoint32(hDC,m_vMenuItem[pmisItem->itemData].m_pName,lstrlen(m_vMenuItem[pmisItem->itemData].m_pName),&szFontSize);
- // clean up
- DeleteObject(SelectObject(hDC,hOldFont));
- DeleteDC(hDC);
- // add this to the final
- pmisItem->itemWidth += szFontSize.cx;
- pmisItem->itemHeight += szFontSize.cy;
- // add on the image size
- pmisItem->itemWidth += m_szImageSize.cx;
- if(pmisItem->itemHeight < m_szImageSize.cy)
- pmisItem->itemHeight = m_szImageSize.cy;
- // add the extra space
- pmisItem->itemWidth += m_szExtraSize.cx;
- pmisItem->itemHeight += m_szExtraSize.cy;
- return 1;
- }// end OnMeasureItem
-
- LRESULT CImageMenu::OnDrawItem(WPARAM wParam, LPARAM lParam)
- {// begin OnDrawItem
- if(wParam != 0)
- return 0; // not a menu
- DRAWITEMSTRUCT *pdisItem = (DRAWITEMSTRUCT *)lParam;
- if((HMENU)pdisItem->hwndItem != m_hMenu)
- return 0;
- // calculate text rectangle
- RECT rText = pdisItem->rcItem;
- rText.left += m_szImageSize.cx+m_szExtraSize.cx*2;
- // if it has the focus hilite it
- UINT nColorBackground = NULL;
- UINT nColorText = NULL;
- if(pdisItem->itemState & ODS_SELECTED)
- {// begin hilite
- nColorBackground = COLOR_HIGHLIGHT;
- nColorText = COLOR_HIGHLIGHTTEXT;
- }// end hilite
- else
- {// begin draw normal
- nColorBackground = COLOR_MENU;
- nColorText = COLOR_MENUTEXT;
- }// end draw normal
- SetBkMode(pdisItem->hDC,TRANSPARENT);
- FillRect(pdisItem->hDC,&(pdisItem->rcItem),GetSysColorBrush(nColorBackground));
- SetTextColor(pdisItem->hDC,GetSysColor(nColorText));
-
- // draw the icon
- POINT ptIconPos = {NULL};
- ptIconPos.x = pdisItem->rcItem.left+m_szExtraSize.cx;
- ptIconPos.y = pdisItem->rcItem.top+((pdisItem->rcItem.bottom-pdisItem->rcItem.top-m_szImageSize.cy)/2);
- RECT rIcon = pdisItem->rcItem;
- rIcon.right = rIcon.left+m_szImageSize.cx+m_szExtraSize.cx*2;
- if(pdisItem->itemState & ODS_SELECTED)
- InvertRect(pdisItem->hDC,&rIcon);
- DrawIconEx(pdisItem->hDC,ptIconPos.x,ptIconPos.y,m_vMenuItem[pdisItem->itemData].m_hIcon,m_szImageSize.cx,m_szImageSize.cy,0,NULL,DI_NORMAL);
- if(pdisItem->itemState & ODS_SELECTED)
- InvertRect(pdisItem->hDC,&rIcon);
- // draw the text
- UINT nTextFlags = DT_SINGLELINE|DT_VCENTER|DT_NOCLIP;
- if(pdisItem->itemState & ODS_SELECTED && !(pdisItem->itemState & ODS_GRAYED))
- nTextFlags |= DT_CENTER;
- if(pdisItem->itemState & ODS_GRAYED)
- {// begin draw disabled
- if(!(pdisItem->itemState & ODS_SELECTED))
- {// begin non-selected
- rText.left += 1;
- rText.top += 1;
- SetTextColor(pdisItem->hDC,GetSysColor(COLOR_3DHILIGHT));
- DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
- rText.left -= 1;
- rText.top -= 1;
- }// end non-selected
- SetTextColor(pdisItem->hDC,GetSysColor(COLOR_3DSHADOW));
- DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
- }// end draw disabled
- else
- DrawTextEx(pdisItem->hDC,m_vMenuItem[pdisItem->itemData].m_pName,-1,&rText,nTextFlags,NULL);
- // cleanup
- return 1;
- }// end OnDrawItem
-
- bool CImageMenu::AppendMenu(UINT uIDNewItem,const char *pString, HICON hIcon, UINT nFlags, HANDLE hExtra)
- // the image is destroyed by the class so send to this function a copy
- {// begin AppendMenu
- int nLength = lstrlen(pString);
- m_vMenuItem.resize(m_vMenuItem.size()+1);
- int nIndex = m_vMenuItem.size()-1;
- m_vMenuItem[nIndex].m_hIcon = hIcon;
- m_vMenuItem[nIndex].m_pName = new char[nLength+1];
- lstrcpy(m_vMenuItem[nIndex].m_pName,pString);
- // check for submenu
- if(nFlags & MF_POPUP && hExtra != NULL)
- {// begin add submenu
- uIDNewItem = (UINT)hExtra;
- }// end add submenu
- return (bool)::AppendMenu(m_hMenu,MF_OWNERDRAW|nFlags,uIDNewItem,(char *)(void *)nIndex);
- }// end AppendMenu
-
- bool CImageMenu::AppendMenu(UINT uIDNewItem,const char *pString, UINT idIcon)
- {// begin AppendMenu
- return AppendMenu(uIDNewItem,pString,(HICON)LoadImage(m_hInstance,MAKEINTRESOURCE(idIcon),IMAGE_ICON,m_szImageSize.cx,m_szImageSize.cy,LR_DEFAULTCOLOR));
- }// end AppendMenu
-
- int CImageMenu::TrackPopupMenu(UINT uFlags, int x, int y, HWND hOwner)
- {// begin TrackPopupMenu
- return ::TrackPopupMenu(m_hMenu,uFlags,x,y,0,hOwner,NULL);
- }// end TrackPopupMenu
-
- LRESULT CImageMenu::OnMenuSelect(WPARAM wParam,LPARAM lParam)
- {// begin OnMenuSelect
- if(lParam)
- m_hCurrentMenu = (HMENU)lParam;
- return 0;
- }// end OnMenuSelect
-
- HMENU CImageMenu::GetCurrentMenu()
- {// begin GetCurrentMenu
- return m_hCurrentMenu;
- }// end GetCurrentMenu
-
- HMENU CImageMenu::GetSubMenu(int nIndex)
- {// begin GetSubMenu
- if(nIndex > m_vMenuItem.size()-1 || m_vMenuItem[nIndex].m_pimSubMenu == NULL)
- return NULL;
- return m_vMenuItem[nIndex].m_pimSubMenu->GetSafeHmenu();
- }// end GetSubMenu
-
- HMENU CImageMenu::GetSafeHmenu()
- {// begin GetSafeHmenu
- return m_hMenu;
- }// end GetSafeHmenu
-
- int CImageMenu::GetItemCount()
- {// begin GetItemCount
- return m_vMenuItem.size();
- }// end GetItemCount
-