///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	MMENU.CPP: Defines custom menu interface for multimedia applet
//
//	Copyright (c) Microsoft Corporation	1998
//    
//	1/28/98 David Stewart / dstewart
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "windows.h"
#include "mmenu.h"
#include "tchar.h"
#include "resource.h"

#define ICON_SPACING 3

extern HINSTANCE hInst;

typedef struct ownermenu
{
    TCHAR szText[MAX_PATH];
    HICON hIcon;
} OWNERMENU, *LPOWNERMENU;

HRESULT AllocCustomMenu(CustomMenu** ppMenu)
{
    *ppMenu = new CCustomMenu();
    
    if (*ppMenu==NULL)
    {
        return E_OUTOFMEMORY;
    }

    return S_OK;
}

CCustomMenu::CCustomMenu()
{
    m_hMenu = CreatePopupMenu();

    //get system font for any owner drawing
    NONCLIENTMETRICS metrics;
    metrics.cbSize = sizeof(metrics);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(metrics),&metrics,0);

    m_hFont = CreateFontIndirect(&metrics.lfMenuFont);

    if (metrics.lfMenuFont.lfCharSet == ANSI_CHARSET)
    {
        metrics.lfMenuFont.lfWeight = FW_BOLD;
    }
       
    m_hBoldFont = CreateFontIndirect(&metrics.lfMenuFont);
}

CCustomMenu::~CCustomMenu()
{
    //clean up string data in menus
    int x  = GetMenuItemCount(m_hMenu);

    for (int i = 0; i < x; i++)
    {
        MENUITEMINFO mii;
        ZeroMemory(&mii,sizeof(mii));
        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_DATA|MIIM_TYPE;
        GetMenuItemInfo(m_hMenu,i,TRUE,&mii);

        if ((mii.dwItemData!=0) && (mii.fType & MFT_OWNERDRAW))
        {
            OWNERMENU* pMenu = (OWNERMENU*)mii.dwItemData;
            if (pMenu)
            {
                DestroyIcon(pMenu->hIcon);
                delete [] pMenu;
            }
        }
    }

    DestroyMenu(m_hMenu);
    DeleteObject(m_hFont);
    DeleteObject(m_hBoldFont);
}

void CCustomMenu::Destroy()
{
    delete this;
}

BOOL CCustomMenu::AppendMenu(HINSTANCE hInst, int nStringID, CustomMenu* pMenu)
{
    TCHAR szMenu[MAX_PATH];
    LoadString(hInst,nStringID,szMenu,sizeof(szMenu)/sizeof(TCHAR));

    return ::AppendMenu(m_hMenu,MF_STRING|MF_POPUP,(UINT_PTR)pMenu->GetMenuHandle(),szMenu);
}

BOOL CCustomMenu::AppendMenu(int nMenuID, TCHAR* szMenu)
{
    return ::AppendMenu(m_hMenu,MF_STRING,nMenuID,szMenu);
}

BOOL CCustomMenu::AppendMenu(int nMenuID, HINSTANCE hInst, int nStringID)
{
    TCHAR szMenu[MAX_PATH];
    LoadString(hInst,nStringID,szMenu,sizeof(szMenu)/sizeof(TCHAR));

    return ::AppendMenu(m_hMenu,MF_STRING,nMenuID,szMenu);
}

BOOL CCustomMenu::AppendSeparator()
{
    return ::AppendMenu(m_hMenu,MF_SEPARATOR,0,0);
}

BOOL CCustomMenu::AppendMenu(int nMenuID, HINSTANCE hInst, int nIconID, int nStringID)
{
    OWNERMENU* pMenu = new OWNERMENU;

    if (!pMenu)
    {
        return FALSE;
    }

    LoadString(hInst,nStringID,pMenu->szText,sizeof(pMenu->szText)/sizeof(TCHAR));

    int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
    int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);

    pMenu->hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(nIconID), IMAGE_ICON, cxMiniIcon, cyMiniIcon, LR_DEFAULTCOLOR);

    return ::AppendMenu(m_hMenu,MF_OWNERDRAW,nMenuID,(LPTSTR)pMenu);
}

BOOL CCustomMenu::TrackPopupMenu(UINT uFlags, int x, int y, HWND hwnd, CONST RECT* pRect)
{
    TPMPARAMS tpm;
    tpm.cbSize = sizeof(tpm);
    memcpy(&(tpm.rcExclude),pRect,sizeof(RECT));
    
    return ::TrackPopupMenuEx(m_hMenu,uFlags,x,y,hwnd,&tpm);
}

BOOL CCustomMenu::SetMenuDefaultItem(UINT uItem, UINT fByPos)
{
    return ::SetMenuDefaultItem(m_hMenu,uItem,fByPos);
}

void CCustomMenu::MeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT pMeasure)
{
    OWNERMENU* szMenu = (OWNERMENU*)pMeasure->itemData;

    int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
    int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);

    HDC hdc = GetDC(hwnd);

    HFONT hOrgFont = (HFONT)SelectObject(hdc,m_hBoldFont);
    SIZE size;

    GetTextExtentPoint32(hdc, szMenu->szText, _tcslen(szMenu->szText), &size );

    pMeasure->itemWidth = size.cx + cxMiniIcon + (ICON_SPACING*2);
    pMeasure->itemHeight = max(cyMiniIcon,size.cy);

    SelectObject(hdc,hOrgFont);
    ReleaseDC(hwnd,hdc);
}

void CCustomMenu::DrawItem(HWND hwnd, LPDRAWITEMSTRUCT pDraw)
{
    OWNERMENU* szMenu = (OWNERMENU*)pDraw->itemData;
    HDC hdc = pDraw->hDC;

    COLORREF colorFill = GetSysColor(COLOR_MENU);
    COLORREF colorText = GetSysColor(COLOR_MENUTEXT);

    if (pDraw->itemState & ODS_SELECTED)
    {
        colorFill = GetSysColor(COLOR_HIGHLIGHT);
        colorText = GetSysColor(COLOR_HIGHLIGHTTEXT);
    }

    HBRUSH hbrBack = CreateSolidBrush(GetSysColor(COLOR_MENU));

    //blit the icon, always with menu color background
    int cxMiniIcon = (int)GetSystemMetrics(SM_CXSMICON);
    int cyMiniIcon = (int)GetSystemMetrics(SM_CYSMICON);
    DrawIconEx(hdc,pDraw->rcItem.left,pDraw->rcItem.top,szMenu->hIcon,cxMiniIcon,cyMiniIcon,0,hbrBack,DI_NORMAL);

    DeleteObject(hbrBack);
    hbrBack = CreateSolidBrush(colorFill);

    HFONT hOrgFont;
        
    if (pDraw->itemState & ODS_DEFAULT)
    {
        hOrgFont = (HFONT)SelectObject(hdc,m_hBoldFont);
    }
    else
    {
        hOrgFont = (HFONT)SelectObject(hdc,m_hFont);
    }

    pDraw->rcItem.left += (cxMiniIcon + ICON_SPACING);

    FillRect(hdc,&pDraw->rcItem,hbrBack);
    
    DeleteObject(hbrBack);

    pDraw->rcItem.left += ICON_SPACING;

    SetBkMode(hdc,TRANSPARENT);
    SetTextColor(hdc,colorText);

    DrawText(hdc, szMenu->szText, -1, &pDraw->rcItem, DT_SINGLELINE);

    SelectObject(hdc,hOrgFont);
}

LRESULT CCustomMenu::MenuChar(TCHAR tChar, UINT fuFlag, HMENU hMenu)
{
    //go through the menus one-by-one looking for the accel key
    int nReturn = 0;
    int nCode = MNC_IGNORE;

    int x  = GetMenuItemCount(m_hMenu);

    TCHAR teststr[3];
    wsprintf(teststr,TEXT("&%c"),tChar);
    _tcsupr(teststr);

    for (int i = 0; i < x; i++)
    {
        MENUITEMINFO mii;
        ZeroMemory(&mii,sizeof(mii));
        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_DATA|MIIM_TYPE;
        GetMenuItemInfo(m_hMenu,i,TRUE,&mii);

        if ((mii.dwItemData!=0) && (mii.fType & MFT_OWNERDRAW))
        {
            OWNERMENU* szMenu = (OWNERMENU*)mii.dwItemData;
            TCHAR* pMenu = new TCHAR[_tcslen(szMenu->szText)+sizeof(TCHAR)];
            _tcscpy(pMenu,szMenu->szText);

            _tcsupr(pMenu);

            if (_tcsstr(pMenu,teststr)!=NULL)
            {
                nReturn = i;
                nCode = MNC_EXECUTE;
                if (pMenu)
                {
                    delete [] pMenu;
                    pMenu = NULL;
                }
                break;
            }

            if (pMenu)
            {
                delete [] pMenu;
                pMenu = NULL;
            }
        } //end if not separator
    }

    return (MAKELRESULT(nReturn, nCode));
}