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