diff --git a/Src/StartMenu/StartMenuDLL/DragDrop.cpp b/Src/StartMenu/StartMenuDLL/DragDrop.cpp index 7b3262db8..f272f75f0 100644 --- a/Src/StartMenu/StartMenuDLL/DragDrop.cpp +++ b/Src/StartMenu/StartMenuDLL/DragDrop.cpp @@ -609,7 +609,8 @@ HRESULT STDMETHODCALLTYPE CMenuContainer::DragOver( DWORD grfKeyState, POINTL pt } else { - if (!m_bSubMenu && indexrc.top-m_ScrollButtonSize) pos=rc.top-m_ScrollButtonSize; else if (posid==MENU_LAST) @@ -1090,7 +1094,7 @@ void CMenuContainer::AddStandardItems( void ) continue; if (pStdItem->id==MENU_COLUMN_BREAK && !m_bSubMenu && s_Skin.TwoColumns) - bSecondColumn=true; + breaks++; int stdOptions=GetStdOptions(pStdItem->id); if (!(stdOptions&MENU_ENABLED)) continue; @@ -1271,7 +1275,7 @@ void CMenuContainer::AddStandardItems( void ) item.bSplit=item.bFolder && (item.pStdItem->settings&StdMenuItem::MENU_SPLIT_BUTTON)!=0; // get icon - MenuSkin::TIconSize mainIconSize=!bSecondColumn ? s_Skin.Main_icon_size : s_Skin.Main2_icon_size; + MenuSkin::TIconSize mainIconSize=!IsSecondPaneAfterBreaks(breaks,breakCount) ? s_Skin.Main_icon_size : s_Skin.Main2_icon_size; if (item.bInline && mainIconSize==MenuSkin::ICON_SIZE_NONE) mainIconSize=s_Skin.Main_icon_size; @@ -1499,6 +1503,137 @@ void CMenuContainer::AddStandardItems( void ) } } +// The SecondPane setting in effect +TSecondPane CMenuContainer::GetSecondPaneMode( void ) +{ + // the Windows 7 style always uses the last column, and right-to-left menus are mirrored already + if (s_bWin7Style) return SECOND_PANE_LAST; + TSecondPane mode=(TSecondPane)GetSettingInt(L"SecondPane"); + if (mode==SECOND_PANE_FIRST && s_bRTL) return SECOND_PANE_LAST; + return mode; +} + +// The number of column breaks in a menu's items +int CMenuContainer::CountColumnBreaks( const StdMenuItem *pStdItem ) +{ + int count=0; + for (;pStdItem->id!=MENU_LAST;pStdItem++) + if (pStdItem->id==MENU_COLUMN_BREAK) + count++; + return count; +} + +// Whether the items after the given number of column breaks (out of count) get the second-pane look. +// AddStandardItems needs it for their icon size, before the layout knows the columns +bool CMenuContainer::IsSecondPaneAfterBreaks( int breaks, int count ) +{ + if (m_bSubMenu || !s_Skin.TwoColumns || count==0) return false; + if (s_bWin7Style) return breaks>0; // the Windows 7 style uses only the first break + switch (GetSecondPaneMode()) + { + case SECOND_PANE_NONE: return false; + case SECOND_PANE_FIRST: return breaks==0; + default: return breaks==count; + } +} + +// Reads the SecondPane setting for the layout. Returns the index of the last column break, +// or -1 when only the first break starts a column (the Windows 7 style keeps two columns) +int CMenuContainer::InitSecondPane( void ) +{ + m_bSecondPane=true; + m_bSecondPaneFirst=false; + m_Pane2Column=1; // until a column break says otherwise + if (!IsClassicMainMenu()) + return -1; + + int lastBreak=-1; + for (int i=1;i<(int)m_Items.size();i++) + if (m_Items[i].bBreak) + lastBreak=i; + TSecondPane mode=GetSecondPaneMode(); + if (mode==SECOND_PANE_NONE) + m_bSecondPane=false; // every break starts another first-pane column + else if (mode==SECOND_PANE_FIRST && lastBreak>=0) + m_bSecondPaneFirst=true; // the first column has the second-pane look, every break starts a first-pane column + return lastBreak; +} + +// The pane (0 or 1) of the column that a column break starts, given the pane of the column before it. +// Remembers where the panes meet in m_Pane2Column +int CMenuContainer::GetPaneOfNewColumn( int column, int pane, bool bLastBreak ) +{ + if (m_bSecondPaneFirst) + { + if (pane==1) + m_Pane2Column=column; // the first break ends the second pane + return 0; + } + if (m_bSecondPane && bLastBreak) + { + m_Pane2Column=column; + return 1; + } + return pane; +} + +// Sets m_PaneColumns from m_Pane2Column once the number of columns is known +void CMenuContainer::UpdatePaneColumns( void ) +{ + int count=(int)m_ColumnOffsets.size(); + int boundary=m_Pane2Column &columnWidths ) +{ + const PaneColumns &columns=m_PaneColumns[pane]; + if (columns.last<=columns.first) return 0; + return m_ColumnOffsets[columns.last-1]+columnWidths[columns.last-1]-m_ColumnOffsets[columns.first]; +} + +// The left edge of a column, in window coordinates. Each pane starts at its own content rectangle +int CMenuContainer::GetColumnX( int column ) +{ + if (IsSecondPaneColumn(column)) + return m_rContent2.left+m_ColumnOffsets[column]-m_ColumnOffsets[m_PaneColumns[1].first]; + return m_rContent.left+m_ColumnOffsets[column]-m_ColumnOffsets[m_PaneColumns[0].first]; +} + +// Where the pager scrolls: the content of a sub-menu, or the first column of the main menu, where the pinned programs are +RECT CMenuContainer::GetScrollRect( void ) +{ + if (!m_bTwoColumns || m_ColumnOffsets.empty()) + return m_rContent; + int pane=IsSecondPaneColumn(0)?1:0; + RECT rc=pane?m_rContent2:m_rContent; + if (m_PaneColumns[pane].last>1) + rc.right=GetColumnX(1)-s_Skin.Main_separatorWidth; // more columns share the pane: stop at the gap before the next one + return rc; +} + +// How far the pager can scroll: the height of the scrolling items beyond what it shows +int CMenuContainer::GetScrollRange( void ) +{ + return m_Items[m_ScrollCount-1].itemRect.bottom-GetScrollRect().top-m_ScrollHeight; +} + void CMenuContainer::UpdateAccelerators( int first, int last ) { TRecentKeys recentKeys=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); @@ -3233,16 +3368,21 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, bool bMultiColumn=s_ScrollMenus!=0 && (m_Options&CONTAINER_MULTICOLUMN); int shutdownIndex=-1; + // in the Classic two-column menu the last column break starts the second pane, and any earlier break adds a column to the first pane. + // the Windows 7 style keeps using only the first break + int lastBreak=InitSecondPane(); + { int row=0, column=0, subColumn=0; int y=0; int maxw=0; - int index=0; + int index=m_bSecondPaneFirst?1:0; for (int i=0;i<(int)m_Items.size();i++) { MenuItem &item=m_Items[i]; - if (m_bTwoColumns && column==0 && i>0 && item.bBreak) + bool bColumnBreak=item.bBreak && (index==0 || m_bSecondPaneFirst) && (column==0 || lastBreak>=0); + if (m_bTwoColumns && i>0 && bColumnBreak) { // start a new column column++; @@ -3256,7 +3396,7 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, else y=s_Skin.User_frame_position.x+s_Skin.User_image_padding.y-menuPadding[0].top; } - index=1; + index=GetPaneOfNewColumn(column,index,lastBreak<0 || i==lastBreak); } item.bNew=false; if (m_bTwoColumns && im_SearchIndex) && item.id!=MENU_SHUTDOWN_BUTTON) @@ -3455,7 +3595,7 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, y=0; } } - else if (item.id==MENU_SEPARATOR && !item.bBlankSeparator && !item.bInline && m_bTwoColumns && column==0 && i+1<(int)m_Items.size() && m_Items[i+1].bBreak) + else if (item.id==MENU_SEPARATOR && !item.bBlankSeparator && !item.bInline && m_bTwoColumns && (index==0 || m_bSecondPaneFirst) && i+1<(int)m_Items.size() && m_Items[i+1].bBreak) h=0; item.row=row; item.column=column; @@ -3490,6 +3630,8 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, row++; } } + if (!m_bSecondPane) + m_Pane2Column=(int)columnWidths.size(); // past the last column: every column is in the first pane SelectObject(hdc,font0); DeleteDC(hdc); @@ -3561,7 +3703,8 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, // calculate the horizontal position of each item int maxw=0; - int maxh[2]={0,0}; + int maxh[2]={0,0}; // height of the tallest column in each pane + int scrollHeight=0; // the pager scrolls only the first column of the main menu, where the pinned programs are int scrollWidth=GetSystemMetrics(SM_CXVSCROLL); { m_ColumnOffsets.resize(columnWidths.size()); @@ -3571,6 +3714,7 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, m_ColumnOffsets[i]=maxw; maxw+=columnWidths[i]; } + UpdatePaneColumns(); columnWidths.push_back(maxw); bool bInline=false; for (int i=0;i<(int)m_Items.size();i++) @@ -3606,16 +3750,11 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, item.itemRect.right-=scrollWidth; } } - if (m_bTwoColumns) - { - if (maxh[item.column]2) { - w1=columnWidths[0]; - w2=columnWidths[1]; + w1=GetPaneWidth(0,columnWidths); + w2=GetPaneWidth(1,columnWidths); if (s_bWin7Style) { @@ -3794,10 +3933,16 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, MenuItem &item=m_Items[i]; int dx=m_rContent.left; int dy=m_rContent.top; - if (m_bTwoColumns && item.column==1) + if (m_bTwoColumns) { - dx=m_rContent2.left-m_ColumnOffsets[1]; - dy=m_rContent2.top; + // each pane starts at its own content rectangle + if (IsSecondPaneColumn(item.column)) + { + dx=m_rContent2.left-m_ColumnOffsets[m_PaneColumns[1].first]; + dy=m_rContent2.top; + } + else if (m_PaneColumns[0].first<(int)m_ColumnOffsets.size()) + dx=m_rContent.left-m_ColumnOffsets[m_PaneColumns[0].first]; } if (item.id==MENU_SHUTDOWN_BUTTON) dx=0; @@ -3806,49 +3951,34 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, if (m_bTwoColumns && columnWidths.size()>2) { - int dh1=0, dh2=0; + // each column is aligned to the bottom separately (from its first COLUMN_PADDING on) + std::vector columnDH(m_ColumnOffsets.size(),0); // how far down the column's aligned items move for (int i=0;i bAlign(columnDH.size(),false); for (int i=0;imaxHeight[0] && m_ScrollCount>0 && (m_bSubMenu || !s_bWin7Style)) + int scrollPane=IsSecondPaneColumn(0)?1:0; // the first column can have the second-pane look (SecondPane=First) + int scrollTop=GetScrollRect().top; + if (!bMultiColumn && scrollHeight>maxHeight[scrollPane] && m_ScrollCount>0 && (m_bSubMenu || !s_bWin7Style)) { - int d=maxh[0]-maxHeight[0]; - m_ScrollHeight=m_Items[m_ScrollCount-1].itemRect.bottom-d-m_rContent.top; + int d=scrollHeight-maxHeight[scrollPane]; + m_ScrollHeight=m_Items[m_ScrollCount-1].itemRect.bottom-d-scrollTop; if (m_ScrollHeight<=0) { if (m_ScrollCount<(int)m_Items.size()) - d=m_Items[m_ScrollCount].itemRect.bottom-m_rContent.top; + d=m_Items[m_ScrollCount].itemRect.bottom-scrollTop; m_ScrollOffset=m_ScrollHeight=0; for (int i=0;ibottom) m_Items[i].itemRect.bottom=m_Items[i].itemRect.top; } @@ -4120,8 +4252,8 @@ void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, { m_SearchBox.Create(L"EDIT",m_hWnd,itemRect,NULL,WS_CHILD|(s_Skin.Search_frame?WS_BORDER:0)|ES_AUTOHSCROLL|ES_WANTRETURN); SetWindowSubclass(m_SearchBox,SubclassSearchBox,(UINT_PTR)this,0); - int index=(m_bTwoColumns && m_Items[m_SearchIndex].column==1)?1:0; - if (index==1 && (m_SearchIndex==0 || m_Items[m_SearchIndex-1].column==0)) + int index=IsSecondPaneColumn(m_Items[m_SearchIndex].column)?1:0; + if (index==1 && (m_SearchIndex==0 || !IsSecondPaneColumn(m_Items[m_SearchIndex-1].column))) m_SearchBox.SetFont(s_Skin.ItemSettings[MenuSkin::COLUMN2_ITEM].font); else m_SearchBox.SetFont(s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].font); @@ -4355,7 +4487,7 @@ void CMenuContainer::UpdateScroll( void ) else { m_bScrollUp=(m_ScrollOffset>0); - m_bScrollDown=(m_ScrollOffset+m_ScrollHeight0 && index=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize) + if (m_bScrollDown && rc.top>=scrollTop+m_ScrollHeight-m_ScrollButtonSize) return false; } if (m_SearchScrollCount>m_SearchScrollHeight && index>=m_OriginalCount) @@ -4529,10 +4662,13 @@ bool CMenuContainer::GetItemRect( int index, RECT &rc ) int CMenuContainer::HitTest( const POINT &pt, bool *bArrow, bool bDrop ) { - if (m_bScrollUp && pt.y=rScroll.left && pt.x=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize) + if (m_bScrollDown && bInPager && pt.y>=rScroll.top+m_ScrollHeight-m_ScrollButtonSize) start=m_ScrollCount; int n=(int)m_Items.size(); for (int i=start;itotal) { scroll=total; @@ -5276,7 +5412,7 @@ LRESULT CMenuContainer::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& else if (m_bScrollDown && m_bScrollDownHot) { scroll+=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight*speed/6; - int total=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + int total=GetScrollRange(); if (scroll>total) scroll=total; } if (m_ScrollOffset!=scroll) @@ -5745,7 +5881,7 @@ LRESULT CMenuContainer::OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL if (index<0) { // no item is selected - find the first selectable item in the last column then go up - int col=(m_bTwoColumns?1:0); + int col=(m_bTwoColumns?(int)m_ColumnOffsets.size()-1:0); index=0; for (int i=0;i0) - scrollOffset=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + scrollOffset=GetScrollRange(); if (index0) - scrollOffset=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + scrollOffset=GetScrollRange(); if (indextotal) scroll=total; if (m_ScrollOffset!=scroll) { @@ -8606,7 +8742,7 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr if (pStartMenu->m_SearchIndex>=0 && GetSettingInt(L"SearchBox")==SEARCHBOX_NORMAL && GetSettingBool(L"SearchSelect")) { pStartMenu->ActivateItem(pStartMenu->m_SearchIndex,ACTIVATE_SELECT,NULL); - if (pStartMenu->m_bTwoColumns && pStartMenu->m_Items[pStartMenu->m_SearchIndex].column==0 && pStartMenu->m_SearchIndex+1<(int)pStartMenu->m_Items.size() && pStartMenu->m_Items[pStartMenu->m_SearchIndex+1].column==1) + if (pStartMenu->m_bTwoColumns && pStartMenu->m_Items[pStartMenu->m_SearchIndex].column==0 && pStartMenu->m_SearchIndex+1<(int)pStartMenu->m_Items.size() && pStartMenu->m_Items[pStartMenu->m_SearchIndex+1].column!=0) s_bOverrideFirstDown=true; } else if (!bTreeSelected) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.h b/Src/StartMenu/StartMenuDLL/MenuContainer.h index 057982104..f8107635c 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.h +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.h @@ -25,6 +25,7 @@ #endif enum TRecentPrograms; +enum TSecondPane; enum TMenuID { @@ -661,6 +662,14 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub POINT m_PaintOffset; int m_MaxWidth; bool m_bTwoColumns; + bool m_bSecondPane; // false when the SecondPane setting gives no column the second-pane look + bool m_bSecondPaneFirst; // SecondPane=First: the second pane is the columns before m_Pane2Column, on the left + int m_Pane2Column; // where the panes meet: the second pane starts here (or ends here with m_bSecondPaneFirst) + struct PaneColumns + { + int first, last; // [first,last) + }; + PaneColumns m_PaneColumns[2]; // the columns of the first and the second pane, set by InitWindowInternal RECT m_rMenu; RECT m_rContent; RECT m_rContent2; @@ -701,6 +710,18 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub int AddSearchItems( const std::vector &items, const CString &categoryName, unsigned int categoryHash, int originalCount ); void GetRecentPrograms( std::vector &items, int maxCount ); + static TSecondPane GetSecondPaneMode( void ); + static int CountColumnBreaks( const StdMenuItem *pStdItem ); + bool IsSecondPaneAfterBreaks( int breaks, int count ); + int InitSecondPane( void ); + int GetPaneOfNewColumn( int column, int pane, bool bLastBreak ); + void UpdatePaneColumns( void ); + int GetPaneWidth( int pane, const std::vector &columnWidths ); + int GetColumnX( int column ); + RECT GetScrollRect( void ); + int GetScrollRange( void ); + bool IsClassicMainMenu( void ) { return m_bTwoColumns && !m_bSubMenu && !s_bWin7Style; } + bool IsSecondPaneColumn( int column ) { return column>=m_PaneColumns[1].first && column0 && !s_bRTL; + int pane1[2]={0,totalWidth1}, pane2[2]={totalWidth1,totalWidth}; // [left,right) of each pane, to align emblems and the user + if (bPane2First) + { + pane2[0]=textHeight; + pane2[1]=textHeight+totalWidth2; + pane1[0]=pane2[1]; + pane1[1]=totalWidth; + } totalHeight=height1+menuPadding[0].top+menuPadding[0].bottom; - if (m_bTwoColumns) + if (m_bTwoColumns && m_bSecondPane) { int totalHeight2=height2+menuPadding[1].top+menuPadding[1].bottom; if (totalHeight0) - pos.x=totalWidth1+(totalWidth2-frameSize.cx)/2; + pos.x=(pane2[0]+pane2[1]-frameSize.cx)/2; else pos.x=(totalWidth-frameSize.cx)/2; } @@ -1228,10 +1274,7 @@ void CMenuContainer::CreateBackground( int width1, int width2, int height1, int { RECT rc0; int x0=0, x1=totalWidth; - if (s_Skin.User_name_align==MenuSkin::HALIGN_CENTER1 || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT1 || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT1) - x1=totalWidth1; - else if (s_Skin.User_name_align==MenuSkin::HALIGN_CENTER2 || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT2 || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT2) - x0=totalWidth1; + AlignToPane(s_Skin.User_name_align,pane1,pane2,x0,x1); if (s_Skin.User_name_position.left<0) rc0.left=x1+s_Skin.User_name_position.left; @@ -1606,8 +1649,13 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) MenuBitmap bmpPagerArrows; SIZE pagArrowSize; MenuSkin::TOpacity opacity=m_bSubMenu?s_Skin.Submenu_opacity:s_Skin.Main_opacity; - int glow=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].glowSize; + // the scrolling items can be in the second pane (SecondPane=First) + const MenuSkin::ItemDrawSettings &scrollSettings=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:(IsSecondPaneColumn(0)?MenuSkin::COLUMN2_ITEM:MenuSkin::COLUMN1_ITEM)]; + int glow=scrollSettings.glowSize; if (!s_Theme) glow=0; + // composited text ignores the clip rectangle, so the pager buttons need their background drawn again (see DrawThemeTextEx below) + bool bTextSpills=(glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS || + scrollSettings.opacity==MenuSkin::OPACITY_FULLALPHA || scrollSettings.opacity==MenuSkin::OPACITY_FULLGLASS); TRecentKeys recentType=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); if (m_bSubMenu) @@ -1638,13 +1686,14 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) HGDIOBJ font0=GetCurrentObject(hdc,OBJ_FONT); SetBkMode(hdc,TRANSPARENT); - // set clip rectangle for the scrollable items - int clipTop=m_rContent.top; - int clipBottom=m_rContent.bottom; + // set clip rectangle for the scrollable items (the pager covers only the column that scrolls, see GetScrollRect) + RECT rScroll=GetScrollRect(); + int clipTop=rScroll.top; + int clipBottom=rScroll.bottom; if (m_bScrollUp) - clipTop=m_rContent.top+m_ScrollButtonSize; + clipTop=rScroll.top+m_ScrollButtonSize; if (m_bScrollDown) - clipBottom=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize; + clipBottom=rScroll.top+m_ScrollHeight-m_ScrollButtonSize; if (m_ScrollHeight>0) IntersectClipRect(hdc,0,clipTop,m_rMenu.right,clipBottom); @@ -1665,10 +1714,10 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) SelectClipRgn(hdc,NULL); if (m_bScrollUp) { - if (glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS) + if (bTextSpills) { // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) - RECT rc={m_rContent.left,0,m_rContent.right,clipTop}; + RECT rc={rScroll.left,0,rScroll.right,clipTop}; if (bAlphaMain || !bmpMain) { SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); @@ -1677,7 +1726,7 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) if (bmpMain) { HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); - IntersectClipRect(hdc,m_rContent.left,0,m_rContent.right,clipTop); + IntersectClipRect(hdc,rScroll.left,0,rScroll.right,clipTop); MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); SelectObject(hdc2,bmp0); SelectClipRgn(hdc,NULL); @@ -1685,7 +1734,7 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) } // draw up button - RECT rc=m_rContent; + RECT rc=rScroll; rc.bottom=clipTop; if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) { @@ -1722,10 +1771,10 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) { int bottom=clipBottom+s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight; if (bottom>=m_rMenu.bottom) bottom=m_rMenu.bottom; - if (bottom>clipBottom && (glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS)) + if (bottom>clipBottom && bTextSpills) { // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) - RECT rc={m_rContent.left,clipBottom,m_rContent.right,bottom}; + RECT rc={rScroll.left,clipBottom,rScroll.right,bottom}; if (bAlphaMain || !bmpMain) { SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); @@ -1734,7 +1783,7 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) if (bmpMain) { HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); - IntersectClipRect(hdc,m_rContent.left,clipBottom,m_rContent.right,bottom); + IntersectClipRect(hdc,rScroll.left,clipBottom,rScroll.right,bottom); MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); SelectObject(hdc2,bmp0); SelectClipRgn(hdc,NULL); @@ -1742,8 +1791,8 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) } // draw down button - RECT rc=m_rContent; - rc.bottom=m_rContent.top+m_ScrollHeight; + RECT rc=rScroll; + rc.bottom=rScroll.top+m_ScrollHeight; rc.top=clipBottom; if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) { @@ -2451,18 +2500,23 @@ void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) } } - // draw vertical separators - if (m_bSubMenu && m_ColumnOffsets.size()>1) + // draw vertical separators between the columns of a sub-menu, or within each pane of the main menu + // (the separator between the two panes is part of the background) + for (int pane=0;pane<2;pane++) { + const RECT &content=pane?m_rContent2:m_rContent; + int sepFirst=m_PaneColumns[pane].first+1, sepLast=m_PaneColumns[pane].last; // separators go before these columns + if (sepFirst>=sepLast) + continue; if (bmpSeparatorV.GetBitmap()) { HGDIOBJ bmp0=SelectObject(hdc2,bmpSeparatorV.GetBitmap()); RECT rSrc={0,0,sepWidth,sepSlicesY[0]+sepSlicesY[1]+sepSlicesY[2]}; RECT rMargins={0,sepSlicesY[0],0,sepSlicesY[2]}; - for (size_t i=1;i