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

📄 hsmenu.cpp

📁 漂亮菜单
💻 CPP
📖 第 1 页 / 共 3 页
字号:
int CHSMenu::GetMenuPosition(UINT uID) const
{
	return GetItemIndex( uID, MF_BYCOMMAND );
}

void CHSMenu::SetCustomMenu(PFNCUSTOMMENU pfnAddress)
{
	m_pfnCustomMenu = pfnAddress;
}

void CHSMenu::SetCustomMenuItem(PFNCUSTOMMENUITEM pfnAddress)
{
	m_pfnCustomMenuItem = pfnAddress;
}

// Get menu item id by position
UINT CHSMenu::GetMenuID(int nPosition) const
{
	if ( nPosition < 0 || nPosition >= m_qMenuItem.size() ) 
		return 0;

	return ( m_qMenuItem[nPosition].m_uID );
}

void CHSMenu::GetMenuCXY(int &nMenuWidth, int &nMenuHeight)
{
	m_nMenuHeight	= m_nMenuEdge*2 + MENUCAPTION;
	m_nMenuWidth	= m_nMenuEdge*2 + 0;

	int nTotalItem = m_qMenuItem.size();

	for ( int nIndex=0; nIndex<nTotalItem; nIndex++ )
	{
		MEASUREITEMSTRUCT	mis;

		mis.itemData = nIndex;
		MeasureItem( &mis );

		m_qMenuItem[nIndex].m_nTop	  = m_nMenuHeight - mis.itemHeight - m_nMenuEdge ;
		m_qMenuItem[nIndex].m_nHeight = mis.itemHeight;
	}

	nMenuWidth  = m_nMenuWidth;
	nMenuHeight = m_nMenuHeight;
}

void CHSMenu::SetMenuAnimate(UINT nType, UINT nStep, UINT nDelay, BOOL bAnimateMenu )
{
	if ( bAnimateMenu )
	{
		m_nMenuAniType  = nType;
		m_nMenuAniStep	= nStep;
		m_nMenuAniDelay = nDelay;
	}
	else
	{
		m_nItemAniType  = nType;
		m_nItemAniStep	= nStep;
		m_nItemAniDelay = nDelay;
	}
}

UINT CHSMenu::GetMenuAnimateType( BOOL bAnimateMenu )
{
	return bAnimateMenu ? m_nMenuAniType : m_nItemAniType;
}

UINT CHSMenu::GetMenuAnimateStep( BOOL bAnimateMenu )
{
	return bAnimateMenu ? m_nMenuAniStep : m_nItemAniStep;
}

UINT CHSMenu::GetMenuAnimateDelay( BOOL bAnimateMenu )
{
	return bAnimateMenu ? m_nMenuAniDelay : m_nItemAniDelay;
}

// Static FN Set Menu Font
void CHSMenu::SetMenuFont(HFONT hFont)
{
	m_hFont = ( hFont ? hFont : (HFONT)GetStockObject( DEFAULT_GUI_FONT ) );
}

HFONT CHSMenu::GetMenuFont( void )
{
	return m_hFont;
}

//Static FN Set menu edge width
void CHSMenu::SetMenuEdge(int nEdge)
{
	m_nMenuEdge = ( nEdge <= 0 ? 1 : nEdge );
}

//Static FN Get menu edge width
UINT CHSMenu::GetMenuEdge() const
{
	return m_nMenuEdge;
}

//Static FN Set submenu popup delay time
void CHSMenu::SetMenuPopDelay(UINT nDelay)
{
	m_nPopupDelay = nDelay;
}

//FN Set menu item height
void CHSMenu::SetMenuItemHeight(int nHeight)
{
	m_nMenuItemHeight = ( ( nHeight - 4 ) > m_nFontHeight ? nHeight : m_nFontHeight + 4 ) ;
}

//Static FN Set the menu color which you want to change
void CHSMenu::SetColor(int nIndex, COLORREF clrSet )
{
	if ( nIndex >= 0 && nIndex < CLRCOUNT_BASE )
		m_clrMenu[nIndex] = clrSet;
}

//Static FN Set menu Separator height 
void CHSMenu::SetSeparatorHeight(int nHeight)
{
	m_nSprHeight = abs( nHeight );
}

//Static FN  Get menu separator height
int CHSMenu::GetSeparatorHeight()
{
	return m_nSprHeight;
}

//Static FN Get submenu popup delay time
UINT CHSMenu::GetMenuPopDelay() 
{
	return m_nPopupDelay;
}

//FN Get menu item height
int CHSMenu::GetMenuItemHeight() 
{
	return m_nMenuItemHeight;
}

//Static FN Get menu color which you want to know
COLORREF CHSMenu::GetColor(int nIndex)
{
	if ( nIndex >= 0 && nIndex < CLRCOUNT_BASE )
		 return m_clrMenu[nIndex];
	
	return -1;
}

void CHSMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
	HSITEM& MenuItem = m_qMenuItem[lpMIS->itemData];

	HGDIOBJ hfntOld;
	SIZE	sizeText;

	// To Get New Item Name width
	HDC	hDC = CreateIC( "DISPLAY", NULL, NULL, NULL );
	hfntOld = SelectObject( hDC, m_hFont );
	GetTextExtentPoint32( hDC, MenuItem.m_strName.c_str(), MenuItem.m_strName.length(), &sizeText );
	SelectObject( hDC, hfntOld );
	DeleteDC( hDC );
////////
	if ( MenuItem.m_uFlags & ITEM_SEPARATOR )
		 lpMIS->itemHeight = m_nSprHeight;	
	else
	{
		m_nFontHeight = sizeText.cy;

		if ( sizeText.cy > m_nMenuItemHeight )
			  lpMIS->itemHeight = sizeText.cy + 2 ;
		 else lpMIS->itemHeight = m_nMenuItemHeight;
	}

	lpMIS->itemWidth  = sizeText.cx;
///////
	if ( sizeText.cx + 75 > m_nMenuWidth - m_nMenuEdge*2 )
		 m_nMenuWidth = sizeText.cx + 75 + m_nMenuEdge*2;

	m_nMenuHeight += lpMIS->itemHeight;
}


// ( Point x and y is Screen point )
void CHSMenu::ResetDispPoint( int& x, int& y)
{
	static RECT	rectScreen;
	static BOOL bNoGet = TRUE;
	
	// Get System Screen Rectangle
	if ( bNoGet )
	{
		SystemParametersInfo( SPI_GETWORKAREA, 0, &rectScreen, 0 );
		bNoGet = FALSE;
	}

	if ( x + m_nMenuWidth > rectScreen.right )
	{
		if ( m_pParent )
			 x = x - m_nMenuWidth - m_pParent->CHSMenu::m_nMenuWidth + m_nMenuEdge*2;
		else x = x - m_nMenuWidth;
	}

	if ( y + m_nMenuHeight > rectScreen.bottom )
	{
		if ( m_pParent )
		{
			HSITEM& MenuItem = m_pParent->m_qMenuItem[m_pParent->m_nCurSel];

			 y = y - m_nMenuHeight + MenuItem.m_nHeight + m_nMenuEdge*2;
		}
		else y = y - m_nMenuHeight;
	}

	if ( x < 0 )	x = 0;
	if ( y < 0 )	y = 0;
}

// Display and track menu
UINT CHSMenu::TrackPopMenu(short x, short y, HWND hwndParent, UINT uFlag)
{
	int nX = x, nY = y;

	m_hWndParent = hwndParent;

	GetMenuCXY( m_nMenuWidth, m_nMenuHeight );
	ResetDispPoint( (int&)nX, (int&)nY );

	// Create Menu Window
	m_hMenu = ::CreateWindowEx( WS_EX_TOOLWINDOW|WS_EX_TOPMOST,
								"HSMENU_PRODUCT_BY_HANSONG",
								"",
								WS_POPUP,
								nX,
								nY,
								m_nMenuWidth,
								m_nMenuHeight,
								m_hWndParent,
								NULL,
								AfxGetInstanceHandle(),
								(LPVOID)this );

	if ( !m_hMenu )	return FALSE;

	HRGN hrgnMenu = CreateRectRgn( 0, 0, m_nMenuWidth, m_nMenuHeight );
	::SetWindowRgn( m_hMenu, hrgnMenu, TRUE );
	::DeleteObject( hrgnMenu );

	if ( m_pfnCustomMenu && m_qMenuItem.size() )
		 m_pfnCustomMenu( m_hMenu );

	::ShowWindow( m_hMenu, SW_SHOW );

	::ReleaseCapture();
	::SetCapture( m_hMenu );
//	m_ulMenuFlag |= MENU_HASCAPTURE;

	if ( m_pParent )
	{
		m_pParent->CHSMenu::SetState( MENU_POPUPED, TRUE );
		m_pParent->CHSMenu::m_nCurPop = m_pParent->CHSMenu::m_nCurSel;
	}

	m_nCurSel = SELNONE;
	m_nCurPop = SELNONE;

	MSG	Msg;

	while ( GetMessage( &Msg, NULL, 0, 0 ) && IsWindow( m_hMenu ) )
	{
		TranslateMessage( &Msg );
		DispatchMessage( &Msg );
	}

	if ( m_nCurSel != SELNONE )
		return m_qMenuItem[m_nCurSel].m_uID;

	return (UINT)0;
}

// Update the Menu Item be Selected now
int CHSMenu::GetNewSel(short x, short y)
{
	int iend  = m_qMenuItem.size();

	// Outside menu active area ?
	if ( !(	x > m_nMenuEdge &&
			y > m_nMenuEdge &&
			x < m_nMenuWidth  - m_nMenuEdge &&
			y < m_nMenuHeight - m_nMenuEdge &&
			iend != 0
		  )
		) return SELNONE;

	// if current selected item Isn't none, Use it 
	// else find start at middle
	int index = ( m_nCurSel != SELNONE ) ? m_nCurSel : iend / 2;

	while ( TRUE )
	{
		HSITEM& MenuItem = m_qMenuItem[index];

		if ( y > MenuItem.m_nTop )
		{
			if ( y <= ( MenuItem.m_nTop + MenuItem.m_nHeight ) )
				return index;

			if ( ++index >= iend )	return SELNONE;
		}
		else
		{
			if ( --index < 0 )  return SELNONE;
		}
	}
}

// Get HSMenu When Mouse Move to SubMenu or Form Sub to Parent
CHSMenu* CHSMenu::GetNewMenu(HWND hWnd, short x, short y)
{
	HWND	hWndPoint;
	TCHAR	sClassName[50];
	POINT	pt;

	pt.x = x;
	pt.y = y;

	::ClientToScreen( hWnd, &pt );

	if ( ( hWndPoint = ::WindowFromPoint( pt ) ) == NULL )	return this;
	GetClassName( hWndPoint, sClassName, sizeof(sClassName)/sizeof(TCHAR) );
	// If it isn't CHSMenu Class return this menu, Mean no change Capture
	if ( lstrcmp( sClassName, "HSMENU_PRODUCT_BY_HANSONG" ) )	return this;

	// Return the CHSMenu Pointer, Have mouse Focus
	return ( ( CHSMenu* )( GetWindowLong( hWndPoint, GWL_USERDATA ) ) ); 
}

//void CHSMenu::OnChar( HWND hWnd, char c )
//{
//}

void CHSMenu::OnKeyDown( HWND hWnd, UINT nChar, UINT nRepCnt, UINT nFlags)
{
	int nNewSel = m_nCurSel;
	int nOldSel = m_nCurSel;
	int nCount  = m_qMenuItem.size();
	
	nCount <= 0 ? nChar = VK_ESCAPE : nOldSel %= nCount;

	switch( nChar )
	{
		case VK_DOWN:
			if ( m_nCurSel == SELNONE ) 
			{
				nNewSel = -1;
				nOldSel = SELNONE;
			}

			do
			{
				nNewSel = ( nNewSel + 1 ) % nCount;
			}while ( m_qMenuItem[nNewSel].m_uFlags & ITEM_SEPARATOR );

			RedrawItem( hWnd, nNewSel, nOldSel );
			break;

		case VK_UP:
			if ( m_nCurSel == SELNONE ) 
			{
				nNewSel = nCount;
				nOldSel = SELNONE;
			}

			do
			{
				nNewSel = nNewSel ? ( nNewSel - 1 ) % nCount : nCount - 1;
			}while ( m_qMenuItem[nNewSel].m_uFlags & ITEM_SEPARATOR );

			RedrawItem( hWnd, nNewSel, nOldSel );
			break;

		case VK_RIGHT:
			if ( m_nCurSel != SELNONE )
			{
				const HSITEM& MenuItem = m_qMenuItem[m_nCurSel];

				if ( MenuItem.m_pPopupHSMenu && !( MenuItem.m_uFlags & ( ITEM_GRAY | ITEM_DISABLE ) ) )
				{
					POINT	ptDisp;	
					ptDisp.x = m_nMenuWidth - m_nMenuEdge;
					ptDisp.y = MenuItem.m_nTop - m_nMenuEdge;
					::ClientToScreen( hWnd, &ptDisp );
					// track the new menu
					MenuItem.m_pPopupHSMenu->TrackPopMenu( ptDisp.x, ptDisp.y, m_hWndParent );
				}
			}
			break;

		case VK_LEFT:
			if ( m_pParent )
			{
				::ReleaseCapture();
				::SetActiveWindow( m_pParent->CHSMenu::m_hMenu );
				::SetCapture( m_pParent->CHSMenu::m_hMenu );
				DestroyMenu();
			}
			break;

		case VK_ESCAPE:
			if ( m_pParent )
			{
				::ReleaseCapture();
				::SetActiveWindow( m_pParent->CHSMenu::m_hMenu );
				::SetCapture( m_pParent->CHSMenu::m_hMenu );
			}
			DestroyMenu();
			break;		
			
//		case VK_LWIN:
//		case VK_RWIN:
//			DestroyAllMenu();
			break;

		case VK_SPACE:
		case VK_RETURN:
			if ( IsEffectItem() )
			{
				DestroyAllMenu();
				::SendMessage( m_hWndParent, WM_COMMAND, MAKEWORD( m_qMenuItem[m_nCurSel].m_uID, 0 ),0 );
			}
	}
}
/*
void CHSMenu::OnKeyUp( HWND hWnd, UINT nChar, UINT nRepCnt, UINT nFlags)
{
}
*/

// Mouse Move Message
void CHSMenu::OnMouseMove(HWND hWnd, short x, short y)
{
	// No need to Call function "GetNewMenu" when this menu have no submenu
	if ( GetState( MENU_POPUPED ) || GetState( MENU_CHILD) )
	{
		CHSMenu *pNewMenu;
		// If Mouse move on a other HSMenu Change Capture
		if ( ( pNewMenu = GetNewMenu( hWnd, x, y ) ) != this )
		{
			if ( m_nCurSel != m_nCurPop )
			{
				RedrawItem( hWnd, m_nCurPop, m_nCurSel );
				TimerDelay( hWnd );
			}

			::ReleaseCapture();
			// Reset Capture To New (Under Point)Menu
//			::SetActiveWindow( pNewMenu->m_hMenu );
			::SetCapture( pNewMenu->m_hMenu );
			return;
		}
	}

	// Get the new item be selected now
	int	nNewSel = GetNewSel( x, y );
	// if Select no change return
	if ( nNewSel != m_nCurSel )
	{
		RedrawItem( hWnd, nNewSel, m_nCurSel );
		TimerDelay( hWnd );
	}
}

void CHSMenu::RedrawItem(HWND hWnd, int nCurSel, int nOldSel)
{
	DRAWITEMSTRUCTPRO	disp;

	disp.hDC = ::GetDC( hWnd );
	disp.rect.left  = m_nMenuEdge;
	disp.rect.right	= m_nMenuWidth - m_nMenuEdge;
	
	// Clear Old selected item background
	if ( nOldSel != SELNONE )
	{	
		SetState( MENU_SELECTED, FALSE );		// Flag for Clear

		HSITEM& MenuItem = m_qMenuItem[nOldSel];

		disp.ulData		 = MenuItem.m_ulData;
		disp.uFlags		 = MenuItem.m_uFlags | m_uMenuFlag;
		disp.lpcStr		 = MenuItem.m_strName.c_str();	
		disp.rect.top	 = MenuItem.m_nTop;
		disp.rect.bottom = MenuItem.m_nTop + MenuItem.m_nHeight;

		DrawItemAnimation( &disp );
	}

	// Draw the new select item background
	if ( nCurSel != SELNONE )
	{
		SetState( MENU_SELECTED, TRUE );	// Draw Select 

		HSITEM& MenuItem = m_qMenuItem[nCurSel];

		disp.ulData		 = MenuItem.m_ulData;
		disp.uFlags		 = MenuItem.m_uFlags | m_uMenuFlag;
		disp.lpcStr		 = MenuItem.m_strName.c_str();	
		disp.rect.top	 = MenuItem.m_nTop;
		disp.rect.bottom = MenuItem.m_nTop + MenuItem.m_nHeight;

		DrawItemAnimation( &disp );
	}

	::ReleaseDC( hWnd, disp.hDC );
	m_nCurSel = nCurSel;
}

void CHSMenu::OnTimer(HWND hWnd, unsigned short uID)
{
	::KillTimer( hWnd, uID );

	switch ( uID )
	{ 
		case TIMERTRACK:
			if ( !GetState( MENU_POPUPED ) && m_nCurSel != SELNONE )
			{
				POINT	ptDisp;	
				const	HSITEM& MenuItem = m_qMenuItem[m_nCurSel];
				// the init disp point
				ptDisp.x = m_nMenuWidth - m_nMenuEdge ;
				ptDisp.y = MenuItem.m_nTop - m_nMenuEdge - MENUCAPTION;
				::ClientToScreen( hWnd, &ptDisp );
				// track the new menu
				MenuItem.m_pPopupHSMenu->TrackPopMenu( ptDisp.x, ptDisp.y, m_hWndParent );
			}
			else
			::SetTimer( hWnd, TIMERTRACK, 10, NULL );
			break;

		case TIMERDESTROY:
			SetState( MENU_TIMERDESTROY, FALSE );
			DestroyAllPop();
			break;
	}
}

void CHSMenu::TimerDelay(HWND hWnd)
{
	::KillTimer( hWnd, TIMERTRACK );

	if ( !GetState( MENU_TIMERDESTROY ) && GetState( MENU_POPUPED ) )
	{
		SetState( MENU_TIMERDESTROY, TRUE );
		::SetTimer( hWnd, TIMERDESTROY, m_nPopupDelay, NULL );
	}

	// Draw the new select item background
	if ( m_nCurSel != SELNONE )
	{
		if ( m_nCurSel == m_nCurPop )
		{
			::KillTimer( hWnd, TIMERTRACK );
			::KillTimer( hWnd, TIMERDESTROY );
			SetState( MENU_TIMERDESTROY, FALSE );
		}
		else	// Popup a New Menu ?
		{
			const HSITEM& MenuItem = m_qMenuItem[m_nCurSel];

			if (  MenuItem.m_pPopupHSMenu && !(MenuItem.m_uFlags & ITEM_GRAY) )
			{
				::SetTimer( hWnd, TIMERTRACK, m_nPopupDelay, NULL );
			}
		}
	}
}

void CHSMenu::DrawAnimateMenuItem(RECT *pRect, HDC hDC, HDC hDCMem, int nType, int nStep, int nTimeDelay)
{
	DrawAnimation( pRect, hDC, hDCMem, nType, nStep, nTimeDelay ); 
/*
	int nWidth		= pRect->right	- pRect->left;
	int nHeight		= pRect->bottom	- pRect->top;
	::BitBlt( hDC, pRect->left, pRect->top, nWidth, nHeight, hDCMem, 0, 0, SRCCOPY );
*/

⌨️ 快捷键说明

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