📄 menubar.cpp
字号:
{
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 + -