2014-02-24 11:59:34 +00:00
/*
* Shell Menu Band
*
* Copyright 2014 David Quintana
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
2015-08-19 09:05:54 +00:00
# include "shellmenu.h"
2014-03-20 15:39:25 +00:00
# include <commoncontrols.h>
2014-02-24 11:59:34 +00:00
# include <shlwapi_undoc.h>
2014-06-19 23:14:39 +00:00
# include <uxtheme.h>
2015-04-24 14:12:24 +00:00
# include <vssym32.h>
2014-02-24 11:59:34 +00:00
# include "CMenuBand.h"
# include "CMenuToolbars.h"
2014-11-12 17:13:05 +00:00
# define IDS_MENU_EMPTY 34561
2014-02-24 11:59:34 +00:00
WINE_DEFAULT_DEBUG_CHANNEL ( CMenuToolbars ) ;
2014-03-03 11:14:04 +00:00
// FIXME: Enable if/when wine comctl supports this flag properly
2014-03-16 01:21:54 +00:00
# define USE_TBSTYLE_EX_VERTICAL 0
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
// User-defined timer ID used while hot-tracking around the menu
2014-02-24 11:59:34 +00:00
# define TIMERID_HOTTRACK 1
2014-03-15 21:38:15 +00:00
2014-11-11 01:05:39 +00:00
LRESULT CMenuToolbarBase : : OnWinEventWrap ( UINT uMsg , WPARAM wParam , LPARAM lParam , BOOL & bHandled )
{
LRESULT lr ;
bHandled = OnWinEvent ( m_hWnd , uMsg , wParam , lParam , & lr ) ! = S_FALSE ;
return lr ;
}
2014-02-26 11:13:23 +00:00
HRESULT CMenuToolbarBase : : OnWinEvent ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam , LRESULT * theResult )
{
NMHDR * hdr ;
2018-03-08 09:28:33 +00:00
HRESULT hr ;
LRESULT result ;
2014-02-26 11:13:23 +00:00
2018-03-08 09:28:33 +00:00
if ( theResult )
* theResult = 0 ;
2014-02-26 11:13:23 +00:00
switch ( uMsg )
{
case WM_COMMAND :
2014-06-29 15:42:06 +00:00
//return OnCommand(wParam, lParam, theResult);
return S_OK ;
2014-02-26 11:13:23 +00:00
case WM_NOTIFY :
hdr = reinterpret_cast < LPNMHDR > ( lParam ) ;
switch ( hdr - > code )
{
2014-03-11 10:42:25 +00:00
case TBN_DELETINGBUTTON :
return OnDeletingButton ( reinterpret_cast < LPNMTOOLBAR > ( hdr ) ) ;
2014-02-26 11:13:23 +00:00
case PGN_CALCSIZE :
2014-04-02 17:37:37 +00:00
return OnPagerCalcSize ( reinterpret_cast < LPNMPGCALCSIZE > ( hdr ) ) ;
2014-02-26 11:13:23 +00:00
case TBN_DROPDOWN :
2014-07-09 00:42:05 +00:00
return ProcessClick ( reinterpret_cast < LPNMTOOLBAR > ( hdr ) - > iItem ) ;
2014-02-26 11:13:23 +00:00
case TBN_HOTITEMCHANGE :
2014-04-03 18:30:25 +00:00
//return OnHotItemChange(reinterpret_cast<LPNMTBHOTITEM>(hdr), theResult);
return S_OK ;
2014-02-26 11:13:23 +00:00
case NM_CUSTOMDRAW :
2018-03-08 09:28:33 +00:00
hr = OnCustomDraw ( reinterpret_cast < LPNMTBCUSTOMDRAW > ( hdr ) , & result ) ;
if ( theResult )
* theResult = result ;
return hr ;
2014-02-26 11:13:23 +00:00
2014-04-02 17:37:37 +00:00
case TBN_GETINFOTIP :
return OnGetInfoTip ( reinterpret_cast < LPNMTBGETINFOTIP > ( hdr ) ) ;
// Silence unhandled items so that they don't print as unknown
2014-03-11 10:42:25 +00:00
case RBN_CHILDSIZE :
return S_OK ;
2014-02-26 11:13:23 +00:00
2014-04-02 17:37:37 +00:00
case TTN_GETDISPINFO :
return S_OK ;
2014-03-20 15:39:25 +00:00
case NM_RELEASEDCAPTURE :
break ;
2014-04-02 17:37:37 +00:00
case NM_CLICK :
2014-03-20 15:39:25 +00:00
case NM_RDOWN :
case NM_LDOWN :
break ;
case TBN_GETDISPINFO :
break ;
case TBN_BEGINDRAG :
case TBN_ENDDRAG :
break ;
case NM_TOOLTIPSCREATED :
break ;
2017-10-30 20:53:00 +00:00
case TBN_DRAGOUT : return S_FALSE ;
2014-04-03 18:30:25 +00:00
2014-03-11 10:42:25 +00:00
default :
2014-04-09 11:45:02 +00:00
TRACE ( " WM_NOTIFY unknown code %d, %d \n " , hdr - > code , hdr - > idFrom ) ;
2014-03-26 11:33:52 +00:00
return S_OK ;
2014-03-11 10:42:25 +00:00
}
2014-03-26 11:33:52 +00:00
return S_FALSE ;
2017-06-17 07:43:52 +00:00
case WM_WININICHANGE :
if ( wParam = = SPI_SETFLATMENU )
{
SystemParametersInfo ( SPI_GETFLATMENU , 0 , & m_useFlatMenus , 0 ) ;
}
2014-03-11 10:42:25 +00:00
}
2014-02-26 11:13:23 +00:00
2014-03-11 10:42:25 +00:00
return S_FALSE ;
}
2014-02-26 11:13:23 +00:00
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : DisableMouseTrack ( BOOL bDisable )
{
if ( m_disableMouseTrack ! = bDisable )
{
m_disableMouseTrack = bDisable ;
2014-04-09 11:45:02 +00:00
TRACE ( " DisableMouseTrack %d \n " , bDisable ) ;
2014-04-02 17:37:37 +00:00
}
return S_OK ;
}
HRESULT CMenuToolbarBase : : OnPagerCalcSize ( LPNMPGCALCSIZE csize )
{
SIZE tbs ;
2014-04-07 18:41:47 +00:00
GetSizes ( NULL , & tbs , NULL ) ;
2014-04-02 17:37:37 +00:00
if ( csize - > dwFlag = = PGF_CALCHEIGHT )
{
csize - > iHeight = tbs . cy ;
}
else if ( csize - > dwFlag = = PGF_CALCWIDTH )
{
csize - > iWidth = tbs . cx ;
}
return S_OK ;
}
2014-03-11 10:42:25 +00:00
HRESULT CMenuToolbarBase : : OnCustomDraw ( LPNMTBCUSTOMDRAW cdraw , LRESULT * theResult )
{
2018-01-13 12:57:24 +00:00
bool isHot , isPopup , isActive ;
2014-03-11 10:42:25 +00:00
TBBUTTONINFO btni ;
2014-02-27 11:56:28 +00:00
2014-03-11 10:42:25 +00:00
switch ( cdraw - > nmcd . dwDrawStage )
{
case CDDS_PREPAINT :
2014-04-02 17:37:37 +00:00
* theResult = CDRF_NOTIFYITEMDRAW ;
2014-03-11 10:42:25 +00:00
return S_OK ;
2014-02-26 11:13:23 +00:00
2014-03-11 10:42:25 +00:00
case CDDS_ITEMPREPAINT :
2014-11-11 01:05:39 +00:00
2018-01-13 12:57:24 +00:00
HWND tlw ;
m_menuBand - > _GetTopLevelWindow ( & tlw ) ;
2014-04-02 17:37:37 +00:00
// The item with an active submenu gets the CHECKED flag.
2014-04-09 11:45:02 +00:00
isHot = m_hotBar = = this & & ( int ) cdraw - > nmcd . dwItemSpec = = m_hotItem ;
isPopup = m_popupBar = = this & & ( int ) cdraw - > nmcd . dwItemSpec = = m_popupItem ;
2018-01-13 12:57:24 +00:00
isActive = ( GetForegroundWindow ( ) = = tlw ) | | ( m_popupBar = = this ) ;
2014-03-11 10:42:25 +00:00
2017-06-16 17:53:50 +00:00
if ( m_hotItem < 0 & & isPopup )
isHot = TRUE ;
if ( ( m_useFlatMenus & & isHot ) | | ( m_initFlags & SMINIT_VERTICAL ) )
2014-03-11 10:42:25 +00:00
{
2014-11-11 01:05:39 +00:00
COLORREF clrText ;
HBRUSH bgBrush ;
RECT rc = cdraw - > nmcd . rc ;
HDC hdc = cdraw - > nmcd . hdc ;
2014-04-02 17:37:37 +00:00
// Remove HOT and CHECKED flags (will restore HOT if necessary)
2014-04-09 11:45:02 +00:00
cdraw - > nmcd . uItemState & = ~ ( CDIS_HOT | CDIS_CHECKED ) ;
2014-03-11 10:42:25 +00:00
2014-04-02 17:37:37 +00:00
// Decide on the colors
2017-06-16 17:53:50 +00:00
if ( isHot )
2014-04-02 17:37:37 +00:00
{
cdraw - > nmcd . uItemState | = CDIS_HOT ;
clrText = GetSysColor ( COLOR_HIGHLIGHTTEXT ) ;
bgBrush = GetSysColorBrush ( m_useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT ) ;
}
else
{
clrText = GetSysColor ( COLOR_MENUTEXT ) ;
bgBrush = GetSysColorBrush ( COLOR_MENU ) ;
}
// Paint the background color with the selected color
2014-03-11 10:42:25 +00:00
FillRect ( hdc , & rc , bgBrush ) ;
2014-04-02 17:37:37 +00:00
// Set the text color in advance, this color will be assigned when the ITEMPOSTPAINT triggers
2014-03-11 10:42:25 +00:00
SetTextColor ( hdc , clrText ) ;
2014-04-02 17:37:37 +00:00
// Set the text color, will be used by the internal drawing code
2014-03-11 10:42:25 +00:00
cdraw - > clrText = clrText ;
2014-04-02 17:37:37 +00:00
cdraw - > iListGap + = 4 ;
// Tell the default drawing code we don't want any fanciness, not even a background.
* theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000 ; // FIXME: the last bit is Vista+, useful for debugging only
2014-03-11 10:42:25 +00:00
}
2014-04-02 17:37:37 +00:00
else
{
2018-01-05 09:53:35 +00:00
// Set the text color, will be used by the internal drawing code
2018-01-13 12:57:24 +00:00
cdraw - > clrText = GetSysColor ( isActive ? COLOR_MENUTEXT : COLOR_GRAYTEXT ) ;
2018-01-05 09:53:35 +00:00
2014-04-02 17:37:37 +00:00
// Remove HOT and CHECKED flags (will restore HOT if necessary)
cdraw - > nmcd . uItemState & = ~ CDIS_HOT ;
2014-03-11 10:42:25 +00:00
2014-04-02 17:37:37 +00:00
// Decide on the colors
2017-06-16 17:53:50 +00:00
if ( isHot )
2014-04-02 17:37:37 +00:00
{
cdraw - > nmcd . uItemState | = CDIS_HOT ;
}
* theResult = 0 ;
}
2014-03-11 10:42:25 +00:00
2014-02-26 11:13:23 +00:00
return S_OK ;
2014-03-11 10:42:25 +00:00
case CDDS_ITEMPOSTPAINT :
2014-04-02 17:37:37 +00:00
// Fetch the button style
2014-03-11 10:42:25 +00:00
btni . cbSize = sizeof ( btni ) ;
btni . dwMask = TBIF_STYLE ;
2014-11-11 01:05:39 +00:00
GetButtonInfo ( cdraw - > nmcd . dwItemSpec , & btni ) ;
2014-04-02 17:37:37 +00:00
// Check if we need to draw a submenu arrow
2014-03-11 10:42:25 +00:00
if ( btni . fsStyle & BTNS_DROPDOWN )
{
2014-04-02 17:37:37 +00:00
// TODO: Support RTL text modes by drawing a leftwards arrow aligned to the left of the control
// "8" is the rightwards dropdown arrow in the Marlett font
2014-04-09 11:45:02 +00:00
WCHAR text [ ] = L " 8 " ;
2014-04-02 17:37:37 +00:00
// Configure the font to draw with Marlett, keeping the current background color as-is
2014-03-11 10:42:25 +00:00
SelectObject ( cdraw - > nmcd . hdc , m_marlett ) ;
SetBkMode ( cdraw - > nmcd . hdc , TRANSPARENT ) ;
2014-04-02 17:37:37 +00:00
// Tweak the alignment by 1 pixel so the menu draws like the Windows start menu.
2014-03-11 10:42:25 +00:00
RECT rc = cdraw - > nmcd . rc ;
rc . right + = 1 ;
2014-04-02 17:37:37 +00:00
// The arrow is drawn at the right of the item's rect, aligned vertically.
2014-03-11 10:42:25 +00:00
DrawTextEx ( cdraw - > nmcd . hdc , text , 1 , & rc , DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE , NULL ) ;
}
* theResult = TRUE ;
return S_OK ;
}
return S_OK ;
2014-02-26 11:13:23 +00:00
}
2014-02-24 11:59:34 +00:00
CMenuToolbarBase : : CMenuToolbarBase ( CMenuBand * menuBand , BOOL usePager ) :
2014-11-11 01:05:39 +00:00
m_pager ( this , 1 ) ,
2014-02-26 11:13:23 +00:00
m_useFlatMenus ( FALSE ) ,
2014-03-15 21:38:15 +00:00
m_disableMouseTrack ( FALSE ) ,
2014-04-02 17:37:37 +00:00
m_timerEnabled ( FALSE ) ,
2014-02-24 11:59:34 +00:00
m_menuBand ( menuBand ) ,
m_dwMenuFlags ( 0 ) ,
2014-04-07 18:41:47 +00:00
m_hasSizes ( FALSE ) ,
2014-02-27 11:56:28 +00:00
m_usePager ( usePager ) ,
2014-11-11 01:05:39 +00:00
m_hotBar ( NULL ) ,
2014-02-27 11:56:28 +00:00
m_hotItem ( - 1 ) ,
2014-11-11 01:05:39 +00:00
m_popupBar ( NULL ) ,
2014-03-19 15:33:41 +00:00
m_popupItem ( - 1 ) ,
2014-11-11 01:05:39 +00:00
m_isTrackingPopup ( FALSE ) ,
m_cancelingPopup ( FALSE )
2014-02-24 11:59:34 +00:00
{
2014-04-07 18:41:47 +00:00
m_idealSize . cx = 0 ;
m_idealSize . cy = 0 ;
m_itemSize . cx = 0 ;
m_itemSize . cy = 0 ;
2014-02-26 11:13:23 +00:00
m_marlett = CreateFont (
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , DEFAULT_CHARSET ,
OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS ,
DEFAULT_QUALITY , FF_DONTCARE , L " Marlett " ) ;
}
CMenuToolbarBase : : ~ CMenuToolbarBase ( )
{
2018-02-23 10:27:48 +00:00
ClearToolbar ( ) ;
2014-11-11 01:05:39 +00:00
if ( m_hWnd )
DestroyWindow ( ) ;
2014-02-24 11:59:34 +00:00
2014-11-11 01:05:39 +00:00
if ( m_pager . m_hWnd )
m_pager . DestroyWindow ( ) ;
2014-04-02 17:37:37 +00:00
DeleteObject ( m_marlett ) ;
2014-02-24 11:59:34 +00:00
}
void CMenuToolbarBase : : InvalidateDraw ( )
{
2014-11-11 01:05:39 +00:00
InvalidateRect ( NULL , FALSE ) ;
2014-02-24 11:59:34 +00:00
}
2014-11-11 01:05:39 +00:00
HRESULT CMenuToolbarBase : : ShowDW ( BOOL fShow )
2014-02-24 11:59:34 +00:00
{
2014-11-11 01:05:39 +00:00
ShowWindow ( fShow ? SW_SHOW : SW_HIDE ) ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
// Ensure that the right image list is assigned to the toolbar
2014-02-25 10:44:28 +00:00
UpdateImageLists ( ) ;
2014-04-02 17:37:37 +00:00
// For custom-drawing
2017-05-03 21:49:38 +00:00
SystemParametersInfo ( SPI_GETFLATMENU , 0 , & m_useFlatMenus , 0 ) ;
2014-02-26 11:13:23 +00:00
2014-02-25 10:44:28 +00:00
return S_OK ;
}
HRESULT CMenuToolbarBase : : UpdateImageLists ( )
{
2014-04-02 17:37:37 +00:00
if ( ( m_initFlags & ( SMINIT_TOPLEVEL | SMINIT_VERTICAL ) ) = = SMINIT_TOPLEVEL ) // not vertical.
2014-03-07 22:28:55 +00:00
{
2014-04-02 17:37:37 +00:00
// No image list, prevents the buttons from having a margin at the left side
2014-11-11 01:05:39 +00:00
SetImageList ( NULL ) ;
2014-03-07 22:28:55 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
// Assign the correct imagelist and padding based on the current icon size
2014-02-24 11:59:34 +00:00
int shiml ;
if ( m_menuBand - > UseBigIcons ( ) )
{
shiml = SHIL_LARGE ;
2014-11-11 01:05:39 +00:00
SetPadding ( 4 , 0 ) ;
2014-02-24 11:59:34 +00:00
}
else
{
shiml = SHIL_SMALL ;
2014-11-11 01:05:39 +00:00
SetPadding ( 4 , 4 ) ;
2014-02-24 11:59:34 +00:00
}
IImageList * piml ;
HRESULT hr = SHGetImageList ( shiml , IID_PPV_ARG ( IImageList , & piml ) ) ;
2014-04-02 17:37:37 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
{
2014-11-11 01:05:39 +00:00
SetImageList ( NULL ) ;
2014-02-24 11:59:34 +00:00
}
else
{
2014-11-11 01:05:39 +00:00
SetImageList ( ( HIMAGELIST ) piml ) ;
2014-02-24 11:59:34 +00:00
}
return S_OK ;
}
HRESULT CMenuToolbarBase : : Close ( )
{
2014-11-11 01:05:39 +00:00
if ( m_hWnd )
DestroyWindow ( ) ;
2014-04-02 17:37:37 +00:00
2014-11-11 01:05:39 +00:00
if ( m_pager . m_hWnd )
m_pager . DestroyWindow ( ) ;
2014-04-02 17:37:37 +00:00
2014-02-24 11:59:34 +00:00
return S_OK ;
}
HRESULT CMenuToolbarBase : : CreateToolbar ( HWND hwndParent , DWORD dwFlags )
{
LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE |
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP ;
2014-04-02 17:37:37 +00:00
LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER | WS_EX_TOOLWINDOW ;
2014-02-24 11:59:34 +00:00
if ( dwFlags & SMINIT_VERTICAL )
{
2014-04-02 17:37:37 +00:00
// Activate vertical semantics
2014-02-24 11:59:34 +00:00
tbStyles | = CCS_VERT ;
2014-03-02 19:35:13 +00:00
2014-03-16 01:21:54 +00:00
# if USE_TBSTYLE_EX_VERTICAL
2014-04-02 17:37:37 +00:00
tbExStyles | = TBSTYLE_EX_VERTICAL ;
2014-03-03 11:14:04 +00:00
# endif
2014-02-24 11:59:34 +00:00
}
2014-04-02 17:37:37 +00:00
m_initFlags = dwFlags ;
2014-03-07 22:28:55 +00:00
2014-04-02 17:37:37 +00:00
// Get a temporary rect to use while creating the toolbar window.
// Ensure that it is not a null rect.
2014-02-24 11:59:34 +00:00
RECT rc ;
2014-04-02 17:37:37 +00:00
if ( ! : : GetClientRect ( hwndParent , & rc ) | |
( rc . left = = rc . right ) | |
( rc . top = = rc . bottom ) )
2014-02-24 11:59:34 +00:00
{
rc . left = 0 ;
rc . top = 0 ;
rc . right = 1 ;
rc . bottom = 1 ;
}
2015-04-29 00:07:54 +00:00
SubclassWindow ( CToolbar : : Create ( hwndParent , tbStyles , tbExStyles ) ) ;
2014-02-24 11:59:34 +00:00
2014-12-17 12:38:19 +00:00
SetWindowTheme ( m_hWnd , L " " , L " " ) ;
2017-05-03 21:49:38 +00:00
SystemParametersInfo ( SPI_GETFLATMENU , 0 , & m_useFlatMenus , 0 ) ;
2015-04-24 14:12:24 +00:00
2014-12-18 18:24:01 +00:00
m_menuBand - > AdjustForTheme ( m_useFlatMenus ) ;
2014-04-02 17:37:37 +00:00
// If needed, create the pager.
2014-02-24 11:59:34 +00:00
if ( m_usePager )
{
LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE ;
LONG pgExStyles = 0 ;
HWND hwndPager = CreateWindowEx (
pgExStyles , WC_PAGESCROLLER , NULL ,
pgStyles , rc . left , rc . top , rc . right - rc . left , rc . bottom - rc . top ,
hwndParent , NULL , _AtlBaseModule . GetModuleInstance ( ) , 0 ) ;
2014-11-11 01:05:39 +00:00
m_pager . SubclassWindow ( hwndPager ) ;
2014-02-24 11:59:34 +00:00
2014-11-11 01:05:39 +00:00
: : SetParent ( m_hWnd , hwndPager ) ;
m_pager . SendMessageW ( PGM_SETCHILD , 0 , reinterpret_cast < LPARAM > ( m_hWnd ) ) ;
2014-02-24 11:59:34 +00:00
}
2014-03-26 11:33:52 +00:00
2014-04-02 17:37:37 +00:00
// Configure the image lists
2014-02-25 10:44:28 +00:00
UpdateImageLists ( ) ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-07 18:41:47 +00:00
HRESULT CMenuToolbarBase : : GetSizes ( SIZE * pMinSize , SIZE * pMaxSize , SIZE * pIntegralSize )
2014-02-24 11:59:34 +00:00
{
2014-04-07 18:41:47 +00:00
if ( pMinSize )
* pMinSize = m_idealSize ;
if ( pMaxSize )
* pMaxSize = m_idealSize ;
if ( pIntegralSize )
* pIntegralSize = m_itemSize ;
2014-04-09 11:45:02 +00:00
2014-04-07 18:41:47 +00:00
if ( m_hasSizes )
return S_OK ;
2014-02-24 11:59:34 +00:00
2014-11-12 17:13:05 +00:00
TRACE ( " Sizes out of date, recalculating. \n " ) ;
2014-11-11 01:05:39 +00:00
if ( ! m_hWnd )
2014-11-12 17:13:05 +00:00
{
2014-04-07 18:41:47 +00:00
return S_OK ;
2014-11-12 17:13:05 +00:00
}
2014-02-24 11:59:34 +00:00
2014-04-07 18:41:47 +00:00
// Obtain the ideal size, to be used as min and max
2014-11-11 01:05:39 +00:00
GetMaxSize ( & m_idealSize ) ;
GetIdealSize ( ( m_initFlags & SMINIT_VERTICAL ) ! = 0 , & m_idealSize ) ;
2014-04-09 11:45:02 +00:00
2014-11-12 17:13:05 +00:00
TRACE ( " Ideal Size: (%d, %d) for %d buttons \n " , m_idealSize , GetButtonCount ( ) ) ;
2014-04-07 18:41:47 +00:00
// Obtain the button size, to be used as the integral size
2014-11-11 01:05:39 +00:00
DWORD size = GetButtonSize ( ) ;
2014-04-07 18:41:47 +00:00
m_itemSize . cx = GET_X_LPARAM ( size ) ;
m_itemSize . cy = GET_Y_LPARAM ( size ) ;
m_hasSizes = TRUE ;
if ( pMinSize )
* pMinSize = m_idealSize ;
if ( pMaxSize )
* pMaxSize = m_idealSize ;
if ( pIntegralSize )
* pIntegralSize = m_itemSize ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
HRESULT CMenuToolbarBase : : SetPosSize ( int x , int y , int cx , int cy )
{
2014-11-11 01:05:39 +00:00
// Update the toolbar or pager to fit the requested rect
2014-04-02 17:37:37 +00:00
// If we have a pager, set the toolbar height to the ideal height of the toolbar
2014-11-11 01:05:39 +00:00
if ( m_pager . m_hWnd )
2014-02-24 11:59:34 +00:00
{
2014-11-11 01:05:39 +00:00
SetWindowPos ( NULL , x , y , cx , m_idealSize . cy , 0 ) ;
m_pager . SetWindowPos ( NULL , x , y , cx , cy , 0 ) ;
}
else
{
SetWindowPos ( NULL , x , y , cx , cy , 0 ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-02 17:37:37 +00:00
// In a vertical menu, resize the buttons to fit the width
if ( m_initFlags & SMINIT_VERTICAL )
2014-03-07 22:28:55 +00:00
{
2014-11-11 01:05:39 +00:00
DWORD btnSize = GetButtonSize ( ) ;
SetButtonSize ( cx , GET_Y_LPARAM ( btnSize ) ) ;
2014-03-07 22:28:55 +00:00
}
2014-04-02 17:37:37 +00:00
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : IsWindowOwner ( HWND hwnd )
{
2014-11-11 01:05:39 +00:00
if ( m_hWnd & & m_hWnd = = hwnd ) return S_OK ;
if ( m_pager . m_hWnd & & m_pager . m_hWnd = = hwnd ) return S_OK ;
2014-04-02 17:37:37 +00:00
return S_FALSE ;
}
2014-02-24 11:59:34 +00:00
HRESULT CMenuToolbarBase : : GetWindow ( HWND * phwnd )
{
if ( ! phwnd )
return E_FAIL ;
2014-11-11 01:05:39 +00:00
if ( m_pager . m_hWnd )
* phwnd = m_pager . m_hWnd ;
else
* phwnd = m_hWnd ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : OnGetInfoTip ( NMTBGETINFOTIP * tip )
2014-02-24 11:59:34 +00:00
{
2014-04-02 17:37:37 +00:00
INT index ;
DWORD_PTR dwData ;
INT iItem = tip - > iItem ;
GetDataFromId ( iItem , & index , & dwData ) ;
2014-04-15 10:08:08 +00:00
return InternalGetTooltip ( iItem , index , dwData , tip - > pszText , tip - > cchTextMax ) ;
2014-02-24 11:59:34 +00:00
}
2014-11-11 01:05:39 +00:00
HRESULT CMenuToolbarBase : : OnPopupTimer ( UINT uMsg , WPARAM wParam , LPARAM lParam , BOOL & bHandled )
2014-02-24 11:59:34 +00:00
{
2014-11-11 01:05:39 +00:00
if ( wParam ! = TIMERID_HOTTRACK )
{
bHandled = FALSE ;
return 0 ;
}
2014-03-07 22:28:55 +00:00
2014-11-11 01:05:39 +00:00
KillTimer ( TIMERID_HOTTRACK ) ;
2014-03-19 15:33:41 +00:00
2014-04-02 17:37:37 +00:00
if ( ! m_timerEnabled )
2014-11-11 01:05:39 +00:00
return 0 ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
m_timerEnabled = FALSE ;
2014-03-26 11:33:52 +00:00
2014-04-02 17:37:37 +00:00
if ( m_hotItem < 0 )
2014-11-11 01:05:39 +00:00
return 0 ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
// Returns S_FALSE if the current item did not show a submenu
2014-04-24 17:42:16 +00:00
HRESULT hr = PopupItem ( m_hotItem , FALSE ) ;
2014-04-02 17:37:37 +00:00
if ( hr ! = S_FALSE )
2014-11-11 01:05:39 +00:00
return 0 ;
2014-03-26 11:33:52 +00:00
2014-04-02 17:37:37 +00:00
// If we didn't switch submenus, cancel the current popup regardless
if ( m_popupBar )
{
HRESULT hr = CancelCurrentPopup ( ) ;
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-11-11 01:05:39 +00:00
return 0 ;
2014-02-24 11:59:34 +00:00
}
2014-11-11 01:05:39 +00:00
return 0 ;
2014-04-02 17:37:37 +00:00
}
HRESULT CMenuToolbarBase : : KillPopupTimer ( )
{
if ( m_timerEnabled )
{
m_timerEnabled = FALSE ;
2014-11-11 01:05:39 +00:00
KillTimer ( TIMERID_HOTTRACK ) ;
2014-04-02 17:37:37 +00:00
return S_OK ;
}
return S_FALSE ;
2014-02-24 11:59:34 +00:00
}
2014-04-07 18:41:47 +00:00
HRESULT CMenuToolbarBase : : ChangeHotItem ( CMenuToolbarBase * toolbar , INT item , DWORD dwFlags )
2014-02-24 11:59:34 +00:00
{
2014-04-07 18:41:47 +00:00
// Ignore the change if it already matches the stored info
if ( m_hotBar = = toolbar & & m_hotItem = = item )
return S_FALSE ;
2014-04-02 17:37:37 +00:00
// Prevent a change of hot item if the change was triggered by the mouse,
// and mouse tracking is disabled.
2014-04-07 18:41:47 +00:00
if ( m_disableMouseTrack & & dwFlags & HICF_MOUSE )
2014-03-15 21:38:15 +00:00
{
2014-04-09 11:45:02 +00:00
TRACE ( " Hot item change prevented by DisableMouseTrack \n " ) ;
2014-03-15 21:38:15 +00:00
return S_OK ;
}
2014-04-07 18:41:47 +00:00
// Notify the toolbar if the hot-tracking left this toolbar
2014-04-02 17:37:37 +00:00
if ( m_hotBar = = this & & toolbar ! = this )
2014-03-07 22:28:55 +00:00
{
2014-11-11 01:05:39 +00:00
SetHotItem ( - 1 ) ;
2014-03-07 22:28:55 +00:00
}
2014-04-02 17:37:37 +00:00
2014-04-22 17:44:19 +00:00
TRACE ( " Hot item changed from %p %p, to %p %p \n " , m_hotBar , m_hotItem , toolbar , item ) ;
2014-02-27 11:56:28 +00:00
m_hotBar = toolbar ;
m_hotItem = item ;
2014-04-02 17:37:37 +00:00
if ( m_hotBar = = this )
2014-03-07 22:28:55 +00:00
{
2014-04-16 12:14:02 +00:00
if ( m_isTrackingPopup & & ! ( m_initFlags & SMINIT_VERTICAL ) )
{
// If the menubar has an open submenu, switch to the new item's submenu immediately
2014-04-24 17:42:16 +00:00
PopupItem ( m_hotItem , FALSE ) ;
2014-04-16 12:14:02 +00:00
}
else if ( dwFlags & HICF_MOUSE )
2014-04-02 17:37:37 +00:00
{
// Vertical menus show/hide the submenu after a delay,
2014-04-16 12:14:02 +00:00
// but only with the mouse.
2014-04-02 17:37:37 +00:00
if ( m_initFlags & SMINIT_VERTICAL )
{
DWORD elapsed = 0 ;
SystemParametersInfo ( SPI_GETMENUSHOWDELAY , 0 , & elapsed , 0 ) ;
2014-11-11 01:05:39 +00:00
SetTimer ( TIMERID_HOTTRACK , elapsed ) ;
2014-04-02 17:37:37 +00:00
m_timerEnabled = TRUE ;
2014-04-09 11:45:02 +00:00
TRACE ( " SetTimer called with m_hotItem=%d \n " , m_hotItem ) ;
2014-04-02 17:37:37 +00:00
}
}
else
{
TBBUTTONINFO info ;
info . cbSize = sizeof ( info ) ;
info . dwMask = 0 ;
2014-11-11 01:05:39 +00:00
int index = GetButtonInfo ( item , & info ) ;
2014-04-02 17:37:37 +00:00
2014-11-11 01:05:39 +00:00
SetHotItem ( index ) ;
2014-04-02 17:37:37 +00:00
}
2014-03-07 22:28:55 +00:00
}
2014-04-02 17:37:37 +00:00
2014-02-27 11:56:28 +00:00
InvalidateDraw ( ) ;
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : ChangePopupItem ( CMenuToolbarBase * toolbar , INT item )
2014-02-27 11:56:28 +00:00
{
2014-04-07 18:41:47 +00:00
// Ignore the change if it already matches the stored info
2014-04-02 17:37:37 +00:00
if ( m_popupBar = = toolbar & & m_popupItem = = item )
return S_FALSE ;
2014-04-07 18:41:47 +00:00
// Notify the toolbar if the popup-tracking this toolbar
2014-04-02 17:37:37 +00:00
if ( m_popupBar = = this & & toolbar ! = this )
2014-03-16 09:28:51 +00:00
{
2014-11-11 01:05:39 +00:00
CheckButton ( m_popupItem , FALSE ) ;
2014-04-07 18:41:47 +00:00
m_isTrackingPopup = FALSE ;
2014-03-16 09:28:51 +00:00
}
2014-04-02 17:37:37 +00:00
2014-02-27 11:56:28 +00:00
m_popupBar = toolbar ;
m_popupItem = item ;
2014-04-02 17:37:37 +00:00
if ( m_popupBar = = this )
{
2014-11-11 01:05:39 +00:00
CheckButton ( m_popupItem , TRUE ) ;
2014-04-02 17:37:37 +00:00
}
2014-02-27 11:56:28 +00:00
InvalidateDraw ( ) ;
return S_OK ;
}
2014-11-11 01:05:39 +00:00
LRESULT CMenuToolbarBase : : IsTrackedItem ( UINT uMsg , WPARAM wParam , LPARAM lParam , BOOL & bHandled )
2014-03-19 15:33:41 +00:00
{
TBBUTTON btn ;
2015-01-17 12:59:57 +00:00
INT idx = ( INT ) wParam ;
2014-03-19 15:33:41 +00:00
if ( m_hotBar ! = this )
return S_FALSE ;
2015-01-17 12:59:57 +00:00
if ( idx < 0 )
2014-04-09 11:45:02 +00:00
return S_FALSE ;
2015-01-17 12:59:57 +00:00
if ( ! GetButton ( idx , & btn ) )
2014-04-02 17:37:37 +00:00
return E_FAIL ;
2014-03-19 15:33:41 +00:00
if ( m_hotItem = = btn . idCommand )
return S_OK ;
2014-04-02 17:37:37 +00:00
if ( m_popupItem = = btn . idCommand )
return S_OK ;
2014-03-19 15:33:41 +00:00
return S_FALSE ;
}
2014-11-11 01:05:39 +00:00
LRESULT CMenuToolbarBase : : ChangeTrackedItem ( UINT uMsg , WPARAM wParam , LPARAM lParam , BOOL & bHandled )
2014-03-19 15:33:41 +00:00
{
2015-01-17 12:59:57 +00:00
TBBUTTON btn ;
2014-11-11 01:05:39 +00:00
BOOL wasTracking = LOWORD ( lParam ) ;
BOOL mouse = HIWORD ( lParam ) ;
2015-01-17 12:59:57 +00:00
INT idx = ( INT ) wParam ;
2014-11-11 01:05:39 +00:00
2015-01-17 12:59:57 +00:00
if ( idx < 0 )
2014-04-09 11:45:02 +00:00
{
m_isTrackingPopup = FALSE ;
return m_menuBand - > _ChangeHotItem ( NULL , - 1 , HICF_MOUSE ) ;
}
2015-01-17 12:59:57 +00:00
if ( ! GetButton ( idx , & btn ) )
2014-04-02 17:37:37 +00:00
return E_FAIL ;
2014-03-19 15:33:41 +00:00
2015-01-17 12:59:57 +00:00
TRACE ( " ChangeTrackedItem %d, %d \n " , idx , wasTracking ) ;
2014-04-07 18:41:47 +00:00
m_isTrackingPopup = wasTracking ;
2014-04-22 17:44:19 +00:00
return m_menuBand - > _ChangeHotItem ( this , btn . idCommand , mouse ? HICF_MOUSE : 0 ) ;
2014-03-19 15:33:41 +00:00
}
2014-04-24 17:42:16 +00:00
HRESULT CMenuToolbarBase : : PopupSubMenu ( UINT iItem , UINT index , IShellMenu * childShellMenu , BOOL keyInitiated )
2014-02-24 11:59:34 +00:00
{
2014-04-07 18:41:47 +00:00
// Calculate the submenu position and exclude area
2014-02-24 11:59:34 +00:00
RECT rc = { 0 } ;
2014-11-11 01:05:39 +00:00
if ( ! GetItemRect ( index , & rc ) )
2014-02-24 11:59:34 +00:00
return E_FAIL ;
2015-01-12 18:03:39 +00:00
2014-02-24 11:59:34 +00:00
POINT a = { rc . left , rc . top } ;
POINT b = { rc . right , rc . bottom } ;
2015-07-06 19:38:22 +00:00
ClientToScreen ( & a ) ;
ClientToScreen ( & b ) ;
2014-02-24 11:59:34 +00:00
2014-03-13 16:21:56 +00:00
POINTL pt = { a . x , b . y } ;
2015-01-12 18:03:39 +00:00
RECTL rcl = { a . x , a . y , b . x , b . y } ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
if ( m_initFlags & SMINIT_VERTICAL )
2014-03-13 16:21:56 +00:00
{
2015-01-12 18:03:39 +00:00
// FIXME: Hardcoding this here feels hacky.
if ( IsAppThemed ( ) )
{
pt . x = b . x - 1 ;
pt . y = a . y - 1 ;
}
else
{
pt . x = b . x - 3 ;
pt . y = a . y - 3 ;
}
2014-03-13 16:21:56 +00:00
}
2014-04-07 18:41:47 +00:00
// Display the submenu
m_isTrackingPopup = TRUE ;
2014-03-20 15:39:25 +00:00
2014-04-02 17:37:37 +00:00
m_menuBand - > _ChangePopupItem ( this , iItem ) ;
2014-04-24 17:42:16 +00:00
m_menuBand - > _OnPopupSubMenu ( childShellMenu , & pt , & rcl , keyInitiated ) ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : PopupSubMenu ( UINT iItem , UINT index , HMENU menu )
2014-02-24 11:59:34 +00:00
{
2014-04-07 18:41:47 +00:00
// Calculate the submenu position and exclude area
2014-02-24 11:59:34 +00:00
RECT rc = { 0 } ;
2014-11-11 01:05:39 +00:00
if ( ! GetItemRect ( index , & rc ) )
2014-02-24 11:59:34 +00:00
return E_FAIL ;
2014-04-09 11:45:02 +00:00
2014-03-07 22:28:55 +00:00
POINT a = { rc . left , rc . top } ;
2014-02-24 11:59:34 +00:00
POINT b = { rc . right , rc . bottom } ;
2015-07-06 19:38:22 +00:00
ClientToScreen ( & a ) ;
ClientToScreen ( & b ) ;
2014-03-07 22:28:55 +00:00
POINT pt = { a . x , b . y } ;
2014-04-07 18:41:47 +00:00
RECT rcl = { a . x , a . y , b . x , b . y } ;
2014-03-07 22:28:55 +00:00
2014-04-02 17:37:37 +00:00
if ( m_initFlags & SMINIT_VERTICAL )
2014-03-07 22:28:55 +00:00
{
pt . x = b . x ;
pt . y = a . y ;
}
2014-02-24 11:59:34 +00:00
HMENU popup = GetSubMenu ( menu , index ) ;
2014-04-07 18:41:47 +00:00
// Display the submenu
m_isTrackingPopup = TRUE ;
2014-04-02 17:37:37 +00:00
m_menuBand - > _ChangePopupItem ( this , iItem ) ;
2014-04-07 18:41:47 +00:00
m_menuBand - > _TrackSubMenu ( popup , pt . x , pt . y , rcl ) ;
2014-04-02 17:37:37 +00:00
m_menuBand - > _ChangePopupItem ( NULL , - 1 ) ;
2014-04-07 18:41:47 +00:00
m_isTrackingPopup = FALSE ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuToolbarBase : : TrackContextMenu ( IContextMenu * contextMenu , POINT pt )
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
// Cancel submenus
m_menuBand - > _KillPopupTimers ( ) ;
if ( m_popupBar )
m_menuBand - > _CancelCurrentPopup ( ) ;
2014-02-24 11:59:34 +00:00
2014-04-15 10:08:08 +00:00
// Display the context menu
2014-04-07 18:41:47 +00:00
return m_menuBand - > _TrackContextMenu ( contextMenu , pt . x , pt . y ) ;
2014-02-24 11:59:34 +00:00
}
2014-11-11 01:05:39 +00:00
HRESULT CMenuToolbarBase : : BeforeCancelPopup ( )
{
m_cancelingPopup = TRUE ;
2014-12-18 17:34:46 +00:00
TRACE ( " BeforeCancelPopup \n " ) ;
2014-11-11 01:05:39 +00:00
return S_OK ;
}
2014-07-09 00:42:05 +00:00
HRESULT CMenuToolbarBase : : ProcessClick ( INT iItem )
2014-02-24 11:59:34 +00:00
{
2014-04-02 17:37:37 +00:00
if ( m_disableMouseTrack )
{
2014-04-09 11:45:02 +00:00
TRACE ( " Item click prevented by DisableMouseTrack \n " ) ;
2014-04-02 17:37:37 +00:00
return S_OK ;
}
2014-03-20 15:39:25 +00:00
2014-04-07 18:41:47 +00:00
// If a button is clicked while a submenu was open, cancel the submenu.
if ( ! ( m_initFlags & SMINIT_VERTICAL ) & & m_isTrackingPopup )
{
2014-04-09 11:45:02 +00:00
TRACE ( " OnCommand cancelled because it was tracking submenu. \n " ) ;
2014-04-07 18:41:47 +00:00
return S_FALSE ;
}
2014-04-09 11:45:02 +00:00
2014-04-24 17:42:16 +00:00
if ( PopupItem ( iItem , FALSE ) = = S_OK )
2014-04-02 17:37:37 +00:00
{
2014-04-09 11:45:02 +00:00
TRACE ( " PopupItem returned S_OK \n " ) ;
2014-02-24 11:59:34 +00:00
return S_FALSE ;
2014-04-02 17:37:37 +00:00
}
2014-04-09 11:45:02 +00:00
TRACE ( " Executing... \n " ) ;
2014-03-20 15:39:25 +00:00
2014-12-18 17:34:46 +00:00
return m_menuBand - > _MenuItemSelect ( MPOS_EXECUTE ) ;
}
HRESULT CMenuToolbarBase : : ProcessContextMenu ( INT iItem )
{
INT index ;
DWORD_PTR data ;
GetDataFromId ( iItem , & index , & data ) ;
DWORD pos = GetMessagePos ( ) ;
POINT pt = { GET_X_LPARAM ( pos ) , GET_Y_LPARAM ( pos ) } ;
return InternalContextMenu ( iItem , index , data , pt ) ;
2014-04-24 16:17:53 +00:00
}
2014-03-20 15:39:25 +00:00
2014-12-18 17:34:46 +00:00
HRESULT CMenuToolbarBase : : MenuBarMouseDown ( INT iIndex , BOOL isLButton )
2014-06-29 15:42:06 +00:00
{
TBBUTTON btn ;
2014-12-18 17:34:46 +00:00
GetButton ( iIndex , & btn ) ;
2014-11-11 01:05:39 +00:00
if ( ( m_initFlags & SMINIT_VERTICAL )
| | m_popupBar
| | m_cancelingPopup )
{
m_cancelingPopup = FALSE ;
2014-06-29 15:42:06 +00:00
return S_OK ;
2014-11-11 01:05:39 +00:00
}
2014-06-29 15:42:06 +00:00
2014-07-09 00:42:05 +00:00
return ProcessClick ( btn . idCommand ) ;
2014-06-29 15:42:06 +00:00
}
2016-08-20 22:05:12 +00:00
HRESULT CMenuToolbarBase : : MenuBarMouseUp ( INT iIndex , BOOL isLButton )
2014-06-29 15:42:06 +00:00
{
TBBUTTON btn ;
2014-11-11 01:05:39 +00:00
m_cancelingPopup = FALSE ;
2014-06-29 15:42:06 +00:00
if ( ! ( m_initFlags & SMINIT_VERTICAL ) )
return S_OK ;
2014-11-11 01:05:39 +00:00
GetButton ( iIndex , & btn ) ;
2016-08-20 22:05:12 +00:00
if ( isLButton )
return ProcessClick ( btn . idCommand ) ;
else
return ProcessContextMenu ( btn . idCommand ) ;
2014-06-29 15:42:06 +00:00
}
2014-10-28 15:39:47 +00:00
HRESULT CMenuToolbarBase : : PrepareExecuteItem ( INT iItem )
2014-04-24 16:17:53 +00:00
{
2014-06-19 23:14:39 +00:00
this - > m_menuBand - > _KillPopupTimers ( ) ;
2014-03-20 15:39:25 +00:00
2014-10-28 15:39:47 +00:00
m_executeItem = iItem ;
return GetDataFromId ( iItem , & m_executeIndex , & m_executeData ) ;
}
2014-04-15 10:08:08 +00:00
2014-10-28 15:39:47 +00:00
HRESULT CMenuToolbarBase : : ExecuteItem ( )
{
return InternalExecuteItem ( m_executeItem , m_executeItem , m_executeData ) ;
2014-04-15 10:08:08 +00:00
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : KeyboardItemChange ( DWORD dwSelectType )
2014-02-24 11:59:34 +00:00
{
int prev = m_hotItem ;
int index = - 1 ;
if ( dwSelectType ! = 0xFFFFFFFF )
{
2014-11-11 01:05:39 +00:00
int count = GetButtonCount ( ) ;
2014-02-24 11:59:34 +00:00
if ( dwSelectType = = VK_HOME )
{
index = 0 ;
dwSelectType = VK_DOWN ;
}
else if ( dwSelectType = = VK_END )
{
index = count - 1 ;
dwSelectType = VK_UP ;
}
2014-04-15 10:08:08 +00:00
else
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
if ( m_hotItem > = 0 )
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
TBBUTTONINFO info = { 0 } ;
info . cbSize = sizeof ( TBBUTTONINFO ) ;
info . dwMask = 0 ;
2014-11-11 01:05:39 +00:00
index = GetButtonInfo ( m_hotItem , & info ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-15 10:08:08 +00:00
if ( index < 0 )
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
if ( dwSelectType = = VK_UP )
{
index = count - 1 ;
}
else if ( dwSelectType = = VK_DOWN )
{
index = 0 ;
}
2014-02-24 11:59:34 +00:00
}
2014-04-15 10:08:08 +00:00
else
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
if ( dwSelectType = = VK_UP )
{
index - - ;
}
else if ( dwSelectType = = VK_DOWN )
{
index + + ;
}
2014-02-24 11:59:34 +00:00
}
}
TBBUTTON btn = { 0 } ;
while ( index > = 0 & & index < count )
{
2014-11-11 01:05:39 +00:00
DWORD res = GetButton ( index , & btn ) ;
2014-02-24 11:59:34 +00:00
if ( ! res )
return E_FAIL ;
if ( btn . dwData )
{
2014-03-15 21:38:15 +00:00
if ( prev ! = btn . idCommand )
2014-02-24 11:59:34 +00:00
{
2014-04-22 17:44:19 +00:00
TRACE ( " Setting Hot item to %d \n " , index ) ;
2014-04-16 12:14:02 +00:00
if ( ! ( m_initFlags & SMINIT_VERTICAL ) & & m_isTrackingPopup )
{
HWND tlw ;
m_menuBand - > _GetTopLevelWindow ( & tlw ) ;
2019-12-29 14:57:57 +00:00
: : SendMessageW ( tlw , WM_CANCELMODE , 0 , 0 ) ;
2015-07-06 19:38:22 +00:00
PostMessageW ( WM_USER_CHANGETRACKEDITEM , index , MAKELPARAM ( m_isTrackingPopup , FALSE ) ) ;
2014-04-16 12:14:02 +00:00
}
else
m_menuBand - > _ChangeHotItem ( this , btn . idCommand , 0 ) ;
2014-02-24 11:59:34 +00:00
}
return S_OK ;
}
if ( dwSelectType = = VK_UP )
{
index - - ;
}
else if ( dwSelectType = = VK_DOWN )
{
index + + ;
}
}
2014-04-15 15:53:17 +00:00
return S_FALSE ;
2014-02-24 11:59:34 +00:00
}
2014-03-15 21:38:15 +00:00
if ( prev ! = - 1 )
2014-02-24 11:59:34 +00:00
{
2014-04-09 11:45:02 +00:00
TRACE ( " Setting Hot item to null \n " ) ;
2014-04-07 18:41:47 +00:00
m_menuBand - > _ChangeHotItem ( NULL , - 1 , 0 ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-07 18:41:47 +00:00
2014-02-24 11:59:34 +00:00
return S_FALSE ;
}
2014-03-03 11:14:04 +00:00
HRESULT CMenuToolbarBase : : AddButton ( DWORD commandId , LPCWSTR caption , BOOL hasSubMenu , INT iconId , DWORD_PTR buttonData , BOOL last )
2014-03-03 10:19:35 +00:00
{
TBBUTTON tbb = { 0 } ;
2014-03-03 11:14:04 +00:00
tbb . fsState = TBSTATE_ENABLED ;
2014-03-16 01:21:54 +00:00
# if !USE_TBSTYLE_EX_VERTICAL
2014-04-02 17:37:37 +00:00
if ( ! last & & ( m_initFlags & SMINIT_VERTICAL ) )
2014-03-03 11:14:04 +00:00
tbb . fsState | = TBSTATE_WRAP ;
# endif
2014-04-02 17:37:37 +00:00
tbb . fsStyle = BTNS_CHECKGROUP ;
2014-03-03 10:19:35 +00:00
2014-04-02 17:37:37 +00:00
if ( hasSubMenu & & ( m_initFlags & SMINIT_VERTICAL ) )
2014-03-03 10:19:35 +00:00
tbb . fsStyle | = BTNS_DROPDOWN ;
2014-04-02 17:37:37 +00:00
if ( ! ( m_initFlags & SMINIT_VERTICAL ) )
tbb . fsStyle | = BTNS_AUTOSIZE ;
2014-03-07 22:28:55 +00:00
2014-03-03 10:19:35 +00:00
tbb . iString = ( INT_PTR ) caption ;
tbb . idCommand = commandId ;
tbb . iBitmap = iconId ;
tbb . dwData = buttonData ;
2014-11-11 01:05:39 +00:00
m_hasSizes = FALSE ;
2014-03-03 10:19:35 +00:00
2014-11-11 01:05:39 +00:00
if ( ! AddButtons ( 1 , & tbb ) )
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
2014-03-03 10:19:35 +00:00
return S_OK ;
}
2014-03-03 11:14:04 +00:00
HRESULT CMenuToolbarBase : : AddSeparator ( BOOL last )
2014-03-03 10:19:35 +00:00
{
TBBUTTON tbb = { 0 } ;
2014-03-03 11:14:04 +00:00
tbb . fsState = TBSTATE_ENABLED ;
2014-03-16 01:21:54 +00:00
# if !USE_TBSTYLE_EX_VERTICAL
2014-04-02 17:37:37 +00:00
if ( ! last & & ( m_initFlags & SMINIT_VERTICAL ) )
2014-03-03 11:14:04 +00:00
tbb . fsState | = TBSTATE_WRAP ;
# endif
2014-03-03 10:19:35 +00:00
tbb . fsStyle = BTNS_SEP ;
tbb . iBitmap = 0 ;
2014-11-11 01:05:39 +00:00
m_hasSizes = FALSE ;
if ( ! AddButtons ( 1 , & tbb ) )
2014-03-03 16:11:47 +00:00
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
2014-03-03 10:19:35 +00:00
return S_OK ;
}
HRESULT CMenuToolbarBase : : AddPlaceholder ( )
{
TBBUTTON tbb = { 0 } ;
2014-11-12 17:13:05 +00:00
WCHAR MenuString [ 128 ] ;
LoadStringW ( GetModuleHandle ( L " shell32.dll " ) , IDS_MENU_EMPTY , MenuString , _countof ( MenuString ) ) ;
2014-03-03 10:19:35 +00:00
2014-03-03 11:14:04 +00:00
tbb . fsState = 0 ;
2014-03-03 10:19:35 +00:00
tbb . fsStyle = 0 ;
tbb . iString = ( INT_PTR ) MenuString ;
tbb . iBitmap = - 1 ;
2014-11-11 01:05:39 +00:00
m_hasSizes = FALSE ;
if ( ! AddButtons ( 1 , & tbb ) )
2014-03-03 16:11:47 +00:00
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
2014-03-03 10:19:35 +00:00
return S_OK ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuToolbarBase : : ClearToolbar ( )
{
2014-11-11 01:05:39 +00:00
while ( DeleteButton ( 0 ) )
2014-04-15 10:08:08 +00:00
{
// empty;
}
2014-11-11 01:05:39 +00:00
m_hasSizes = FALSE ;
2014-04-15 10:08:08 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : GetDataFromId ( INT iItem , INT * pIndex , DWORD_PTR * pData )
2014-03-03 10:19:35 +00:00
{
2014-04-02 17:37:37 +00:00
if ( pData )
* pData = NULL ;
if ( pIndex )
* pIndex = - 1 ;
if ( iItem < 0 )
return S_OK ;
2014-03-03 10:19:35 +00:00
TBBUTTONINFO info = { 0 } ;
2014-03-20 15:39:25 +00:00
2014-03-03 10:19:35 +00:00
info . cbSize = sizeof ( TBBUTTONINFO ) ;
2014-03-20 15:39:25 +00:00
info . dwMask = TBIF_COMMAND | TBIF_LPARAM ;
2014-11-11 01:05:39 +00:00
int index = GetButtonInfo ( iItem , & info ) ;
2014-03-03 10:19:35 +00:00
if ( index < 0 )
return E_FAIL ;
if ( pIndex )
* pIndex = index ;
if ( pData )
2014-03-20 15:39:25 +00:00
* pData = info . lParam ;
2014-03-03 10:19:35 +00:00
return S_OK ;
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuToolbarBase : : CancelCurrentPopup ( )
{
return m_menuBand - > _CancelCurrentPopup ( ) ;
}
2014-04-24 17:42:16 +00:00
HRESULT CMenuToolbarBase : : PopupItem ( INT iItem , BOOL keyInitiated )
2014-02-24 11:59:34 +00:00
{
2014-03-03 10:19:35 +00:00
INT index ;
DWORD_PTR dwData ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
if ( iItem < 0 )
return S_OK ;
if ( m_popupBar = = this & & m_popupItem = = iItem )
return S_OK ;
2014-03-20 15:39:25 +00:00
2014-04-02 17:37:37 +00:00
GetDataFromId ( iItem , & index , & dwData ) ;
2014-03-19 15:33:41 +00:00
2014-04-02 17:37:37 +00:00
HRESULT hr = InternalHasSubMenu ( iItem , index , dwData ) ;
2014-03-20 15:39:25 +00:00
if ( hr ! = S_OK )
return hr ;
2014-02-24 11:59:34 +00:00
2014-04-02 17:37:37 +00:00
if ( m_popupBar )
{
HRESULT hr = CancelCurrentPopup ( ) ;
if ( FAILED_UNEXPECTEDLY ( hr ) )
return hr ;
}
if ( ! ( m_initFlags & SMINIT_VERTICAL ) )
{
2014-04-09 11:45:02 +00:00
TRACE ( " PopupItem non-vertical %d %d \n " , index , iItem ) ;
2014-04-02 17:37:37 +00:00
m_menuBand - > _ChangeHotItem ( this , iItem , 0 ) ;
}
2014-04-24 17:42:16 +00:00
return InternalPopupItem ( iItem , index , dwData , keyInitiated ) ;
2014-03-03 10:19:35 +00:00
}
2014-02-24 11:59:34 +00:00
CMenuStaticToolbar : : CMenuStaticToolbar ( CMenuBand * menuBand ) :
CMenuToolbarBase ( menuBand , FALSE ) ,
2014-10-29 22:28:51 +00:00
m_hmenu ( NULL ) ,
m_hwndMenu ( NULL )
2014-02-24 11:59:34 +00:00
{
}
2014-06-03 01:04:19 +00:00
CMenuStaticToolbar : : ~ CMenuStaticToolbar ( )
{
}
2014-02-24 11:59:34 +00:00
HRESULT CMenuStaticToolbar : : GetMenu (
2014-03-13 16:21:56 +00:00
_Out_opt_ HMENU * phmenu ,
_Out_opt_ HWND * phwnd ,
_Out_opt_ DWORD * pdwFlags )
2014-02-24 11:59:34 +00:00
{
2014-03-13 16:21:56 +00:00
if ( phmenu )
* phmenu = m_hmenu ;
if ( phwnd )
2014-10-29 22:28:51 +00:00
* phwnd = m_hwndMenu ;
2014-03-13 16:21:56 +00:00
if ( pdwFlags )
* pdwFlags = m_dwMenuFlags ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
HRESULT CMenuStaticToolbar : : SetMenu (
HMENU hmenu ,
HWND hwnd ,
DWORD dwFlags )
{
m_hmenu = hmenu ;
2014-10-29 22:28:51 +00:00
m_hwndMenu = hwnd ;
2014-02-24 11:59:34 +00:00
m_dwMenuFlags = dwFlags ;
2014-11-12 17:13:05 +00:00
ClearToolbar ( ) ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-03-11 10:42:25 +00:00
HRESULT CMenuStaticToolbar : : FillToolbar ( BOOL clearFirst )
2014-02-24 11:59:34 +00:00
{
int i ;
int ic = GetMenuItemCount ( m_hmenu ) ;
2014-03-11 10:42:25 +00:00
if ( clearFirst )
{
2014-04-15 10:08:08 +00:00
ClearToolbar ( ) ;
2014-03-11 10:42:25 +00:00
}
2014-03-03 17:55:43 +00:00
int count = 0 ;
2014-02-24 11:59:34 +00:00
for ( i = 0 ; i < ic ; i + + )
{
2014-03-03 11:14:04 +00:00
BOOL last = i + 1 = = ic ;
2014-02-24 11:59:34 +00:00
MENUITEMINFOW info ;
info . cbSize = sizeof ( info ) ;
2014-03-03 10:19:35 +00:00
info . dwTypeData = NULL ;
2014-03-03 16:11:47 +00:00
info . fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID ;
2014-02-24 11:59:34 +00:00
2014-03-03 16:11:47 +00:00
if ( ! GetMenuItemInfoW ( m_hmenu , i , TRUE , & info ) )
{
2014-04-09 11:45:02 +00:00
TRACE ( " Error obtaining info for menu item at pos=%d \n " , i ) ;
2014-03-03 16:11:47 +00:00
continue ;
}
2014-03-03 17:55:43 +00:00
count + + ;
2014-03-03 16:11:47 +00:00
if ( info . fType & MFT_SEPARATOR )
{
AddSeparator ( last ) ;
}
2014-03-05 09:12:40 +00:00
else if ( ! ( info . fType & MFT_BITMAP ) )
2014-02-24 11:59:34 +00:00
{
2014-03-03 10:19:35 +00:00
info . cch + + ;
info . dwTypeData = ( PWSTR ) HeapAlloc ( GetProcessHeap ( ) , 0 , ( info . cch + 1 ) * sizeof ( WCHAR ) ) ;
2014-03-03 11:14:04 +00:00
info . fMask = MIIM_STRING | MIIM_SUBMENU | MIIM_ID ;
2014-03-03 10:19:35 +00:00
GetMenuItemInfoW ( m_hmenu , i , TRUE , & info ) ;
2014-02-24 11:59:34 +00:00
SMINFO * sminfo = new SMINFO ( ) ;
sminfo - > dwMask = SMIM_ICON | SMIM_FLAGS ;
2014-03-03 10:19:35 +00:00
HRESULT hr = m_menuBand - > _CallCBWithItemId ( info . wID , SMC_GETINFO , 0 , reinterpret_cast < LPARAM > ( sminfo ) ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-10-21 12:24:15 +00:00
{
delete sminfo ;
2014-03-03 10:19:35 +00:00
return hr ;
2014-10-21 12:24:15 +00:00
}
2014-03-03 10:19:35 +00:00
2014-03-03 11:14:04 +00:00
AddButton ( info . wID , info . dwTypeData , info . hSubMenu ! = NULL , sminfo - > iIcon , reinterpret_cast < DWORD_PTR > ( sminfo ) , last ) ;
2014-03-03 10:19:35 +00:00
HeapFree ( GetProcessHeap ( ) , 0 , info . dwTypeData ) ;
2014-02-24 11:59:34 +00:00
}
}
2014-03-11 10:42:25 +00:00
return S_OK ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuStaticToolbar : : InternalGetTooltip ( INT iItem , INT index , DWORD_PTR dwData , LPWSTR pszText , INT cchTextMax )
2014-04-02 17:37:37 +00:00
{
//SMINFO * info = reinterpret_cast<SMINFO*>(dwData);
UNIMPLEMENTED ;
return E_NOTIMPL ;
}
2014-03-11 10:42:25 +00:00
HRESULT CMenuStaticToolbar : : OnDeletingButton ( const NMTOOLBAR * tb )
{
delete reinterpret_cast < SMINFO * > ( tb - > tbButton . dwData ) ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuStaticToolbar : : InternalContextMenu ( INT iItem , INT index , DWORD_PTR dwData , POINT pt )
2014-02-24 11:59:34 +00:00
{
CComPtr < IContextMenu > contextMenu ;
2014-04-15 10:08:08 +00:00
HRESULT hr = m_menuBand - > _CallCBWithItemId ( iItem , SMC_GETOBJECT ,
reinterpret_cast < WPARAM > ( & IID_IContextMenu ) , reinterpret_cast < LPARAM > ( & contextMenu ) ) ;
2014-02-24 11:59:34 +00:00
if ( hr ! = S_OK )
return hr ;
2014-04-15 10:08:08 +00:00
return TrackContextMenu ( contextMenu , pt ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuStaticToolbar : : InternalExecuteItem ( INT iItem , INT index , DWORD_PTR data )
2014-02-24 11:59:34 +00:00
{
2014-04-15 10:08:08 +00:00
return m_menuBand - > _CallCBWithItemId ( iItem , SMC_EXEC , 0 , 0 ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-24 17:42:16 +00:00
HRESULT CMenuStaticToolbar : : InternalPopupItem ( INT iItem , INT index , DWORD_PTR dwData , BOOL keyInitiated )
2014-02-24 11:59:34 +00:00
{
2014-03-03 10:19:35 +00:00
SMINFO * nfo = reinterpret_cast < SMINFO * > ( dwData ) ;
2014-02-24 11:59:34 +00:00
if ( ! nfo )
return E_FAIL ;
if ( nfo - > dwFlags & SMIF_TRACKPOPUP )
{
2014-04-02 17:37:37 +00:00
return PopupSubMenu ( iItem , index , m_hmenu ) ;
2014-02-24 11:59:34 +00:00
}
else
{
CComPtr < IShellMenu > shellMenu ;
2014-04-02 17:37:37 +00:00
HRESULT hr = m_menuBand - > _CallCBWithItemId ( iItem , SMC_GETOBJECT , reinterpret_cast < WPARAM > ( & IID_IShellMenu ) , reinterpret_cast < LPARAM > ( & shellMenu ) ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
2014-04-24 17:42:16 +00:00
return PopupSubMenu ( iItem , index , shellMenu , keyInitiated ) ;
2014-02-24 11:59:34 +00:00
}
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuStaticToolbar : : InternalHasSubMenu ( INT iItem , INT index , DWORD_PTR dwData )
2014-02-24 11:59:34 +00:00
{
return : : GetSubMenu ( m_hmenu , index ) ? S_OK : S_FALSE ;
}
CMenuSFToolbar : : CMenuSFToolbar ( CMenuBand * menuBand ) :
CMenuToolbarBase ( menuBand , TRUE ) ,
2014-03-13 16:21:56 +00:00
m_shellFolder ( NULL ) ,
m_idList ( NULL ) ,
m_hKey ( NULL )
2014-02-24 11:59:34 +00:00
{
}
CMenuSFToolbar : : ~ CMenuSFToolbar ( )
{
}
2015-03-16 16:30:24 +00:00
int CALLBACK PidlListSort ( void * item1 , void * item2 , LPARAM lParam )
{
IShellFolder * psf = ( IShellFolder * ) lParam ;
PCUIDLIST_RELATIVE pidl1 = ( PCUIDLIST_RELATIVE ) item1 ;
PCUIDLIST_RELATIVE pidl2 = ( PCUIDLIST_RELATIVE ) item2 ;
HRESULT hr = psf - > CompareIDs ( 0 , pidl1 , pidl2 ) ;
if ( FAILED ( hr ) )
{
// No way to cancel, so sort to equal.
return 0 ;
}
return ( int ) ( short ) LOWORD ( hr ) ;
}
2014-03-11 10:42:25 +00:00
HRESULT CMenuSFToolbar : : FillToolbar ( BOOL clearFirst )
2014-02-24 11:59:34 +00:00
{
HRESULT hr ;
2015-03-16 16:30:24 +00:00
CComPtr < IEnumIDList > eidl ;
hr = m_shellFolder - > EnumObjects ( GetToolbar ( ) , SHCONTF_FOLDERS | SHCONTF_NONFOLDERS , & eidl ) ;
if ( FAILED_UNEXPECTEDLY ( hr ) )
return hr ;
HDPA dpaSort = DPA_Create ( 10 ) ;
2014-02-24 11:59:34 +00:00
2014-06-28 18:05:01 +00:00
LPITEMIDLIST item = NULL ;
2014-06-28 15:38:25 +00:00
hr = eidl - > Next ( 1 , & item , NULL ) ;
while ( hr = = S_OK )
2014-02-24 11:59:34 +00:00
{
2015-03-16 16:30:24 +00:00
if ( m_menuBand - > _CallCBWithItemPidl ( item , 0x10000000 , 0 , 0 ) = = S_FALSE )
{
2018-02-22 10:51:07 +00:00
DPA_AppendPtr ( dpaSort , item ) ;
}
else
{
CoTaskMemFree ( item ) ;
2015-03-16 16:30:24 +00:00
}
hr = eidl - > Next ( 1 , & item , NULL ) ;
}
// If no items were added, show the "empty" placeholder
if ( DPA_GetPtrCount ( dpaSort ) = = 0 )
{
2015-10-24 10:24:37 +00:00
DPA_Destroy ( dpaSort ) ;
2015-03-16 16:30:24 +00:00
return AddPlaceholder ( ) ;
}
TRACE ( " FillToolbar added %d items to the DPA \n " , DPA_GetPtrCount ( dpaSort ) ) ;
DPA_Sort ( dpaSort , PidlListSort , ( LPARAM ) m_shellFolder . p ) ;
for ( int i = 0 ; i < DPA_GetPtrCount ( dpaSort ) ; )
{
PWSTR MenuString ;
2014-02-24 11:59:34 +00:00
INT index = 0 ;
INT indexOpen = 0 ;
2015-03-16 16:30:24 +00:00
STRRET sr = { STRRET_CSTR , { 0 } } ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
item = ( LPITEMIDLIST ) DPA_GetPtr ( dpaSort , i ) ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
hr = m_shellFolder - > GetDisplayNameOf ( item , SIGDN_NORMALDISPLAY , & sr ) ;
if ( FAILED_UNEXPECTEDLY ( hr ) )
2015-10-24 10:24:37 +00:00
{
DPA_Destroy ( dpaSort ) ;
2015-03-16 16:30:24 +00:00
return hr ;
2015-10-24 10:24:37 +00:00
}
2014-02-26 11:13:23 +00:00
2015-03-16 16:30:24 +00:00
StrRetToStr ( & sr , NULL , & MenuString ) ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
index = SHMapPIDLToSystemImageListIndex ( m_shellFolder , item , & indexOpen ) ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
LPCITEMIDLIST itemc = item ;
2014-02-26 11:13:23 +00:00
2015-03-16 16:30:24 +00:00
SFGAOF attrs = SFGAO_FOLDER ;
hr = m_shellFolder - > GetAttributesOf ( 1 , & itemc , & attrs ) ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
DWORD_PTR dwData = reinterpret_cast < DWORD_PTR > ( item ) ;
2014-03-03 11:14:04 +00:00
2015-03-16 16:30:24 +00:00
// Fetch next item already, so we know if the current one is the last
i + + ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
AddButton ( i , MenuString , attrs & SFGAO_FOLDER , index , dwData , i > = DPA_GetPtrCount ( dpaSort ) ) ;
2014-02-24 11:59:34 +00:00
2015-03-16 16:30:24 +00:00
CoTaskMemFree ( MenuString ) ;
2014-02-24 11:59:34 +00:00
}
2015-03-16 16:30:24 +00:00
DPA_Destroy ( dpaSort ) ;
2014-02-24 11:59:34 +00:00
return hr ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuSFToolbar : : InternalGetTooltip ( INT iItem , INT index , DWORD_PTR dwData , LPWSTR pszText , INT cchTextMax )
2014-04-02 17:37:37 +00:00
{
//ITEMIDLIST * pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
UNIMPLEMENTED ;
return E_NOTIMPL ;
}
2014-03-11 10:42:25 +00:00
HRESULT CMenuSFToolbar : : OnDeletingButton ( const NMTOOLBAR * tb )
{
ILFree ( reinterpret_cast < LPITEMIDLIST > ( tb - > tbButton . dwData ) ) ;
return S_OK ;
}
2014-02-24 11:59:34 +00:00
HRESULT CMenuSFToolbar : : SetShellFolder ( IShellFolder * psf , LPCITEMIDLIST pidlFolder , HKEY hKey , DWORD dwFlags )
{
m_shellFolder = psf ;
2014-03-13 16:21:56 +00:00
m_idList = ILClone ( pidlFolder ) ;
2014-02-24 11:59:34 +00:00
m_hKey = hKey ;
m_dwMenuFlags = dwFlags ;
2014-11-12 17:13:05 +00:00
ClearToolbar ( ) ;
2014-02-24 11:59:34 +00:00
return S_OK ;
}
HRESULT CMenuSFToolbar : : GetShellFolder ( DWORD * pdwFlags , LPITEMIDLIST * ppidl , REFIID riid , void * * ppv )
{
HRESULT hr ;
hr = m_shellFolder - > QueryInterface ( riid , ppv ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
if ( pdwFlags )
* pdwFlags = m_dwMenuFlags ;
if ( ppidl )
{
LPITEMIDLIST pidl = NULL ;
if ( m_idList )
{
pidl = ILClone ( m_idList ) ;
if ( ! pidl )
{
2014-10-28 21:40:50 +00:00
ERR ( " ILClone failed! \n " ) ;
2014-05-02 11:58:07 +00:00
( * reinterpret_cast < IUnknown * * > ( ppv ) ) - > Release ( ) ;
2014-02-24 11:59:34 +00:00
return E_FAIL ;
}
}
* ppidl = pidl ;
}
return hr ;
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuSFToolbar : : InternalContextMenu ( INT iItem , INT index , DWORD_PTR dwData , POINT pt )
2014-02-24 11:59:34 +00:00
{
HRESULT hr ;
2014-04-15 10:08:08 +00:00
CComPtr < IContextMenu > contextMenu = NULL ;
LPCITEMIDLIST pidl = reinterpret_cast < LPCITEMIDLIST > ( dwData ) ;
2014-02-24 11:59:34 +00:00
2014-04-15 10:08:08 +00:00
hr = m_shellFolder - > GetUIObjectOf ( GetToolbar ( ) , 1 , & pidl , IID_NULL_PPV_ARG ( IContextMenu , & contextMenu ) ) ;
if ( FAILED_UNEXPECTEDLY ( hr ) )
{
2014-02-24 11:59:34 +00:00
return hr ;
2014-04-15 10:08:08 +00:00
}
hr = TrackContextMenu ( contextMenu , pt ) ;
2014-02-24 11:59:34 +00:00
2014-04-15 10:08:08 +00:00
return hr ;
2014-02-24 11:59:34 +00:00
}
2014-04-15 10:08:08 +00:00
HRESULT CMenuSFToolbar : : InternalExecuteItem ( INT iItem , INT index , DWORD_PTR data )
2014-02-24 11:59:34 +00:00
{
2014-03-03 10:19:35 +00:00
return m_menuBand - > _CallCBWithItemPidl ( reinterpret_cast < LPITEMIDLIST > ( data ) , SMC_SFEXEC , 0 , 0 ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-24 17:42:16 +00:00
HRESULT CMenuSFToolbar : : InternalPopupItem ( INT iItem , INT index , DWORD_PTR dwData , BOOL keyInitiated )
2014-02-24 11:59:34 +00:00
{
HRESULT hr ;
UINT uId ;
UINT uIdAncestor ;
DWORD flags ;
CComPtr < IShellMenuCallback > psmc ;
CComPtr < IShellMenu > shellMenu ;
2014-03-03 10:19:35 +00:00
LPITEMIDLIST pidl = reinterpret_cast < LPITEMIDLIST > ( dwData ) ;
2014-02-24 11:59:34 +00:00
if ( ! pidl )
return E_FAIL ;
2017-06-19 14:27:51 +00:00
hr = CMenuBand_CreateInstance ( IID_PPV_ARG ( IShellMenu , & shellMenu ) ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
m_menuBand - > GetMenuInfo ( & psmc , & uId , & uIdAncestor , & flags ) ;
// FIXME: not sure what to use as uId/uIdAncestor here
hr = shellMenu - > Initialize ( psmc , 0 , uId , SMINIT_VERTICAL ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
CComPtr < IShellFolder > childFolder ;
hr = m_shellFolder - > BindToObject ( pidl , NULL , IID_PPV_ARG ( IShellFolder , & childFolder ) ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
2020-04-30 08:09:14 +00:00
hr = shellMenu - > SetShellFolder ( childFolder , NULL , NULL , SMSET_TOP ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
2014-04-24 17:42:16 +00:00
return PopupSubMenu ( iItem , index , shellMenu , keyInitiated ) ;
2014-02-24 11:59:34 +00:00
}
2014-04-02 17:37:37 +00:00
HRESULT CMenuSFToolbar : : InternalHasSubMenu ( INT iItem , INT index , DWORD_PTR dwData )
2014-02-24 11:59:34 +00:00
{
HRESULT hr ;
2014-03-03 10:19:35 +00:00
LPCITEMIDLIST pidl = reinterpret_cast < LPITEMIDLIST > ( dwData ) ;
2014-02-24 11:59:34 +00:00
2014-02-26 11:13:23 +00:00
SFGAOF attrs = SFGAO_FOLDER ;
hr = m_shellFolder - > GetAttributesOf ( 1 , & pidl , & attrs ) ;
2014-03-03 16:11:47 +00:00
if ( FAILED_UNEXPECTEDLY ( hr ) )
2014-02-24 11:59:34 +00:00
return hr ;
2014-02-26 11:13:23 +00:00
return ( attrs & SFGAO_FOLDER ) ? S_OK : S_FALSE ;
2014-02-24 11:59:34 +00:00
}