📄 dwautohide.h
字号:
LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM/* lParam*/, BOOL& bHandled)
{
T* pThis=reinterpret_cast<T*>(this);
bHandled=pThis->OnClosing();
return 0;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Note: We can depend on CDWSettings already being updated
// since we will always be a descendant of the main frame
m_caption.UpdateMetrics();
T* pThis=static_cast<T*>(this);
pThis->SetWindowPos(NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
bHandled = FALSE;
return 1;
}
// LRESULT OnSysColorChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// {
// return 1;
// }
protected:
CCaption m_caption;
CSplitterBar m_splitter;
CSide m_side;
};
template<class TAutoHidePaneTraits>
class CAutoHideManager
: public CAutoHidePaneImpl<CAutoHideManager<TAutoHidePaneTraits>,CWindow,TAutoHidePaneTraits>
{
typedef CAutoHidePaneImpl<CAutoHideManager<TAutoHidePaneTraits>,CWindow,TAutoHidePaneTraits> baseClass;
typedef CAutoHideManager thisClass;
protected:
typedef typename CAutoHideBar::CSide CSide;
enum{ tmID=1,tmTimeout=1300};
enum{ animateTimeout=100};
enum{ hoverTimeout=50/*HOVER_DEFAULT*/};
enum{ barsCount=4 };
class CSizeTrackerFull : public IDDTracker
{
protected:
typedef ssec::bounds_type<long> CBounds;
public:
bool IsHorizontal() const
{
return m_side.IsHorizontal();
}
bool IsTop() const
{
return m_side.IsTop();
}
CSizeTrackerFull(HWND hWnd,CPoint pt,const CSide& side,long minSize,const CRect& rcBound)
: m_wnd(hWnd),m_side(side)
{
m_wnd.GetWindowRect(&m_rc);
CWindow wndParent=m_wnd.GetParent();
wndParent.ScreenToClient(&m_rc);
wndParent.ScreenToClient(&pt);
if(IsHorizontal())
{
if(IsTop())
m_ppos=&m_rc.bottom;
else
m_ppos=&m_rc.top;
m_bounds.low=rcBound.top;
m_bounds.hi=rcBound.bottom;
m_offset=pt.y-*m_ppos;
}
else
{
if(IsTop())
m_ppos=&m_rc.right;
else
m_ppos=&m_rc.left;
m_bounds.low=rcBound.left;
m_bounds.hi=rcBound.right;
m_offset=pt.x-*m_ppos;
}
m_bounds.low+=minSize;
m_bounds.hi-=minSize;
}
void OnMove(long x, long y)
{
long pos = IsHorizontal() ? y : x;
pos-=m_offset;
pos=m_bounds.bind(pos);
if(*m_ppos!=pos)
{
*m_ppos=pos;
Move();
}
}
void SetPosition()
{
m_wnd.SetWindowPos(NULL,&m_rc,SWP_NOZORDER | SWP_NOACTIVATE);
}
virtual void Move()
{
SetPosition();
}
bool ProcessWindowMessage(MSG* pMsg)
{
return (pMsg->message==WM_TIMER);
}
protected:
CWindow m_wnd;
CBounds m_bounds;
CRect m_rc;
const CSide m_side;
long* m_ppos;
long m_offset;
};
class CSizeTrackerGhost : public CSizeTrackerFull
{
typedef CSimpleSplitterBarSlider<CSplitterBar> CSlider;
public:
CSizeTrackerGhost(HWND hWnd,CPoint pt,const CSide& side,CSplitterBar& splitter,const CRect& rcBound)
: CSizeTrackerFull(hWnd,pt,side,splitter.GetThickness(),rcBound),m_dc(::GetWindowDC(NULL))
,m_splitter(splitter),m_slider(splitter)
{
m_spOffset=m_slider-*m_ppos;
}
void BeginDrag()
{
m_splitter.DrawGhostBar(m_dc);
}
void EndDrag(bool bCanceled)
{
m_splitter.CleanGhostBar(m_dc);
if(!bCanceled)
SetPosition();
}
virtual void Move()
{
m_splitter.CleanGhostBar(m_dc);
m_slider=*m_ppos+m_spOffset;
m_splitter.DrawGhostBar(m_dc);
}
protected:
CDC m_dc;
CSplitterBar& m_splitter;
CSlider m_slider;
long m_spOffset;
};
public:
CAutoHideManager()
: m_pActive(0)
{
m_side=0;
}
bool Initialize(HWND hWnd)
{
ApplySystemSettings(hWnd);
m_bars[CSide::sTop].Initialize(CSide(CSide::sTop));
m_bars[CSide::sBottom].Initialize(CSide(CSide::sBottom));
m_bars[CSide::sLeft].Initialize(CSide(CSide::sLeft));
m_bars[CSide::sRight].Initialize(CSide(CSide::sRight));
RECT rc={0,0,0,0};
return (Create(hWnd,rc)!=NULL);
}
void ApplySystemSettings(HWND hWnd)
{
CClientDC dc(hWnd);
CDWSettings settings;
HFONT hOldFont=dc.SelectFont(settings.VSysFont());
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
m_barThickness=tm.tmHeight;
dc.SelectFont(settings.HSysFont());
dc.GetTextMetrics(&tm);
if(m_barThickness<tm.tmHeight)
m_barThickness=tm.tmHeight;
dc.SelectFont(hOldFont);
int widthIcon=settings.CXMinIcon();
assert(widthIcon==settings.CYMinIcon()); //if it throw let me know ;)
if(widthIcon>m_barThickness)
m_barThickness=widthIcon;
m_barThickness+=2*IPinnedLabel::captionPadding+IPinnedLabel::labelEdge;
}
void UpdateLayout(CDC& dc,CRect& rc)
{
long leftPadding= ( m_bars[CSide::sLeft].IsVisible() ) ? m_barThickness : 0;
long rightPadding=( m_bars[CSide::sRight].IsVisible() ) ? m_barThickness : 0;
m_bars[CSide::sTop].CalculateRect( dc,rc,m_barThickness,leftPadding,rightPadding);
m_bars[CSide::sBottom].CalculateRect( dc,rc,m_barThickness,leftPadding,rightPadding);
leftPadding=0;
rightPadding=0;
m_bars[CSide::sLeft].CalculateRect( dc,rc,m_barThickness,leftPadding,rightPadding);
m_bars[CSide::sRight].CalculateRect( dc,rc,m_barThickness,leftPadding,rightPadding);
m_rcBound.CopyRect(&rc);
if(m_pActive)
FitPane();
}
long Width() const
{
long width=0;
if(m_bars[CSide::sLeft].IsVisible())
width+=m_barThickness;
if(m_bars[CSide::sRight].IsVisible())
width+=m_barThickness;
return width;
}
long Height() const
{
long height=0;
if(m_bars[CSide::sTop].IsVisible())
height+=m_barThickness;
if(m_bars[CSide::sBottom].IsVisible())
height+=m_barThickness;
return height;
}
bool FitPane()
{
CRect rc(m_rcBound);
long spliterWidth=m_splitter.GetThickness();
long width=m_pActive->Width()+spliterWidth;
if(IsHorizontal())
{
long maxWidth=rc.Height();
maxWidth=(maxWidth<spliterWidth) ? spliterWidth : maxWidth-spliterWidth;
if(IsTop())
rc.bottom=rc.top+( (maxWidth>width) ? width : maxWidth );
else
rc.top=rc.bottom-( (maxWidth>width) ? width : maxWidth );
}
else
{
long maxWidth=rc.Width();
maxWidth=(maxWidth<spliterWidth) ? spliterWidth : maxWidth-spliterWidth;
if(IsTop())
rc.right=rc.left+( (maxWidth>width) ? width : maxWidth );
else
rc.left=rc.right-( (maxWidth>width) ? width : maxWidth );
}
return (SetWindowPos(HWND_TOP,rc,SWP_NOACTIVATE)!=FALSE);
}
IPinnedLabel::CPinnedWindow* LocatePinnedWindow(const CPoint& pt) const
{
IPinnedLabel::CPinnedWindow* ptr=0;
for(int i=0;i<barsCount;i++)
{
ptr=m_bars[i].MouseEnter(pt);
if(ptr!=0)
break;
}
return ptr;
}
bool IsPtIn(const CPoint& pt) const
{
bool bRes;
for(int i=0;i<barsCount;i++)
{
bRes=m_bars[i].IsPtIn(pt);
if(bRes)
break;
}
return bRes;
}
bool MouseEnter(HWND hWnd,const CPoint& pt)
{
IPinnedLabel::CPinnedWindow* ptr=0;
for(int i=0;i<barsCount;i++)
{
CAutoHideBar* pbar=m_bars+i;
ptr=pbar->MouseEnter(pt);
if((ptr!=0)
&& IsVisualizationNeeded(ptr))
{
m_pTracked=ptr;
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = hoverTimeout;
::_TrackMouseEvent(&tme);
break;
}
}
return (ptr!=0);
}
bool MouseHover(HWND hWnd,const CPoint& pt)
{
IPinnedLabel::CPinnedWindow* ptr=0;
for(int i=0;i<barsCount;i++)
{
CAutoHideBar* pbar=m_bars+i;
ptr=pbar->MouseEnter(pt,true);
if((ptr!=0)
&& (ptr==m_pTracked)
&&IsVisualizationNeeded(ptr))
{
CClientDC dc(hWnd);
pbar->Draw(dc);
Visualize(ptr,i,true);
break;
}
}
return (ptr!=0);
}
void Draw(CDC& dc)
{
EraseBackground(dc);
for(int i=0;i<barsCount;i++)
m_bars[i].Draw(dc,false);
}
void EraseBackground(CDC& dc)
{
CDWSettings settings;
CBrush bgrBrush;
bgrBrush.CreateSolidBrush(settings.CoolCtrlBackgroundColor());
HBRUSH hOldBrush=dc.SelectBrush(bgrBrush);
CRect rcTop(m_bars[CSide::sTop].operator const CRect&());
CRect rcBottom(m_bars[CSide::sBottom].operator const CRect&());
if(m_bars[CSide::sLeft].IsVisible())
{
const CRect& rc=m_bars[CSide::sLeft].operator const CRect&();
rcTop.left-=rc.Height();
rcBottom.left-=rc.Height();
dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
}
if(m_bars[CSide::sRight].IsVisible())
{
const CRect& rc=m_bars[CSide::sRight].operator const CRect&();
rcTop.right+=rc.Height();
rcBottom.right+=rc.Height();
dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
}
if(m_bars[CSide::sTop].IsVisible())
dc.PatBlt(rcTop.left, rcTop.top, rcTop.Width(), rcTop.Height(), PATCOPY);
if(m_bars[CSide::sBottom].IsVisible())
dc.PatBlt(rcBottom.left, rcBottom.top, rcBottom.Width(), rcBottom.Height(), PATCOPY);
dc.SelectBrush(hOldBrush);
}
bool PinUp(HWND hWnd,DFPINUP* pHdr,bool& bUpdate)
{
pHdr->hdr.hBar=m_hWnd;
CSide side(pHdr->dwDockSide);
assert(side.IsValid());
CAutoHideBar* pbar=m_bars+side.Side();
bUpdate=!pbar->IsVisible();
IPinnedLabel* pLabel=pbar->Insert(pHdr);
bool bRes=(pLabel!=0);
if(bRes&& ((pHdr->dwFlags&DFPU_VISUALIZE)!=0))
Visualize(pLabel->ActivePinnedWindow(),side);
if(!bUpdate)
{
CClientDC dc(hWnd);
pbar->UpdateLayout(dc);
pbar->Draw(dc);
}
return bRes;
}
bool Remove(HWND hWnd,bool bUnpin=false)
{
if(m_pActive!=0 && (m_pActive->Wnd()==hWnd ) )
Vanish();
HDOCKBAR hBar=GetParent();
assert(::IsWindow(hBar));
DFDOCKPOS* pHdr=0;
DFDOCKPOS dockHdr;
if(bUnpin)
{
// dockHdr.hdr.code=DC_SETDOCKPOSITION;
dockHdr.hdr.hWnd=hWnd;
dockHdr.hdr.hBar=hBar;
pHdr=&dockHdr;
}
bool bRes=false;
for(int i=0;i<barsCount;i++)
{
CAutoHideBar* pbar=m_bars+i;
bRes=pbar->Remove(hWnd,m_hWnd,pHdr);
if(bRes)
{
if(pbar->IsVisible())
{
CClientDC dc(hBar);
pbar->UpdateLayout(dc);
pbar->Draw(dc);
}
else
{
::SendMessage(hBar, WM_SIZE, 0, 0);
::RedrawWindow(hBar,NULL,NULL,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
}
break;
}
}
return bRes;
}
bool GetDockingPosition(DFDOCKPOS* pHdr) const
{
bool bRes=false;
for(int i=0;i<barsCount;i++)
{
bRes=m_bars[i].GetDockingPosition(pHdr);
if(bRes)
break;
}
return bRes;
}
///////////////////////////////////////////////////////////
bool IsVisualizationNeeded(const IPinnedLabel::CPinnedWindow* ptr) const
{
return (ptr!=m_pActive);
}
bool Visualize(IPinnedLabel::CPinnedWindow* ptr,const CSide& side,bool bAnimate=false)
{
assert(ptr);
assert(IsVisualizationNeeded(ptr));
Vanish();
Orientation(side);
assert(m_pActive==0);
m_pActive=ptr;
bool bRes=(::SetWindowPos(m_pActive->Wnd(),HWND_TOP,0,0,0,0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW)!=FALSE);
if(bRes)
{
bRes=FitPane();
if(bRes)
{
SetWindowText(m_pActive->Text());
CDWSettings setting;
if(bAnimate && setting.IsAnimationEnabled())
AnimateWindow(animateTimeout,true);
else
bRes=(SetWindowPos(HWND_TOP,0,0,0,0,
SWP_NOMOVE | SWP_NOSIZE |
SWP_SHOWWINDOW | SWP_FRAMECHANGED )!=FALSE);
if(bRes)
{
BOOL dummy;
OnSize(0,0,0,dummy);
bRes=(SetTimer(tmID,tmTimeout)==tmID);
}
}
}
assert(bRes);
return bRes;
}
bool Vanish(bool bAnimate=false)
{
bool bRes=(m_pActive==0);
if(!bRes)
{
KillTimer(tmID);
::ShowWindow(m_pActive->Wnd(),SW_HIDE);
m_pActive=0;
CDWSettings setting;
if(bAnimate && setting.IsAnimationEnabled())
AnimateWindow(animateTimeout,false);
bRes=ShowWindow(SW_HIDE)!=FALSE;
}
return bRes;
}
///////////////////////////////////////////////////////////
void StartResizing(const CPoint& pt)
{
std::auto_ptr<CSizeTrackerFull> pTracker;
CDWSettings settings;
if(settings.GhostDrag())
{
CRect rc;
GetWindowRect(&rc);
CSplitterBar splitter(IsHorizontal());
splitter.CalculateRect(rc,m_side.Side());
pTracker=std::auto_ptr<CSizeTrackerFull>(
new CSizeTrackerGhost(m_hWnd,pt,Orientation(),splitter,m_rcBound));
}
else
pTracker=std::auto_ptr<CSizeTrackerFull>(
new CSizeTrackerFull(m_hWnd,pt,Orientation(),m_splitter.GetThickness(),m_rcBound));
HWND hWndParent=GetParent();
assert(hWndParent);
TrackDragAndDrop(*pTracker,hWndParent);
}
bool PinBtnPress()
{
assert(m_pActive);
return Remove(m_pActive->Wnd(),true);
}
bool OnClosing()
{
assert(m_pActive);
::PostMessage(m_pActive->Wnd(),WM_CLOSE,NULL,NULL);
return true;
}
DECLARE_WND_CLASS(_T("CAutoHideManager"))
protected:
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_TIMER,OnTimer)
MESSAGE_HANDLER(WM_SIZE, OnSize)
/////////////////
MESSAGE_HANDLER(WMDF_DOCK,OnDock)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = false;
Vanish(false);
return 0;
}
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
POINT pt;
CRect rc;
GetCursorPos(&pt);
GetWindowRect(&rc);
if(!rc.PtInRect(pt))
{
CWindow wndParent (GetParent());
wndParent.ScreenToClient(&pt);
IPinnedLabel::CPinnedWindow* ptr=LocatePinnedWindow(pt);
if(ptr==0 || IsVisualizationNeeded(ptr))
{
HWND hWnd=GetFocus();
while( hWnd!=m_hWnd )
{
if(hWnd==NULL)
{
Vanish(true);
break;
}
hWnd=::GetParent(hWnd);
}
}
}
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(wParam != SIZE_MINIMIZED && (m_pActive!=0))
{
CRect rc;
GetClientRect(&rc);
::SetWindowPos(m_pActive->Wnd(),NULL,
rc.left,rc.top,
rc.Width(),rc.Height(),
SWP_NOZORDER | SWP_NOACTIVATE);
GetWindowRect(&rc);
long width = (IsHorizontal()) ? rc.Height() : rc.Width();
width -= m_splitter.GetThickness();
if(width>m_caption.GetThickness()/*0*/)
m_pActive->Width(width);
}
bHandled = FALSE;
return 1;
}
LRESULT OnDock(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRes=FALSE;
DFMHDR* pHdr=reinterpret_cast<DFMHDR*>(lParam);
switch(pHdr->code)
{
case DC_UNDOCK:
assert(::IsWindow(pHdr->hWnd));
lRes=Remove(pHdr->hWnd);
break;
}
return lRes;
}
protected:
long m_barThickness;
IPinnedLabel::CPinnedWindow* m_pActive;
IPinnedLabel::CPinnedWindow* m_pTracked;
CRect m_rcBound;
CAutoHideBar m_bars[barsCount];
};
}//namespace dockwins
#endif // __WTL_DW__DWAUTOHIDE_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -