2024-12-21 10:04:04 +08:00
// ==========================================================================
// Class Implementation : COXBitmapMenu
// ==========================================================================
// Source file : OXBitmapMenu.cpp
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is <20> 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
# include "stdafx.h"
// v93 update 03 - 64-bit
# include "UTB64Bit.h"
# pragma warning(disable : 4706)
# include <multimon.h>
# include "OXBitmapMenu.h"
# include "OXBitmapMenuOrganizer.h"
# include "OXSkins.h"
# include "OXCoolToolBar.h"
# include "OXMenuBar.h"
# ifdef OX_CUSTOMIZE_COMMANDS
# include "OXDragDropCommands.h"
# endif // OX_CUSTOMIZE_COMMANDS
# ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE [ ] = __FILE__ ;
# endif
/////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC ( COXBitmapMenuPopupWnd , CWnd )
COXBitmapMenuPopupWnd : : COXBitmapMenuPopupWnd ( ) :
m_pBitmapMenu ( NULL ) ,
m_nCheckForDragDropEventTimerID ( 0 )
{
}
COXBitmapMenuPopupWnd : : ~ COXBitmapMenuPopupWnd ( )
{
ResetPopupMenu ( ) ;
}
BEGIN_MESSAGE_MAP ( COXBitmapMenuPopupWnd , CWnd )
//{{AFX_MSG_MAP(COXBitmapMenuPopupWnd)
ON_WM_RBUTTONUP ( )
ON_WM_LBUTTONDOWN ( )
ON_WM_MBUTTONDOWN ( )
ON_WM_RBUTTONDOWN ( )
ON_WM_PAINT ( )
ON_WM_MOUSEACTIVATE ( )
ON_WM_SETTINGCHANGE ( )
ON_WM_TIMER ( )
ON_WM_MOUSEMOVE ( )
ON_WM_NCPAINT ( )
//}}AFX_MSG_MAP
// handle drag'n'drop messages
ON_MESSAGE ( SHBDTM_DRAGENTER , OnDragEnter )
ON_MESSAGE ( SHBDTM_DRAGLEAVE , OnDragLeave )
ON_MESSAGE ( SHBDTM_DRAGOVER , OnDragOver )
ON_MESSAGE ( SHBDTM_DROP , OnDrop )
// handle advanced customization commands
ON_COMMAND ( ID_OXCUSTBM_DELETE , OnCustBMDelete )
ON_COMMAND ( ID_OXCUSTBM_APPEARANCE , OnCustBMAppearance )
ON_COMMAND ( ID_OXCUSTBM_SEPARATOR_BEFORE , OnCustBMSeparatorBefore )
ON_COMMAND ( ID_OXCUSTBM_SEPARATOR_AFTER , OnCustBMSeparatorAfter )
ON_COMMAND ( ID_OXCUSTBM_RECENTLY_USED , OnCustBMRecentlyUsed )
END_MESSAGE_MAP ( )
void COXBitmapMenuPopupWnd : : OnLButtonDown ( UINT nFlags , CPoint point )
{
TRACE ( _T ( " COXBitmapMenuPopupWnd::OnLButtonDown \n " ) ) ;
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( m_nCheckForDragDropEventTimerID = = 0 & &
pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
int nItemIndex = pMenu - > HitTest ( & point ) ;
if ( nItemIndex > = 0 & & nItemIndex < ( int ) pMenu - > GetMenuItemCount ( ) )
{
pMenu - > SetCustomizedItem ( nItemIndex ) ;
}
else
{
pMenu - > SetCustomizedItem ( - 1 ) ;
}
m_nCheckForDragDropEventTimerID = SetTimer ( IDT_OXCHECKFORDRAGDROPEVENT ,
ID_OXCHECKFORDRAGDROPEVENT_DELAY , NULL ) ;
ASSERT ( m_nCheckForDragDropEventTimerID ! = 0 ) ;
return ;
}
CWnd : : OnLButtonDown ( nFlags , point ) ;
}
void COXBitmapMenuPopupWnd : : OnMButtonDown ( UINT nFlags , CPoint point )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
int nItemIndex = pMenu - > HitTest ( & point ) ;
if ( nItemIndex > = 0 & & nItemIndex < ( int ) pMenu - > GetMenuItemCount ( ) )
{
pMenu - > SetCustomizedItem ( nItemIndex ) ;
}
else
{
pMenu - > SetCustomizedItem ( - 1 ) ;
}
return ;
}
CWnd : : OnMButtonDown ( nFlags , point ) ;
}
void COXBitmapMenuPopupWnd : : OnRButtonDown ( UINT nFlags , CPoint point )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
int nItemIndex = pMenu - > HitTest ( & point ) ;
if ( nItemIndex > = 0 & & nItemIndex < ( int ) pMenu - > GetMenuItemCount ( ) )
{
pMenu - > SetCustomizedItem ( nItemIndex ) ;
}
else
{
pMenu - > SetCustomizedItem ( - 1 ) ;
}
return ;
}
CWnd : : OnRButtonDown ( nFlags , point ) ;
}
void COXBitmapMenuPopupWnd : : OnRButtonUp ( UINT nFlags , CPoint point )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
int nCustomizedItemIndex = pMenu - > GetCustomizedItem ( ) ;
if ( nCustomizedItemIndex ! = - 1 )
{
ClientToScreen ( & point ) ;
pMenu - > DisplayCustomizeItemContextMenu ( nCustomizedItemIndex , point ) ;
return ;
}
}
CWnd : : OnRButtonUp ( nFlags , point ) ;
}
void COXBitmapMenuPopupWnd : : OnMouseMove ( UINT nFlags , CPoint point )
{
if ( m_nCheckForDragDropEventTimerID ! = 0 & & : : GetKeyState ( VK_LBUTTON ) > = 0 )
{
KillTimer ( m_nCheckForDragDropEventTimerID ) ;
m_nCheckForDragDropEventTimerID = 0 ;
}
CWnd : : OnMouseMove ( nFlags , point ) ;
}
// v9.3 - update 03 - 64-bit - return value was declared as LONG - changed to LRESULT
LRESULT COXBitmapMenuPopupWnd : : OnDragEnter ( WPARAM wParam , LPARAM lParam )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
ASSERT ( pSHBDTAction - > pWnd ) ;
ASSERT ( pSHBDTAction - > pWnd - > GetSafeHwnd ( ) = = GetSafeHwnd ( ) ) ;
return pMenu - > OnDragOver ( wParam , lParam ) ;
}
return ( LONG ) FALSE ;
}
// v9.3 - update 03 - 64-bit - return value was declared as LONG - changed to LRESULT
LRESULT COXBitmapMenuPopupWnd : : OnDragOver ( WPARAM wParam , LPARAM lParam )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
ASSERT ( pSHBDTAction - > pWnd ) ;
ASSERT ( pSHBDTAction - > pWnd - > GetSafeHwnd ( ) = = GetSafeHwnd ( ) ) ;
return pMenu - > OnDragOver ( wParam , lParam ) ;
}
return ( LONG ) FALSE ;
}
// v9.3 - update 03 - 64-bit - return value was declared as LONG - changed to LRESULT
LRESULT COXBitmapMenuPopupWnd : : OnDragLeave ( WPARAM wParam , LPARAM lParam )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
ASSERT ( pSHBDTAction - > pWnd ) ;
ASSERT ( pSHBDTAction - > pWnd - > GetSafeHwnd ( ) = = GetSafeHwnd ( ) ) ;
return pMenu - > OnDragLeave ( wParam , lParam ) ;
}
return ( LONG ) FALSE ;
}
// v9.3 - update 03 - 64-bit - return value was declared as LONG - changed to LRESULT
LRESULT COXBitmapMenuPopupWnd : : OnDrop ( WPARAM wParam , LPARAM lParam )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
ASSERT ( pSHBDTAction - > pWnd ) ;
ASSERT ( pSHBDTAction - > pWnd - > GetSafeHwnd ( ) = = GetSafeHwnd ( ) ) ;
return pMenu - > OnDrop ( wParam , lParam ) ;
}
return ( LONG ) FALSE ;
}
void COXBitmapMenuPopupWnd : : OnCustBMDelete ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
pMenu - > OnCustBMDelete ( ) ;
}
}
void COXBitmapMenuPopupWnd : : OnCustBMAppearance ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
pMenu - > OnCustBMAppearance ( ) ;
}
}
void COXBitmapMenuPopupWnd : : OnCustBMSeparatorBefore ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
pMenu - > OnCustBMSeparatorBefore ( ) ;
}
}
void COXBitmapMenuPopupWnd : : OnCustBMSeparatorAfter ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
pMenu - > OnCustBMSeparatorAfter ( ) ;
}
}
void COXBitmapMenuPopupWnd : : OnCustBMRecentlyUsed ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
pMenu - > OnCustBMRecentlyUsed ( ) ;
}
}
void COXBitmapMenuPopupWnd : : OnPaint ( )
{
CPaintDC dc ( this ) ;
int nSavedDC = dc . SaveDC ( ) ;
ASSERT ( nSavedDC ! = 0 ) ;
dc . SetTextColor ( : : GetSysColor ( COLOR_MENUTEXT ) ) ;
dc . SelectObject ( & m_fontMenu ) ;
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL )
{
ASSERT ( ( int ) pMenu - > GetMenuItemCount ( ) = = m_arrItemRects . GetSize ( ) ) ;
MENUITEMINFO mii = { sizeof ( mii ) } ;
mii . fMask = MIIM_DATA ;
DRAWITEMSTRUCT dis ;
dis . CtlType = ODT_MENU ;
dis . hDC = dc . GetSafeHdc ( ) ;
dis . itemAction = ODA_DRAWENTIRE ;
dis . CtlID = 0 ;
dis . itemState = 0 ;
dis . hwndItem = ( HWND ) pMenu - > GetSafeHmenu ( ) ;
for ( int nIndex = 0 ; nIndex < m_arrItemRects . GetSize ( ) ; nIndex + + )
{
dis . itemID = pMenu - > GetMenuItemID ( nIndex ) ;
dis . rcItem = m_arrItemRects [ nIndex ] ;
VERIFY ( : : GetMenuItemInfo ( pMenu - > GetSafeHmenu ( ) , nIndex , TRUE , & mii ) ) ;
dis . itemData = mii . dwItemData ;
pMenu - > DrawItem ( & dis ) ;
}
}
VERIFY ( dc . RestoreDC ( nSavedDC ) ) ;
}
int COXBitmapMenuPopupWnd : : OnMouseActivate ( CWnd * pDesktopWnd , UINT nHitTest ,
UINT message )
{
UNREFERENCED_PARAMETER ( pDesktopWnd ) ;
UNREFERENCED_PARAMETER ( nHitTest ) ;
UNREFERENCED_PARAMETER ( message ) ;
return MA_NOACTIVATE ;
}
void COXBitmapMenuPopupWnd : : OnSettingChange ( UINT uFlags , LPCTSTR lpszSection )
{
UpdateMenuMetrics ( ) ;
OnMenuChanged ( ) ;
CWnd : : OnSettingChange ( uFlags , lpszSection ) ;
}
// v9.3 - update 03 - 64-bit - using OXTPARAM here - see UTB64Bit.h
void COXBitmapMenuPopupWnd : : OnTimer ( OXTPARAM nIDEvent )
{
if ( ( int ) nIDEvent = = m_nCheckForDragDropEventTimerID )
{
KillTimer ( m_nCheckForDragDropEventTimerID ) ;
m_nCheckForDragDropEventTimerID = 0 ;
if ( : : IsWindow ( GetSafeHwnd ( ) ) )
{
// do drag and drop
//
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL & & pMenu - > IsInCustomizationMode ( ) )
{
if ( : : GetKeyState ( VK_LBUTTON ) < 0 )
{
pMenu - > OnBeginDragDrop ( pMenu - > GetCustomizedItem ( ) ) ;
}
}
//
////////////////////////////////////
}
return ;
}
CWnd : : OnTimer ( nIDEvent ) ;
}
BOOL COXBitmapMenuPopupWnd : : TrackPopupMenu ( COXBitmapMenu * pMenu , UINT nFlags ,
int x , int y , CWnd * pWnd )
{
ASSERT ( pMenu ! = NULL ) ;
m_pBitmapMenu = pMenu ;
COXBitmapMenu * pBitmapMenu = GetBitmapMenu ( ) ;
pBitmapMenu - > SetPopupWnd ( this ) ;
if ( ! : : IsWindow ( GetSafeHwnd ( ) ) )
{
if ( ! CreateEx ( WS_EX_DLGMODALFRAME , AfxRegisterWndClass (
CS_SAVEBITS | CS_DBLCLKS , 0 , ( HBRUSH ) ( COLOR_BTNFACE + 1 ) , 0 ) , _T ( " " ) ,
WS_POPUP , m_rectWindow , pWnd , 0 , NULL ) )
{
return FALSE ;
}
}
// register OLE Drag'n'Drop
COleDropTarget * pOleDropTarget = pBitmapMenu - > GetDropTarget ( ) ;
ASSERT ( pOleDropTarget ! = NULL ) ;
pOleDropTarget - > Revoke ( ) ;
if ( ! pOleDropTarget - > Register ( this ) )
{
TRACE ( _T ( " COXBitmapMenuPopupWnd::Create: failed to register the control with COleDropTarget. You've probably forgotten to initialize OLE libraries using AfxOleInit function \n " ) ) ;
}
pBitmapMenu - > SetCutomizationMode ( TRUE , pWnd - > GetSafeHwnd ( ) ) ;
// update info about the font used to display the menu
UpdateMenuMetrics ( ) ;
// calculate the rectangles for the menu items and for the popup menu itself
VERIFY ( CalcLayout ( nFlags , x , y ) ) ;
SetWindowPos ( & wndTop , m_rectWindow . left , m_rectWindow . top , m_rectWindow . Width ( ) ,
m_rectWindow . Height ( ) , SWP_NOACTIVATE | SWP_SHOWWINDOW ) ;
ShowWindow ( SW_SHOWNA ) ;
return TRUE ;
}
void COXBitmapMenuPopupWnd : : ResetPopupMenu ( )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu ! = NULL )
{
if ( ! pMenu - > IsDragDropOwner ( ) )
{
pMenu - > SetCustomizedItem ( - 1 ) ;
pMenu - > SetPopupWnd ( NULL ) ;
m_pBitmapMenu = NULL ;
}
}
if ( : : IsWindow ( GetSafeHwnd ( ) ) )
{
ShowWindow ( SW_HIDE ) ;
}
}
BOOL COXBitmapMenuPopupWnd : : CalcLayout ( UINT nFlags , int x , int y )
{
COXBitmapMenu * pMenu = GetBitmapMenu ( ) ;
if ( pMenu = = NULL )
{
return FALSE ;
}
m_arrItemRects . RemoveAll ( ) ;
m_rectWindow . SetRectEmpty ( ) ;
int nWidth = 0 ;
int nHeight = 0 ;
int nIndex = 0 ;
for ( nIndex = 0 ; nIndex < ( int ) pMenu - > GetMenuItemCount ( ) ; nIndex + + )
{
MENUITEMINFO mii = { sizeof ( mii ) } ;
mii . fMask = MIIM_DATA ;
VERIFY ( : : GetMenuItemInfo ( pMenu - > GetSafeHmenu ( ) , nIndex , TRUE , & mii ) ) ;
MEASUREITEMSTRUCT mis ;
mis . CtlType = ODT_MENU ;
mis . itemData = mii . dwItemData ;
mis . itemID = pMenu - > GetMenuItemID ( nIndex ) ;
mis . itemHeight = 0 ;
mis . itemWidth = 0 ;
pMenu - > MeasureItem ( & mis ) ;
CRect rect ( 0 , nHeight , mis . itemWidth , nHeight + mis . itemHeight ) ;
m_arrItemRects . Add ( rect ) ;
nHeight + = mis . itemHeight ;
if ( nWidth < ( int ) mis . itemWidth )
nWidth = mis . itemWidth ;
}
if ( nWidth = = 0 & & nHeight = = 0 )
{
nWidth = ID_OXBITMAPMENUPOPUPWND_DEFAULT_WIDTH ;
nHeight = ID_OXBITMAPMENUPOPUPWND_DEFAULT_HEIGHT ;
}
m_rectWindow . top = y ;
switch ( nFlags )
{
case TPM_CENTERALIGN :
m_rectWindow . left = x - nWidth / 2 ;
break ;
case TPM_LEFTALIGN :
m_rectWindow . left = x ;
break ;
case TPM_RIGHTALIGN :
m_rectWindow . left = x - nWidth ;
break ;
}
m_rectWindow . right = m_rectWindow . left + nWidth ;
m_rectWindow . bottom = m_rectWindow . top + nHeight ;
CRect rectCopy = m_rectWindow ;
CalcWindowRect ( m_rectWindow ) ;
CSize szOffset ( rectCopy . left - m_rectWindow . left , rectCopy . top - m_rectWindow . top ) ;
m_rectWindow . OffsetRect ( szOffset . cx , szOffset . cy ) ;
m_rectWindow . InflateRect ( 0 , 0 , 2 * szOffset . cx , 0 ) ;
nWidth + = 2 * szOffset . cx ;
// adjust rectangles for items
for ( nIndex = 0 ; nIndex < m_arrItemRects . GetSize ( ) ; nIndex + + )
{
CRect & rect = m_arrItemRects [ nIndex ] ;
if ( rect . Width ( ) < nWidth )
rect . right = rect . left + nWidth ;
}
return TRUE ;
}
void COXBitmapMenuPopupWnd : : UpdateMenuMetrics ( )
{
if ( ( HFONT ) m_fontMenu ! = NULL )
m_fontMenu . DeleteObject ( ) ;
// Menu font, height and color
//////////////////////////////////////////////////////////////////
// v9.3 update 02 - the NONCLIENTMETRICS struct is an int larger
// on Vista vs XP (iPaddedBorderWidth added). Code compiled for
// WINVER 0x0600 will fail the call to SystemParametersInfo on XP.
// Code compiled for XP should still run on Vista.
int ncmSize = sizeof ( NONCLIENTMETRICS ) ;
# if WINVER >= 0x0600
// compiled for Vista - check for OS version
OSVERSIONINFO vi = { sizeof ( OSVERSIONINFO ) } ;
ASSERT ( GetVersionEx ( & vi ) ) ;
if ( vi . dwMajorVersion < 6 ) {
// running on lesser version - adjust size of NONCLIENTMETRICS struct
ncmSize - = sizeof ( int ) ;
}
# endif
NONCLIENTMETRICS ncm = { ncmSize } ;
VERIFY ( SystemParametersInfo ( SPI_GETNONCLIENTMETRICS , ncmSize , & ncm , 0 ) ) ;
// end NONCLIENTMETRICS mods v9.3 update 02
/////////////////////////////////////////////////
VERIFY ( m_fontMenu . CreateFontIndirect ( & ncm . lfMenuFont ) ) ;
}
void COXBitmapMenuPopupWnd : : OnMenuChanged ( )
{
ASSERT ( GetBitmapMenu ( ) ! = NULL ) ;
ASSERT ( : : IsWindow ( GetSafeHwnd ( ) ) ) ;
CRect rect ;
GetWindowRect ( rect ) ;
CPoint ptStart = rect . TopLeft ( ) ;
GetBitmapMenu ( ) - > CalcExtents ( ) ;
VERIFY ( CalcLayout ( TPM_LEFTALIGN , ptStart . x , ptStart . y ) ) ;
if ( IsWindowVisible ( ) )
{
SetWindowPos ( & wndTop , m_rectWindow . left , m_rectWindow . top , m_rectWindow . Width ( ) ,
m_rectWindow . Height ( ) , SWP_NOACTIVATE | SWP_SHOWWINDOW ) ;
RedrawWindow ( ) ;
}
else
{
ResetPopupMenu ( ) ;
}
}
void COXBitmapMenuPopupWnd : : RedrawItem ( int nIndex )
{
ASSERT ( GetBitmapMenu ( ) ! = NULL ) ;
ASSERT ( : : IsWindow ( GetSafeHwnd ( ) ) ) ;
ASSERT ( nIndex > = 0 & & nIndex < m_arrItemRects . GetSize ( ) ) ;
CRect rect ;
rect = m_arrItemRects [ nIndex ] ;
RedrawWindow ( rect ) ;
}
///////////////////////////////////////////////////////
// COXShadowedItemWnd
COXShadowedItemWnd : : COXShadowedItemWnd ( COXCoolToolBar * pCoolToolbar , int iMenuItem , UINT nPosFlags )
{
m_pCoolToolbar = pCoolToolbar ;
m_iMenuItem = iMenuItem ;
m_nPosFlags = nPosFlags ;
}
COXShadowedItemWnd : : ~ COXShadowedItemWnd ( )
{
}
BEGIN_MESSAGE_MAP ( COXShadowedItemWnd , CWnd )
//{{AFX_MSG_MAP(COXShadowedItemWnd)
ON_WM_PAINT ( )
//}}AFX_MSG_MAP
END_MESSAGE_MAP ( )
/////////////////////////////////////////////////////////////////////////////
WNDPROC COXBitmapMenu : : m_origWndProc = NULL ;
IMPLEMENT_DYNAMIC ( COXBitmapMenu , CMenu )
COXMenuSkin * COXBitmapMenu : : m_pMenuSkin = NULL ;
COXBitmapMenu : : COXBitmapMenu ( )
:
m_nBitmapExtent ( 0 ) ,
m_nTextHeight ( 0 ) ,
m_nAcceleratorExtent ( 0 ) ,
m_nStringExtent ( 0 ) ,
m_nCustomizedItemIndex ( - 1 ) ,
m_bCutomizable ( FALSE ) ,
m_bInCutomizationMode ( FALSE ) ,
m_bDragDropOwner ( FALSE ) ,
m_bDragDropOperation ( FALSE ) ,
m_hWndCustomizeOrganizer ( NULL ) ,
m_nInsertMarkIndex ( - 1 ) ,
m_pPopupWnd ( NULL ) ,
m_rectDropDownItem ( 0 , 0 , 0 , 0 )
{
// Sublass the menus
RegisterWindowClass ( AfxGetInstanceHandle ( ) ) ;
}
COXBitmapMenu : : ~ COXBitmapMenu ( )
{
m_KeyAccessMap . RemoveAll ( ) ;
COXItemInfo * pItemInfo ;
while ( ! m_ItemInfoList . IsEmpty ( ) )
{
pItemInfo = m_ItemInfoList . RemoveHead ( ) ;
delete pItemInfo ;
pItemInfo = NULL ;
}
TRACE ( _T ( " \n " ) ) ;
// delete the classic skin
if ( m_pMenuSkin ! = NULL )
{
delete m_pMenuSkin ;
m_pMenuSkin = NULL ;
}
COleDropTarget * pOleDropTarget = GetDropTarget ( ) ;
ASSERT ( pOleDropTarget ! = NULL ) ;
pOleDropTarget - > Revoke ( ) ;
}
void COXBitmapMenu : : DrawItem ( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
ASSERT ( m_hMenu ! = NULL ) ;
ASSERT ( lpDrawItemStruct ! = NULL ) ;
ASSERT ( lpDrawItemStruct - > CtlType = = ODT_MENU ) ;
UINT nState = lpDrawItemStruct - > itemState ;
CRect itemRect ( lpDrawItemStruct - > rcItem ) ;
CRect buttonRect ( 0 , 0 , 0 , 0 ) ;
CRect imageRect ( 0 , 0 , 0 , 0 ) ;
CRect text1Rect ( 0 , 0 , 0 , 0 ) ;
CRect text2Rect ( 0 , 0 , 0 , 0 ) ;
CDC dc ;
dc . Attach ( lpDrawItemStruct - > hDC ) ;
COXItemInfo * pItemInfo = ( COXItemInfo * ) lpDrawItemStruct - > itemData ;
ASSERT ( AfxIsValidAddress ( pItemInfo , sizeof ( COXItemInfo ) ) ) ;
COXImageInfo * pImageInfo = pItemInfo - > GetImageInfo ( ) ;
CString sText = pItemInfo - > GetText ( ) ;
if ( lpDrawItemStruct - > itemID ! = 0 & & lpDrawItemStruct - > itemID ! = 0xffff )
{
// Compute the space for each menu item part
DistributeSpace (
nState , pImageInfo , itemRect , buttonRect , imageRect , text1Rect , text2Rect ) ;
}
COXBitmapMenuOrganizer * pOrganizer =
COXBitmapMenuOrganizer : : FindOrganizer ( AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ) ;
ASSERT ( pOrganizer ! = NULL ) ;
BOOL bBefore = TRUE ;
CPoint ptTest = itemRect . CenterPoint ( ) ;
int nItemIndex = HitTest ( & ptTest , & bBefore ) ;
if ( pOrganizer - > IsShowOnlyRecentlyUsedItems ( ) & &
! pOrganizer - > IsRecentlyUsed ( this , nItemIndex ) )
{
nState | = OXODS_HIDDEN ;
if ( nItemIndex > 0 & & pOrganizer - > IsRecentlyUsed ( this , nItemIndex - 1 ) )
{
nState | = OXODS_HIDDENFIRST ;
}
if ( nItemIndex < ( int ) GetMenuItemCount ( ) - 1 & &
pOrganizer - > IsRecentlyUsed ( this , nItemIndex + 1 ) )
{
nState | = OXODS_HIDDENLAST ;
}
}
// Draw every part of the menu item
if ( lpDrawItemStruct - > itemID = = 0 | | lpDrawItemStruct - > itemID = = 0xffff )
{
DrawSeparator ( & dc , itemRect ) ;
}
else if ( IsPopupItem ( lpDrawItemStruct - > itemID ) )
{
DrawSubmenuItem ( & dc , nState , sText , pImageInfo ,
itemRect , buttonRect , text1Rect , text2Rect ) ;
}
else
{
DrawBackground ( & dc , nState , pImageInfo , itemRect , buttonRect ) ;
DrawButton ( & dc , nState , pImageInfo , buttonRect ) ;
DrawImage ( & dc , nState , pImageInfo , imageRect ) ;
if ( ( ( ( int ) lpDrawItemStruct - > itemID ) & 0x0000ffff ) = = ID_OX_SHOWALLITEMS )
{
ASSERT ( ! IsInCustomizationMode ( ) ) ;
DrawExpansionItem ( & dc , itemRect , nState ) ;
}
else
{
DrawText ( & dc , nState , sText , text1Rect , text2Rect ) ;
}
}
// draw customized item
int nCustomizedItem = GetCustomizedItem ( ) ;
if ( nCustomizedItem ! = - 1 & &
GetMenuItemID ( nCustomizedItem ) = = lpDrawItemStruct - > itemID )
{
CPoint pt = itemRect . CenterPoint ( ) ;
if ( HitTest ( & pt ) = = nCustomizedItem )
{
DrawCustomized ( & dc , itemRect ) ;
}
}
// draw insert mark
int nInsertMark = GetInsertMark ( ) ;
if ( nInsertMark ! = - 1 )
{
ASSERT ( nInsertMark > = 0 & & nInsertMark < = ( int ) GetMenuItemCount ( ) ) ;
BOOL bBefore = ( nInsertMark < ( int ) GetMenuItemCount ( ) ) ;
if ( ! bBefore )
nInsertMark - - ;
CPoint pt = itemRect . CenterPoint ( ) ;
if ( HitTest ( & pt ) = = nInsertMark )
{
DrawInsertMark ( & dc , itemRect , bBefore ) ;
}
}
dc . Detach ( ) ;
}
void COXBitmapMenu : : DistributeSpace ( UINT nState ,
COXImageInfo * pImageInfo ,
CRect itemRect ,
CRect & buttonRect ,
CRect & imageRect ,
CRect & text1Rect ,
CRect & text2Rect )
{
GetMenuSkin ( ) - > DistributeSpace ( nState , pImageInfo , itemRect , buttonRect , imageRect ,
text1Rect , text2Rect , this ) ;
}
HBRUSH COXBitmapMenu : : HBrushDitherCreate ( COLORREF rgbFace , COLORREF rgbHilight )
{
struct / / BITMAPINFO with 16 colors
{
BITMAPINFOHEADER bmiHeader ;
RGBQUAD bmiColors [ 16 ] ;
} bmi ;
HBRUSH hBrush = NULL ;
DWORD patGray [ 8 ] ;
HDC hDC ;
HBITMAP hBmp ;
static COLORREF rgbFaceOld = 0xFFFFFFFF ; //Initially impossible
static COLORREF rgbHilightOld = 0xFFFFFFFF ; //Initially impossible
/*
* We ' re going to create an 8 * 8 brush for PatBlt using the
* face color and highlight color .
*/
bmi . bmiHeader . biSize = sizeof ( BITMAPINFOHEADER ) ;
bmi . bmiHeader . biWidth = 8 ;
bmi . bmiHeader . biHeight = 8 ;
bmi . bmiHeader . biPlanes = 1 ;
bmi . bmiHeader . biBitCount = 1 ;
bmi . bmiHeader . biCompression = BI_RGB ;
bmi . bmiHeader . biSizeImage = 0 ;
bmi . bmiHeader . biXPelsPerMeter = 0 ;
bmi . bmiHeader . biYPelsPerMeter = 0 ;
bmi . bmiHeader . biClrUsed = 0 ;
bmi . bmiHeader . biClrImportant = 0 ;
bmi . bmiColors [ 0 ] . rgbBlue = GetBValue ( rgbFace ) ;
bmi . bmiColors [ 0 ] . rgbGreen = GetGValue ( rgbFace ) ;
bmi . bmiColors [ 0 ] . rgbRed = GetRValue ( rgbFace ) ;
bmi . bmiColors [ 0 ] . rgbReserved = 0 ;
bmi . bmiColors [ 1 ] . rgbBlue = GetBValue ( rgbHilight ) ;
bmi . bmiColors [ 1 ] . rgbGreen = GetGValue ( rgbHilight ) ;
bmi . bmiColors [ 1 ] . rgbRed = GetRValue ( rgbHilight ) ;
bmi . bmiColors [ 1 ] . rgbReserved = 0 ;
//Create the byte array for CreateDIBitmap.
patGray [ 6 ] = patGray [ 4 ] = patGray [ 2 ] = patGray [ 0 ] = 0x5555AAAAL ;
patGray [ 7 ] = patGray [ 5 ] = patGray [ 3 ] = patGray [ 1 ] = 0xAAAA5555L ;
//Create the bitmap
hDC = : : GetDC ( NULL ) ;
hBmp = : : CreateDIBitmap ( hDC , & bmi . bmiHeader , CBM_INIT , patGray ,
( LPBITMAPINFO ) & bmi , DIB_RGB_COLORS ) ;
: : ReleaseDC ( NULL , hDC ) ;
//Create the brush from the bitmap
if ( NULL ! = hBmp )
{
hBrush = CreatePatternBrush ( hBmp ) ;
DeleteObject ( hBmp ) ;
}
return hBrush ;
}
void COXBitmapMenu : : DrawBackground ( CDC * pDC , UINT nState , COXImageInfo * pImageInfo ,
CRect itemRect , CRect buttonRect )
{
GetMenuSkin ( ) - > DrawBackground ( pDC , nState , pImageInfo , itemRect , buttonRect , this ) ;
}
void COXBitmapMenu : : DrawButton ( CDC * pDC , UINT nState , COXImageInfo * pImageInfo ,
CRect buttonRect )
{
GetMenuSkin ( ) - > DrawButton ( pDC , nState , pImageInfo , buttonRect , this ) ;
}
void COXBitmapMenu : : DrawImage ( CDC * pDC , UINT nState , COXImageInfo * pImageInfo ,
CRect imageRect )
{
GetMenuSkin ( ) - > DrawImage ( pDC , nState , pImageInfo , imageRect , this ) ;
}
void COXBitmapMenu : : DrawText ( CDC * pDC , UINT nState ,
CString sText , CRect text1Rect , CRect text2Rect )
{
GetMenuSkin ( ) - > DrawText ( pDC , nState , sText , text1Rect , text2Rect , this ) ;
}
void COXBitmapMenu : : DrawSeparator ( CDC * pDC , CRect itemRect )
{
GetMenuSkin ( ) - > DrawSeparator ( pDC , itemRect , this ) ;
}
void COXBitmapMenu : : DrawCustomized ( CDC * pDC , CRect itemRect )
{
GetMenuSkin ( ) - > DrawCustomized ( pDC , itemRect , this ) ;
}
void COXBitmapMenu : : DrawInsertMark ( CDC * pDC , CRect itemRect , BOOL bBefore )
{
GetMenuSkin ( ) - > DrawInsertMark ( pDC , itemRect , bBefore , this ) ;
}
void COXBitmapMenu : : DrawSubmenuItem ( CDC * pDC , UINT nState , CString sText ,
COXImageInfo * pImageInfo ,
CRect itemRect , CRect buttonRect ,
CRect text1Rect , CRect text2Rect )
{
GetMenuSkin ( ) - > DrawSubmenuItem ( pDC , nState , sText , pImageInfo , itemRect , buttonRect ,
text1Rect , text2Rect , this ) ;
}
void COXBitmapMenu : : DrawExpansionItem ( CDC * pDC , CRect itemRect , UINT nState )
{
GetMenuSkin ( ) - > DrawExpansionItem ( pDC , itemRect , nState , this ) ;
}
void COXBitmapMenu : : MeasureItem ( LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
OXDIMENSIONCONSTANTS & oxdc = GetMenuSkin ( ) - > GetDimentionConstants ( ) ;
ASSERT ( lpMeasureItemStruct ! = NULL ) ;
COXItemInfo * pItemInfo = ( COXItemInfo * ) lpMeasureItemStruct - > itemData ;
if ( pItemInfo )
{
ASSERT ( AfxIsValidAddress ( pItemInfo , sizeof ( COXItemInfo ) ) ) ;
COXImageInfo * pImageInfo = pItemInfo - > GetImageInfo ( ) ;
int nImageWidth = 0 ;
int nImageHeight = 0 ;
if ( pImageInfo ! = NULL )
{
IMAGEINFO ii ;
: : ZeroMemory ( & ii , sizeof ( ii ) ) ;
pImageInfo - > GetImageList ( ) - > GetImageInfo ( pImageInfo - > GetIndex ( ) , & ii ) ;
nImageWidth = ii . rcImage . right - ii . rcImage . left + 2 ;
nImageHeight = ii . rcImage . bottom - ii . rcImage . top + 2 ;
}
lpMeasureItemStruct - > itemWidth =
oxdc . m_nGapLeftBitmap + m_nBitmapExtent + oxdc . m_nGapBitmapText +
m_nStringExtent + ( m_nAcceleratorExtent ? oxdc . m_nGapTextAcclrtr : 0 ) +
m_nAcceleratorExtent + oxdc . m_nGapAcclrtrRight ;
if ( lpMeasureItemStruct - > itemID = = 0 | | lpMeasureItemStruct - > itemID = = 0xffff )
{
// separator
lpMeasureItemStruct - > itemHeight = oxdc . m_nSeparatorHeight ;
}
else
{
// item with text
lpMeasureItemStruct - > itemHeight = __max ( nImageHeight + oxdc . m_nGapVertBitmap ,
m_nTextHeight + oxdc . m_nGapVertText ) ;
if ( ( ( ( int ) lpMeasureItemStruct - > itemID ) & 0x0000ffff ) = = ID_OX_SHOWALLITEMS )
GetMenuSkin ( ) - > AdjustExpansionItemHeight ( lpMeasureItemStruct - > itemHeight , this ) ;
}
}
else if ( IsPopupItem ( lpMeasureItemStruct - > itemID ) )
lpMeasureItemStruct - > itemHeight = m_nTextHeight + oxdc . m_nGapVertText ;
}
void COXBitmapMenu : : CalcExtents ( )
{
UINT nItemCount = GetMenuItemCount ( ) ;
CString sText ;
CString sBeforeTab ;
CString sAfterTab ;
int nTabCharIndex = 0 ;
m_nStringExtent = 0 ;
m_nAcceleratorExtent = 0 ;
m_nBitmapExtent = 0 ;
MENUITEMINFO mii = { sizeof ( MENUITEMINFO ) } ;
COXItemInfo * pItemInfo = NULL ;
COXImageInfo * pImageInfo = NULL ;
IMAGEINFO ii = { 0 } ;
CFont Font , boldFont ;
//////////////////////////////////////////////////////////////////
// v9.3 update 02 - the NONCLIENTMETRICS struct is an int larger
// on Vista vs XP (iPaddedBorderWidth added). Code compiled for
// WINVER 0x0600 will fail the call to SystemParametersInfo on XP.
// Code compiled for XP should still run on Vista.
int ncmSize = sizeof ( NONCLIENTMETRICS ) ;
# if WINVER >= 0x0600
// compiled for Vista - check for OS version
OSVERSIONINFO vi = { sizeof ( OSVERSIONINFO ) } ;
ASSERT ( GetVersionEx ( & vi ) ) ;
if ( vi . dwMajorVersion < 6 ) {
// running on lesser version - adjust size of NONCLIENTMETRICS struct
ncmSize - = sizeof ( int ) ;
}
# endif
NONCLIENTMETRICS ncm = { ncmSize } ;
VERIFY ( SystemParametersInfo ( SPI_GETNONCLIENTMETRICS , ncmSize , & ncm , 0 ) ) ;
// end NONCLIENTMETRICS mods v9.3 update 02
/////////////////////////////////////////////////
VERIFY ( Font . CreateFontIndirect ( & ncm . lfMenuFont ) ) ;
ncm . lfMenuFont . lfWeight = FW_BOLD ; // make the font bold
VERIFY ( boldFont . CreateFontIndirect ( & ncm . lfMenuFont ) ) ;
CWnd * pMainWnd = AfxGetThread ( ) - > GetMainWnd ( ) ;
CDC * pDC = pMainWnd - > GetDC ( ) ;
CSize TextExt ;
for ( UINT nItemIndex = 0 ; nItemIndex < nItemCount ; nItemIndex + + )
{
CFont * pOldFont ;
if ( GetDefaultItem ( GMDI_USEDISABLED , MF_BYPOSITION ) = = nItemIndex )
pOldFont = pDC - > SelectObject ( & boldFont ) ;
else
pOldFont = pDC - > SelectObject ( & Font ) ;
mii . fMask = MIIM_TYPE | MIIM_DATA | MIIM_SUBMENU ;
mii . cch = 300 ;
mii . dwTypeData = sText . GetBuffer ( mii . cch ) ;
// ... zero-terminate string
mii . dwTypeData [ 0 ] = _T ( ' \0 ' ) ;
: : GetMenuItemInfo ( GetSafeHmenu ( ) , nItemIndex , TRUE , & mii ) ;
sText . ReleaseBuffer ( ) ;
if ( mii . fType & MFT_SEPARATOR )
continue ;
pItemInfo = ( COXItemInfo * ) ( mii . dwItemData ) ;
if ( pItemInfo )
{
pImageInfo = pItemInfo - > GetImageInfo ( ) ;
if ( pImageInfo )
{
pImageInfo - > GetImageList ( ) - > GetImageInfo ( pImageInfo - > GetIndex ( ) , & ii ) ;
m_nBitmapExtent = __max ( m_nBitmapExtent , __max ( GetMenuSkin ( ) - > GetDimentionConstants ( ) . m_nMinBitmapWidth , ii . rcImage . right - ii . rcImage . left ) ) ;
}
sText = pItemInfo - > GetText ( ) ;
}
nTabCharIndex = sText . Find ( _T ( ' \t ' ) ) ;
if ( nTabCharIndex ! = - 1 )
{
sBeforeTab = sText . Left ( nTabCharIndex ) ;
sAfterTab = sText . Mid ( nTabCharIndex + 1 ) ;
}
else
{
sBeforeTab = sText ;
if ( mii . hSubMenu ! = NULL )
sAfterTab = _T ( " W " ) ;
else
sAfterTab . Empty ( ) ;
}
CRect text1Rect ( 0 , 0 , 0 , 0 ) ;
CRect text2Rect ( 0 , 0 , 0 , 0 ) ;
pDC - > DrawText ( sBeforeTab , text1Rect , DT_CALCRECT | DT_SINGLELINE ) ;
pDC - > DrawText ( sAfterTab , text2Rect , DT_CALCRECT | DT_SINGLELINE ) ;
m_nStringExtent = __max ( m_nStringExtent , text1Rect . Width ( ) ) ;
m_nAcceleratorExtent = __max ( m_nAcceleratorExtent , text2Rect . Width ( ) ) ;
pDC - > SelectObject ( pOldFont ) ;
}
TextExt = pDC - > GetTextExtent ( _T ( " A " ) ) ;
m_nTextHeight = TextExt . cy ;
pMainWnd - > ReleaseDC ( pDC ) ;
}
void COXBitmapMenu : : AddItemInfo ( COXItemInfo * pItemInfo )
{
m_ItemInfoList . AddTail ( pItemInfo ) ;
}
/////////////////////////////////////////////////////////////////////////////
// COXBitmapMenu idle update through CBitmapMenuCmdUI class
class OX_CLASS_DECL CBitmapMenuCmdUI : public CCmdUI // class private to this file !
{
public : // re-implementations only
virtual void SetText ( LPCTSTR lpszText ) ;
} ;
void CBitmapMenuCmdUI : : SetText ( LPCTSTR lpszText )
{
ASSERT ( lpszText ! = NULL ) ;
ASSERT ( AfxIsValidString ( lpszText ) ) ;
ASSERT ( m_pMenu - > IsKindOf ( RUNTIME_CLASS ( COXBitmapMenu ) ) ) ;
if ( m_pMenu ! = NULL )
{
if ( m_pSubMenu ! = NULL )
return ; // don't change popup menus indirectly
MENUITEMINFO mii = { sizeof ( mii ) } ;
mii . fMask = MIIM_TYPE | MIIM_DATA ;
: : GetMenuItemInfo ( m_pMenu - > GetSafeHmenu ( ) , m_nIndex , TRUE , & mii ) ;
if ( mii . fType = = MFT_OWNERDRAW )
{
COXItemInfo * pItemInfo = ( COXItemInfo * ) ( mii . dwItemData ) ;
ASSERT ( pItemInfo ! = NULL ) ;
pItemInfo - > SetText ( lpszText ) ;
}
else
{
CCmdUI : : SetText ( lpszText ) ;
}
}
}
void COXBitmapMenu : : OnUpdateCmdUI ( CWnd * pWnd , UINT /*nIndex*/ , BOOL bSysMenu )
{
// Code almost entirely copied from CFrameWnd::OnInitPopup
if ( bSysMenu )
{
return ; // don't support system menu
}
// check the enabled state of various menu items
CBitmapMenuCmdUI state ;
state . m_pMenu = this ;
ASSERT ( state . m_pOther = = NULL ) ;
ASSERT ( state . m_pParentMenu = = NULL ) ;
// determine if menu is popup in top-level menu and set m_pOther to
// it if so (m_pParentMenu == NULL indicates that it is secondary popup)
HMENU hParentMenu ;
if ( AfxGetThreadState ( ) - > m_hTrackingMenu = = m_hMenu )
{
state . m_pParentMenu = this ; // parent == child for tracking popup
}
else if ( ( hParentMenu = : : GetMenu ( pWnd - > m_hWnd ) ) ! = NULL )
{
CWnd * pParent = pWnd - > GetTopLevelParent ( ) ;
// child windows don't have menus -- need to go to the top!
if ( pParent ! = NULL & &
( hParentMenu = : : GetMenu ( pParent - > m_hWnd ) ) ! = NULL )
{
int nIndexMax = : : GetMenuItemCount ( hParentMenu ) ;
for ( int nIndex = 0 ; nIndex < nIndexMax ; nIndex + + )
{
if ( : : GetSubMenu ( hParentMenu , nIndex ) = = m_hMenu )
{
// when popup is found, m_pParentMenu is containing menu
state . m_pParentMenu = CMenu : : FromHandle ( hParentMenu ) ;
break ;
}
}
}
}
state . m_nIndexMax = GetMenuItemCount ( ) ;
for ( state . m_nIndex = 0 ; state . m_nIndex < state . m_nIndexMax ; state . m_nIndex + + )
{
state . m_nID = GetMenuItemID ( state . m_nIndex ) ;
if ( state . m_nID = = 0 )
continue ; // menu separator or invalid cmd - ignore it
ASSERT ( state . m_pOther = = NULL ) ;
ASSERT ( state . m_pMenu ! = NULL ) ;
if ( state . m_nID = = ( UINT ) - 1 )
{
// possibly a popup menu, route to first item of that popup
state . m_pSubMenu = GetSubMenu ( state . m_nIndex ) ;
if ( state . m_pSubMenu = = NULL | |
( state . m_nID = state . m_pSubMenu - > GetMenuItemID ( 0 ) ) = = 0 | |
state . m_nID = = ( UINT ) - 1 )
{
continue ; // first item of popup can't be routed to
}
state . DoUpdate ( pWnd , FALSE ) ; // popups are never auto disabled
}
else
{
// normal menu item
// Auto enable/disable if frame window has 'm_bAutoMenuEnable'
// set and command is _not_ a system command.
state . m_pSubMenu = NULL ;
state . DoUpdate ( pWnd ,
( ( CFrameWnd * ) pWnd ) - > m_bAutoMenuEnable & & state . m_nID < 0xF000 ) ;
}
// adjust for menu deletions and additions
UINT nCount = GetMenuItemCount ( ) ;
if ( nCount < state . m_nIndexMax )
{
state . m_nIndex - = ( state . m_nIndexMax - nCount ) ;
while ( state . m_nIndex < nCount & &
GetMenuItemID ( state . m_nIndex ) = = state . m_nID )
{
state . m_nIndex + + ;
}
}
state . m_nIndexMax = nCount ;
}
}
int COXBitmapMenu : : SetCustomizedItem ( int nIndex )
{
int nOldCustomizedItemIndex = m_nCustomizedItemIndex ;
m_nCustomizedItemIndex = nIndex ;
if ( m_pPopupWnd ! = NULL & & : : IsWindow ( m_pPopupWnd - > GetSafeHwnd ( ) ) )
{
if ( nOldCustomizedItemIndex ! = m_nCustomizedItemIndex )
{
if ( nOldCustomizedItemIndex ! = - 1 )
m_pPopupWnd - > RedrawItem ( nOldCustomizedItemIndex ) ;
if ( m_nCustomizedItemIndex ! = - 1 )
m_pPopupWnd - > RedrawItem ( m_nCustomizedItemIndex ) ;
}
SendCustomizeNotification ( ID_OXCUSTBM_SET_CUSTOMIZE_ITEM ) ;
}
return nOldCustomizedItemIndex ;
}
BOOL COXBitmapMenu : : DisplayCustomizeItemContextMenu ( int nItemIndex , CPoint point )
{
ASSERT ( nItemIndex > = 0 & & nItemIndex < ( int ) GetMenuItemCount ( ) ) ;
COXBitmapMenuOrganizer * pOrganizer =
COXBitmapMenuOrganizer : : FindOrganizer ( AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ) ;
ASSERT ( pOrganizer ! = NULL ) ;
CString sText ;
MENUITEMINFO mii = { sizeof ( MENUITEMINFO ) } ;
mii . fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_SUBMENU ;
mii . cch = 300 ;
mii . dwTypeData = sText . GetBuffer ( mii . cch ) ;
// ... zero-terminate string
mii . dwTypeData [ 0 ] = _T ( ' \0 ' ) ;
VERIFY ( : : GetMenuItemInfo ( GetSafeHmenu ( ) , nItemIndex , TRUE , & mii ) ) ;
sText . ReleaseBuffer ( ) ;
COXItemInfo * pItemInfo = ( COXItemInfo * ) ( mii . dwItemData ) ;
ASSERT ( AfxIsValidAddress ( pItemInfo , sizeof ( COXItemInfo ) ) ) ;
sText = pItemInfo - > GetText ( ) ;
// don't add most recent files used
if ( ( int ) mii . wID > = ID_FILE_MRU_FILE1 & & ( int ) mii . wID < = ID_FILE_MRU_FILE16 )
{
return FALSE ;
}
// don't add MDIChild windows menu items
if ( ( int ) mii . wID > = AFX_IDM_FIRST_MDICHILD & & mii . hSubMenu = = NULL )
{
return FALSE ;
}
CMenu menu ;
if ( ! menu . CreatePopupMenu ( ) )
return FALSE ;
// populate menu
CString sItem ;
VERIFY ( sItem . LoadString ( IDS_OX_CUSTBM_DELETE ) ) ;
VERIFY ( menu . AppendMenu ( MF_STRING , ID_OXCUSTBM_DELETE , sItem ) ) ;
if ( ( mii . fType & MFT_SEPARATOR ) = = 0 )
{
VERIFY ( menu . AppendMenu ( MF_SEPARATOR ) ) ;
VERIFY ( sItem . LoadString ( IDS_OX_CUSTBM_APPEARANCE ) ) ;
VERIFY ( menu . AppendMenu ( MF_STRING , ID_OXCUSTBM_APPEARANCE ,
sItem ) ) ;
VERIFY ( menu . AppendMenu ( MF_SEPARATOR ) ) ;
if ( pOrganizer - > IsShowOnlyRecentlyUsedItems ( ) )
{
VERIFY ( sItem . LoadString ( IDS_OX_CUSTBM_RECENTLY_USED ) ) ;
VERIFY ( menu . AppendMenu ( MF_STRING |
( pOrganizer - > IsRecentlyUsed ( this , nItemIndex ) ? MF_CHECKED :
MF_UNCHECKED ) , ID_OXCUSTBM_RECENTLY_USED , sItem ) ) ;
VERIFY ( menu . AppendMenu ( MF_SEPARATOR ) ) ;
}
BOOL bSeparatorBefore = FALSE ;
if ( nItemIndex > 0 )
{
MENUITEMINFO mii = { sizeof ( MENUITEMINFO ) } ;
mii . fMask = MIIM_TYPE ;
mii . cch = 300 ;
mii . dwTypeData = sText . GetBuffer ( mii . cch ) ;
// ... zero-terminate string
mii . dwTypeData [ 0 ] = _T ( ' \0 ' ) ;
VERIFY ( : : GetMenuItemInfo ( GetSafeHmenu ( ) , nItemIndex - 1 , TRUE , & mii ) ) ;
sText . ReleaseBuffer ( ) ;
bSeparatorBefore = ( ( mii . fType & MFT_SEPARATOR ) = = 0 ) ;
}
VERIFY ( sItem . LoadString ( IDS_OX_CUSTBM_SEPARATOR_BEFORE ) ) ;
VERIFY ( menu . AppendMenu ( MF_STRING | ( bSeparatorBefore ? 0 : MF_GRAYED ) ,
ID_OXCUSTBM_SEPARATOR_BEFORE , sItem ) ) ;
BOOL bSeparatorAfter = FALSE ;
if ( nItemIndex < ( int ) ( GetMenuItemCount ( ) - 1 ) )
{
MENUITEMINFO mii = { sizeof ( MENUITEMINFO ) } ;
mii . fMask = MIIM_TYPE ;
mii . cch = 300 ;
mii . dwTypeData = sText . GetBuffer ( mii . cch ) ;
// ... zero-terminate string
mii . dwTypeData [ 0 ] = _T ( ' \0 ' ) ;
VERIFY ( : : GetMenuItemInfo ( GetSafeHmenu ( ) , nItemIndex + 1 , TRUE , & mii ) ) ;
sText . ReleaseBuffer ( ) ;
bSeparatorAfter = ( ( mii . fType & MFT_SEPARATOR ) = = 0 ) ;
}
VERIFY ( sItem . LoadString ( IDS_OX_CUSTBM_SEPARATOR_AFTER ) ) ;
VERIFY ( menu . AppendMenu ( MF_STRING | ( bSeparatorAfter ? 0 : MF_GRAYED ) ,
ID_OXCUSTBM_SEPARATOR_AFTER , sItem ) ) ;
}
CWnd * pWndOwner = NULL ;
if ( m_pPopupWnd ! = NULL & & : : IsWindow ( m_pPopupWnd - > GetSafeHwnd ( ) ) )
pWndOwner = m_pPopupWnd ;
menu . TrackPopupMenu ( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON ,
point . x , point . y , pWndOwner ) ;
return TRUE ;
}
void COXBitmapMenu : : OnCustBMDelete ( )
{
ASSERT ( IsInCustomizationMode ( ) ) ;
int nCustomizedItemIndex = GetCustomizedItem ( ) ;
ASSERT ( nCustomizedItemIndex ! = - 1 ) ;
if ( SendCustomizeNotification ( ID_OXCUSTBM_DELETE ) )
return ;
VERIFY ( DeleteMenu ( nCustomizedItemIndex , MF_BYPOSITION ) ) ;
m_nCustomizedItemIndex = - 1 ;
UpdateContents ( ) ;
}
void COXBitmapMenu : : OnCustBMAppearance ( )
{
ASSERT ( IsInCustomizationMode ( ) ) ;
int nCustomizedItemIndex = GetCustomizedItem ( ) ;
ASSERT ( nCustomizedItemIndex ! = - 1 ) ;
UNUSED ( nCustomizedItemIndex ) ;
SendCustomizeNotification ( ID_OXCUSTBM_APPEARANCE ) ;
}
void COXBitmapMenu : : OnCustBMSeparatorBefore ( )
{
ASSERT ( IsInCustomizationMode ( ) ) ;
int nCustomizedItemIndex = GetCustomizedItem ( ) ;
ASSERT ( nCustomizedItemIndex ! = - 1 ) ;
if ( SendCustomizeNotification ( ID_OXCUSTBM_SEPARATOR_BEFORE ) )
return ;
VERIFY ( InsertMenu ( nCustomizedItemIndex , MF_SEPARATOR | MF_BYPOSITION ) ) ;
UpdateContents ( ) ;
SetCustomizedItem ( nCustomizedItemIndex + 1 ) ;
}
void COXBitmapMenu : : OnCustBMSeparatorAfter ( )
{
ASSERT ( IsInCustomizationMode ( ) ) ;
int nCustomizedItemIndex = GetCustomizedItem ( ) ;
ASSERT ( nCustomizedItemIndex ! = - 1 ) ;
if ( SendCustomizeNotification ( ID_OXCUSTBM_SEPARATOR_AFTER ) )
return ;
VERIFY ( InsertMenu ( nCustomizedItemIndex + 1 , MF_SEPARATOR | MF_BYPOSITION ) ) ;
UpdateContents ( ) ;
}
void COXBitmapMenu : : OnCustBMRecentlyUsed ( )
{
ASSERT ( IsInCustomizationMode ( ) ) ;
int nCustomizedItemIndex = GetCustomizedItem ( ) ;
ASSERT ( nCustomizedItemIndex ! = - 1 ) ;
if ( SendCustomizeNotification ( ID_OXCUSTBM_RECENTLY_USED ) )
return ;
COXBitmapMenuOrganizer * pOrganizer =
COXBitmapMenuOrganizer : : FindOrganizer ( AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ) ;
ASSERT ( pOrganizer ! = NULL ) ;
if ( pOrganizer - > IsRecentlyUsed ( this , nCustomizedItemIndex ) )
{
VERIFY ( pOrganizer - >
ExcludeFromRecentlyUsed ( this , nCustomizedItemIndex ) ) ;
}
else
{
VERIFY ( pOrganizer - >
AddToRecentlyUsed ( this , nCustomizedItemIndex ) ) ;
}
UpdateContents ( ) ;
}
LRESULT COXBitmapMenu : : SendCustomizeNotification ( UINT nCustomizeCmdID )
{
ASSERT ( GetPopupWnd ( ) ! = NULL ) ;
HWND hWnd = m_hWndCustomizeOrganizer ;
if ( hWnd = = NULL )
{
hWnd = AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ;
}
if ( hWnd = = NULL )
return ( LRESULT ) 0 ;
NMBMCUSTOMIZE nmbmCustomize ;
nmbmCustomize . nmhdr . code = OXBMN_CUSTOMIZECMD ;
nmbmCustomize . nmhdr . hwndFrom = GetPopupWnd ( ) - > GetSafeHwnd ( ) ;
nmbmCustomize . nmhdr . idFrom = : : GetDlgCtrlID ( hWnd ) ;
nmbmCustomize . nCustomizeEventID = nCustomizeCmdID ;
return : : SendMessage ( hWnd , WM_NOTIFY , ( WPARAM ) nmbmCustomize . nmhdr . idFrom ,
( LPARAM ) & nmbmCustomize ) ;
}
LONG COXBitmapMenu : : OnDragEnter ( WPARAM wParam , LPARAM lParam )
{
// toolbar must be in customizable state
if ( ! IsCustomizable ( ) )
return ( LONG ) FALSE ;
// set flag that specifies that drag'n'drop operation is active
m_bDragDropOperation = TRUE ;
return OnDragOver ( wParam , lParam ) ;
}
LONG COXBitmapMenu : : OnDragOver ( WPARAM wParam , LPARAM lParam )
{
UNREFERENCED_PARAMETER ( wParam ) ;
// toolbar must be in customizable state
if ( ! IsCustomizable ( ) )
return ( LONG ) FALSE ;
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
pSHBDTAction - > result = ( LRESULT ) DROPEFFECT_NONE ;
# ifdef OX_CUSTOMIZE_COMMANDS
// Can we use this object?
if ( pSHBDTAction - > pDataObject - >
IsDataAvailable ( COXDragDropCommands : : m_cfCommandButton ) )
{
// analize the current cursor position
//
BOOL bBefore = TRUE ;
int nItemIndex = HitTest ( & pSHBDTAction - > point , & bBefore ) ;
int nInsertMarkIndex = ( bBefore ? nItemIndex : nItemIndex + 1 ) ;
SetInsertMark ( nInsertMarkIndex ) ;
// Check if the control key was pressed
if ( ( pSHBDTAction - > dwKeyState & MK_CONTROL ) = = MK_CONTROL )
pSHBDTAction - > result = ( LRESULT ) DROPEFFECT_COPY ;
else
pSHBDTAction - > result = ( LRESULT ) DROPEFFECT_MOVE ;
}
# endif // OX_CUSTOMIZE_COMMANDS
return ( LONG ) TRUE ;
}
LONG COXBitmapMenu : : OnDragLeave ( WPARAM wParam , LPARAM lParam )
{
UNREFERENCED_PARAMETER ( wParam ) ;
if ( ! IsCustomizable ( ) )
return ( LONG ) FALSE ;
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
SetInsertMark ( - 1 ) ;
// reset flag that specifies that drag'n'drop operation is active
m_bDragDropOperation = FALSE ;
return ( LONG ) TRUE ;
}
LONG COXBitmapMenu : : OnDrop ( WPARAM wParam , LPARAM lParam )
{
UNREFERENCED_PARAMETER ( wParam ) ;
if ( ! IsCustomizable ( ) )
return ( LONG ) FALSE ;
// lParam is the pointer to SHBDROPTARGETACTION structure
LPSHBDROPTARGETACTION pSHBDTAction = ( LPSHBDROPTARGETACTION ) lParam ;
ASSERT ( pSHBDTAction ! = NULL ) ;
pSHBDTAction - > result = ( LRESULT ) FALSE ;
# ifdef OX_CUSTOMIZE_COMMANDS
// if dragged item is to be copied or moved
if ( ( pSHBDTAction - > dropEffect & DROPEFFECT_COPY ) ! = 0 | |
( pSHBDTAction - > dropEffect & DROPEFFECT_MOVE ) ! = 0 )
{
// data must be in the specific format
ASSERT ( pSHBDTAction - > pDataObject - >
IsDataAvailable ( COXDragDropCommands : : m_cfCommandButton ) ) ;
int nItemIndex = GetInsertMark ( ) ;
if ( nItemIndex ! = - 1 | | GetMenuItemCount ( ) = = 0 )
{
// Get the drag item info
//
HGLOBAL hgData = pSHBDTAction - > pDataObject - >
GetGlobalData ( COXDragDropCommands : : m_cfCommandButton ) ;
ASSERT ( hgData ! = NULL ) ;
// lock it
BYTE * lpItemData = ( BYTE * ) : : GlobalLock ( hgData ) ;
if ( ! SendCustomizeNotification ( ID_OXCUSTBM_INSERT_ITEM ) )
{
RetrieveDragDropMenuItem ( lpItemData , GetSafeHmenu ( ) , nItemIndex ) ;
if ( m_bDragDropOwner & & m_nCustomizedItemIndex > = nItemIndex )
{
ASSERT ( m_nCustomizedItemIndex ! = - 1 ) ;
m_nCustomizedItemIndex + + ;
ASSERT ( GetDraggedItem ( ) ! = - 1 ) ;
SetDraggedItem ( GetDraggedItem ( ) + 1 ) ;
}
}
// unlock it
: : GlobalUnlock ( hgData ) ;
// free it
: : GlobalFree ( hgData ) ;
// remove insert mark
SetInsertMark ( - 1 ) ;
// drag'n'drop operation completed successfully
pSHBDTAction - > result = ( LRESULT ) TRUE ;
}
else
{
pSHBDTAction - > result = ( LRESULT ) FALSE ;
}
}
# endif // OX_CUSTOMIZE_COMMANDS
m_bDragDropOperation = FALSE ;
// we handled the message
return ( LONG ) TRUE ;
}
void COXBitmapMenu : : RetrieveDragDropMenuItem ( BYTE * & lpData , HMENU hMenu ,
int nItemIndex )
{
ASSERT ( lpData ! = NULL ) ;
ASSERT ( hMenu ! = NULL ) ;
ASSERT ( : : IsMenu ( hMenu ) ) ;
COXBitmapMenuOrganizer * pOrganizer =
COXBitmapMenuOrganizer : : FindOrganizer ( AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ) ;
ASSERT ( pOrganizer ! = NULL ) ;
while ( TRUE )
{
// get button command ID
int nCommandID = * ( int * ) lpData ;
lpData + = sizeof ( int ) ;
// get button text
CString sText ( ( LPTSTR ) lpData ) ;
lpData + = sText . GetLength ( ) + sizeof ( TCHAR ) ;
if ( sText . IsEmpty ( ) & & nCommandID ! = 0 )
{
HINSTANCE hInstance =
AfxFindResourceHandle ( MAKEINTRESOURCE ( nCommandID ) , RT_STRING ) ;
ASSERT ( hInstance ! = NULL ) ;
sText . LoadString ( nCommandID ) ;
int nPosition = sText . Find ( _T ( ' \n ' ) ) ;
if ( nPosition ! = - 1 )
sText = sText . Mid ( nPosition + 1 ) ;
}
ASSERT ( ! sText . IsEmpty ( ) | | nCommandID = = 0 ) ;
// get button image index
int nImageIndex = * ( int * ) lpData ;
lpData + = sizeof ( int ) ;
UNREFERENCED_PARAMETER ( nImageIndex ) ;
// get button style
BYTE fsStyle = * ( BYTE * ) lpData ;
lpData + = sizeof ( BYTE ) ;
UNREFERENCED_PARAMETER ( fsStyle ) ;
// get finish flag
int nFinish = * ( int * ) lpData ;
lpData + = sizeof ( int ) ;
// update menu
if ( nCommandID = = - 1 )
{
HMENU hSubMenu = : : CreatePopupMenu ( ) ;
ASSERT ( hSubMenu ! = NULL ) ;
pOrganizer - > m_arrCreatedPopupMenus . Add ( hSubMenu ) ;
VERIFY ( : : InsertMenu ( hMenu , nItemIndex ,
MF_BYPOSITION | MF_POPUP | MF_STRING , ( UINT_PTR ) hSubMenu , sText ) ! = 0 ) ;
/*
CMenu * pMenu = CMenu : : FromHandle ( hMenu ) ;
ASSERT ( pMenu ! = NULL ) ;
COXBitmapMenu * pBitmapMenu = DYNAMIC_DOWNCAST ( COXBitmapMenu , pMenu ) ;
if ( pBitmapMenu ! = NULL )
{
pOrganizer - > ConvertBitmapMenu ( pBitmapMenu , FALSE ) ;
}
*/
if ( nFinish ! = 0 )
{
RetrieveDragDropMenuItem ( lpData , hSubMenu , 0 ) ;
}
}
else
{
VERIFY ( : : InsertMenu ( hMenu , nItemIndex ,
MF_BYPOSITION | ( nCommandID = = 0 ? MF_SEPARATOR : MF_STRING ) ,
( UINT ) nCommandID , sText ) ! = 0 ) ;
}
nItemIndex + + ;
if ( nFinish = = 0 | | nFinish = = 2 )
break ;
}
CMenu * pMenu = CMenu : : FromHandle ( hMenu ) ;
ASSERT ( pMenu ! = NULL ) ;
COXBitmapMenu * pBitmapMenu = DYNAMIC_DOWNCAST ( COXBitmapMenu , pMenu ) ;
if ( pBitmapMenu = = NULL )
{
pOrganizer - > OnInitMenuPopup ( pMenu , 0 , FALSE ) ;
pMenu = CMenu : : FromHandle ( hMenu ) ;
pBitmapMenu = DYNAMIC_DOWNCAST ( COXBitmapMenu , pMenu ) ;
}
ASSERT ( pBitmapMenu ! = NULL ) ;
pBitmapMenu - > UpdateContents ( ) ;
}
int COXBitmapMenu : : SetInsertMark ( int nItemIndex )
{
ASSERT ( nItemIndex > = - 1 & & nItemIndex < = ( int ) GetMenuItemCount ( ) ) ;
int nOldInsertMark = m_nInsertMarkIndex ;
m_nInsertMarkIndex = nItemIndex ;
if ( nOldInsertMark ! = m_nInsertMarkIndex )
{
if ( m_pPopupWnd ! = NULL & & : : IsWindow ( m_pPopupWnd - > GetSafeHwnd ( ) ) )
{
if ( nOldInsertMark ! = - 1 )
{
int nInsertMark = nOldInsertMark ;
if ( nInsertMark = = ( int ) GetMenuItemCount ( ) )
{
nInsertMark - - ;
}
m_pPopupWnd - > RedrawItem ( nInsertMark ) ;
if ( nOldInsertMark ! = 0 & & nOldInsertMark ! = ( int ) GetMenuItemCount ( ) & &
nOldInsertMark ! = m_nInsertMarkIndex + 1 )
{
m_pPopupWnd - > RedrawItem ( nOldInsertMark - 1 ) ;
}
}
if ( m_nInsertMarkIndex ! = - 1 )
{
int nInsertMark = m_nInsertMarkIndex ;
if ( nInsertMark = = ( int ) GetMenuItemCount ( ) )
nInsertMark - - ;
m_pPopupWnd - > RedrawItem ( nInsertMark ) ;
if ( m_nInsertMarkIndex ! = 0 & &
m_nInsertMarkIndex ! = ( int ) GetMenuItemCount ( ) & &
m_nInsertMarkIndex ! = nOldInsertMark + 1 )
{
m_pPopupWnd - > RedrawItem ( m_nInsertMarkIndex - 1 ) ;
}
}
}
SendCustomizeNotification ( ID_OXCUSTBM_SET_INSERT_MARK ) ;
}
return nOldInsertMark ;
}
int COXBitmapMenu : : HitTest ( LPPOINT ppt , BOOL * pbBefore /*=NULL*/ )
{
int nItemIndex = - 1 ;
int nHeight = 0 ;
for ( int nIndex = 0 ; nIndex < ( int ) GetMenuItemCount ( ) ; nIndex + + )
{
MENUITEMINFO mii = { sizeof ( mii ) } ;
mii . fMask = MIIM_DATA ;
VERIFY ( : : GetMenuItemInfo ( GetSafeHmenu ( ) , nIndex , TRUE , & mii ) ) ;
MEASUREITEMSTRUCT mis ;
mis . CtlType = ODT_MENU ;
mis . itemData = mii . dwItemData ;
mis . itemID = GetMenuItemID ( nIndex ) ;
mis . itemHeight = ( UINT ) - 1 ;
mis . itemWidth = ( UINT ) - 1 ;
MeasureItem ( & mis ) ;
nHeight + = mis . itemHeight ;
if ( ppt - > y < = nHeight )
{
nItemIndex = nIndex ;
if ( pbBefore ! = NULL )
* pbBefore = ( ppt - > y < = nHeight - ( int ) mis . itemHeight / 2 ) ;
break ;
}
}
return nItemIndex ;
}
void COXBitmapMenu : : UpdateContents ( )
{
COXBitmapMenuOrganizer * pOrganizer =
COXBitmapMenuOrganizer : : FindOrganizer ( AfxGetMainWnd ( ) - > GetSafeHwnd ( ) ) ;
if ( pOrganizer ! = NULL )
{
pOrganizer - > ConvertBitmapMenu ( this , FALSE ) ;
}
if ( m_pPopupWnd ! = NULL & & : : IsWindow ( m_pPopupWnd - > GetSafeHwnd ( ) ) )
{
m_pPopupWnd - > OnMenuChanged ( ) ;
}
}
void COXBitmapMenu : : OnBeginDragDrop ( int nIndex )
{
ASSERT ( nIndex > = 0 & & nIndex < ( int ) GetMenuItemCount ( ) ) ;
ASSERT ( m_pPopupWnd ! = NULL & & : : IsWindow ( m_pPopupWnd - > GetSafeHwnd ( ) ) ) ;
UNUSED ( nIndex ) ;
// mark the control as the one that launched drag'n'drop operation
m_bDragDropOwner = TRUE ;
# ifdef OX_CUSTOMIZE_COMMANDS
CString sText ;
MENUITEMINFO mii = { sizeof ( mii ) } ;
mii . fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_SUBMENU ;
mii . cch = 300 ;
mii . dwTypeData = sText . GetBuffer ( mii . cch ) ;
VERIFY ( : : GetMenuItemInfo ( GetSafeHmenu ( ) , nIndex , TRUE , & mii ) ) ;
sText . ReleaseBuffer ( ) ;
// don't allow to drag most recent files used
if ( ( int ) mii . wID > = ID_FILE_MRU_FILE1 & & ( int ) mii . wID < = ID_FILE_MRU_FILE16 )
{
// unmark as the control which launched drag'n'drop operation
m_bDragDropOwner = FALSE ;
return ;
}
// don't allow to drag MDIChild windows menu items
if ( ( int ) mii . wID > = AFX_IDM_FIRST_MDICHILD & & mii . hSubMenu = = NULL )
{
// unmark as the control which launched drag'n'drop operation
m_bDragDropOwner = FALSE ;
return ;
}
COXItemInfo * pItemInfo = ( COXItemInfo * ) ( mii . dwItemData ) ;
ASSERT ( AfxIsValidAddress ( pItemInfo , sizeof ( COXItemInfo ) ) ) ;
ASSERT ( ! pItemInfo - > GetText ( ) . IsEmpty ( ) | | mii . fType & MFT_SEPARATOR ) ;
CMenu * pSubmenu = GetSubMenu ( nIndex ) ;
if ( pSubmenu ! = NULL )
{
COXBitmapMenu * pBMSubmenu = DYNAMIC_DOWNCAST ( COXBitmapMenu , pSubmenu ) ;
if ( pBMSubmenu ! = NULL )
{
if ( pBMSubmenu - > GetPopupWnd ( ) ! = NULL )
{
pBMSubmenu - > GetPopupWnd ( ) - > ResetPopupMenu ( ) ;
}
}
}
COleDataSource * pDataSource =
COXDragDropCommands : : PrepareDragDropData ( pItemInfo - > GetText ( ) ,
pItemInfo - > GetImageInfo ( ) - > GetIndex ( ) , GetMenuItemID ( nIndex ) , 0 ,
GetSubMenu ( nIndex ) - > GetSafeHmenu ( ) ) ;
ASSERT ( pDataSource ! = NULL ) ;
m_bDragDropOperation = TRUE ;
SetDraggedItem ( nIndex ) ;
DROPEFFECT dropEffect =
COXDragDropCommands : : DoDragDrop ( pDataSource , GetDropSource ( m_pPopupWnd ) ) ;
if ( DROPEFFECT_MOVE = = dropEffect | | ( DROPEFFECT_NONE = = dropEffect & &
: : GetKeyState ( VK_LBUTTON ) > = 0 & & ! m_bDragDropOperation ) )
{
if ( ! SendCustomizeNotification ( ID_OXCUSTBM_DELETE_ITEM ) )
{
int nDraggedItemIndex = GetDraggedItem ( ) ;
// delete item if it was moved
VERIFY ( DeleteMenu ( nDraggedItemIndex , MF_BYPOSITION ) ) ;
m_nCustomizedItemIndex = - 1 ;
UpdateContents ( ) ;
}
}
SetDraggedItem ( - 1 ) ;
//delete drag source (we are responsible to do that)
delete pDataSource ;
# endif // OX_CUSTOMIZE_COMMANDS
// unmark as the control which launched drag'n'drop operation
m_bDragDropOwner = FALSE ;
}
COXMenuSkin * COXBitmapMenu : : GetMenuSkin ( )
{
// Check if the app is derived from COXSkinnedApp
COXSkinnedApp * pSkinnedApp = DYNAMIC_DOWNCAST ( COXSkinnedApp , AfxGetApp ( ) ) ;
if ( pSkinnedApp ! = NULL & & pSkinnedApp - > GetCurrentSkin ( ) ! = NULL )
return pSkinnedApp - > GetCurrentSkin ( ) - > GetMenuSkin ( ) ;
else
{
// Create a classic skin for this class if not created already
if ( m_pMenuSkin = = NULL )
m_pMenuSkin = new COXMenuSkinClassic ( ) ;
return m_pMenuSkin ;
}
}
// Returns TRUE if the given item is a popup menu (has a submenu)
BOOL COXBitmapMenu : : IsPopupItem ( UINT nItemID )
{
if ( nItemID = = ( UINT ) - 1 )
return TRUE ;
MENUITEMINFO mii ;
: : memset ( & mii , 0 , sizeof ( MENUITEMINFO ) ) ;
mii . cbSize = sizeof ( MENUITEMINFO ) ;
mii . fMask = MIIM_SUBMENU ;
GetMenuItemInfo ( nItemID , & mii ) ;
if ( mii . hSubMenu ! = NULL )
return TRUE ;
else
return FALSE ;
}
void COXBitmapMenu : : RestoreMDI ( )
{
CMDIFrameWnd * pMainWnd = ( CMDIFrameWnd * ) AfxGetMainWnd ( ) ;
CMDIChildWnd * active = pMainWnd - > MDIGetActive ( ) ;
active - > MDIRestore ( ) ;
pMainWnd - > MDINext ( ) ;
while ( active ! = pMainWnd - > MDIGetActive ( ) )
{
pMainWnd - > MDIGetActive ( ) - > MDIRestore ( ) ;
pMainWnd - > MDINext ( ) ;
}
}
void COXBitmapMenu : : CloseMDI ( )
{
CMDIFrameWnd * pMainWnd = ( CMDIFrameWnd * ) AfxGetMainWnd ( ) ;
CMDIChildWnd * active = pMainWnd - > MDIGetActive ( ) ;
if ( active - > GetActiveDocument ( ) - > IsModified ( ) )
{
CString sTitle ;
active - > GetActiveFrame ( ) - > GetWindowText ( sTitle ) ;
int ID = AfxMessageBox ( _T ( " Save changes to " ) + sTitle + _T ( " ? " ) , MB_YESNOCANCEL ) ;
switch ( ID )
{
case IDCANCEL :
// Do nothing
break ;
case IDYES :
active - > GetActiveDocument ( ) - > DoFileSave ( ) ;
// Fall through intended
case IDNO :
active - > DestroyWindow ( ) ;
}
}
else
{
active - > DestroyWindow ( ) ;
}
}
void COXBitmapMenu : : MinimizeMDI ( )
{
CMDIFrameWnd * pMainWnd = ( CMDIFrameWnd * ) AfxGetMainWnd ( ) ;
CMDIChildWnd * active = pMainWnd - > MDIGetActive ( ) ;
active - > MDIRestore ( ) ;
active - > ShowWindow ( SW_MINIMIZE ) ; }
BOOL COXBitmapMenu : : HandleMDICommandMessage ( UINT nID , int nCode , void * pExtra , AFX_CMDHANDLERINFO * pHandlerInfo )
{
UNREFERENCED_PARAMETER ( pHandlerInfo ) ;
if ( nCode = = CN_UPDATE_COMMAND_UI )
{
switch ( nID )
{
case ID_OXBITMAPMENU_CLOSE :
case ID_OXBITMAPMENU_MINIMIZE :
case ID_OXBITMAPMENU_RESTORE :
( ( CCmdUI * ) pExtra ) - > Enable ( TRUE ) ;
return TRUE ;
}
}
else
if ( nCode = = CN_COMMAND )
{
bool bHandled = false ;
switch ( nID )
{
case ID_OXBITMAPMENU_CLOSE :
CloseMDI ( ) ;
bHandled = true ;
break ;
case ID_OXBITMAPMENU_MINIMIZE :
MinimizeMDI ( ) ;
bHandled = true ;
break ;
case ID_OXBITMAPMENU_RESTORE :
RestoreMDI ( ) ;
bHandled = true ;
break ;
case SC_MAXIMIZE :
return TRUE ;
}
if ( bHandled )
{
CMDIFrameWnd * pMainWnd = static_cast < CMDIFrameWnd * > ( AfxGetMainWnd ( ) ) ;
if ( pMainWnd )
{
CMDIChildWnd * pActiveWnd = pMainWnd - > MDIGetActive ( ) ;
if ( pActiveWnd )
{
pActiveWnd - > GetSystemMenu ( TRUE ) ;
}
}
return TRUE ;
}
}
return FALSE ;
}
# ifndef CS_DROPSHADOW
# define CS_DROPSHADOW 0x00020000
# endif
BOOL COXBitmapMenu : : RegisterWindowClass ( HINSTANCE hInstance )
{
if ( m_origWndProc ! = NULL )
return TRUE ; // already registed
WNDCLASS wndclass ;
if ( GetClassInfo ( hInstance , _T ( " #32768 " ) , & wndclass ) )
m_origWndProc = wndclass . lpfnWndProc ;
wndclass . lpfnWndProc = PopupWndProc ;
wndclass . style & = ~ CS_DROPSHADOW ;
wndclass . style | = CS_SAVEBITS ;
wndclass . hInstance = hInstance ;
RegisterClass ( & wndclass ) ;
if ( GetClassInfo ( hInstance , _T ( " #32768 " ) , & wndclass ) )
return TRUE ;
else
return FALSE ;
}
LRESULT CALLBACK COXBitmapMenu : : PopupWndProc ( HWND hwnd , UINT nMsg , WPARAM wParam , LPARAM lParam )
{
return GetMenuSkin ( ) - > MenuPopupWndProc ( m_origWndProc , hwnd , nMsg , wParam , lParam ) ;
}
void COXBitmapMenuPopupWnd : : OnNcPaint ( )
{
COXBitmapMenu : : GetMenuSkin ( ) - > OnNcPaintCustomizePopupWnd ( this ) ;
}
BOOL COXBitmapMenu : : TrackPopupMenu ( COXCoolToolBar * pCoolToolBar , CWnd * pWnd , LPCRECT lpRect )
{
// Determine the selected item
int iSelectedItem = - 1 ;
CToolBarCtrl & ctrl = pCoolToolBar - > GetToolBarCtrl ( ) ;
int iButtonCount = ctrl . GetButtonCount ( ) ;
for ( int i = 0 ; i < iButtonCount ; i + + )
{
if ( ctrl . IsButtonPressed ( pCoolToolBar - > GetItemID ( i ) ) )
{
iSelectedItem = i ;
break ;
}
}
if ( iSelectedItem = = - 1 )
iSelectedItem = ctrl . CommandToIndex ( pCoolToolBar - > m_iLastDropDownIndex ) ;
// Determine the rectangle of the selected item
CRect rectItem ;
pCoolToolBar - > GetItemRect ( iSelectedItem , & rectItem ) ;
COXMenuBar * pMenuBar = DYNAMIC_DOWNCAST ( COXMenuBar , pCoolToolBar ) ;
if ( pMenuBar ! = NULL & & iSelectedItem = = - 1 )
{
// This is the icon item
rectItem = pMenuBar - > m_iconRect ;
CRect rectWindow ;
pMenuBar - > GetWindowRect ( rectWindow ) ;
pMenuBar - > ScreenToClient ( & rectWindow ) ;
CRect rectClient ;
pMenuBar - > GetClientRect ( rectClient ) ;
rectItem . left + = rectWindow . left - rectClient . left ;
rectItem . right + = rectWindow . left - rectClient . left ;
rectItem . top + = rectWindow . top - rectClient . top ;
rectItem . bottom + = rectWindow . top - rectClient . top ;
rectItem . InflateRect ( 3 , 3 ) ;
}
pCoolToolBar - > ClientToScreen ( & rectItem ) ;
// Determine the position of the popup menu relative to the selected item
CPoint ptTopLeft ;
UINT nFlags , nPosFlags ;
DeterminePosition ( this , rectItem , pCoolToolBar - > m_dwStyle , ptTopLeft , nFlags , nPosFlags ) ;
// Clear the queue of any pending messages
MSG msg ;
while ( : : PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) ! = 0 )
{
: : TranslateMessage ( & msg ) ;
: : DispatchMessage ( & msg ) ;
}
COXShadowedItemWnd * pSIW = new COXShadowedItemWnd ( pCoolToolBar , iSelectedItem , nPosFlags ) ;
CRect rect ;
pCoolToolBar - > GetItemRect ( iSelectedItem , rect ) ;
rect . DeflateRect ( 0 , 1 ) ;
// Save the item rectangle in screen coordinates
m_rectDropDownItem = rect ;
pCoolToolBar - > ClientToScreen ( m_rectDropDownItem ) ;
// Create the transparent window which will be responsible for drawing the shadow
// The transparent window must be a child of the main window
rect . InflateRect ( 0 , 0 , 4 , 4 ) ;
pCoolToolBar - > ClientToScreen ( rect ) ;
pSIW - > CreateEx ( WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW , NULL , NULL , WS_CHILD | WS_VISIBLE ,
rect , CWnd : : GetDesktopWindow ( ) , 0 , NULL ) ;
BOOL bResult = CMenu : : TrackPopupMenu ( nFlags , ptTopLeft . x , ptTopLeft . y , pWnd , lpRect ) ;
pSIW - > DestroyWindow ( ) ;
delete pSIW ;
pSIW = NULL ;
m_rectDropDownItem . SetRectEmpty ( ) ;
return bResult ;
}
// Returns the size of the popup menu before it is displayed
CSize COXBitmapMenu : : GetPopupMenuSize ( CMenu * pMenu )
{
CSize szMenu ( 0 , 0 ) ;
int iCount = pMenu - > GetMenuItemCount ( ) ;
for ( int i = 0 ; i < iCount ; i + + )
{
UINT nItemID = pMenu - > GetMenuItemID ( i ) ;
// Get the data member
MENUITEMINFO miinfo ;
: : memset ( & miinfo , 0 , sizeof ( MENUITEMINFO ) ) ;
miinfo . cbSize = sizeof ( MENUITEMINFO ) ;
miinfo . fMask = MIIM_DATA ;
pMenu - > GetMenuItemInfo ( nItemID , & miinfo ) ;
// Call CMenu::MeasureItem() to determine the item's dimensions
MEASUREITEMSTRUCT mi ;
: : memset ( & mi , 0 , sizeof ( MEASUREITEMSTRUCT ) ) ;
mi . CtlType = ODT_MENU ;
mi . itemID = nItemID ;
mi . itemData = miinfo . dwItemData ;
pMenu - > MeasureItem ( & mi ) ;
if ( mi . itemHeight = = 0 & & DYNAMIC_DOWNCAST ( COXBitmapMenu , pMenu ) = = NULL )
{
// This is not a COXBitmapMenu
if ( nItemID = = 0 )
mi . itemHeight = 8 ; // separator
else
mi . itemHeight = 17 ; // normal item
}
if ( ( int ) mi . itemWidth > szMenu . cx )
szMenu . cx = mi . itemWidth ;
szMenu . cy + = mi . itemHeight ;
}
// Compensate for the non-client area
szMenu . cx + = 18 ;
szMenu . cy + = 6 ;
return szMenu ;
}
// v9.3 update 01 fixes and changes: Manfred Drasch
// Horizontal menu:
// * wrong ypos under some circumstances
// * avoid a drawingproblem (the menubutton was painted over the popupmenu)
// Vertical menu:
// * wrong xpos under some circumstances
// Both:
// * Menu now shown over vertical Appbar/Sidebar, too
void COXBitmapMenu : : DeterminePosition ( CMenu * pMenu , LPCRECT lpItemRect , DWORD dwStyle , CPoint & ptTopLeft , UINT & nFlags , UINT & nPosFlags )
{
// Get the rectangle of the monitor ( + WorkArea) closest to the menu rectangle
CRect rctMonitorWorkArea ;
CRect rctMonitor ;
CPoint ptCursor ;
HMONITOR hMonitor = : : MonitorFromRect ( lpItemRect , MONITOR_DEFAULTTONEAREST ) ;
MONITORINFO mi ;
mi . cbSize = sizeof ( MONITORINFO ) ;
if ( hMonitor ! = NULL & & : : GetMonitorInfo ( hMonitor , & mi ) )
{
rctMonitorWorkArea = mi . rcWork ;
rctMonitor = mi . rcMonitor ;
}
else
{
rctMonitorWorkArea . SetRect ( 0 , 0 , GetSystemMetrics ( SM_CXSCREEN ) , GetSystemMetrics ( SM_CYSCREEN ) ) ;
rctMonitor . SetRect ( 0 , 0 , GetSystemMetrics ( SM_CXSCREEN ) , GetSystemMetrics ( SM_CYSCREEN ) ) ;
}
CSize sizeMenu = GetPopupMenuSize ( pMenu ) ;
ptTopLeft . x = 0 ;
ptTopLeft . y = 0 ;
nFlags = 0 ;
if ( dwStyle & CBRS_ORIENT_HORZ )
{
// Horizontal menu
ptTopLeft . x = lpItemRect - > left ;
if ( ptTopLeft . x < rctMonitor . left )
ptTopLeft . x = rctMonitor . left ;
if ( ptTopLeft . x + sizeMenu . cx > rctMonitor . right )
ptTopLeft . x = rctMonitor . right - 1 ;
else
{
if ( ptTopLeft . x + sizeMenu . cx + 1 > = rctMonitorWorkArea . right )
{
ptTopLeft . x + = sizeMenu . cx ;
if ( ptTopLeft . x = = 0 )
ptTopLeft . x = - 1 ;
}
}
if ( lpItemRect - > bottom + sizeMenu . cy > rctMonitorWorkArea . bottom )
{
// The popup menu should be above the item
nFlags | = TPM_BOTTOMALIGN ;
nPosFlags = OX_TPM_TOP ;
ptTopLeft . y = lpItemRect - > top + 1 ;
}
else
{
// The popup menu should be below the item
nFlags | = TPM_TOPALIGN ;
nPosFlags = OX_TPM_BOTTOM ;
ptTopLeft . y = lpItemRect - > bottom - 1 ;
}
}
else
{
// Vertical menu
if ( lpItemRect - > right + sizeMenu . cx > rctMonitor . right )
{
// The popup menu should be left of the item
nFlags | = TPM_RIGHTALIGN ;
nPosFlags = OX_TPM_LEFT ;
ptTopLeft . x = lpItemRect - > left ;
}
else
{
// The popup menu should be right of the item
nFlags | = TPM_LEFTALIGN ;
nPosFlags = OX_TPM_RIGHT ;
if ( lpItemRect - > right + sizeMenu . cx + 1 > = rctMonitorWorkArea . right )
ptTopLeft . x = lpItemRect - > right + sizeMenu . cx ;
else
ptTopLeft . x = lpItemRect - > right ;
if ( ptTopLeft . x = = 0 )
ptTopLeft . x = - 1 ;
}
ptTopLeft . y = lpItemRect - > top + 1 ;
if ( ptTopLeft . y < rctMonitorWorkArea . top )
ptTopLeft . y = rctMonitorWorkArea . top ;
if ( ptTopLeft . y + sizeMenu . cy > rctMonitorWorkArea . bottom )
ptTopLeft . y = rctMonitorWorkArea . bottom - sizeMenu . cy ;
}
}