// Copyright (c) 2002 // Sergey Klimov (kidd@ukr.net) // WTL Docking windows // // This code is provided "as is", with absolutely no warranty expressed // or implied. Any use is at your own risk. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name is included. If // the source code in this file is used in any commercial application // then a simple email woulod be nice. #ifndef __WTL_DW__EXTDOCKINGWINDOW_H__ #define __WTL_DW__EXTDOCKINGWINDOW_H__ #pragma once #include "DockingWindow.h" namespace dockwins{ #ifdef DF_AUTO_HIDE_FEATURES class CPinIcons { public: enum States { sUnPinned=0, sPinned=1 }; CPinIcons() { static BYTE pinnedIconData[]={ 0x28, 0000, 0000, 0000, 0x0b, 0000, 0000, 0000, 0x16, 0000, 0000, 0000, 0x01, 0000, 0x04, 0000, 0000, 0000, 0000, 0000, 0x84, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x10, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x80, 0000, 0000, 0x80, 0000, 0000, 0000, 0x80, 0x80, 0000, 0x80, 0000, 0000, 0000, 0x80, 0000, 0x80, 0000, 0x80, 0x80, 0000, 0000, 0x80, 0x80, 0x80, 0000, 0xc0, 0xc0, 0xc0, 0000, 0000, 0000, 0xff, 0000, 0000, 0xff, 0000, 0000, 0000, 0xff, 0xff, 0000, 0xff, 0000, 0000, 0000, 0xff, 0000, 0xff, 0000, 0xff, 0xff, 0000, 0000, 0xff, 0xff, 0xff, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x07, 0x70, 0000, 0000, 0000, 0000, 0000, 0000, 0x77, 0x77, 0000, 0000, 0000, 0000, 0000, 0000, 0x7f, 0x80, 0000, 0000, 0000, 0000, 0000, 0000, 0xf0, 0x07, 0x77, 0000, 0000, 0000, 0000, 0000, 0x0f, 0000, 0xf7, 0x70, 0000, 0000, 0000, 0000, 0000, 0x0f, 0x0f, 0x70, 0000, 0000, 0000, 0000, 0000, 0000, 0xf0, 0x70, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x7f, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x90, 0x3f, 0xff, 0xff, 0xa4, 0x3f, 0xff, 0xff, 0xd2, 0x3f, 0xff, 0xff, 0xe5, 0x3f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static BYTE unpinnedIconData[]={ 0x28, 0000, 0000, 0000, 0x0b, 0000, 0000, 0000, 0x16, 0000, 0000, 0000, 0x01, 0000, 0x04, 0000, 0000, 0000, 0000, 0000, 0x84, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x10, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x80, 0000, 0000, 0x80, 0000, 0000, 0000, 0x80, 0x80, 0000, 0x80, 0000, 0000, 0000, 0x80, 0000, 0x80, 0000, 0x80, 0x80, 0000, 0000, 0x80, 0x80, 0x80, 0000, 0xc0, 0xc0, 0xc0, 0000, 0000, 0000, 0xff, 0000, 0000, 0xff, 0000, 0000, 0000, 0xff, 0xff, 0000, 0xff, 0000, 0000, 0000, 0xff, 0000, 0xff, 0000, 0xff, 0xff, 0000, 0000, 0xff, 0xff, 0xff, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0x08, 0000, 0x08, 0000, 0000, 0000, 0000, 0000, 0000, 0x08, 0000, 0000, 0000, 0000, 0000, 0000, 0x0f, 0x0f, 0x8f, 0000, 0000, 0000, 0000, 0000, 0000, 0xf0, 0000, 0000, 0000, 0000, 0000, 0000, 0x0f, 0000, 0x0f, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xf3, 0x9f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf4, 0x5f, 0xff, 0xff, 0x02, 0x1f, 0xff, 0xff, 0xf5, 0xdf, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf3, 0x9f, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; m_icons[0]=CreateIconFromResourceEx(unpinnedIconData, 0xec, TRUE, 0x00030000, 11, 11, LR_DEFAULTCOLOR); m_icons[1]=CreateIconFromResourceEx(pinnedIconData, 0xec, TRUE, 0x00030000, 11, 11, LR_DEFAULTCOLOR); } ~CPinIcons() { DestroyIcon(m_icons[0]); DestroyIcon(m_icons[1]); } HICON GetIcon(States state) const { return m_icons[state]; } int Width() const { return 11; } int Height() const { return 11; } protected: HICON m_icons[2]; }; #endif class COutlookLikeExCaption : public CCaptionBase { typedef COutlookLikeExCaption thisClass; typedef CCaptionBase baseClass; public: enum{fntSpace=10,cFrameSpace=2,btnSpace=1}; protected: typedef baseClass::CButton CButtonBase; struct CButton : CButtonBase { CTheme *m_pTheme; CButton() : m_pTheme(NULL) { } virtual void CalculateRect(CRect& rc,bool bHorizontal=true) { CopyRect(rc); DeflateRect(cFrameSpace+btnSpace,cFrameSpace+btnSpace); if(bHorizontal) { left=right-Height(); rc.right=left; } else { bottom=top+Width(); rc.top=bottom; } } virtual void Draw (CDC& dc, int state)=0; virtual void Draw (CDC& dc) { Draw(dc, EBHC_NORMAL); } virtual void Press(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc, EBHC_PRESSED); if(!m_pTheme || !m_pTheme->m_hTheme) dc.DrawEdge(this,BDR_SUNKENOUTER/*|BF_ADJUST*/ ,BF_RECT); } virtual void Release(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc); } virtual void Hot(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc, EBHC_HOT); if(!m_pTheme || !m_pTheme->m_hTheme) dc.DrawEdge(this,BDR_RAISEDINNER/*|BF_ADJUST*/ ,BF_RECT); //look like button raise } }; class CCloseButton : public CButton { public: virtual void Draw(CDC& dc, int state = EBHC_NORMAL) { if(m_pTheme && m_pTheme->m_hTheme) { m_pTheme->DrawThemeBackground(dc, EBP_HEADERCLOSE, state, this, NULL); return; } CPen pen; #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); dc.FillRect(this,cf.GetCaptionBgBrush()); pen.CreatePen(PS_SOLID, 0, cf.GetCaptionTextColor()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT)); #endif HPEN hPenOld = dc.SelectPen(pen); const int sp=5; dc.MoveTo(left+sp, top+sp); dc.LineTo(right-sp, bottom-sp); dc.MoveTo(left + sp+1, top+sp); dc.LineTo(right - sp + 1, bottom - sp); dc.MoveTo(left+sp, bottom - sp-1); dc.LineTo(right-sp, top +sp -1 ); dc.MoveTo(left + sp +1, bottom - sp -1); dc.LineTo(right - sp +1, top + sp -1); dc.SelectPen(hPenOld); } }; #ifdef DF_AUTO_HIDE_FEATURES class CPinButton : public CButton { public: typedef CPinIcons CIcons; CPinButton():m_state(CIcons::sPinned) { } void State(CIcons::States state) { m_state=state; } virtual void Draw(CDC& dc, int state = EBHC_NORMAL) { if(m_pTheme && m_pTheme->m_hTheme) { m_pTheme->DrawThemeBackground(dc, EBP_HEADERPIN, state + ((m_state == CIcons::sPinned) ? 0 : 3), this, NULL); return; } #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); dc.FillRect(this,cf.GetCaptionBgBrush()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); #endif CPoint pt(left,top); CSize sz(Width(),Height()); int dif = sz.cx-m_icons.Width(); if(dif>0) { pt.x+=dif/2; sz.cx=m_icons.Width(); } dif = sz.cy-m_icons.Height(); if(dif>0) { pt.y+=dif/2; sz.cy=m_icons.Height(); } dc.DrawIconEx(pt,m_icons.GetIcon(m_state),sz); } protected: static CIcons m_icons; CIcons::States m_state; }; public: void SetPinButtonState(CPinButton::CIcons::States state) { m_btnPin.State(state); } #endif public: COutlookLikeExCaption():baseClass(0,false),m_winTheme(NULL),m_themeFont(NULL) { SetOrientation(!IsHorizontal()); ThemeChanged(); } void UpdateMetrics() { m_thickness=23; CDWSettings settings; HFONT hFont = IsHorizontal() ? settings.HSysFont() : settings.VSysFont(); assert(hFont); HDC dc=::GetDC(NULL); if(dc!=NULL) { HFONT hOldFont = reinterpret_cast(::SelectObject(dc,hFont)); if(hOldFont!=NULL) { TEXTMETRIC tm; if(::GetTextMetrics(dc, &tm)) m_thickness=tm.tmHeight+fntSpace; ::SelectObject(dc,hOldFont); } ::ReleaseDC(NULL,dc); } } void SetOrientation(bool bHorizontal) { if(IsHorizontal()!=bHorizontal) { baseClass::SetOrientation(bHorizontal); UpdateMetrics(); } } bool CalculateRect(CRect& rc,bool bTop) { bool bRes=baseClass::CalculateRect(rc,bTop); CRect rcSpace(*this); m_btnClose.CalculateRect(rcSpace,IsHorizontal()); #ifdef DF_AUTO_HIDE_FEATURES m_btnPin.CalculateRect(rcSpace,IsHorizontal()); #endif return bRes; } ~COutlookLikeExCaption() { ThemeChanged(TRUE); } CTheme m_Theme; HTHEME m_winTheme; HFONT m_themeFont; void ThemeChanged(BOOL dontLoad = FALSE) { if(!m_Theme.IsThemingSupported()) return; if(m_themeFont) { ::DeleteObject(m_themeFont); m_themeFont = NULL; } if(m_winTheme) { ::CloseThemeData(m_winTheme); m_winTheme = NULL; } m_Theme.CloseThemeData(); if(dontLoad) return; m_Theme.OpenThemeData(NULL, L"ExplorerBar"); m_winTheme = ::OpenThemeData(NULL,L"Window"); #ifdef DF_AUTO_HIDE_FEATURES m_btnPin.m_pTheme = &m_Theme; #endif m_btnClose.m_pTheme = &m_Theme; if(m_winTheme) { LOGFONTW lf; // Newer SDKs fix this define: #ifdef _WTL_NEW_UXTHEME ::GetThemeSysFont(m_winTheme, TMT_SMALLCAPTIONFONT, &lf); #else ::GetThemeSysFont(m_winTheme, TMT_SMALLCAPTIONFONT, (LOGFONT *)&lf); #endif m_themeFont = ::CreateFontIndirectW(&lf); } } void Draw(HWND hWnd,CDC& dc) { #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); #endif if(m_Theme.m_hTheme) ::DrawThemeBackground(m_winTheme, dc, WP_MAXCAPTION, CWindow(hWnd).IsChild(GetFocus()) ? CS_ACTIVE : CS_INACTIVE, this, NULL); else { #ifdef DF_FOCUS_FEATURES dc.FillRect(this,cf.GetCaptionBgBrush()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); #endif } int len=GetWindowTextLength(hWnd)+1; TCHAR* sText=new TCHAR[len]; if(GetWindowText(hWnd,sText,len)!=0) { HFONT hFont; CDWSettings settings; CRect rc(this); if(IsHorizontal()) { rc.left+=fntSpace+cFrameSpace; #ifdef DF_AUTO_HIDE_FEATURES rc.right=m_btnPin.left-cFrameSpace-btnSpace; #else rc.right=m_btnClose.left-cFrameSpace-btnSpace; #endif hFont = settings.HSysFont(); } else { rc.bottom-=fntSpace-cFrameSpace; #ifdef DF_AUTO_HIDE_FEATURES rc.top=m_btnPin.bottom+cFrameSpace+btnSpace; #else rc.top=m_btnClose.bottom+cFrameSpace+btnSpace; #endif hFont = settings.VSysFont(); } #ifdef DF_FOCUS_FEATURES dc.SetTextColor(cf.GetCaptionTextColor()); #else dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); #endif dc.SetBkMode(TRANSPARENT); HFONT hFontOld; if(m_themeFont) hFontOld = dc.SelectFont(m_themeFont); else hFontOld = dc.SelectFont(hFont); if( (rc.left tracker(*pbtn,*this,hWnd,nHitTest); TrackDragAndDrop(tracker,hWnd); if(tracker) ::SendMessage(hWnd,WM_NCLBUTTONUP,nHitTest,GetMessagePos()); return bRes; } protected: #ifdef DF_AUTO_HIDE_FEATURES CPinButton m_btnPin; #endif CCloseButton m_btnClose; }; struct COutlookLikeCaption : COutlookLikeExCaption { void SetOrientation(bool /*bHorizontal*/) { // horizontal only } }; typedef CDockingWindowTraits COutlookLikeTitleDockingWindowTraits; typedef CDockingWindowTraits COutlookLikeExTitleDockingWindowTraits; class CVC6LikeCaption : public CCaptionBase { typedef CVC6LikeCaption thisClass; typedef CCaptionBase baseClass; public: enum{btnSpace=2,grThick=3}; protected: typedef baseClass::CButton CButtonBase; struct CButton : CButtonBase { virtual void CalculateRect(CRect& rc,bool bHorizontal) { CopyRect(rc); DeflateRect(btnSpace,btnSpace); if(bHorizontal) { left=right-Height(); rc.right=left+btnSpace; } else { bottom=top+Width(); rc.top=bottom+btnSpace; } } virtual void Draw (CDC& dc)=0; virtual void Press(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc); dc.DrawEdge(this,BDR_SUNKENOUTER/*|BF_ADJUST*/ ,BF_RECT); //look like button push } virtual void Release(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc); } virtual void Hot(HWND hWnd) { CWindowDC dc(hWnd); Draw(dc); dc.DrawEdge(this,BDR_RAISEDINNER/*|BF_ADJUST*/ ,BF_RECT); //look like button raise } }; class CCloseButton: public CButton { public: virtual void Draw(CDC& dc) { CPen pen; #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); dc.FillRect(this,cf.GetCaptionBgBrush()); pen.CreatePen(PS_SOLID, 0, cf.GetCaptionTextColor()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT)); #endif HPEN hPenOld = dc.SelectPen(pen); const int sp=3; dc.MoveTo(left+sp, top+sp); dc.LineTo(right-sp, bottom-sp); dc.MoveTo(left + sp+1, top+sp); dc.LineTo(right - sp + 1, bottom - sp); dc.MoveTo(left+sp, bottom - sp-1); dc.LineTo(right-sp, top +sp -1 ); dc.MoveTo(left + sp +1, bottom - sp -1); dc.LineTo(right - sp +1, top + sp -1); dc.SelectPen(hPenOld); } }; #ifdef DF_AUTO_HIDE_FEATURES class CPinButton : public CButton { public: typedef CPinIcons CIcons; CPinButton():m_state(CIcons::sPinned) { } void State(CIcons::States state) { m_state=state; } virtual void Draw(CDC& dc) { #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); dc.FillRect(this,cf.GetCaptionBgBrush()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); #endif CPoint pt(left,top); CSize sz(Width(),Height()); int dif = sz.cx-m_icons.Width(); if(dif>0) { pt.x+=dif/2; sz.cx=m_icons.Width(); } dif = sz.cy-m_icons.Height(); if(dif>0) { pt.y+=dif/2; sz.cy=m_icons.Height(); } dc.DrawIconEx(pt,m_icons.GetIcon(m_state),sz); } protected: static CIcons m_icons; CIcons::States m_state; }; public: void SetPinButtonState(CPinButton::CIcons::States state) { m_btnPin.State(state); } #endif public: bool CalculateRect(CRect& rc,bool bTop) { bool bRes=baseClass::CalculateRect(rc,bTop); CRect rcSpace(*this); m_btnClose.CalculateRect(rcSpace,IsHorizontal()); #ifdef DF_AUTO_HIDE_FEATURES m_btnPin.CalculateRect(rcSpace,IsHorizontal()); #endif return bRes; } void Draw(HWND /*hWnd*/,CDC& dc) { #ifdef DF_FOCUS_FEATURES CCaptionFocus cf(dc); dc.FillRect(this,cf.GetCaptionBgBrush()); #else dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1)); #endif CRect rc; if(IsHorizontal()) { rc.left=left+btnSpace; #ifdef DF_AUTO_HIDE_FEATURES rc.right=m_btnPin.left-btnSpace; #else rc.right=m_btnClose.left-btnSpace; #endif if(rc.left tracker(*pbtn,*this,hWnd,nHitTest); TrackDragAndDrop(tracker,hWnd); if(tracker) ::SendMessage(hWnd,WM_NCLBUTTONUP,nHitTest,GetMessagePos()); return bRes; } protected: #ifdef DF_AUTO_HIDE_FEATURES CPinButton m_btnPin; #endif CCloseButton m_btnClose; }; typedef CDockingWindowTraits CVC6LikeTitleDockingWindowTraits; }//namespace dockwins #endif // __WTL_DW__EXTDOCKINGWINDOW_H__