⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menubar.cpp

📁 一个多窗口的浏览器的程序benbrowse
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    {
        CWinAppEx* pApp = CWinAppEx::GetInstance();

        // Create new popup menu
        CMenu menu;
        VERIFY( menu.CreatePopupMenu() );

        TCHAR szBuffer[ MAX_PATH ];
        MENUITEMINFO mii;
        mii.cbSize = sizeof( mii );

        // Populate popup menu by adding clipped items
        UINT nItems = pMenu->GetMenuItemCount();
        for ( UINT nIndex = 0; nIndex < nItems; nIndex++ )
        {
            if ( IsItemClipped( nIndex + 1 ) )
            {
                mii.fMask      = MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
                mii.dwTypeData = szBuffer;
                mii.cch        = sizeof( szBuffer ) / sizeof( szBuffer[ 0 ] );
                VERIFY( pMenu->GetMenuItemInfo( nIndex, &mii, TRUE ) );

                UINT nMenuItems = menu.GetMenuItemCount();
                if ( ( nMenuItems > 0 ) || !( mii.fType & MFT_SEPARATOR ) )
                {
                    VERIFY( ::InsertMenuItem( menu.m_hMenu, nMenuItems, TRUE, &mii ) );
                }
            }
        }

        // Populate popup menu by adding menu items for clipped sys-buttons
        if ( m_hWndMDIChild != 0 )
        {
            CMenu* pSysMenu = CMenu::FromHandle( ::GetSystemMenu( m_hWndMDIChild, FALSE ) );
            ASSERT( pSysMenu != 0 );

            if ( menu.GetMenuItemCount() > 0 )
            {
                VERIFY( menu.AppendMenu( MF_SEPARATOR ) );
            }

            CRect rcClient;
            GetClientRect( rcClient );

            for ( int nIndex = 0; nIndex <= m_aMenuBarButtons.GetUpperBound(); nIndex++ )
            {
                CMenuBarButton* pButton = m_aMenuBarButtons[ nIndex ];
                if ( pButton->GetButtonRect().right > rcClient.right )
                {
                    UINT nID = pButton->GetSysCommandID();
                    if ( pApp->IsWin98_2K() )
                    {
                        MENUITEMINFO_WIN50 mii;
                        mii.cbSize     = sizeof( mii );
                        mii.fMask      = MIIM_ID | MIIM_STATE | MIIM_FTYPE | MIIM_STRING | MIIM_BITMAP;
                        mii.dwTypeData = szBuffer;
                        mii.cch        = sizeof( szBuffer ) / sizeof( szBuffer[ 0 ] );
                        VERIFY( pSysMenu->GetMenuItemInfo( nID, &mii ) );

                        mii.fState    &= ~MFS_DEFAULT;
                        VERIFY( ::InsertMenuItem( menu.m_hMenu, menu.GetMenuItemCount(), TRUE, &mii ) );
                    }
                    else
                    {
                        mii.fMask      = MIIM_STATE | MIIM_TYPE;
                        mii.dwTypeData = szBuffer;
                        mii.cch        = sizeof( szBuffer ) / sizeof( szBuffer[ 0 ] );
                        VERIFY( pSysMenu->GetMenuItemInfo( nID, &mii ) );

                        mii.fState    &= ~MFS_DEFAULT;
                        VERIFY( menu.AppendMenu( mii.fState | MF_STRING, nID, szBuffer ) );
                    }
                }
            }
        }

        // Expand sub-menu item, if requested
        if ( nItem >= 0 )
        {
            CString strText;
            GetButtonText( nItem, strText );

            for ( int nPos = 0; strText[ nPos ]; nPos++ )
            {
                if ( strText[ nPos ] == _T('&') )
                {
                    nPos++;

                    if ( strText[ nPos ] && ( strText[ nPos ] != _T('&') ) )
                    {
                        // Simulate hot key press
                        ::keybd_event( strText[ nPos ], 0, 0, 0 );
                        ::keybd_event( strText[ nPos ], 0, KEYEVENTF_KEYUP, 0 );
                        break;
                    }
                }
            }
        }

        // Now, just track menu
        TPMPARAMS tpm;
        tpm.cbSize    = sizeof( tpm );
        tpm.rcExclude = rcChevron;

        CWinAppEx::TrackPopupMenuEx( menu.m_hMenu,
            TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL | ( pApp->IsWin98_2K() ? TPM_VERPOSANIMATION : 0 ),
            rcChevron.left, rcChevron.bottom, GetParentFrame(), &tpm );

        // Clean-up
        while ( menu.RemoveMenu( 0, MF_BYPOSITION ) );
        VERIFY( menu.DestroyMenu() );
    }
}

void CMenuBar::TrackPopupMenu()
{
    ASSERT( m_hMenu != 0 );

    CWinAppEx* pApp = CWinAppEx::GetInstance();
    UINT nMenuAnimation = TPM_VERPOSANIMATION;
    for ( int nItem = m_nItem; m_bContinue; nItem = m_nItem )
    {
        // Get popup menu to be tracked
        m_hMenuTracking = ( nItem == 0 ) ?
            ::GetSystemMenu( m_hWndMDIChild, FALSE ) :
            ::GetSubMenu( m_hMenu, nItem - 1 );
        if ( m_hMenuTracking == 0 )
        {
            ASSERT( false );
            break;
        }

        CToolBarCtrl& tbCtrl = GetToolBarCtrl();
        tbCtrl.PressButton( GetItemID( nItem ), TRUE );

        if ( m_bSelectFirst )
        {
            // Select first menu item
            ::keybd_event( VK_DOWN, 0, 0, 0 );
            ::keybd_event( VK_DOWN, 0, KEYEVENTF_KEYUP, 0 );
        }

        CRect rc;
        tbCtrl.GetItemRect( nItem, rc );
        ClientToScreen( rc );

        TPMPARAMS tpm;
        tpm.cbSize    = sizeof( tpm );
        tpm.rcExclude = rc;

        m_bPrimaryMenu = false;
        m_bSubmenuItem = false;
        m_bContinue    = false;

        // Install message hook
        m_bItemDropped = true;
        m_pMenuBar     = this;
        m_hMsgHook     = ::SetWindowsHookEx( WH_MSGFILTER, MessageProc, 0, ::GetCurrentThreadId() );
        ASSERT( m_hMsgHook != 0 );

        CWinAppEx::TrackPopupMenuEx( m_hMenuTracking,
            TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL | ( pApp->IsWin98_2K() ? nMenuAnimation : 0 ),
            rc.left, rc.bottom, GetParentFrame(), &tpm );

        // Uninstall message hook
        VERIFY( ::UnhookWindowsHookEx( m_hMsgHook ) );
        m_hMsgHook      = 0;
        m_pMenuBar      = 0;
        m_hMenuTracking = 0;
        m_bItemDropped  = false;

        tbCtrl.PressButton( GetItemID( nItem ), FALSE );

        if ( pApp->IsWin2K() )
        {
            // W2K: use animation only for the first menu
            nMenuAnimation = TPM_NOANIMATION;
        }
    }
}

void CMenuBar::ContinueTracking( bool bSelectFirst )
{
    GetParentFrame()->PostMessage( WM_CANCELMODE );   // close currently tracked menu

    m_bSelectFirst = bSelectFirst;
    m_bContinue    = true;
}

void CMenuBar::ExitTrackingMode()
{
    if ( m_bItemTracking )
    {
        GetToolBarCtrl().SetHotItem( -1 );

        // Restore focus
        if ( ( GetFocus() == this ) && ::IsWindow( m_hWndOldFocus ) )
        {
            ::SetFocus( m_hWndOldFocus );
        }

        // Release capture
        if ( GetCapture() == this )
        {
            VERIFY( ReleaseCapture() );
        }

        m_bItemTracking = false;
        m_hWndOldFocus  = 0;
    }
}

void CMenuBar::ShowChevronMenu( int nItem )
{
    if ( m_bItemDropped )
    {
        GetParentFrame()->PostMessage( WM_CANCELMODE );   // close currently tracked menu
    }

    GetParentReBarCtrl().PostMessage( RB_PUSHCHEVRON, GetParentBandIndex(), nItem + 1 );
}

bool CMenuBar::IsItemClipped( int nItem ) const
{
    CRect rcClient;
    GetClientRect( rcClient );

    CRect rcItem;
    GetToolBarCtrl().GetItemRect( nItem, rcItem );

    return ( rcItem.right > rcClient.right );
}

bool CMenuBar::IsOverChevron( CPoint pt ) const
{
    CPoint ptScreen( pt );
    ClientToScreen( &ptScreen );

    CReBarCtrl& rbCtrl = GetParentReBarCtrl();

    // Is mouse over parent re-bar control?
    if ( WindowFromPoint( ptScreen ) == &rbCtrl )
    {
        MapWindowPoints( &rbCtrl, &pt, 1 );

        RBHITTESTINFO rbht;
        rbht.pt = pt;

        // Is mouse over chevron of the parent band?
        return ( ( rbCtrl.HitTest( &rbht ) != -1 ) &&
            ( rbht.flags == RBHT_CHEVRON ) &&
            ( rbht.iBand == GetParentBandIndex() ) );
    }

    return false;
}

/////////////////////////////////////////////////////////////////////////////
// Overrides

void CMenuBar::OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler )
{
    CMDIFrameWnd* pMDIFrame = DYNAMIC_DOWNCAST( CMDIFrameWnd, GetParentFrame() );
    if ( pMDIFrame != 0 )
    {
        // Check active MDI child
        BOOL bMaximized;
        CMDIChildWnd* pActive = pMDIFrame->MDIGetActive( &bMaximized );

        bool bSysMenu = ( pActive != 0 ) && ( pActive->GetStyle() & WS_SYSMENU ) && bMaximized;
        HWND hWndMDIChild = bSysMenu ? pActive->GetSafeHwnd() : 0;

        // Is it new MDI child?
        if ( hWndMDIChild != m_hWndMDIChild )
        {
            m_hWndMDIChild = hWndMDIChild;

            for ( int nIndex = 0; nIndex <= m_aMenuBarButtons.GetUpperBound(); nIndex++ )
            {
                m_aMenuBarButtons[ nIndex ]->SetMDIChild( m_hWndMDIChild );
            }

            UpdateMenuBar();
        }
    }

    CWinAppEx* pApp = CWinAppEx::GetInstance();
    if ( pApp->IsWin2K() && !m_bItemTracking )
    {
        BOOL bAltDown = ( ::GetKeyState( VK_MENU ) & 0x8000 );
        BOOL bF10Down = ( ::GetKeyState( VK_F10  ) & 0x8000 );
        DWORD dwDTFlags = ( pApp->GetMenuUnderlines() || bAltDown || bF10Down ) ? 0 : DT_HIDEPREFIX;
        if ( GetToolBarCtrl().SetDrawTextFlags( DT_HIDEPREFIX, dwDTFlags ) != dwDTFlags )
        {
            Invalidate();
        }
    }

    CToolBar::OnUpdateCmdUI( pTarget, bDisableIfNoHndler );
}

int CMenuBar::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
/*    UINT nTipID = ( UINT )-1;

    if ( CWinAppEx::GetInstance()->IsWin98_2K() ) // W98/W2K specific
    {
        // If mouse is over any of the sys-buttons, show corresponding tooltip
        for ( int nIndex = 0; nIndex <= m_aMenuBarButtons.GetUpperBound(); nIndex++ )
        {
            CMenuBarButton* pButton = m_aMenuBarButtons[ nIndex ];
            if ( pButton->HitTest( point ) )
            {
                switch ( pButton->GetSysCommandID() )
                {
                    case SC_CLOSE:
                        nTipID = IDS_TOOLTIP_CLOSE;
                        break;
                    case SC_MINIMIZE:
                        nTipID = IDS_TOOLTIP_MINIMIZE;
                        break;
                    case SC_MAXIMIZE:
                        nTipID = IDS_TOOLTIP_MAXIMIZE;
                        break;
                    case SC_RESTORE:
                        nTipID = IDS_TOOLTIP_RESTORE;
                        break;
                }

                if ( ( nTipID != ( UINT )-1 ) && ( pTI != 0 ) )
                {
                    pTI->uFlags   = TTF_TRANSPARENT;
                    pTI->rect     = pButton->GetButtonRect();
                    pTI->hwnd     = m_hWnd;
                    pTI->uId      = nTipID;
                    pTI->lpszText = LPSTR_TEXTCALLBACK;
                }

                break;
            }
        }
    }

    return nTipID;  //*/
	return 	CToolBar::OnToolHitTest( point, pTI );
}

/////////////////////////////////////////////////////////////////////////
// CMenuBar message handlers

BEGIN_MESSAGE_MAP(CMenuBar, CToolBar)
    //{{AFX_MSG_MAP(CMenuBar)
    ON_WM_RBUTTONDOWN()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONDBLCLK()
    ON_WM_CAPTURECHANGED()
    ON_WM_KEYDOWN()
    ON_WM_SYSKEYDOWN()
    ON_WM_KILLFOCUS()
    ON_WM_GETDLGCODE()
    ON_WM_SETTINGCHANGE()
    //}}AFX_MSG_MAP

    ON_MESSAGE( WM_MB_SHOWPOPUPMENU, OnShowPopupMenu )
    ON_MESSAGE( WM_REBAR_CHILDSIZE, OnReBarChildSize )
    ON_MESSAGE( WM_REBAR_CHEVRONPUSHED, OnReBarChevronPushed )

    ON_UPDATE_COMMAND_UI_REFLECT( OnUpdateCommandUI )

	ON_UPDATE_COMMAND_UI_RANGE(IDBUTTON_FIRST, IDBUTTON_LAST, OnUpdateMenuButton)
    // Toolbar control notifications
    ON_NOTIFY_REFLECT( TBN_DROPDOWN, OnDropDown )
    ON_NOTIFY_REFLECT( TBN_HOTITEMCHANGE, OnHotItemChange )
    ON_NOTIFY_REFLECT( NM_CUSTOMDRAW, OnCustomDraw )
END_MESSAGE_MAP()

bool CMenuBar::OnButtonDown( UINT nFlags, CPoint pt, bool bLeft )
{
    if ( m_bItemTracking && !m_bItemDropped )
    {
        ClientToScreen( &pt );
        CWnd* pWnd = WindowFromPoint( pt );
        if ( pWnd != this )
        {
            // It's a good idea to allow user exit tracking mode
            // by clicking mouse anywhere outside the menu bar.
            ExitTrackingMode();

            // It would be also nice to forward this event to
            // the window the user has just clicked.
            if ( pWnd != 0 )
            {
                LPARAM nPosition = MAKELPARAM( pt.x, pt.y );
                WPARAM nHitTest  = pWnd->SendMessage( WM_NCHITTEST, 0, nPosition );

                // Is over client area of the window?
                if ( nHitTest == HTCLIENT )
                {
                    pWnd->ScreenToClient( &pt );
                    LPARAM nPosition = MAKELPARAM( pt.x, pt.y );
                    pWnd->PostMessage( bLeft ? WM_LBUTTONDOWN : WM_RBUTTONDOWN,
                        nFlags, nPosition );
                }
                else
                {
                    pWnd->PostMessage( bLeft ? WM_NCLBUTTONDOWN : WM_NCRBUTTONDOWN,
                        nHitTest, nPosition );
                }
            }

            return false;
        }
    }

    return true;
}

void CMenuBar::OnRButtonDown( UINT nFlags, CPoint point )
{
    if ( OnButtonDown( nFlags, point, false ) )
    {
        CToolBar::OnRButtonDown( nFlags, point );
    }
}

void CMenuBar::OnLButtonDown( UINT nFlags, CPoint point )
{
    if ( OnButtonDown( nFlags, point, true ) )
    {
        // Was it over any of the sys-buttons?
        for ( int nIndex = 0; nIndex <= m_aMenuBarButtons.GetUpperBound(); nIndex++ )
        {
            CMenuBarButton* pButton = m_aMenuBarButtons[ nIndex ];
            if ( pButton->IsEnabled() && pButton->HitTest( point ) )
            {
                ExitTrackingMode(); // just in case

                pButton->PushButton( true );
                RedrawWindow( pButton->GetButtonRect(), 0,
                    RDW_INVALIDATE | RDW_ERASE );   // visual feedback

                SetCapture();
                m_bButtonCapture = true;
                return;
            }
        }

        CToolBar::OnLButtonDown( nFlags, point );
  }
}

void CMenuBar::OnLButtonUp( UINT nFlags, CPoint point )
{
    if ( m_bButtonCapture )
    {
        // Was it over any of the sys-buttons?
        for ( int nIndex = 0; nIndex <= m_aMenuBarButtons.GetUpperBound(); nIndex++ )
        {
            CMenuBarButton* pButton = m_aMenuBarButtons[ nIndex ];
            if ( pButton->IsEnabled() && pButton->HitTest( point ) )
            {
                pButton->PushButton( false );
                RedrawWindow( pButton->GetButtonRect(), 0,
                    RDW_INVALIDATE | RDW_ERASE );   // visual feedback

                // Send corresponding sys-command
                ::PostMessage( m_hWndMDIChild, WM_SYSCOMMAND, pButton->GetSysCommandID(), 0 );
                break;
            }
        }

        VERIFY( ReleaseCapture() );
        m_bButtonCapture = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -