疯子的博客

做一件事,专注一件事
MFC笔记—关于的两个问题菜单
  1. 对话框窗口中使用ON_UPDATE_COMMAND_UI消息更新菜单状态。

    默认情况下使不能使用的,因为在下拉菜单显示的时候WM_INITMENUPOPUP消息被先发送以显示菜单项,MFC CFrameWnd::OnInitMenuPopup 函数遍历菜单项并为每个菜单项调用更新命令处理函数(如果有的话),但是对话框中并没有WM_INITMENUPOPUP的消息处理,我怕们可以把 CFrameWnd的超过来用。

  2. 动态定制邮件菜单

    有的时候会使用一个很长的邮件菜单,根据当前点击的位置定制菜单项,不用的灰化处理,但是总觉得不太舒服。一项一项删除有点麻烦,下面利用ON_UPDATE_COMMAND_UI,再弹出菜单前自己处理菜单,删除无效的菜单项。

调用方:

CPoint pt;

    GetCursorPos( &pt );

    m_TreeCtrl->ScreenToClient( &pt );

 

    UINT uFlags;

    m_seleceditem= m_TreeCtrl->HitTest( pt, &uFlags );

    if ( ( NULL != m_seleceditem ) && ( TVHT_ONITEM & uFlags ) )

    {

        m_TreeCtrl->SelectItem( m_seleceditem );

        m_seleceditemtype=(treeitemtype)m_TreeCtrl->GetItemData(m_seleceditem);

        

        CMenu m_popMenu;

        m_popMenu.LoadMenu(IDR_CONTEXT_MENU);

        CReducedMenu* pSubMenu=(CReducedMenu*)m_popMenu.GetSubMenu(0);//将菜单类型强制转换为自定义的累

        m_TreeCtrl->ClientToScreen(&pt);

        if (true)

        {

            pSubMenu->EnableMenuItem(ID_DELETE_ITEM,MF_GRAYED);

        }

        

        pSubMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_TOPALIGN,pt.x,pt.y,this);//调用自定义的弹出菜单函数

    }

自定义类关键代码:

BOOL CReducedMenu::TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect )

{

    CullDisabledItems(this,pWnd);//弹出菜单前做删除无效菜单操作

    return CMenu::TrackPopupMenu( nFlags,x,y,pWnd,lpRect);

}

 

void CReducedMenu::CullDisabledItems( CMenu* pMenu,CWnd* pWnd )

{

    CEnabledCmdUI state;

    UINT n;

 

    for(n =0; n < pMenu->GetMenuItemCount(); n++)//遍历菜单

    {

        state.m_nID = pMenu->GetMenuItemID( n );

 

        

        if (state.m_nID == 0)

            continue;

 

        if (state.m_nID == (UINT)-1)

        {

            

            CMenu* pSub=pMenu->GetSubMenu(n);

            if(pSub)

                CullDisabledItems(pSub,pWnd);

        }

        else

        {

            pWnd->OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL);//调用消息处理菜单的CN_UPDATE_COMMAND_UI处理函数,获取菜单状态

            if( !state.m_bEnabled )

            {

                pMenu->DeleteMenu( n--, MF_BYPOSITION );//删除菜单项

            }

            state.m_bEnabled=false;

        }

    }

 

    for (n =0; n < pMenu->GetMenuItemCount(); n++)//删除多余分隔符

    {

        UINT nID = pMenu->GetMenuItemID( n );

 

        if (nID == 0 && (n == 0 || n == pMenu->GetMenuItemCount()-1) )

        {

            pMenu->DeleteMenu( n--, MF_BYPOSITION );

        }

 

        if (n > 0 && nID == 0 && pMenu->GetMenuItemID( n-1 ) == 0 )

        {

            pMenu->DeleteMenu( n--, MF_BYPOSITION );            

        }

    }        

}

posted on 2010-04-25 00:35  老陈  阅读(404)  评论(0)    收藏  举报