// ## MenuContainer.h // Classic Shell (c) 2009-2017, Ivo Beltchev // Open-Shell (c) 2017-2018, The Open-Shell Team // Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author // MenuPaint.cpp - handles the painting functionality of CMenuContainer #include "stdafx.h" #include "ItemManager.h" #include "MenuContainer.h" #include "StartMenuDLL.h" #include "Settings.h" #include "Translations.h" #include "ResourceHelper.h" #include "LogManager.h" #include "ProgramsTree.h" #include "SettingsUI.h" #include #include #include #include static BLENDFUNCTION g_AlphaFunc={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; MIDL_INTERFACE("4BEDE6E0-A125-46A7-A3BF-4187165E09A5") IUserTileStore8 : public IUnknown { virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; }; MIDL_INTERFACE("A1BA55E7-0F4E-454D-89A4-2376347D504A") IUserTileStore81 : public IUnknown { virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; }; MIDL_INTERFACE("A76E31A3-DED8-4119-ADD8-BF818F05965C") IUserTileStore10 : public IUnknown { virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetExtraSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; }; static CLSID CLSID_UserTileStore={0x09c5dd34, 0x009d, 0x40fa, {0xbc, 0xb9, 0x01, 0x65, 0xad, 0x0c, 0x15, 0xd4}}; static void StretchBlt2( HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, bool bAlpha ) { if (wDest>0 && hDest>0 && wSrc>0 && hSrc>0) { if (bAlpha) AlphaBlend(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,wSrc,hSrc,g_AlphaFunc); else if (wDest==wSrc && hDest==hSrc) { // HACK: when blitting RTL image with no stretching, StretchBlt adds 1 pixel offset. use BitBlt instead BitBlt(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,SRCCOPY); } else StretchBlt(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,wSrc,hSrc,SRCCOPY); } } HBITMAP CMenuContainer::LoadUserImage( int size, HBITMAP hMask ) { wchar_t path[_MAX_PATH]; path[0]=0; CString str=GetSettingString(L"UserPicturePath"); if (str.IsEmpty()) { if (GetWinVersion()==WIN_VER_WIN8) { CComPtr pStore; pStore.CoCreateInstance(CLSID_UserTileStore); if (pStore) { CComString pPath; if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) Strcpy(path,_countof(path),pPath); } } else if (GetWinVersion()==WIN_VER_WIN81) { CComPtr pStore; pStore.CoCreateInstance(CLSID_UserTileStore); if (pStore) { CComString pPath; if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) Strcpy(path,_countof(path),pPath); } } else if (GetWinVersion()>=WIN_VER_WIN10) { CComPtr pStore; pStore.CoCreateInstance(CLSID_UserTileStore); if (pStore) { CComString pPath; if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) Strcpy(path,_countof(path),pPath); } } if (!path[0]) { HMODULE hShell32=GetModuleHandle(L"shell32.dll"); typedef HRESULT (__stdcall*tSHGetUserPicturePath)(LPCWSTR, UINT, LPWSTR, ULONG); tSHGetUserPicturePath SHGetUserPicturePath=(tSHGetUserPicturePath)GetProcAddress(hShell32,MAKEINTRESOURCEA(261)); if (SHGetUserPicturePath) SHGetUserPicturePath(NULL,0x80000000,path,_countof(path)); } } else { Strcpy(path,_countof(path),str); DoEnvironmentSubst(path,_countof(path)); } HBITMAP hBitmap=NULL; if (path[0]) { LOG_MENU(LOG_OPEN,L"Loading user image: '%s'",path); SIZE s={size,size}; if (str.IsEmpty()) hBitmap=LoadImageFile(path,&s,false,false,NULL); else hBitmap=LoadImageFile(path,&s,true,true,NULL); } if (hBitmap && hMask) { BITMAP info1, info2; GetObject(hBitmap,sizeof(info1),&info1); GetObject(hMask,sizeof(info2),&info2); if (info1.bmBits && info2.bmBits && info1.bmWidth==info2.bmWidth && info1.bmHeight==info2.bmHeight && info1.bmBitsPixel==32 && info2.bmBitsPixel==32) { unsigned char *pixels1=(unsigned char*)info1.bmBits; const unsigned char *pixels2=(const unsigned char*)info2.bmBits; int n=info1.bmWidth*info1.bmHeight; bool bHasAlpha=false; pixels1+=3; for (int i=0;irDst.right) x1a=rDst.right; int x2a=rDst.right-rMargins.right; if (x2ax2a) x1a=x2a=(x1a+x2a)/2; int x3a=rDst.right; int x0b=rSrc.left; int x1b=rSrc.left+rMargins.left; int x2b=rSrc.right-rMargins.right; int x3b=rSrc.right; int y0a=rDst.top; int y1a=rDst.top+rMargins.top; if (y1a>rDst.bottom) y1a=rDst.bottom; int y2a=rDst.bottom-rMargins.bottom; if (y2ay2a) y1a=y2a=(y1a+y2a)/2; int y3a=rDst.bottom; int y0b=rSrc.top; int y1b=rSrc.top+rMargins.top; int y2b=rSrc.bottom-rMargins.bottom; int y3b=rSrc.bottom; SetStretchBltMode(hDst,COLORONCOLOR); StretchBlt2(hDst,x0a,y0a,x1a-x0a,y1a-y0a,hSrc,x0b,y0b,x1b-x0b,y1b-y0b,bAlpha); StretchBlt2(hDst,x1a,y0a,x2a-x1a,y1a-y0a,hSrc,x1b,y0b,x2b-x1b,y1b-y0b,bAlpha); StretchBlt2(hDst,x2a,y0a,x3a-x2a,y1a-y0a,hSrc,x2b,y0b,x3b-x2b,y1b-y0b,bAlpha); StretchBlt2(hDst,x0a,y1a,x1a-x0a,y2a-y1a,hSrc,x0b,y1b,x1b-x0b,y2b-y1b,bAlpha); StretchBlt2(hDst,x1a,y1a,x2a-x1a,y2a-y1a,hSrc,x1b,y1b,x2b-x1b,y2b-y1b,bAlpha); StretchBlt2(hDst,x2a,y1a,x3a-x2a,y2a-y1a,hSrc,x2b,y1b,x3b-x2b,y2b-y1b,bAlpha); StretchBlt2(hDst,x0a,y2a,x1a-x0a,y3a-y2a,hSrc,x0b,y2b,x1b-x0b,y3b-y2b,bAlpha); StretchBlt2(hDst,x1a,y2a,x2a-x1a,y3a-y2a,hSrc,x1b,y2b,x2b-x1b,y3b-y2b,bAlpha); StretchBlt2(hDst,x2a,y2a,x3a-x2a,y3a-y2a,hSrc,x2b,y2b,x3b-x2b,y3b-y2b,bAlpha); } struct PatternInfo { int index; SIZE size; int offsetX; int maskShift; unsigned int otherMask; const std::vector *bits; const unsigned int *bitsY; int stride; }; static HBITMAP CreateMaskedEmblem( HBITMAP bmpEmblem, RECT &rcEmblem, const unsigned int *EMaskBits, int maskWidth, int maskHeight, int channel ) { if (channel<3) channel=2-channel; int minx=rcEmblem.left<0?0:rcEmblem.left; int maxx=rcEmblem.right>maskWidth?maskWidth:rcEmblem.right; int miny=rcEmblem.top<0?0:rcEmblem.top; int maxy=rcEmblem.bottom>maskHeight?maskHeight:rcEmblem.bottom; Assert(minx=0 && start+(maxx-minx)*4<=info.bmHeight*info.bmWidthBytes); for (int x=minx;x=0 && start+(maxx-minx)*3<=info.bmHeight*info.bmWidthBytes); for (int x=minx;xsize()/pattern.size.cy; } } for (int y=0;y>pattern.maskShift)&255; if (mask==0) continue; unsigned int pat=pattern.bitsY[x]; if ((pixel&pattern.otherMask)==0) { // fast path if only one channel is set int pa=pat>>24; if (pa) { if (mask==255) { // even faster path for straight copy pixel=pat; } else { mask++; // a cheat to make the mask from 1 to 256, so we can use >>8 instead of /255 a=(pa*mask)>>8; if (a==0) { pixel=0; } else { r=(((pat>>16)&255)*mask)>>8; g=(((pat>>8)&255)*mask)>>8; b=((pat&255)*mask)>>8; pixel=(a<<24)|(r<<16)|(g<<8)|b; } } } else pixel=0; goto end; } int pa=pat>>24; if (pa) { a+=pa*mask; r+=((pat>>16)&255)*mask; g+=((pat>>8)&255)*mask; b+=(pat&255)*mask; } } a/=255; if (a==0) { pixel=0; } else { if (a>255) a=255; r/=255; if (r>255) r=255; g/=255; if (g>255) g=255; b/=255; if (b>255) b=255; pixel=(a<<24)|(r<<16)|(g<<8)|b; } end:; } } LARGE_INTEGER time; QueryPerformanceCounter(&time); LONGLONG dt=(time.QuadPart-time0.QuadPart)*1000000/freq.QuadPart; // Trace("BlendPatterns: %.3f ms",(int)dt/1000.f); } // Creates the bitmap for the background void CMenuContainer::CreateBackground( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight, bool bCreateRegion ) { // get the text from the ini file or from the registry wchar_t caption[256]; Strcpy(caption,_countof(caption),GetSettingString(L"MenuCaption")); DoEnvironmentSubst(caption,_countof(caption)); MenuBitmap bmpSkin; MenuBitmap bmpSkinPattern; MenuBitmap bmpSkinEmblem; const int *slicesX, *slicesY; if (s_MenuMode==MODE_SEARCH) { bmpSkin=s_Skin.Main_bitmap_search; slicesX=s_Skin.Main_bitmap_search_slices_X; slicesY=s_Skin.Main_bitmap_search_slices_Y; bmpSkinPattern=s_Skin.Main_pattern_search_mask; bmpSkinEmblem=s_Skin.Main_emblem_search_mask; } else if (s_MenuMode==MODE_JUMPLIST) { bmpSkin=s_Skin.Main_bitmap_jump; slicesX=s_Skin.Main_bitmap_jump_slices_X; slicesY=s_Skin.Main_bitmap_jump_slices_Y; bmpSkinPattern=s_Skin.Main_pattern_jump_mask; bmpSkinEmblem=s_Skin.Main_emblem_jump_mask; } else { bmpSkin=s_Skin.Main_bitmap; slicesX=s_Skin.Main_bitmap_slices_X; slicesY=s_Skin.Main_bitmap_slices_Y; bmpSkinPattern=s_Skin.Main_pattern_mask; bmpSkinEmblem=s_Skin.Main_emblem_mask; } bool bCaption=(slicesX[1]>0); MenuSkin::TOpacity opacity=s_Skin.Main_opacity; HDC hdcTemp=CreateCompatibleDC(NULL); HFONT font0=NULL; if (bCaption) font0=(HFONT)SelectObject(hdcTemp,s_Skin.Caption_font); RECT rc={0,0,0,0}; DTTOPTS opts={sizeof(opts),DTT_COMPOSITED|DTT_CALCRECT}; if (bCaption) { if (s_Theme) DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT,&rc,&opts); else DrawText(hdcTemp,caption,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT); } int textWidth=rc.right+s_Skin.Caption_padding.top+s_Skin.Caption_padding.bottom; int textHeight=rc.bottom+s_Skin.Caption_padding.left+s_Skin.Caption_padding.right; int total=slicesX[0]+slicesX[2]; if (textHeight=0 && s_bWin7Style) total+=slicesY[3]+slicesY[5]; if (totalHeighttotalHeight) textWidth=totalHeight; m_rContent.left=menuPadding[0].left+textHeight; m_rContent.right=totalWidth1-menuPadding[0].right; m_rContent.top=menuPadding[0].top; m_rContent.bottom=m_rContent.top+height1; if (totalWidth2>0) { m_rContent2.left=m_rContent.right+menuPadding[0].right+menuPadding[1].left; m_rContent2.right=totalWidth-menuPadding[1].right; m_rContent2.top=menuPadding[1].top; m_rContent2.bottom=m_rContent2.top+height2; } MenuBitmap bmpSearch; MenuBitmap bmpSearchPattern; MenuBitmap bmpSearchEmblem; int *searchSlicesX, *searchSlicesY; RECT searchPadding; int searchX[4], searchY[4]; if (m_SearchIndex>=0 && s_bWin7Style) { if (s_MenuMode==MODE_SEARCH) { bmpSearch=s_Skin.Search_background_search; bmpSearchPattern=s_Skin.Search_pattern_search_mask; bmpSearchEmblem=s_Skin.Search_emblem_search_mask; searchSlicesX=s_Skin.Search_background_search_slices_X; searchSlicesY=s_Skin.Search_background_search_slices_Y; searchPadding=s_Skin.Search_background_search_padding; } else if (s_MenuMode==MODE_JUMPLIST) { bmpSearch=s_Skin.Search_background_jump; bmpSearchPattern=s_Skin.Search_pattern_jump_mask; bmpSearchEmblem=s_Skin.Search_emblem_jump_mask; searchSlicesX=s_Skin.Search_background_jump_slices_X; searchSlicesY=s_Skin.Search_background_jump_slices_Y; searchPadding=s_Skin.Search_background_jump_padding; } else { bmpSearch=s_Skin.Search_background; bmpSearchPattern=s_Skin.Search_pattern_mask; bmpSearchEmblem=s_Skin.Search_emblem_mask; searchSlicesX=s_Skin.Search_background_slices_X; searchSlicesY=s_Skin.Search_background_slices_Y; searchPadding=s_Skin.Search_background_padding; } const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM]; int searchH=settings.textMetrics.tmHeight*12/8+s_Skin.Search_padding.top+s_Skin.Search_padding.bottom; // 12 DLUs int searchW=settings.textMetrics.tmAveCharWidth*25; RECT searchRect; searchRect.left=m_rContent.left+s_Skin.Search_padding.left; searchRect.top=m_rContent.bottom-searchH+s_Skin.Search_padding.top; searchRect.bottom=m_rContent.bottom-s_Skin.Search_padding.bottom; searchRect.right=m_rContent.right-s_Skin.Search_padding.right; RECT editRect; if (m_SearchBox.m_hWnd) { m_SearchBox.GetWindowRect(&editRect); ::MapWindowPoints(NULL,m_hWnd,(POINT*)&editRect,2); OffsetRect(&editRect,-m_BitmapOffset,0); searchRect.right=editRect.right+(editRect.bottom-editRect.top); if (!s_Skin.Search_frame) searchRect.right+=7; } else { editRect=searchRect; editRect.right-=(editRect.bottom-editRect.top); if (!s_Skin.Search_frame) InflateRect(&editRect,-1,-3); } searchX[0]=m_rContent.left-searchPadding.left; searchX[1]=editRect.left; searchX[2]=searchRect.right+s_Skin.Search_padding.right; searchX[3]=((s_MenuMode==MODE_JUMPLIST)?m_rContent2.right:m_rContent.right)+searchPadding.right; searchY[0]=searchRect.top-s_Skin.Search_padding.top-searchPadding.top; searchY[1]=editRect.top-2; searchY[2]=editRect.bottom+2; searchY[3]=m_rContent.bottom+searchPadding.bottom; } BITMAPINFO dib={sizeof(dib)}; dib.bmiHeader.biWidth=totalWidth; dib.bmiHeader.biHeight=-totalHeight; dib.bmiHeader.biPlanes=1; dib.bmiHeader.biBitCount=32; dib.bmiHeader.biCompression=BI_RGB; HDC hdc=CreateCompatibleDC(NULL); unsigned int *bits; m_Bitmap=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,(void**)&bits,NULL,0); HGDIOBJ bmp0=SelectObject(hdc,m_Bitmap); if (opacity==MenuSkin::OPACITY_SOLID) { RECT rc={0,0,totalWidth,totalHeight}; SetDCBrushColor(hdc,s_Skin.Main_background); FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } bool bHasPattern=false; if (s_Skin.Patterns[0].GetBitmap() || s_Skin.Patterns[1].GetBitmap() || s_Skin.Patterns[2].GetBitmap() || s_Skin.Patterns[3].GetBitmap()) { bHasPattern=(bmpSkinPattern.GetBitmap() || bmpSkinPattern.GetColor() || bmpSearchPattern.GetBitmap() || bmpSearchPattern.GetColor()); } bool bHasEmblemMask=false; if (s_Skin.Main_emblems[0].GetBitmap() || s_Skin.Main_emblems[1].GetBitmap() || s_Skin.Main_emblems[2].GetBitmap() || s_Skin.Main_emblems[3].GetBitmap()) { bHasEmblemMask=(bmpSkinEmblem.GetBitmap() || bmpSkinEmblem.GetColor() || bmpSearchEmblem.GetBitmap() || bmpSearchEmblem.GetColor()); } HBITMAP PMaskBmp=NULL, EMaskBmp=NULL; unsigned int *PMaskBits=NULL, *EMaskBits=NULL; HGDIOBJ bmp02=GetCurrentObject(hdcTemp,OBJ_BITMAP); HDC hdcPMask=NULL, hdcEMask=NULL; HDC hdcPMaskTemp=NULL, hdcEMaskTemp=NULL; HGDIOBJ PMaskBmp0=NULL, PMaskBmp02=NULL, EMaskBmp0=NULL, EMaskBmp02=NULL; if (bHasPattern) { hdcPMask=CreateCompatibleDC(NULL); PMaskBmp=CreateDIBSection(hdcPMask,&dib,DIB_RGB_COLORS,(void**)&PMaskBits,NULL,0); PMaskBmp0=SelectObject(hdcPMask,PMaskBmp); hdcPMaskTemp=CreateCompatibleDC(NULL); PMaskBmp02=GetCurrentObject(hdcPMaskTemp,OBJ_BITMAP); } if (bHasEmblemMask) { hdcEMask=CreateCompatibleDC(NULL); EMaskBmp=CreateDIBSection(hdcEMask,&dib,DIB_RGB_COLORS,(void**)&EMaskBits,NULL,0); EMaskBmp0=SelectObject(hdcEMask,EMaskBmp); hdcEMaskTemp=CreateCompatibleDC(NULL); EMaskBmp02=GetCurrentObject(hdcEMaskTemp,OBJ_BITMAP); } if (bmpSkin.GetBitmap()) { // draw the skinned background SelectObject(hdcTemp,bmpSkin.GetBitmap()); if (bHasPattern) { if (bmpSkinPattern.GetBitmap()) { SelectObject(hdcPMaskTemp,bmpSkinPattern.GetBitmap()); } else { RECT rc={0,0,totalWidth,totalHeight}; SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } if (bHasEmblemMask) { if (bmpSkinEmblem.GetBitmap()) { SelectObject(hdcEMaskTemp,bmpSkinEmblem.GetBitmap()); } else { RECT rc={0,0,totalWidth,totalHeight}; SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } int searchHeight=0; if (m_SearchIndex>=0 && s_bWin7Style && slicesY[3]+slicesY[4]+slicesY[5]>0) searchHeight=m_Items[m_SearchIndex].itemRect.top-s_Skin.Search_padding.top-searchPadding.top; RECT rSrc={0,0,slicesX[0]+slicesX[1]+slicesX[2],slicesY[0]+slicesY[1]+slicesY[2]}; RECT rDst={0,0,textHeight,searchHeight?searchHeight:totalHeight}; RECT rMargins={slicesX[0],slicesY[0],slicesX[2],slicesY[2]}; MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); if (bmpSkinPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); if (bmpSkinEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); rSrc.left=rSrc.right; rSrc.right+=slicesX[3]+slicesX[4]+slicesX[5]; rDst.left=rDst.right; rDst.right=totalWidth1; rMargins.left=slicesX[3]; rMargins.right=slicesX[5]; MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); if (bmpSkinPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); if (bmpSkinEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); if (searchHeight>0) { RECT rSrc2=rSrc, rDst2=rDst, rMargins2=rMargins; rSrc2.top=rSrc.bottom; rSrc2.bottom+=slicesY[3]+slicesY[4]+slicesY[5]; rDst2.top=rDst.bottom; rDst2.bottom=totalHeight; rMargins2.top=slicesY[3]; rMargins2.bottom=slicesY[5]; MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); if (bmpSkinPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc2,rDst2,rMargins2,false); if (bmpSkinEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc2,rDst2,rMargins2,false); } if (totalWidth2>0) { rSrc.left=rSrc.right; rSrc.right+=slicesX[6]+slicesX[7]+slicesX[8]; rDst.left=rDst.right; rDst.right+=totalWidth2; rMargins.left=slicesX[6]; rMargins.right=slicesX[8]; MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); if (bmpSkinPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); if (bmpSkinEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); if (searchHeight>0) { RECT rSrc2=rSrc, rDst2=rDst, rMargins2=rMargins; rSrc2.top=rSrc.bottom; rSrc2.bottom+=slicesY[3]+slicesY[4]+slicesY[5]; rDst2.top=rDst.bottom; rDst2.bottom=totalHeight; rMargins2.top=slicesY[3]; rMargins2.bottom=slicesY[5]; MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); if (bmpSkinPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc2,rDst2,rMargins2,false); if (bmpSkinEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc2,rDst2,rMargins2,false); } } } else { RECT rc={0,0,totalWidth,totalHeight}; SetDCBrushColor(hdc,s_Skin.Main_background); FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); if (bHasPattern) { SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } if (bHasEmblemMask) { SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } if (m_SearchIndex>=0 && s_bWin7Style) { // draw the search background if (bmpSearch.GetBitmap()) { if (bHasPattern) { if (bmpSearchPattern.GetBitmap()) { SelectObject(hdcPMaskTemp,bmpSearchPattern.GetBitmap()); } else if (!bmpSearchPattern.bIsBitmap) { RECT rc={searchX[0],searchY[0],searchX[3],searchY[3]}; SetDCBrushColor(hdcPMask,bmpSearchPattern.GetColor()); FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } if (bHasEmblemMask) { if (bmpSearchEmblem.GetBitmap()) { SelectObject(hdcEMaskTemp,bmpSearchEmblem.GetBitmap()); } else if (!bmpSearchEmblem.bIsBitmap) { RECT rc={searchX[0],searchY[0],searchX[3],searchY[3]}; SetDCBrushColor(hdcEMask,bmpSearchEmblem.GetColor()); FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } int u[4], v[4]; u[0]=0; u[1]=searchSlicesX[0]+searchSlicesX[1]+searchSlicesX[2]; u[2]=u[1]+searchSlicesX[3]+searchSlicesX[4]+searchSlicesX[5]; u[3]=u[2]+searchSlicesX[6]+searchSlicesX[7]+searchSlicesX[8]; v[0]=0; v[1]=searchSlicesY[0]+searchSlicesY[1]+searchSlicesY[2]; v[2]=v[1]+searchSlicesY[3]+searchSlicesY[4]+searchSlicesY[5]; v[3]=v[2]+searchSlicesY[6]+searchSlicesY[7]+searchSlicesY[8]; SelectObject(hdcTemp,bmpSearch.GetBitmap()); for (int y=0;y<3;y++) { for (int x=0;x<3;x++) { RECT rDst={searchX[x],searchY[y],searchX[x+1],searchY[y+1]}; RECT rSrc={u[x],v[y],u[x+1],v[y+1]}; RECT rMargins={searchSlicesX[x*3],searchSlicesY[y*3],searchSlicesX[x*3+2],searchSlicesY[y*3+2]}; MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,bmpSearch.bIs32); if (bmpSearchPattern.GetBitmap()) MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,bmpSearchPattern.bIs32); if (bmpSearchEmblem.GetBitmap()) MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,bmpSearchPattern.bIs32); } } } else if (!bmpSearch.bIsBitmap) { RECT rDst={searchX[0],searchY[0],searchX[3],searchY[3]}; SetDCBrushColor(hdc,bmpSearch.GetColor()); FillRect(hdc,&rDst,(HBRUSH)GetStockObject(DC_BRUSH)); if (bHasPattern && !bmpSearchPattern.bIsBitmap) { SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } if (bHasEmblemMask && !bmpSearchEmblem.bIsBitmap) { SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } } if (bHasPattern) { if (PMaskBmp02) SelectObject(hdcPMaskTemp,PMaskBmp02); if (PMaskBmp0) SelectObject(hdcPMask,PMaskBmp0); if (hdcPMask) DeleteDC(hdcPMask); if (hdcPMaskTemp) DeleteDC(hdcPMaskTemp); // apply pattern BlendPatterns(PMaskBits,totalWidth,totalHeight); SelectObject(hdcTemp,PMaskBmp); AlphaBlend(hdc,0,0,totalWidth,totalHeight,hdcTemp,0,0,totalWidth,totalHeight,g_AlphaFunc); SelectObject(hdcTemp,bmp02); DeleteObject(PMaskBmp); } // draw vertical separator if (width2) { if (s_Skin.Main_separatorV.GetBitmap()) { SelectObject(hdcTemp,s_Skin.Main_separatorV.GetBitmap()); RECT rSrc2={0,0,s_Skin.Main_separatorWidth,s_Skin.Main_separator_slices_Y[0]+s_Skin.Main_separator_slices_Y[1]+s_Skin.Main_separator_slices_Y[2]}; RECT rDst2={totalWidth1,menuPadding[0].top,totalWidth1+s_Skin.Main_separatorWidth,totalHeight-menuPadding[0].bottom}; if (s_bRTL) { rDst2.left=totalWidth-rDst2.right; rDst2.right=totalWidth-totalWidth1; } RECT rMargins2={0,s_Skin.Main_separator_slices_Y[0],0,s_Skin.Main_separator_slices_Y[2]}; MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,s_Skin.Main_separatorV.bIs32); } else if (!bmpSkin.GetBitmap()) // only when there is no main bitmap (it may have a built-in separator) { rc.left=rc.right=s_bRTL?(totalWidth-totalWidth1-2):totalWidth1; rc.top=menuPadding[0].top; rc.bottom=totalHeight-menuPadding[0].bottom; DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT); } } SelectObject(hdcTemp,bmp02); for (int i=0;i<_countof(s_Skin.Main_emblems);i++) { if (s_Skin.Main_emblems[i].GetBitmap()) { const SIZE &emblemSize=s_Skin.Main_emblem_sizes[i]; const RECT &emblemPadding=s_Skin.Main_emblem_paddings[i]; MenuSkin::THAlign alignH=s_Skin.Main_emblem_alignH1[i]; if (width2==0 && (alignH==MenuSkin::HALIGN_LEFT2 || alignH==MenuSkin::HALIGN_RIGHT2 || alignH==MenuSkin::HALIGN_CENTER2)) alignH=s_Skin.Main_emblem_alignH2[i]; if (alignH==MenuSkin::HALIGN_CORNER) alignH=(m_Options&CONTAINER_LEFT)?MenuSkin::HALIGN_LEFT:MenuSkin::HALIGN_RIGHT; MenuSkin::TVAlign alignV=s_Skin.Main_emblem_alignV[i]; if (alignV==MenuSkin::VALIGN_CORNER) alignV=(m_Options&CONTAINER_TOP)?MenuSkin::VALIGN_TOP:MenuSkin::VALIGN_BOTTOM; if (alignH==MenuSkin::HALIGN_NONE || alignV==MenuSkin::VALIGN_NONE) continue; int w=emblemSize.cx+emblemPadding.left+emblemPadding.right; int h=emblemSize.cy+emblemPadding.top+emblemPadding.bottom; int x0=0, x1=totalWidth; int y0=0, y1=totalHeight; if (alignH==MenuSkin::HALIGN_CENTER1 || alignH==MenuSkin::HALIGN_LEFT1 || alignH==MenuSkin::HALIGN_RIGHT1) x1=totalWidth1; else if (alignH==MenuSkin::HALIGN_CENTER2 || alignH==MenuSkin::HALIGN_LEFT2 || alignH==MenuSkin::HALIGN_RIGHT2) x0=totalWidth1; if (alignH==MenuSkin::HALIGN_LEFT || alignH==MenuSkin::HALIGN_LEFT1 || alignH==MenuSkin::HALIGN_LEFT2) x1=x0+w; else if (alignH==MenuSkin::HALIGN_RIGHT || alignH==MenuSkin::HALIGN_RIGHT1 || alignH==MenuSkin::HALIGN_RIGHT2) x0=x1-w; else if (alignH==MenuSkin::HALIGN_CENTER || alignH==MenuSkin::HALIGN_CENTER1 || alignH==MenuSkin::HALIGN_CENTER2) x0=(x0+x1-w)/2, x1=x0+w; if (alignV==MenuSkin::VALIGN_TOP) y1=y0+h; else if (alignV==MenuSkin::VALIGN_BOTTOM) y0=y1-h; else if (alignV==MenuSkin::VALIGN_CENTER) y0=(y0+y1-h)/2, y1=y0+h; x0+=emblemPadding.left; y0+=emblemPadding.top; RECT rcEmblem={x0,y0,x0+emblemSize.cx,y0+emblemSize.cy}; if (rcEmblem.left>=totalWidth || rcEmblem.right<0 || rcEmblem.top>=totalHeight || rcEmblem.bottom<0) continue; HBITMAP maskedEmblem=NULL; if (bHasEmblemMask && i<4) maskedEmblem=CreateMaskedEmblem(s_Skin.Main_emblems[i].GetBitmap(),rcEmblem,EMaskBits,totalWidth,totalHeight,i); if (maskedEmblem) SelectObject(hdcTemp,maskedEmblem); else SelectObject(hdcTemp,s_Skin.Main_emblems[i].GetBitmap()); BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; w=rcEmblem.right-rcEmblem.left; h=rcEmblem.bottom-rcEmblem.top; AlphaBlend(hdc,rcEmblem.left,rcEmblem.top,w,h,hdcTemp,0,0,w,h,func); SelectObject(hdcTemp,bmp02); if (maskedEmblem) DeleteObject(maskedEmblem); } } if (bHasEmblemMask) { if (EMaskBmp02) SelectObject(hdcEMaskTemp,EMaskBmp02); if (EMaskBmp0) SelectObject(hdcEMask,EMaskBmp0); if (hdcEMask) DeleteDC(hdcEMask); if (hdcEMaskTemp) DeleteDC(hdcEMaskTemp); DeleteObject(EMaskBmp); } if (s_bRTL) { SelectObject(hdc,bmp0); // deselect m_Bitmap so all the GDI operations get flushed // mirror the background image for RTL windows for (int y=0;y0) { // draw the glow opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR|DTT_GLOWSIZE; opts.crText=0xFFFFFF; opts.iGlowSize=s_Skin.Caption_glow_size; DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE,&rc,&opts); SelectObject(hdcTemp,bmp02); // deselect bmpText so all the GDI operations get flushed // change the glow color int gr=(s_Skin.Caption_glow_color)&255; int gg=(s_Skin.Caption_glow_color>>8)&255; int gb=(s_Skin.Caption_glow_color>>16)&255; for (int y=0;y>24); int r1=(pixel>>16)&255; int g1=(pixel>>8)&255; int b1=(pixel)&255; r1=(r1*gr)/255; g1=(g1*gg)/255; b1=(b1*gb)/255; pixel=(a1<<24)|(r1<<16)|(g1<<8)|b1; } SelectObject(hdcTemp,bmpText); } // draw the text int offset=0; if (s_bRTL) offset=totalWidth-textHeight; if (s_Theme) { opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR; opts.crText=s_Skin.Caption_text_color; DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE,&rc,&opts); SelectObject(hdcTemp,bmp02); // rotate and copy the text onto the final bitmap. Combine the alpha channels for (int y=0;y>24); int r1=(src>>16)&255; int g1=(src>>8)&255; int b1=(src)&255; unsigned int &dst=bits[(totalHeight-1-x)*totalWidth+y+offset]; int a2=(dst>>24); int r2=(dst>>16)&255; int g2=(dst>>8)&255; int b2=(dst)&255; r2=(r2*(255-a1))/255+r1; g2=(g2*(255-a1))/255+g1; b2=(b2*(255-a1))/255+b1; a2=a1+a2-(a1*a2)/255; dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; } } else { // draw white text on black background SetTextColor(hdcTemp,0xFFFFFF); SetBkMode(hdcTemp,TRANSPARENT); DrawText(hdcTemp,caption,-1,&rc,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE); SelectObject(hdcTemp,bmp02); // rotate and copy the text onto the final bitmap // change the text color int tr=(s_Skin.Caption_text_color>>16)&255; int tg=(s_Skin.Caption_text_color>>8)&255; int tb=(s_Skin.Caption_text_color)&255; for (int y=0;y>24); int r2=(dst>>16)&255; int g2=(dst>>8)&255; int b2=(dst)&255; r2=(r2*(255-a1)+tr*a1)/255; g2=(g2*(255-a1)+tg*a1)/255; b2=(b2*(255-a1)+tb*a1)/255; a2=a1+a2-(a1*a2)/255; dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; } } DeleteObject(bmpText); SelectObject(hdcTemp,font0); } if (s_Skin.User_image_size && !s_bWin7Style) { // draw user image HBITMAP userPicture; bool bMask=(s_Skin.User_mask.bIsBitmap && s_Skin.User_mask.bIs32 && s_Skin.User_maskSize.cx==s_Skin.User_image_size && s_Skin.User_maskSize.cy==s_Skin.User_image_size); if (bMask) userPicture=LoadUserImage(s_Skin.User_image_size,s_Skin.User_mask.GetBitmap()); else userPicture=LoadUserImage(s_Skin.User_image_size,NULL); if (userPicture) { // draw user picture SIZE frameSize; if (s_Skin.User_bitmap.GetBitmap()) { BITMAP info; GetObject(s_Skin.User_bitmap.GetBitmap(),sizeof(info),&info); frameSize.cx=info.bmWidth; frameSize.cy=info.bmHeight; } else { frameSize.cx=s_Skin.User_image_size+s_Skin.User_image_offset.x*2; frameSize.cy=s_Skin.User_image_size+s_Skin.User_image_offset.y*2; } POINT pos=s_Skin.User_frame_position; if (pos.x==MenuSkin::USER_CENTER) pos.x=(totalWidth-frameSize.cx)/2; else if (pos.x==MenuSkin::USER_CENTER1) pos.x=(totalWidth1+textHeight-frameSize.cx)/2; else if (pos.x==MenuSkin::USER_CENTER2) { if (totalWidth2>0) pos.x=totalWidth1+(totalWidth2-frameSize.cx)/2; else pos.x=(totalWidth-frameSize.cx)/2; } if (pos.x<0) pos.x+=totalWidth-frameSize.cx; if (pos.y<0) pos.y+=totalHeight-frameSize.cy; if (s_bRTL) pos.x=totalWidth-frameSize.cx-pos.x; pos.x+=s_Skin.User_image_offset.x; pos.y+=s_Skin.User_image_offset.y; HGDIOBJ bmp02=SelectObject(hdcTemp,userPicture); unsigned int alpha=s_Skin.User_image_alpha; if (alpha==255 && !bMask) { BitBlt(hdc,pos.x,pos.y,s_Skin.User_image_size,s_Skin.User_image_size,hdcTemp,0,0,SRCCOPY); } else { BLENDFUNCTION func={AC_SRC_OVER,0U,bMask?255U:(BYTE)alpha,bMask?AC_SRC_ALPHA:0U}; AlphaBlend(hdc,pos.x,pos.y,s_Skin.User_image_size,s_Skin.User_image_size,hdcTemp,0,0,s_Skin.User_image_size,s_Skin.User_image_size,func); } if (s_bRTL) m_rUser1.left=totalWidth-pos.x-s_Skin.User_image_size; else m_rUser1.left=pos.x; m_rUser1.right=m_rUser1.left+s_Skin.User_image_size; m_rUser1.top=pos.y; m_rUser1.bottom=pos.y+s_Skin.User_image_size; if (opacity!=MenuSkin::OPACITY_SOLID && !bMask) { // set to opaque SelectObject(hdc,bmp0); // deselect m_Bitmap so all the GDI operations get flushed unsigned int *bits2=bits+pos.y*totalWidth+pos.x; alpha<<=24; for (int y=0;y0) { int nameWidth=rc0.right-rc0.left; int nameHeight=rc0.bottom-rc0.top; RECT rc={0,0,nameWidth,nameHeight}; // draw the title BITMAPINFO dib={sizeof(dib)}; dib.bmiHeader.biWidth=nameWidth; dib.bmiHeader.biHeight=-nameHeight; dib.bmiHeader.biPlanes=1; dib.bmiHeader.biBitCount=32; dib.bmiHeader.biCompression=BI_RGB; font0=(HFONT)SelectObject(hdcTemp,s_Skin.User_font); unsigned int *bits2; HBITMAP bmpText=CreateDIBSection(hdcTemp,&dib,DIB_RGB_COLORS,(void**)&bits2,NULL,0); HGDIOBJ bmp02=SelectObject(hdcTemp,bmpText); FillRect(hdcTemp,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); DWORD align=DT_CENTER; if (s_Skin.User_name_align==MenuSkin::HALIGN_LEFT || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT1 || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT2) align=s_bRTL?DT_RIGHT:DT_LEFT; else if (s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT1 || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT2) align=s_bRTL?DT_LEFT:DT_RIGHT; if (s_Theme && s_Skin.User_glow_size>0) { InflateRect(&rc,-s_Skin.User_glow_size,-s_Skin.User_glow_size); // draw the glow opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR|DTT_GLOWSIZE; opts.crText=0xFFFFFF; opts.iGlowSize=s_Skin.User_glow_size; DrawThemeTextEx(s_Theme,hdcTemp,0,0,name,-1,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP,&rc,&opts); SelectObject(hdcTemp,bmp02); // deselect bmpText so all the GDI operations get flushed // change the glow color int gr=(s_Skin.User_glow_color)&255; int gg=(s_Skin.User_glow_color>>8)&255; int gb=(s_Skin.User_glow_color>>16)&255; for (int y=0;y>24); int r1=(pixel>>16)&255; int g1=(pixel>>8)&255; int b1=(pixel)&255; r1=(r1*gr)/255; g1=(g1*gg)/255; b1=(b1*gb)/255; pixel=(a1<<24)|(r1<<16)|(g1<<8)|b1; } SelectObject(hdcTemp,bmpText); } // draw the text int offset=rc0.top*totalWidth+rc0.left; if (s_bRTL) offset=rc0.top*totalWidth+totalWidth-rc0.right; if (s_Theme) { opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR; opts.crText=s_Skin.User_text_color; DrawThemeTextEx(s_Theme,hdcTemp,0,0,name,-1,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP,&rc,&opts); SelectObject(hdcTemp,bmp02); // copy the text onto the final bitmap. Combine the alpha channels for (int y=0;y>24); int r1=(src>>16)&255; int g1=(src>>8)&255; int b1=(src)&255; unsigned int &dst=bits[y*totalWidth+x+offset]; int a2=(dst>>24); int r2=(dst>>16)&255; int g2=(dst>>8)&255; int b2=(dst)&255; r2=(r2*(255-a1))/255+r1; g2=(g2*(255-a1))/255+g1; b2=(b2*(255-a1))/255+b1; a2=a1+a2-(a1*a2)/255; dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; } } else { // draw white text on black background SetTextColor(hdcTemp,0xFFFFFF); SetBkMode(hdcTemp,TRANSPARENT); DrawText(hdcTemp,name,-1,&rc,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP); SelectObject(hdcTemp,bmp02); // copy the text onto the final bitmap // change the text color int tr=(s_Skin.User_text_color>>16)&255; int tg=(s_Skin.User_text_color>>8)&255; int tb=(s_Skin.User_text_color)&255; for (int y=0;y>24); int r2=(dst>>16)&255; int g2=(dst>>8)&255; int b2=(dst)&255; r2=(r2*(255-a1)+tr*a1)/255; g2=(g2*(255-a1)+tg*a1)/255; b2=(b2*(255-a1)+tb*a1)/255; a2=a1+a2-(a1*a2)/255; dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; } } DeleteObject(bmpText); SelectObject(hdcTemp,font0); } } DeleteDC(hdcTemp); SelectObject(hdc,bmp0); DeleteDC(hdc); // calculate the window region if (bCreateRegion) { if (m_Region) DeleteObject(m_Region); m_Region=NULL; if (opacity==MenuSkin::OPACITY_REGION || opacity==MenuSkin::OPACITY_GLASS || opacity==MenuSkin::OPACITY_FULLGLASS) { for (int y=0;y=0) { maxx++; HRGN r=CreateRectRgn(minx,y,maxx,y+1); AddTrackedObject(r); if (!m_Region) m_Region=r; else { CombineRgn(m_Region,m_Region,r,RGN_OR); DeleteObject(r); } } } } else if (opacity==MenuSkin::OPACITY_ALPHA || opacity==MenuSkin::OPACITY_FULLALPHA) m_Region=CreateRectRgn(0,0,totalWidth,totalHeight); } } void CMenuContainer::CreateContentRects( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight ) { const int *slicesY; RECT menuPadding[2]; if (s_MenuMode==MODE_SEARCH) { slicesY=s_Skin.Main_bitmap_search_slices_Y; menuPadding[0]=s_Skin.Main_search_padding; memset(&menuPadding[1],0,sizeof(menuPadding[1])); } else if (s_MenuMode==MODE_JUMPLIST) { slicesY=s_Skin.Main_bitmap_jump_slices_Y; menuPadding[0]=s_Skin.Main_padding; menuPadding[1]=s_Skin.Main_jump_padding; } else { slicesY=s_Skin.Main_bitmap_slices_Y; menuPadding[0]=s_Skin.Main_padding; menuPadding[1]=s_Skin.Main2_padding; } int totalWidth1=width1+menuPadding[0].left+menuPadding[0].right; int totalWidth2=width2+menuPadding[1].left+menuPadding[1].right; totalWidth=totalWidth1+totalWidth2; totalHeight=height1+menuPadding[0].top+menuPadding[0].bottom; int totalHeight2=height2+menuPadding[1].top+menuPadding[1].bottom; if (totalHeight0) { m_rContent2.left=m_rContent.right+menuPadding[0].right+menuPadding[1].left; m_rContent2.right=totalWidth-menuPadding[1].right; m_rContent2.top=menuPadding[1].top; m_rContent2.bottom=m_rContent2.top+height2; } } void CMenuContainer::CreateSubmenuRegion( int width, int height ) { int totalWidth=s_Skin.Submenu_padding.left+s_Skin.Submenu_padding.right+width; int totalHeight=s_Skin.Submenu_padding.top+s_Skin.Submenu_padding.bottom+height; if (m_Region) DeleteObject(m_Region); m_Region=NULL; if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID) return; if (!s_Skin.Submenu_bitmap.GetBitmap() || !s_Skin.Submenu_bitmap.bIs32) return; if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_ALPHA || s_Skin.Submenu_opacity==MenuSkin::OPACITY_FULLALPHA) { m_Region=CreateRectRgn(0,0,totalWidth,totalHeight-m_ExtraTop-m_ExtraBottom); return; } BITMAP info; GetObject(s_Skin.Submenu_bitmap.GetBitmap(),sizeof(info),&info); const int *slicesX=s_Skin.Submenu_bitmap_slices_X+3; const int *slicesY=s_Skin.Submenu_bitmap_slices_Y; int slicesX0=slicesX[s_bRTL?2:0]; int slicesX2=slicesX[s_bRTL?0:2]; int bmpWidth=slicesX0+slicesX[1]+slicesX2; int bmpHeight=slicesY[0]+slicesY[1]+slicesY[2]; unsigned int *bits=(unsigned int*)info.bmBits; { for (int y=m_ExtraTop;y=totalHeight-slicesY[2]) yy=bmpHeight-totalHeight+y; else yy=slicesY[0]+((y-slicesY[0])*slicesY[1])/(totalHeight-slicesY[0]-slicesY[2]); if (info.bmHeight>0) yy=info.bmHeight-yy-1; int yw=yy*info.bmWidth; int minx=-1, maxx=-1; for (int x=0;x=0) { if (minx>=bmpWidth-slicesX2) minx+=totalWidth-bmpWidth; else if (minx>slicesX0) minx=slicesX0+((minx-slicesX0)*(totalWidth-slicesX0-slicesX2))/slicesX[1]; if (maxx>=bmpWidth-slicesX2) maxx+=totalWidth-bmpWidth; else if (minx>slicesX0) maxx=slicesX0+((maxx-slicesX0)*(totalWidth-slicesX0-slicesX2))/slicesX[1]; maxx++; HRGN r=CreateRectRgn(minx,y-m_ExtraTop,maxx,y-m_ExtraTop+1); AddTrackedObject(r); if (!m_Region) m_Region=r; else { CombineRgn(m_Region,m_Region,r,RGN_OR); DeleteObject(r); } } } } } void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) { HDC hdc2=CreateCompatibleDC(hdc); // draw the background (bitmap or solid color) HBITMAP bmpMain=NULL; RECT rMarginsMain, rSrcMain; bool bAlphaMain; if (m_Bitmap) { HGDIOBJ bmp0=SelectObject(hdc2,m_Bitmap); BitBlt(hdc,m_BitmapOffset,0,m_rMenu.right,m_rMenu.bottom,hdc2,0,0,SRCCOPY); SelectObject(hdc2,bmp0); bmpMain=m_Bitmap; { RECT rc={m_rMenu.right-m_rMenu.left,m_rMenu.bottom,0,0}; rMarginsMain=rc; } { RECT rc={0,0,m_rMenu.right-m_rMenu.left,m_rMenu.bottom}; rSrcMain=rc; } bAlphaMain=false; } else if (m_bSubMenu && s_Skin.Submenu_bitmap.GetBitmap()) { bAlphaMain=(s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID && s_Skin.Submenu_bitmap.bIs32); if (bAlphaMain) { SetDCBrushColor(hdc,s_Skin.Submenu_background); FillRect(hdc,&drawRect,(HBRUSH)GetStockObject(DC_BRUSH)); } HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Submenu_bitmap.GetBitmap()); const int *slicesX=s_Skin.Submenu_bitmap_slices_X; const int *slicesY=s_Skin.Submenu_bitmap_slices_Y; RECT rSrc={0,0,slicesX[3]+slicesX[4]+slicesX[5],slicesY[0]+slicesY[1]+slicesY[2]}; RECT rMargins={slicesX[3],slicesY[0],slicesX[5],slicesY[2]}; RECT rDst=m_rMenu; rDst.top-=m_ExtraTop; rDst.bottom+=m_ExtraBottom; MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,bAlphaMain); SelectObject(hdc2,bmp0); bmpMain=s_Skin.Submenu_bitmap.GetBitmap(); rMarginsMain=rMargins; rSrcMain=rSrc; } else { SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); FillRect(hdc,&m_rMenu,(HBRUSH)GetStockObject(DC_BRUSH)); } MenuBitmap bmpSeparatorV; int sepWidth=0; const int *sepSlicesY=NULL; MenuBitmap bmpPager; const int *pagSlicesX=NULL; const int *pagSlicesY=NULL; 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; if (!s_Theme) glow=0; TRecentKeys recentType=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); if (m_bSubMenu) { bmpSeparatorV=s_Skin.Submenu_separatorV; sepWidth=s_Skin.Submenu_separatorWidth; sepSlicesY=s_Skin.Submenu_separator_slices_Y; bmpPager=s_Skin.Submenu_pager; pagSlicesX=s_Skin.Submenu_pager_slices_X; pagSlicesY=s_Skin.Submenu_pager_slices_Y; bmpPagerArrows=s_Skin.Submenu_pager_arrows; pagArrowSize=s_Skin.Submenu_pager_arrow_Size; } else { bmpSeparatorV=s_Skin.Main_separatorV; sepWidth=s_Skin.Main_separatorWidth; sepSlicesY=s_Skin.Main_separator_slices_Y; bmpPager=s_Skin.Main_pager; pagSlicesX=s_Skin.Main_pager_slices_X; pagSlicesY=s_Skin.Main_pager_slices_Y; bmpPagerArrows=s_Skin.Main_pager_arrows; pagArrowSize=s_Skin.Main_pager_arrow_Size; } 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; if (m_bScrollUp) clipTop=m_rContent.top+m_ScrollButtonSize; if (m_bScrollDown) clipBottom=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize; if (m_ScrollHeight>0) IntersectClipRect(hdc,0,clipTop,m_rMenu.right,clipBottom); // draw items for (int index=0;;index++) { if (!m_bSubMenu) { if (index==m_ProgramTreeIndex) continue; if (s_MenuMode==MODE_PROGRAMS) { if (index0 && index==m_ScrollCount) { // clean up after the scrollable items SelectClipRgn(hdc,NULL); if (m_bScrollUp) { if (glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS) { // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) RECT rc={m_rContent.left,0,m_rContent.right,clipTop}; if (bAlphaMain || !bmpMain) { SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } if (bmpMain) { HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); IntersectClipRect(hdc,m_rContent.left,0,m_rContent.right,clipTop); MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); SelectObject(hdc2,bmp0); SelectClipRgn(hdc,NULL); } } // draw up button RECT rc=m_rContent; rc.bottom=clipTop; if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) { // background HGDIOBJ bmp0=SelectObject(hdc2,bmpPager.GetBitmap()); RECT rSrc={0,0,pagSlicesX[0]+pagSlicesX[1]+pagSlicesX[2],pagSlicesY[0]+pagSlicesY[1]+pagSlicesY[2]}; if (m_bScrollUpHot) OffsetRect(&rSrc,0,rSrc.bottom); RECT rMargins={pagSlicesX[0],pagSlicesY[0],pagSlicesX[2],pagSlicesY[2]}; MarginsBlit(hdc2,hdc,rSrc,rc,rMargins,bmpPager.bIs32); // arrow SelectObject(hdc2,bmpPagerArrows.GetBitmap()); int x=(rc.left+rc.right-pagArrowSize.cx)/2; int y=(rc.top+rc.bottom-pagArrowSize.cy)/2; if (bmpPagerArrows.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollUpHot?pagArrowSize.cx:0,0,pagArrowSize.cx,pagArrowSize.cy,func); } else BitBlt(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollUpHot?pagArrowSize.cx:0,0,SRCCOPY); SelectObject(hdc2,bmp0); } else { if (s_PagerTheme) DrawThemeBackground(s_PagerTheme,hdc,SBP_ARROWBTN,(m_bScrollUpHot?ABS_UPHOT:ABS_UPHOVER),&rc,NULL); else DrawFrameControl(hdc,&rc,DFC_SCROLL,DFCS_SCROLLUP|DFCS_FLAT|(m_bScrollUpHot?DFCS_PUSHED:0)); } } if (m_bScrollDown) { 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)) { // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) RECT rc={m_rContent.left,clipBottom,m_rContent.right,bottom}; if (bAlphaMain || !bmpMain) { SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } if (bmpMain) { HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); IntersectClipRect(hdc,m_rContent.left,clipBottom,m_rContent.right,bottom); MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); SelectObject(hdc2,bmp0); SelectClipRgn(hdc,NULL); } } // draw down button RECT rc=m_rContent; rc.bottom=m_rContent.top+m_ScrollHeight; rc.top=clipBottom; if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) { // background HGDIOBJ bmp0=SelectObject(hdc2,bmpPager.GetBitmap()); RECT rSrc={0,0,pagSlicesX[0]+pagSlicesX[1]+pagSlicesX[2],pagSlicesY[0]+pagSlicesY[1]+pagSlicesY[2]}; if (m_bScrollDownHot) OffsetRect(&rSrc,0,rSrc.bottom); RECT rMargins={pagSlicesX[0],pagSlicesY[0],pagSlicesX[2],pagSlicesY[2]}; MarginsBlit(hdc2,hdc,rSrc,rc,rMargins,bmpPager.bIs32); // arrow SelectObject(hdc2,bmpPagerArrows.GetBitmap()); int x=(rc.left+rc.right-pagArrowSize.cx)/2; int y=(rc.top+rc.bottom-pagArrowSize.cy)/2; if (bmpPagerArrows.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollDownHot?pagArrowSize.cx:0,pagArrowSize.cy,pagArrowSize.cx,pagArrowSize.cy,func); } else BitBlt(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollDownHot?pagArrowSize.cx:0,pagArrowSize.cy,SRCCOPY); SelectObject(hdc2,bmp0); } else { if (s_PagerTheme) DrawThemeBackground(s_PagerTheme,hdc,SBP_ARROWBTN,(m_bScrollDownHot?ABS_DOWNHOT:ABS_DOWNHOVER),&rc,NULL); else DrawFrameControl(hdc,&rc,DFC_SCROLL,DFCS_SCROLLDOWN|DFCS_FLAT|(m_bScrollDownHot?DFCS_PUSHED:0)); } } } if (index>=(int)m_Items.size()) break; const MenuItem &item=m_Items[index]; RECT itemRect=item.itemRect; // ignore offscreen items if (m_ScrollHeight>0 && index=clipBottom) continue; } else if (m_SearchScrollCount>m_SearchScrollHeight && index>=m_OriginalCount) { if (index-m_OriginalCount=m_SearchScrollPos+m_SearchScrollHeight) continue; OffsetRect(&itemRect,0,-m_SearchScrollPos*(itemRect.bottom-itemRect.top)); } { RECT q; if (!IntersectRect(&q,&drawRect,&itemRect)) continue; } bool bHot=(index==m_HotItem || index==m_SubJumpItem || (m_HotItem==-1 && (index==m_Submenu || index==m_ContextItem))); bool bSplit=false; int stateLeft=0, stateRight=0; bool bNew=!bHot && item.bNew && !(s_bWin7Style && item.id==MENU_PROGRAMS && s_MenuMode==MODE_PROGRAMS); MenuSkin::TItemDrawType drawType=item.drawType; if (!bNew) { if (drawType==MenuSkin::COLUMN1_NEW) drawType=MenuSkin::COLUMN1_ITEM; else if (drawType==MenuSkin::COLUMN2_NEW) drawType=MenuSkin::COLUMN2_ITEM; else if (drawType==MenuSkin::PROGRAMS_BUTTON_NEW) drawType=MenuSkin::PROGRAMS_BUTTON; else if (drawType==MenuSkin::PROGRAMS_CASCADING_NEW) drawType=MenuSkin::PROGRAMS_CASCADING; else if (drawType==MenuSkin::SUBMENU_NEW) drawType=MenuSkin::SUBMENU_ITEM; if (!bHot && index==m_DropTargetIndex) { if (drawType==MenuSkin::COLUMN1_SPLIT) drawType=MenuSkin::COLUMN1_ITEM; if (drawType==MenuSkin::COLUMN2_SPLIT) drawType=MenuSkin::COLUMN2_ITEM; } } if (item.id==MENU_SEARCH_BOX) { itemRect.left=itemRect.right-(itemRect.bottom-itemRect.top); bHot=(index==m_HotItem && m_SearchState>=SEARCH_TEXT); } if (item.id==MENU_PROGRAMS_TREE) bHot=false; int splitX=itemRect.right; const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[drawType]; int glowSize=s_Theme?settings.glowSize:0; if (bHot || bNew || item.id==MENU_SHUTDOWN_BUTTON || index==m_DropTargetIndex) { if (bHot || item.id==MENU_SHUTDOWN_BUTTON) { bSplit=(item.bSplit && (item.bFolder || item.jumpIndex>=0 || item.id==MENU_SEARCH_CATEGORY || item.id==MENU_SHUTDOWN_BUTTON)); if (item.id==MENU_SHUTDOWN_BUTTON) { if (GetCapture()==m_hWnd) { if (index==m_ClickIndex && !m_bClickArrow && index==m_HotItem && !m_bHotArrow) stateLeft=2; else if (index==m_ClickIndex || index==m_Submenu || index==m_SubJumpItem) stateLeft=1; } else if (index==m_HotItem || index==m_Submenu || index==m_SubJumpItem) stateLeft=1; if (index==m_Submenu || index==m_SubJumpItem) stateRight=2; else if (GetCapture()==m_hWnd) { if (index==m_ClickIndex && m_bClickArrow && index==m_HotItem && m_bHotArrow) stateRight=2; } else if (index==m_HotItem) stateRight=1; } else { if ((index==m_HotItem && !m_bHotArrow) || index==m_ContextItem) stateLeft=1; if ((index==m_HotItem && m_bHotArrow) || index==m_Submenu || index==m_SubJumpItem || index==m_ContextItem) stateRight=1; } splitX=itemRect.right-settings.arrPadding.cx-settings.arrPadding.cy-1; if (item.jumpIndex>=0) splitX-=s_Skin.Pin_bitmap_Size.cx; else if (item.id==MENU_SEARCH_CATEGORY) splitX-=s_Skin.More_bitmap_Size.cx; else splitX-=settings.arrSize.cx; } // draw selection background if (bSplit && settings.bmpSelection.GetBitmap()) { int srcHeight=settings.selSlicesY[0]+settings.selSlicesY[1]+settings.selSlicesY[2]; HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpSelection.GetBitmap()); { // draw left half RECT rSrc={0,0,settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],srcHeight}; OffsetRect(&rSrc,0,srcHeight*stateLeft); RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; RECT itemRect2=itemRect; itemRect2.right=splitX; int w=itemRect2.right-itemRect2.left; int h=itemRect2.bottom-itemRect2.top; if (rMargins.left>w) rMargins.left=w; if (rMargins.right>w) rMargins.right=w; if (rMargins.top>h) rMargins.top=h; if (rMargins.bottom>h) rMargins.bottom=h; MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); } { // draw right half RECT rSrc={settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],0,0,srcHeight}; OffsetRect(&rSrc,0,srcHeight*stateRight); rSrc.right=rSrc.left+settings.selSlicesX[3]+settings.selSlicesX[4]+settings.selSlicesX[5]; RECT rMargins={settings.selSlicesX[3],settings.selSlicesY[0],settings.selSlicesX[5],settings.selSlicesY[2]}; RECT itemRect2=itemRect; itemRect2.left=splitX; int w=itemRect2.right-itemRect2.left; int h=itemRect2.bottom-itemRect2.top; if (rMargins.left>w) rMargins.left=w; if (rMargins.right>w) rMargins.right=w; if (rMargins.top>h) rMargins.top=h; if (rMargins.bottom>h) rMargins.bottom=h; MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); } SelectObject(hdc2,bmp0); } else if (settings.bmpSelection.GetBitmap()) { HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpSelection.GetBitmap()); RECT rSrc={0,0,settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],settings.selSlicesY[0]+settings.selSlicesY[1]+settings.selSlicesY[2]}; { RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; RECT itemRect2=itemRect; if (bSplit) itemRect2.right=splitX; int w=itemRect2.right-itemRect2.left; int h=itemRect2.bottom-itemRect2.top; if (rMargins.left>w) rMargins.left=w; if (rMargins.right>w) rMargins.right=w; if (rMargins.top>h) rMargins.top=h; if (rMargins.bottom>h) rMargins.bottom=h; MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); } if (bSplit) { RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; RECT itemRect2=itemRect; itemRect2.left=splitX; int w=itemRect2.right-itemRect2.left; int h=itemRect2.bottom-itemRect2.top; if (rMargins.left>w) rMargins.left=w; if (rMargins.right>w) rMargins.right=w; if (rMargins.top>h) rMargins.top=h; if (rMargins.bottom>h) rMargins.bottom=h; MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); } SelectObject(hdc2,bmp0); } else if (item.id==MENU_SHUTDOWN_BUTTON) { RECT itemRect2=itemRect; itemRect2.right=splitX; DrawEdge(hdc,&itemRect2,stateLeft==2?BDR_SUNKENOUTER:BDR_RAISEDINNER,BF_RECT|BF_MIDDLE); if (bHot && m_Submenu==-1 && s_bKeyboardCues) { RECT focus=itemRect2; if (s_Skin.Dpi>=144) InflateRect(&focus,-3,-3); else InflateRect(&focus,-2,-2); SetBkColor(hdc,0); SetTextColor(hdc,0xFFFFFF); DrawFocusRect(hdc,&focus); } itemRect2.left=itemRect2.right; itemRect2.right=itemRect.right; DrawEdge(hdc,&itemRect2,stateRight==2?BDR_SUNKENOUTER:BDR_RAISEDINNER,BF_RECT|BF_MIDDLE); } else { SetDCBrushColor(hdc,settings.bmpSelection.GetColor()); SetDCPenColor(hdc,settings.bmpSelection.GetColor()); if (bSplit) { if (stateLeft>0) { RECT itemRect2=itemRect; itemRect2.right=splitX; FillRect(hdc,&itemRect2,(HBRUSH)GetStockObject(DC_BRUSH)); } else { SelectObject(hdc,GetStockObject(DC_PEN)); SelectObject(hdc,GetStockObject(NULL_BRUSH)); Rectangle(hdc,itemRect.left,itemRect.top,splitX+1,itemRect.bottom); } if (stateRight>0) { RECT itemRect2=itemRect; itemRect2.left=splitX+1; FillRect(hdc,&itemRect2,(HBRUSH)GetStockObject(DC_BRUSH)); } else { SelectObject(hdc,GetStockObject(DC_PEN)); SelectObject(hdc,GetStockObject(NULL_BRUSH)); Rectangle(hdc,splitX-1,itemRect.top,itemRect.right,itemRect.bottom); } } else { FillRect(hdc,&itemRect,(HBRUSH)GetStockObject(DC_BRUSH)); } } } if (item.id==MENU_SEPARATOR || item.id==MENU_SEARCH_CATEGORY) { // draw separator if (!item.bBlankSeparator && itemRect.bottom>itemRect.top) { RECT itemRect2=itemRect; if (item.id==MENU_SEARCH_CATEGORY) { itemRect2.left+=settings.iconPadding.left; if (item.bSplit) itemRect2.right=splitX; if (s_Skin.Search_arrow.GetBitmap()) { int x=itemRect2.left; int y=(itemRect2.top+itemRect2.bottom-s_Skin.Search_arrow_size.cy)/2; int v=(m_SearchCategoryHash==item.categoryHash?s_Skin.Search_arrow_size.cy:0); HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Search_arrow.GetBitmap()); if (s_Skin.Search_arrow.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,hdc2,0,v,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,func); } else BitBlt(hdc,x,y,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,hdc2,0,v,SRCCOPY); SelectObject(hdc2,bmp0); itemRect2.left+=settings.iconPadding.right+s_Skin.Search_arrow_size.cx; } else { const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); int x=itemRect2.left; int y=(itemRect2.top+itemRect2.bottom-sizes[6].y)/2; HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[((bHot && (!bSplit || stateLeft>0))?1:0)])); BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; if (m_SearchCategoryHash==item.categoryHash) { SIZE s={sizes[5].y-sizes[5].x,sizes[6].y}; AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[5].y:sizes[5].x,0,s.cx,s.cy,func); } else { SIZE s={sizes[3].y-sizes[3].x,sizes[6].y}; int dx=(sizes[5].y-sizes[5].x-s.cx+1)/2; AlphaBlend(hdc,x+dx,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); } SelectObject(hdc2,bmp0); itemRect2.left+=settings.iconPadding.right+sizes[5].y-sizes[5].x+1; } } if (!item.name.IsEmpty()) { if (item.id==MENU_SEARCH_CATEGORY && !item.bSplit && item.categoryHash>=CSearchManager::CATEGORY_FILE && index==m_HotItem && m_bHotArrow) SelectObject(hdc,s_Skin.Search_underline_font); else SelectObject(hdc,settings.font); COLORREF color=settings.textColors[(bHot && (!bSplit || stateLeft>0))?1:0]; COLORREF shadowColor=settings.textShadowColors[(bHot && (!bSplit || stateLeft>0))?1:0]; RECT rc={itemRect2.left+settings.textPadding.left,itemRect2.top+settings.textTopOffset+settings.textPadding.top-settings.textPadding.bottom, itemRect2.right-settings.arrSize.cx-settings.arrPadding.cx-settings.arrPadding.cy-settings.textPadding.right,itemRect2.bottom-settings.textTopOffset}; DWORD flags=DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOPREFIX; if (s_Theme) { DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; if (glowSize || settings.opacity==MenuSkin::OPACITY_FULLALPHA || settings.opacity==MenuSkin::OPACITY_FULLGLASS) opts.dwFlags|=DTT_COMPOSITED; if (glowSize) { opts.dwFlags|=DTT_GLOWSIZE; opts.iGlowSize=glowSize; } if (shadowColor!=0xFFFFFFFF) { opts.crText=shadowColor; RECT rc2=rc; OffsetRect(&rc2,1,1); DrawThemeTextEx(s_Theme,hdc,0,0,item.name,item.name.GetLength(),flags,&rc2,&opts); } opts.crText=color; DrawThemeTextEx(s_Theme,hdc,0,0,item.name,item.name.GetLength(),flags,&rc,&opts); } else { if (shadowColor!=0xFFFFFFFF) { RECT rc2=rc; OffsetRect(&rc2,1,1); SetTextColor(hdc,shadowColor); DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); } SetTextColor(hdc,color); DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); } SIZE size; GetTextExtentPoint32(hdc,item.name,item.name.GetLength(),&size); itemRect2.left=rc.left+size.cx+settings.textPadding.right; } if (itemRect2.left=30) { iconSize=20; iconY=16; if (s_bRTL) icon--; } HGDIOBJ bmp0=SelectObject(hdc2,searchIcons.GetBitmap()); RECT rSrc={0,0,iconSize,iconSize}; RECT rDst=rSrc; OffsetRect(&rSrc,iconSize*icon,iconY); OffsetRect(&rDst,(itemRect.right+itemRect.left-iconSize)/2,(itemRect.bottom+itemRect.top-iconSize)/2); RECT rMargins={0,0,0,0}; MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,searchIcons.bIs32); SelectObject(hdc2,bmp0); continue; } bool bNoIcon=!item.bInline && settings.iconSize==MenuSkin::ICON_SIZE_NONE; SIZE iconSize; if (settings.iconSize==MenuSkin::ICON_SIZE_SMALL) iconSize.cx=iconSize.cy=g_ItemManager.SMALL_ICON_SIZE; else if (settings.iconSize==MenuSkin::ICON_SIZE_LARGE) iconSize.cx=iconSize.cy=g_ItemManager.LARGE_ICON_SIZE; else if (settings.iconSize==MenuSkin::ICON_SIZE_PROGRAMS) { if (s_Skin.Programs_icon.GetBitmap()) iconSize=s_Skin.Programs_icon_size; else { iconSize.cx=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].iconSize==MenuSkin::ICON_SIZE_SMALL?g_ItemManager.SMALL_ICON_SIZE:g_ItemManager.LARGE_ICON_SIZE; iconSize.cy=7; } } else iconSize.cx=iconSize.cy=0; COLORREF color, shadowColor; { bool bHotColor = (bHot && !bSplit) || stateLeft > 0; if (item.id == MENU_EMPTY || item.id == MENU_EMPTY_TOP) { color = settings.textColors[bHotColor ? 3 : 2]; shadowColor = settings.textShadowColors[bHotColor ? 3 : 2]; } else { color = settings.textColors[bHotColor ? 1 : 0]; shadowColor = settings.textShadowColors[bHotColor ? 1 : 0]; } } // draw icon if (drawType==MenuSkin::PROGRAMS_BUTTON || drawType==MenuSkin::PROGRAMS_BUTTON_NEW) { if (s_Skin.Programs_icon.GetBitmap()) { int iconX=itemRect.left+settings.iconPadding.left; int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; const MenuBitmap &icon=bHot?s_Skin.Programs_icon_selected:s_Skin.Programs_icon; HGDIOBJ bmp0=SelectObject(hdc2,icon.GetBitmap()); if (icon.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,iconX,iconY,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,hdc2,0,s_MenuMode==MODE_PROGRAMS?s_Skin.Programs_icon_size.cy:0,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,func); } else BitBlt(hdc,iconX,iconY,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,hdc2,0,s_MenuMode==MODE_PROGRAMS?s_Skin.Programs_icon_size.cy:0,SRCCOPY); SelectObject(hdc2,bmp0); } else { const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); SIZE s={sizes[4].y-sizes[4].x,sizes[6].y}; int x=itemRect.left+settings.arrPadding.cx; int y=(itemRect.top+itemRect.bottom-s.cy)/2; HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[bHot?1:0])); BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; if (s_MenuMode==MODE_PROGRAMS) { AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[3].y:sizes[4].x,0,s.cx,s.cy,func); } else { AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); } SelectObject(hdc2,bmp0); } } else if (item.pItemInfo && !bNoIcon) { int iconX=itemRect.left+settings.iconPadding.left; int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; if (settings.bmpIconFrame.GetBitmap()) { HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpIconFrame.GetBitmap()); RECT rSrc={0,0,settings.frameSlicesX[0]+settings.frameSlicesX[1]+settings.frameSlicesX[2],settings.frameSlicesY[0]+settings.frameSlicesY[1]+settings.frameSlicesY[2]}; if (bHot) OffsetRect(&rSrc,rSrc.right,0); RECT rDst={iconX,iconY,iconX+iconSize.cx,iconY+iconSize.cy}; InflateRect(&rDst,settings.iconFrameOffset.x,settings.iconFrameOffset.y); RECT rMargins={settings.frameSlicesX[0],settings.frameSlicesY[0],settings.frameSlicesX[2],settings.frameSlicesY[2]}; MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,settings.bmpIconFrame.bIs32); SelectObject(hdc2,bmp0); } const CItemManager::IconInfo *pIcon=(settings.iconSize==MenuSkin::ICON_SIZE_LARGE)?item.pItemInfo->largeIcon:item.pItemInfo->smallIcon; if (pIcon && pIcon->bitmap) { HBITMAP temp = ColorizeMonochromeImage(pIcon->bitmap, color); HBITMAP bitmap = temp ? temp : pIcon->bitmap; BITMAP info; GetObject(bitmap,sizeof(info),&info); HGDIOBJ bmp0=SelectObject(hdc2,bitmap); if (bmp0) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,iconX,iconY,iconSize.cx,iconSize.cy,hdc2,0,0,info.bmWidth,info.bmHeight,func); SelectObject(hdc2,bmp0); } if (temp) DeleteObject(temp); } } else if (item.id==MENU_SHUTDOWN_BUTTON && s_bHasUpdates && s_Skin.Shutdown_bitmap.GetBitmap()) { int iconX=itemRect.left+settings.iconPadding.left; int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; if (stateLeft==2 && !settings.bmpSelection.GetBitmap()) iconX++, iconY++; HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Shutdown_bitmap.GetBitmap()); if (s_Skin.Shutdown_bitmap.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,iconX,iconY,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,hdc2,0,0,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,func); } else BitBlt(hdc,iconX,iconY,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,hdc2,0,0,SRCCOPY); SelectObject(hdc2,bmp0); } // draw text SelectObject(hdc,settings.font); RECT rc={itemRect.left+settings.iconPadding.left+settings.iconPadding.right+settings.textPadding.left,itemRect.top+settings.textPadding.top, itemRect.right-settings.arrPadding.cx-settings.arrPadding.cy-settings.textPadding.right,itemRect.bottom-settings.textPadding.bottom}; if (item.id==MENU_SHUTDOWN_BUTTON) { if (s_bHasUpdates && s_Skin.Shutdown_bitmap.GetBitmap()) rc.left+=s_Skin.Shutdown_bitmap_Size.cx-settings.iconPadding.left-settings.iconPadding.right; if (stateLeft==2 && !settings.bmpSelection.GetBitmap()) OffsetRect(&rc,1,1); } if (s_MenuMode==MODE_SEARCH && !m_bSubMenu && item.id==MENU_NO && index>=m_OriginalCount) rc.right+=settings.arrPadding.cx+settings.arrPadding.cy; else rc.right-=(item.jumpIndex>=0)?s_Skin.Pin_bitmap_Size.cx:settings.arrSize.cx; if (!bNoIcon) rc.left+=iconSize.cx; DWORD flags=DT_END_ELLIPSIS; if (item.id==MENU_NO || (item.id==MENU_RECENT && recentType!=RECENT_KEYS_DIGITS)) flags|=DT_NOPREFIX; else if (!s_bKeyboardCues) flags|=DT_HIDEPREFIX; CString name; if (drawType==MenuSkin::PROGRAMS_BUTTON || drawType==MenuSkin::PROGRAMS_BUTTON_NEW || drawType==MenuSkin::PROGRAMS_CASCADING || drawType==MenuSkin::PROGRAMS_CASCADING_NEW) name=s_MenuMode==MODE_PROGRAMS?FindTranslation(L"Menu.Back",L"Back"):FindTranslation(L"Menu.AllPrograms",L"All Programs"); else name=item.name; if (settings.textMetrics.tmHeight*2<=rc.bottom-rc.top) { // if the height can fit two lines, see if we can make use of them RECT rc2={0,0,rc.right-rc.left,0}; DrawText(hdc,name,name.GetLength(),&rc2,flags|DT_WORDBREAK|DT_CALCRECT); if (2*rc2.bottom>settings.textMetrics.tmHeight*3) { flags|=DT_EDITCONTROL|DT_WORDBREAK; int d=rc.bottom-rc.top-settings.textMetrics.tmHeight*2; rc.top+=d/2; } } if (!(flags&DT_WORDBREAK)) flags|=DT_VCENTER|DT_SINGLELINE; if (s_Theme) { DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; if (glowSize || settings.opacity==MenuSkin::OPACITY_FULLALPHA || settings.opacity==MenuSkin::OPACITY_FULLGLASS) opts.dwFlags|=DTT_COMPOSITED; if (glowSize) { opts.dwFlags|=DTT_GLOWSIZE; opts.iGlowSize=glowSize; } if (shadowColor!=0xFFFFFFFF) { opts.crText=shadowColor; RECT rc2=rc; OffsetRect(&rc2,1,1); DrawThemeTextEx(s_Theme,hdc,0,0,name,name.GetLength(),flags,&rc2,&opts); } opts.crText=color; DrawThemeTextEx(s_Theme,hdc,0,0,name,name.GetLength(),flags,&rc,&opts); } else { if (shadowColor!=0xFFFFFFFF) { RECT rc2=rc; OffsetRect(&rc2,1,1); SetTextColor(hdc,shadowColor); DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); } SetTextColor(hdc,color); DrawText(hdc,name,name.GetLength(),&rc,flags); } if (item.bFolder && drawType!=MenuSkin::PROGRAMS_BUTTON && drawType!=MenuSkin::PROGRAMS_BUTTON_NEW) { // draw the sub-menu arrows bool bHotArrow=(bHot && !bSplit) || stateRight>0; if (settings.bmpArrow.GetBitmap()) { int x=itemRect.right-settings.arrPadding.cy-settings.arrSize.cx; int y=(itemRect.top+itemRect.bottom-settings.arrSize.cy)/2; if (stateRight==2 && !settings.bmpSelection.GetBitmap()) x++, y++; HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpArrow.GetBitmap()); if (settings.bmpArrow.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,settings.arrSize.cx,settings.arrSize.cy,hdc2,0,bHotArrow?settings.arrSize.cy:0,settings.arrSize.cx,settings.arrSize.cy,func); } else { BitBlt(hdc,x,y,settings.arrSize.cx,settings.arrSize.cy,hdc2,0,bHotArrow?settings.arrSize.cy:0,SRCCOPY); } SelectObject(hdc2,bmp0); } else { const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); SIZE s={sizes[3].y-sizes[3].x,sizes[6].y}; int x=itemRect.right-settings.arrPadding.cy-s.cx; int y=(itemRect.top+itemRect.bottom-s.cy)/2; if (stateRight==2 && !settings.bmpSelection.GetBitmap()) x++, y++; HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[bHotArrow?1:0])); BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); SelectObject(hdc2,bmp0); } } else if (bHot && item.bSplit && item.jumpIndex>=0) { int x=itemRect.right-settings.arrPadding.cy-s_Skin.Pin_bitmap_Size.cx; int y=(itemRect.top+itemRect.bottom-s_Skin.Pin_bitmap_Size.cy)/2; HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Pin_bitmap.GetBitmap()); bool bPinned=s_JumpList.groups[LOWORD(item.jumpIndex)].type==CJumpGroup::TYPE_PINNED; if (s_Skin.Pin_bitmap.bIs32) { BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,hdc2,bPinned?s_Skin.Pin_bitmap_Size.cx:0,stateRight==0?s_Skin.Pin_bitmap_Size.cy:0,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,func); } else { BitBlt(hdc,x,y,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,hdc2,bPinned?s_Skin.Pin_bitmap_Size.cx:0,stateRight==0?s_Skin.Pin_bitmap_Size.cy:0,SRCCOPY); } SelectObject(hdc2,bmp0); } } // draw vertical separators if (m_bSubMenu && m_ColumnOffsets.size()>1) { 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>24; a=remapAlpha[a]; pixel=(a<<24)|(pixel&0xFFFFFF); } } SelectObject(hdcPaint,bmp); DeleteObject(bmp0); } if (m_SearchBox.m_hWnd && ((uMsg==WM_PRINTCLIENT && (lParam&PRF_CHILDREN)) || (uMsg==WM_PAINT && !m_bSearchDrawn))) { RECT rc; GetWindowRect(&rc); m_SearchBox.GetWindowRect(&rc); ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); // print the editbox to a new bitmap, and then blit to hdcPaint. printing directly into hdcPaint doesn't quite work with RTL HDC hdcSearch=CreateCompatibleDC(hdcPaint); HBITMAP bmpSearch=CreateCompatibleBitmap(hdcPaint,rc.right-rc.left,rc.bottom-rc.top); HGDIOBJ bmp0=SelectObject(hdcSearch,bmpSearch); if (s_bRTL) SetLayout(hdcSearch,0); m_SearchBox.SendMessage(WM_PRINTCLIENT,(WPARAM)hdcSearch,PRF_CLIENT); if (s_bRTL) SetLayout(hdcSearch,LAYOUT_RTL); BitBlt(hdcPaint,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hdcSearch,0,0,SRCCOPY); BufferedPaintSetAlpha(hBufferedPaint,&rc,255); SelectObject(hdcSearch,bmp0); DeleteDC(hdcSearch); DeleteObject(bmpSearch); } if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) { bool bDrawTree=(uMsg==WM_PAINT && (m_PaintOffset.x!=0 || m_PaintOffset.y!=0)) || (uMsg==WM_PRINTCLIENT && (lParam&PRF_CHILDREN)); if (bDrawTree) { RECT rc; m_pProgramsTree->GetWindowRect(&rc); ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); SetViewportOrgEx(hdcPaint,rc.left,rc.top,NULL); m_pProgramsTree->GetClientRect(&rc); m_pProgramsTree->DrawTree(hdcPaint,rc); m_pProgramsTree->Print(hdcPaint,PRF_NONCLIENT); SetViewportOrgEx(hdcPaint,0,0,NULL); } } if (opacity==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT && m_bSubMenu && s_Skin.Submenu_bitmap.bIsBitmap && !s_Skin.Submenu_bitmap.bIs32) { // if the bitmap is 24-bit, the alpha channel may be undefined BufferedPaintSetAlpha(hBufferedPaint,&ps.rcPaint,255); } else { if (s_OldMenuState.mode==MODE_UNKNOWN) { if (opacity==MenuSkin::OPACITY_GLASS || opacity==MenuSkin::OPACITY_ALPHA || (opacity==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT)) { RECT rc; IntersectRect(&rc,&ps.rcPaint,&m_rContent); BufferedPaintSetAlpha(hBufferedPaint,&rc,255); } if (m_bTwoColumns && (opacity2==MenuSkin::OPACITY_GLASS || opacity2==MenuSkin::OPACITY_ALPHA || (opacity2==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT))) { RECT rc; IntersectRect(&rc,&ps.rcPaint,&m_rContent2); BufferedPaintSetAlpha(hBufferedPaint,&rc,255); } } if (m_SearchIndex>=0 && s_bWin7Style && ((s_Skin.Search_background_jump.GetBitmap() && !s_Skin.Search_background_jump.bIs32) || !s_Skin.Search_background_jump.bIsBitmap)) { RECT padding; if (s_MenuMode==MODE_SEARCH) padding=s_Skin.Search_background_search_padding; else if (s_MenuMode==MODE_JUMPLIST) padding=s_Skin.Search_background_jump_padding; else padding=s_Skin.Search_background_padding; RECT rcSearch; rcSearch.left=m_rContent.right-padding.left; rcSearch.right=m_rContent2.left+padding.right; rcSearch.top=m_Items[m_SearchIndex].itemRect.top-s_Skin.Search_padding.top-padding.top; rcSearch.bottom=m_rContent.bottom+padding.bottom; RECT rc; IntersectRect(&rc,&ps.rcPaint,&rcSearch); BufferedPaintSetAlpha(hBufferedPaint,&rc,255); } } EndBufferedPaint(hBufferedPaint,TRUE); } if (uMsg!=WM_PRINTCLIENT) EndPaint(&ps); return 0; } static void FillSolidGlassRect( HDC hdc, LPCRECT pRect, COLORREF color ) { BP_PAINTPARAMS paintParams={sizeof(paintParams)}; paintParams.dwFlags=0; HDC hdcPaint=NULL; HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,pRect,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); if (hdcPaint) { SetDCBrushColor(hdcPaint,color); FillRect(hdcPaint,pRect,(HBRUSH)GetStockObject(DC_BRUSH)); BufferedPaintSetAlpha(hBufferedPaint,pRect,255); EndBufferedPaint(hBufferedPaint,TRUE); } } void CProgramsTree::DrawTree( HDC hdc, const RECT &drawRect ) { RECT rcClient; GetClientRect(&rcClient); { RECT rc; TreeView_GetItemRect(m_hWnd,TreeView_GetRoot(m_hWnd),&rc,TRUE); m_MinX=rc.left-m_RootX; // detect when the tree auto-scrolls // find the widest of the visible elements m_MaxX=rcClient.right; int maxy=rcClient.bottom; for (HTREEITEM hItem=TreeView_GetFirstVisible(m_hWnd);hItem;hItem=TreeView_GetNextVisible(m_hWnd,hItem)) { TreeView_GetItemRect(m_hWnd,hItem,&rc,TRUE); if (m_MaxX=maxy) break; } } BP_PAINTPARAMS paintParams={sizeof(paintParams)}; HDC hdcPaint=NULL; HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,&drawRect,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); if (hdcPaint) { HDC hsrc=CreateCompatibleDC(hdcPaint); const MenuSkin &skin=CMenuContainer::s_Skin; int alpha; if (skin.Programs_background==0) { RECT bmpRect=drawRect; ::MapWindowPoints(m_hWnd,m_pOwner->m_hWnd,(POINT*)&bmpRect,2); HGDIOBJ bmp0=SelectObject(hsrc,m_pOwner->m_Bitmap); BitBlt(hdcPaint,drawRect.left,drawRect.top,drawRect.right-drawRect.left,drawRect.bottom-drawRect.top,hsrc,bmpRect.left,bmpRect.top,SRCCOPY); SelectObject(hsrc,bmp0); alpha=(skin.Main_opacity==MenuSkin::OPACITY_ALPHA || skin.Main_opacity==MenuSkin::OPACITY_GLASS)?255:0; } else { SetDCBrushColor(hdcPaint,skin.Programs_background&0xFFFFFF); FillRect(hdcPaint,&drawRect,(HBRUSH)GetStockObject(DC_BRUSH)); alpha=skin.Programs_background>>24; if (alpha<255) { if (skin.Main_FakeGlass) alpha=(unsigned char)(255*pow(alpha/255.f,0.2f)); BufferedPaintSetAlpha(hBufferedPaint,&drawRect,alpha); } } SelectObject(hdcPaint,GetFont()); HTREEITEM hSelection=TreeView_GetSelection(m_hWnd); HTREEITEM hHilight=TreeView_GetDropHilight(m_hWnd); HWND focus=GetFocus(); for (HTREEITEM hItem=TreeView_GetFirstVisible(m_hWnd);hItem;hItem=TreeView_GetNextVisible(m_hWnd,hItem)) { RECT itemRect; TreeView_GetItemRect(m_hWnd,hItem,&itemRect,TRUE); if (itemRect.top>=drawRect.bottom) break; bool bHot=((hItem==hSelection && m_DropLocation==DROP_NOWHERE) || hItem==hHilight) && (m_pOwner->m_HotItem==m_pOwner->m_ProgramTreeIndex || focus==m_hWnd); if (itemRect.bottom>drawRect.top) DrawTreeItem(hdcPaint,hsrc,hItem,itemRect,bHot); } RECT rc; if (GetInsertRect(rc)) { const POINT *sizes=skin.GetArrowsBitmapSizes(); HGDIOBJ bmp0=SelectObject(hsrc,CMenuContainer::GetArrowsBitmap(CMenuContainer::s_Skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].textColors[0])); RECT rSrc={CMenuContainer::s_bRTL?sizes[6].x-sizes[2].y:sizes[0].x,0,CMenuContainer::s_bRTL?sizes[6].x-sizes[0].x:sizes[2].y,sizes[1].y}; RECT rMargins={sizes[0].y-sizes[0].x,0,sizes[2].y-sizes[2].x,0}; MarginsBlit(hsrc,hdcPaint,rSrc,rc,rMargins,true); SelectObject(hsrc,bmp0); } DeleteDC(hsrc); if (alpha==255) BufferedPaintSetAlpha(hBufferedPaint,&drawRect,alpha); EndBufferedPaint(hBufferedPaint,TRUE); } } void CProgramsTree::DrawTreeItem( HDC hdc, HDC hsrc, HTREEITEM hItem, const RECT &itemRect, bool bHot ) const { TVITEM item={TVIF_PARAM|TVIF_STATE,hItem,0,TVIS_SELECTED}; TreeView_GetItem(m_hWnd,&item); const MenuSkin &skin=CMenuContainer::s_Skin; const CTreeItem *pItem=(CTreeItem*)item.lParam; COLORREF textColor; COLORREF shadowColor; MenuBitmap bmp; const int *slicesX, *slicesY; RECT iconPadding; int iconTopOffset, textTopOffset; int glowSize; if (bHot) { // selected const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM]; bmp=settings.bmpSelection; slicesX=settings.selSlicesX; slicesY=settings.selSlicesY; iconPadding=settings.iconPadding; iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; textTopOffset=settings.textTopOffset+settings.textPadding.top; textColor=settings.textColors[pItem->bEmpty?3:1]; shadowColor=settings.textShadowColors[bHot?1:0]; glowSize=settings.glowSize; } else if (pItem->bNew) { // highlighted const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_NEW]; bmp=settings.bmpSelection; slicesX=settings.selSlicesX; slicesY=settings.selSlicesY; iconPadding=settings.iconPadding; iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; textTopOffset=settings.textTopOffset+settings.textPadding.top; textColor=settings.textColors[pItem->bEmpty?2:0]; shadowColor=settings.textShadowColors[bHot?1:0]; glowSize=settings.glowSize; } else { // not selected bmp=skin.Programs_background; const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM]; iconPadding=settings.iconPadding; iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; textTopOffset=settings.textTopOffset+settings.textPadding.top; textColor=settings.textColors[pItem->bEmpty?2:0]; shadowColor=settings.textShadowColors[bHot?1:0]; glowSize=settings.glowSize; } RECT rc=itemRect; int left=rc.left; rc.left=m_MinX; rc.right=m_MaxX; if (bHot || pItem->bNew) { // draw background if (bmp.bIsBitmap) { HGDIOBJ bmp0=SelectObject(hsrc,bmp.GetBitmap()); RECT rSrc={0,0,slicesX[0]+slicesX[1]+slicesX[2],slicesY[0]+slicesY[1]+slicesY[2]}; RECT rMargins={slicesX[0],slicesY[0],slicesX[2],slicesY[2]}; MarginsBlit(hsrc,hdc,rSrc,rc,rMargins,bmp.bIs32); SelectObject(hsrc,bmp0); } else { SetDCBrushColor(hdc,bmp.GetColor()); FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); } } // draw icon rc.left=left; int iconSize=CItemManager::SMALL_ICON_SIZE; int x=rc.left-iconSize-3-iconPadding.right; int y=rc.top+iconTopOffset; if (pItem->pItemInfo1 && pItem->pItemInfo1->smallIcon) { HGDIOBJ bmp0=SelectObject(hsrc,pItem->pItemInfo1->smallIcon->bitmap); BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; AlphaBlend(hdc,x,y,iconSize,iconSize,hsrc,0,0,iconSize,iconSize,func); SelectObject(hsrc,bmp0); } // draw text rc.top+=textTopOffset; if (m_TreeTheme) { DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; if (glowSize || skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].opacity==MenuSkin::OPACITY_FULLALPHA || skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].opacity==MenuSkin::OPACITY_FULLGLASS) opts.dwFlags|=DTT_COMPOSITED; if (glowSize) { opts.dwFlags|=DTT_GLOWSIZE; opts.iGlowSize=glowSize; } if (shadowColor!=0xFFFFFFFF) { opts.crText=shadowColor; RECT rc2=rc; OffsetRect(&rc2,1,1); DrawThemeTextEx(m_TreeTheme,hdc,0,0,pItem->name,pItem->name.GetLength(),DT_SINGLELINE|DT_NOPREFIX,&rc2,&opts); } opts.crText=textColor; DrawThemeTextEx(m_TreeTheme,hdc,0,0,pItem->name,pItem->name.GetLength(),DT_SINGLELINE|DT_NOPREFIX,&rc,&opts); } else { SetBkMode(hdc,TRANSPARENT); if (shadowColor!=0xFFFFFFFF) { RECT rc2=rc; OffsetRect(&rc2,1,1); SetTextColor(hdc,shadowColor); DrawText(hdc,pItem->name,pItem->name.GetLength(),&rc,DT_SINGLELINE|DT_NOPREFIX); } SetTextColor(hdc,textColor); DrawText(hdc,pItem->name,pItem->name.GetLength(),&rc,DT_SINGLELINE|DT_NOPREFIX); } } void CProgramsTree::DrawScrollbarBackground( HDC hdc, int iPartId, int iStateId, LPCRECT pRect ) { const MenuSkin &skin=CMenuContainer::s_Skin; HDC hSrc=CreateCompatibleDC(hdc); if (iPartId==SBP_ARROWBTN) { // draw arrows int state=0; if (iStateId==ABS_UPHOT || iStateId==ABS_DOWNHOT) state=1; else if (iStateId==ABS_UPPRESSED || iStateId==ABS_DOWNPRESSED) state=2; HGDIOBJ bmp0=GetCurrentObject(hSrc,OBJ_BITMAP); if (skin.Scrollbar_button.bIsBitmap) { SelectObject(hSrc,skin.Scrollbar_button.GetBitmap()); int w=skin.Scrollbar_button_slices_X[0]+skin.Scrollbar_button_slices_X[1]+skin.Scrollbar_button_slices_X[2]; int h=skin.Scrollbar_button_slices_Y[0]+skin.Scrollbar_button_slices_Y[1]+skin.Scrollbar_button_slices_Y[2]; RECT rSrc={0,h*state,w,h*(state+1)}; RECT rMargins={skin.Scrollbar_button_slices_X[0],skin.Scrollbar_button_slices_Y[0],skin.Scrollbar_button_slices_X[2],skin.Scrollbar_button_slices_Y[2]}; MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); } else { FillSolidGlassRect(hdc,pRect,skin.Scrollbar_button.GetColor()); } int arrowOffset=0; if ((iStateId>=ABS_DOWNNORMAL && iStateId<=ABS_DOWNDISABLED) || iStateId==ABS_DOWNHOVER) arrowOffset=skin.Scrollbar_arrows_size.cx; SelectObject(hSrc,skin.Scrollbar_arrows.GetBitmap()); int x=(pRect->right+pRect->left-skin.Scrollbar_arrows_size.cx)/2; int y=(pRect->bottom+pRect->top-skin.Scrollbar_arrows_size.cy)/2; StretchBlt2(hdc,x,y,skin.Scrollbar_arrows_size.cx,skin.Scrollbar_arrows_size.cy,hSrc,arrowOffset,skin.Scrollbar_arrows_size.cy*state,skin.Scrollbar_arrows_size.cx,skin.Scrollbar_arrows_size.cy,true); SelectObject(hSrc,bmp0); } else if (iPartId==SBP_LOWERTRACKVERT || iPartId==SBP_UPPERTRACKVERT) { // draw background if (skin.Scrollbar_background.bIsBitmap) { int state=0; if (iStateId==SCRBS_HOT) state=1; else if (iStateId==SCRBS_PRESSED) state=2; HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_background.GetBitmap()); int w=skin.Scrollbar_background_slices_X[0]+skin.Scrollbar_background_slices_X[1]+skin.Scrollbar_background_slices_X[2]; int h=skin.Scrollbar_background_slices_Y[0]+skin.Scrollbar_background_slices_Y[1]+skin.Scrollbar_background_slices_Y[2]; RECT rSrc={0,h*state,w,h*(state+1)}; RECT rMargins={skin.Scrollbar_background_slices_X[0],skin.Scrollbar_background_slices_Y[0],skin.Scrollbar_background_slices_X[2],skin.Scrollbar_background_slices_Y[2]}; MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); SelectObject(hSrc,bmp0); } else { FillSolidGlassRect(hdc,pRect,skin.Scrollbar_background.GetColor()); } } else if (iPartId==SBP_THUMBBTNVERT) { // draw thumb if (skin.Scrollbar_thumb.bIsBitmap) { int state=0; if (iStateId==SCRBS_HOT) state=1; else if (iStateId==SCRBS_PRESSED) state=2; HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_thumb.GetBitmap()); int w=skin.Scrollbar_thumb_slices_X[0]+skin.Scrollbar_thumb_slices_X[1]+skin.Scrollbar_thumb_slices_X[2]; int h=skin.Scrollbar_thumb_slices_Y[0]+skin.Scrollbar_thumb_slices_Y[1]+skin.Scrollbar_thumb_slices_Y[2]; RECT rSrc={0,h*state,w,h*(state+1)}; RECT rMargins={skin.Scrollbar_thumb_slices_X[0],skin.Scrollbar_thumb_slices_Y[0],skin.Scrollbar_thumb_slices_X[2],skin.Scrollbar_thumb_slices_Y[2]}; MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); } else { FillSolidGlassRect(hdc,pRect,skin.Scrollbar_thumb.GetColor()); } } else if (iPartId==SBP_GRIPPERVERT) { // draw gripper if (skin.Scrollbar_gripper.GetBitmap()) { int state=0; if (iStateId==SCRBS_HOT) state=1; else if (iStateId==SCRBS_PRESSED) state=2; HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_gripper.GetBitmap()); int x=(pRect->right+pRect->left-skin.Scrollbar_gripper_size.cx)/2; int y=(pRect->bottom+pRect->top-skin.Scrollbar_gripper_size.cy)/2; StretchBlt2(hdc,x,y,skin.Scrollbar_gripper_size.cx,skin.Scrollbar_gripper_size.cy,hSrc,0,skin.Scrollbar_gripper_size.cy*state,skin.Scrollbar_gripper_size.cx,skin.Scrollbar_gripper_size.cy,true); SelectObject(hSrc,bmp0); } } DeleteDC(hSrc); } void CMenuContainer::AnimateMenu( int flags, int speed, const RECT &rect ) { RECT clipRect=m_bSubMenu?s_MenuLimits:s_MainMenuLimits; bool bUserPic=(!m_bSubMenu && s_bWin7Style && s_UserPicture.m_hWnd && s_UserPictureRect.top0) { // fade in SetWindowLong(GWL_EXSTYLE,GetWindowLong(GWL_EXSTYLE)|WS_EX_LAYERED); SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); if (!m_bSubMenu && s_TaskBar && s_bBehindTaskbar) { // position the start button on top if (s_StartButton) ::SetWindowPos(s_StartButton,(flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); // position the start menu behind the taskbar SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); } if (bUserPic) { s_UserPicture.Update(0); s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); } // animate int time0=GetTickCount(); while (true) { int dt=GetTickCount()-time0; if (dt>speed) break; float f=dt/(float)speed; int alpha=(int)(f*255); SetLayeredWindowAttributes(m_hWnd,0,(BYTE)alpha,LWA_ALPHA); RedrawWindow(); if (bUserPic) s_UserPicture.Update(alpha); } SetWindowLong(GWL_EXSTYLE,GetWindowLong(GWL_EXSTYLE)&~WS_EX_LAYERED); RedrawWindow(); } else if ((flags&AW_SLIDE) && speed>0) { // slide in HRGN rgn=CreateRectRgn(0,0,0,0); if (!SetWindowRgn(rgn,FALSE)) // set empty region DeleteObject(rgn); SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); if (!m_bSubMenu && s_TaskBar && s_bBehindTaskbar) { // position the start button on top if (s_StartButton) ::SetWindowPos(s_StartButton,(flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); // position the start menu behind the taskbar SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); } if (bUserPic) { s_UserPicture.Update(0); s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); } if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) m_pProgramsTree->ShowWindow(SW_HIDE); HRGN rgn0=NULL; if (m_Region) { int rgnSize=GetRegionData(m_Region,0,NULL); std::vector buf(rgnSize); GetRegionData(m_Region,rgnSize,(RGNDATA*)&buf[0]); XFORM xform={1,0,0,1}; if (s_bRTL) { // mirror the region (again) xform.eM11=-1; xform.eDx=(float)(m_rMenu.right+m_rMenu.left-m_BitmapOffset); } rgn0=ExtCreateRegion(&xform,rgnSize,(RGNDATA*)&buf[0]); } // animate int time0=GetTickCount(); int movex=0, movey=0; if (flags&AW_HOR_POSITIVE) { movex=rect.right-rect.left; clipRect.left=rect.left; } else if (flags&AW_HOR_NEGATIVE) { movex=rect.left-rect.right; clipRect.right=rect.right; } else if (flags&AW_VER_POSITIVE) { movey=rect.bottom-rect.top; clipRect.top=rect.top; } else { movey=rect.top-rect.bottom; clipRect.bottom=rect.bottom; } HRGN clipRgn=CreateRectRgn(clipRect.left-rect.left,clipRect.top-rect.top,clipRect.right-rect.left,clipRect.bottom-rect.top); // clip region in window space while (true) { int dt=GetTickCount()-time0; if (dt>speed) break; float f=1-dt/(float)speed; f=powf(f,5); int dx=(int)(movex*f); int dy=(int)(movey*f); if (dx==0 && dy==0) break; m_PaintOffset.x=-dx; m_PaintOffset.y=-dy; // calculate region HRGN wndRgn=CreateRectRgn(0,0,rect.right-rect.left,rect.bottom-rect.top); // window region if (rgn0) CombineRgn(wndRgn,rgn0,NULL,RGN_COPY); OffsetRgn(wndRgn,-dx,-dy); HRGN rgn=CreateRectRgn(0,0,0,0); CombineRgn(rgn,clipRgn,wndRgn,RGN_AND); // clipped window region if (!SetWindowRgn(rgn,FALSE)) DeleteObject(rgn); DeleteObject(wndRgn); RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); // move user pic if (bUserPic) { POINT pos={s_UserPictureRect.left-dx,s_UserPictureRect.top-dy}; s_UserPicture.UpdatePartial(pos,&clipRect); } } DeleteObject(clipRgn); m_PaintOffset.x=m_PaintOffset.y=0; if (!SetWindowRgn(rgn0,FALSE) && rgn0) DeleteObject(rgn0); if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) m_pProgramsTree->ShowWindow(SW_SHOW); RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); } else { // no animation SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); if (bUserPic) { s_UserPicture.Update(255); s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); } } if (m_SearchBox.m_hWnd) m_SearchBox.ShowWindow(SW_SHOW); if (bUserPic) { POINT pos={s_UserPictureRect.left,s_UserPictureRect.top}; s_UserPicture.UpdatePartial(pos,NULL); } }