如题。

解决方案 »

  1.   

    自绘,然后在onmeasureitem的时候改变高度
      

  2.   

    第一步:将所有菜单项设置为MF_OWNERDRAW,即自绘模式第二步:在WM_MEASUREITEM消息中设置菜单项的大小第三步:在WM_DRAWITEM消息中进行菜单项的绘制问题首先出现在了第一步,我要绘制的是一个上下文菜单,即右键菜单,要将菜单项设置为MF_OWNERDRAW,需要用到ModifyMenu函数,起始由于ModifyMenu函数的参数设置错误,导致程序怎么也响应不了WM_MEASUREITEM和WM_DRAWITEM消息,所以建议在使用ModifyMenu时对返回值进行检查。view plaincopy to clipboardprint?
    void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)   
    {   
        ClientToScreen(&point);   
        CMenu Menu;   
        Menu.LoadMenuW(IDR_MENU2);   
        CMenu *pMenu = Menu.GetSubMenu(0);   
        CString strText;   
        for (int i = 0; i < pMenu->GetMenuItemCount(); i++)   
        {   
            BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);   
            if (!bModi)   
           {   
                  TRACK("ModifyMenu fail!");   
           }   
            pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);   
        }   
        pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,   
            point.x,   
            point.y,   
            this);   
    }  
    void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)
    {
        ClientToScreen(&point);
        CMenu Menu;
        Menu.LoadMenuW(IDR_MENU2);
        CMenu *pMenu = Menu.GetSubMenu(0);
        CString strText;
        for (int i = 0; i < pMenu->GetMenuItemCount(); i++)
        {
            BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);
            if (!bModi)
           {
                  TRACK("ModifyMenu fail!");
           }
            pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);
        }
        pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,
            point.x,
            point.y,
            this);
    }第一步的问题解决后,接在在第二步的WM_MEASUREITEM消息中设置菜单项的大小:view plaincopy to clipboardprint?
    void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis)   
    {   
        //lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;   
        lpmis->itemWidth = 150;   
        lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU);   
    }  
    void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
    {
        //lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;
        lpmis->itemWidth = 150;
        lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU);

    在WM_MEASUREITEM消息中设置的菜单项大小会传入WM_DRAWITEM消息中,然后再在WM_DRAWITEM消息中根据菜单项的大小来进行重绘。到第三步也遇到了几个问题,由于最初对WM_DRAWITEM消息中的LPDRAWITEMSTRUCT结构体不了解,以致写出的程序不管在什么时候都会作同一个绘制操作,先来看看WM_DRAWITEM消息的声明:afx_msg void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis);在这个消息中有两个参数,在自绘菜单时,两个参数都要用到。其中nIDCtl,书上说是所属控件的ID,不太明白是什么意思,在MSDN看到,对于菜单发出的WM_DRAWITEM消息,nIDCtl为0。再说LPDRAWITEMSTRUCT结构体,该结构体中包含了菜单复选状态、选中状态以及菜单项的大小等信息。下面是OnDrawItem消息的实现代码:view plaincopy to clipboardprint?
    void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis)   
    {   
        CBrush *brush = new CBrush;   
        CPen *pen = new CPen;   
        CString strText;   
        CDC *pDC = CDC::FromHandle(lpdis->hDC); //获取菜单项的设备句柄   
        //菜单项是否为选中状态   
        if ((lpdis->itemState & ODS_SELECTED))   
        {   
            //在菜单项上自绘矩形框的背景颜色   
            brush->CreateSolidBrush(RGB(182, 189,210));   
            //在菜单项自绘矩形的边框颜色   
            pen->CreatePen(PS_SOLID, 1, RGB(10,36,106));   
            //设置菜单项的文字背景颜色   
            pDC->SetBkColor(RGB(182,189,210));   
        }   
        else  
        {   
            brush->CreateSolidBrush(GetSysColor(COLOR_MENU));   
            pen->CreatePen(PS_SOLID, 0, GetSysColor(COLOR_MENU));   
            pDC->SetBkColor(GetSysColor(COLOR_MENU));   
        }   
        pDC->SelectObject(pen);   
        pDC->SelectObject(brush);   
        //在当前菜单项上画一个矩形框   
        pDC->Rectangle(lpdis->rcItem.left,   
            lpdis->rcItem.top,   
            lpdis->rcItem.right,   
            lpdis->rcItem.bottom);   
        /*--------------------------------------*/  
        //获取当前消息所在菜单项的文本   
        CMenu menu;   
        menu.Attach((HMENU)lpdis->hwndItem);   
        menu.GetMenuStringW(lpdis->itemID, strText,MF_BYCOMMAND);   
        /*--------------------------------------*/  
        //如果为菜单发出的DrawItem消息   
        if (nIDCtl == 0)   
        {   
            //在菜单项上输出菜单文本   
            pDC->TextOutW(lpdis->rcItem.left + 20, lpdis->rcItem.top + 4, strText.GetBuffer(0), strText.GetLength());   
        }   
        menu.Detach();   
        delete brush;   
        delete pen;   
    }