📄 dockingwindow.h
字号:
virtual void Release(HWND /*hWnd*/){};
virtual void Hot(HWND /*hWnd*/){}
};
class CBtnClickTracker : public CDDTrackerBaseT<CBtnClickTracker>
{
public:
CBtnClickTracker(HWND hWnd,CButton& btn)
:m_hWnd(hWnd),m_btn(btn)
{
}
void BeginDrag()
{
m_btn.Press(m_hWnd);
}
void EndDrag(bool /*bCanceled*/)
{
m_btn.Release(m_hWnd);
}
protected:
HWND m_hWnd;
CButton& m_btn;
};
protected:
template<class T>
class CHotBtnTracker : public CDDTrackerBaseT<CHotBtnTracker<T> >
{
public:
CHotBtnTracker(CButton& btn,T& owner,HWND hWnd,int nHotHitTest)
:m_btn(btn),m_owner(owner),m_hWnd(hWnd),m_nHotHitTest(nHotHitTest),m_bDoAction(false)
{
CRect rc;
::GetClientRect(m_hWnd,&rc);
m_offset.x=rc.left;
m_offset.y=rc.top;
::ClientToScreen(m_hWnd,&m_offset);
::GetWindowRect(hWnd,&rc);
m_offset.x-=rc.left;
m_offset.y-=rc.top;
}
void BeginDrag()
{
m_btn.Hot(m_hWnd);
}
void EndDrag(bool /*bCanceled*/)
{
m_btn.Release(m_hWnd);
}
void OnDropLeftButton(long x, long y)
{
CPoint pt(x+m_offset.x,y+m_offset.y);
m_bDoAction=(m_owner.HitTest(pt)==m_nHotHitTest);
}
void OnMove(long x, long y)
{
CPoint pt(x+m_offset.x,y+m_offset.y);
if(m_owner.HitTest(pt)!=m_nHotHitTest)
::ReleaseCapture();
}
bool ProcessWindowMessage(MSG* pMsg)
{
bool bRes=false;
bRes=(pMsg->message==WM_LBUTTONDOWN);
if(bRes)
m_btn.Press(m_hWnd);
return bRes;
}
operator bool () const
{
return m_bDoAction;
}
protected:
bool m_bDoAction;
CPoint m_offset;
T& m_owner;
CButton& m_btn;
HWND m_hWnd;
int m_nHotHitTest;
};
public:
CCaptionBase(bool bHorizontal=true)
:COrientedRect(bHorizontal,::GetSystemMetrics(SM_CYSMCAPTION))
{
}
CCaptionBase(unsigned long thickness,bool bHorizontal=true)
:COrientedRect(bHorizontal,thickness)
{
}
bool CalculateRect(CRect& rc,bool bTop)
{
return baseClass::CalculateRect(rc,bTop);
}
LRESULT HitTest(const CPoint& /*pt*/) const
{
return HTNOWHERE;
}
void Draw(HWND /*hWnd*/,CDC& dc)
{
dc.FillRect(this,(HBRUSH)LongToPtr(COLOR_3DFACE + 1));
}
bool OnAction(HWND hWnd,unsigned int nHitTest)
{
return HotTrack(hWnd,nHitTest);
}
bool HotTrack(HWND /*hWnd*/,unsigned int /*nHitTest*/)
{
return false;
}
void UpdateMetrics()
{
// Override in derived class if it depends on system metrics
}
};
template <class TCaption,DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
struct CDockingWindowTraits : CDockingBarWinTraits<t_dwStyle,t_dwExStyle>
{
typedef TCaption CCaption;
};
typedef CDockingWindowTraits<CCaptionBase,WS_OVERLAPPEDWINDOW | WS_POPUP/* WS_CHILD*/ | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,WS_EX_TOOLWINDOW/* WS_EX_CLIENTEDGE*/> CEmptyTitleDockingWindowTraits;
template <class T,
class TBase = CWindow,
class TDockingWinTraits = CEmptyTitleDockingWindowTraits>
class ATL_NO_VTABLE CTitleDockingWindowBaseImpl :
public CDockingWindowBaseImpl< T, TBase, TDockingWinTraits >
{
typedef CDockingWindowBaseImpl< T, TBase, TDockingWinTraits > baseClass;
typedef CTitleDockingWindowBaseImpl< T, TBase, TDockingWinTraits > thisClass;
protected:
typedef typename TDockingWinTraits::CCaption CCaption;
public:
LRESULT NcHitTest(const CPoint& pt)
{
LRESULT lRes=m_caption.HitTest(pt);
if(lRes==HTNOWHERE)
lRes=HTCLIENT;
else
{
if(GetCapture()==NULL)
m_caption.HotTrack(m_hWnd,lRes);
}
return lRes;
}
void GetMinMaxInfo(LPMINMAXINFO pMinMaxInfo) const
{
long width=m_caption.GetThickness();
if(pMinMaxInfo->ptMinTrackSize.y<width)
pMinMaxInfo->ptMinTrackSize.y=width;
if(pMinMaxInfo->ptMinTrackSize.x<width)
pMinMaxInfo->ptMinTrackSize.x=width;
}
void NcCalcSize(CRect* pRc)
{
DWORD style = GetWindowLong(GWL_STYLE);
if((style&WS_CAPTION)==0)
m_caption.SetRectEmpty();
else
m_caption.CalculateRect(*pRc,true);
}
void NcDraw(CDC& dc)
{
DWORD style = GetWindowLong(GWL_STYLE);
if((style&WS_CAPTION)!=0)
m_caption.Draw(m_hWnd,dc);
}
void OnDocked(HDOCKBAR hBar,bool bHorizontal)
{
m_caption.SetOrientation(!bHorizontal);
baseClass::OnDocked(hBar,bHorizontal);
}
void OnUndocked(HDOCKBAR hBar)
{
m_caption.SetOrientation(true);
baseClass::OnUndocked(hBar);
}
bool CloseBtnPress()
{
PostMessage(WM_CLOSE);
return false;
}
#ifdef DF_AUTO_HIDE_FEATURES
bool PinUp(const CDockingSide& side)
{
CRect rc;
GetWindowRect(&rc);
T* pThis=static_cast<T*>(this);
assert(rc.Width()>0);
assert(rc.Height()>0);
return pThis->PinUp(side,(side.IsHorizontal() ? rc.Width() : rc.Height()));
}
bool PinUp(const CDockingSide& side,unsigned long width,bool bVisualize=false)
{
if(IsDocking())
Undock();
DFPINUP pinHdr;
pinHdr.hdr.hWnd=m_hWnd;
pinHdr.hdr.hBar=GetOwnerDockingBar();
// pinHdr.hdr.code=DC_PINUP;
pinHdr.dwDockSide=side;
pinHdr.nWidth=width;
pinHdr.dwFlags= bVisualize ? DFPU_VISUALIZE : 0 ;
pinHdr.n=0;
return m_docker.PinUp(&pinHdr);
}
bool PinBtnPress()
{
assert(IsDocking());
DFDOCKPOS dockHdr;
// dockHdr.hdr.code=DC_GETDOCKPOSITION;
dockHdr.hdr.hWnd=m_hWnd;
dockHdr.hdr.hBar=GetOwnerDockingBar();
bool bRes=GetDockingPosition(&dockHdr);
if(bRes)
{
bRes=Undock();
if(bRes)
{
T* pThis=static_cast<T*>(this);
bRes=pThis->PinUp(CDockingSide(dockHdr.dwDockSide),dockHdr.nWidth,true);
}
}
return bRes;
}
#endif
protected:
BEGIN_MSG_MAP(thisClass)
if(IsDocking())
{
MESSAGE_HANDLER(WM_WINDOWPOSCHANGING,OnWindowPosChanging)
MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
MESSAGE_HANDLER(WM_NCACTIVATE, OnNcActivate)
MESSAGE_HANDLER(WM_NCHITTEST,OnNcHitTest)
MESSAGE_HANDLER(WM_NCPAINT,OnNcPaint)
MESSAGE_HANDLER(WM_SETTEXT,OnCaptionChange)
MESSAGE_HANDLER(WM_SETICON,OnCaptionChange)
MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
MESSAGE_HANDLER(WM_NCLBUTTONUP,OnNcLButtonUp)
MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK,OnNcLButtonDblClk)
#ifdef DF_FOCUS_FEATURES
assert(CDockingFocusHandler::This());
CHAIN_MSG_MAP_ALT_MEMBER((*CDockingFocusHandler::This()),0)
#endif
}
MESSAGE_HANDLER(WM_GETMINMAXINFO,OnGetMinMaxInfo)
MESSAGE_HANDLER(WM_SETTINGCHANGE,OnSettingChange)
MESSAGE_HANDLER(WM_SYSCOLORCHANGE,OnSettingChange/*OnSysColorChange*/)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
T* pThis=static_cast<T*>(this);
LRESULT lRes=pThis->DefWindowProc(uMsg,wParam,lParam);
pThis->GetMinMaxInfo(reinterpret_cast<LPMINMAXINFO>(lParam));
return lRes;
}
LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(!IsDocking())
{
// If we're floating, we're a top level window.
// We might be getting this message before the main frame
// (which is also a top-level window).
// The main frame handles this message, and refreshes
// system settings cached in CDWSettings. In case we
// are getting this message before the main frame,
// update these cached settings (so that when we update
// our caption's settings that depend on them,
// its using the latest).
CDWSettings settings;
settings.Update();
// In addition, because we are a top-level window,
// we should be sure to send this message to all our descendants
// in case there are common controls and other windows that
// depend on cached system metrics.
this->SendMessageToDescendants(uMsg, wParam, lParam, TRUE);
}
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 0;
}
*/
LRESULT OnWindowPosChanging(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return NULL;
}
LRESULT OnNcActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled=IsWindowEnabled();
return TRUE;
}
LRESULT OnNcCalcSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
T* pThis=static_cast<T*>(this);
CRect* pRc=reinterpret_cast<CRect*>(lParam);
CPoint ptTop(pRc->TopLeft());
(*pRc)-=ptTop;
pThis->NcCalcSize(pRc);
(*pRc)+=ptTop;
return NULL;
}
LRESULT OnNcHitTest(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
T* pThis=static_cast<T*>(this);
CRect rcWnd;
GetWindowRect(&rcWnd);
pt.x-=rcWnd.TopLeft().x;
pt.y-=rcWnd.TopLeft().y;
return pThis->NcHitTest(pt);
}
//OnSetIcon
//OnSetText
LRESULT OnCaptionChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// LockWindowUpdate();
DWORD style = ::GetWindowLong(m_hWnd,GWL_STYLE);
::SetWindowLong(m_hWnd, GWL_STYLE, style&(~WS_CAPTION));
LRESULT lRes=DefWindowProc(uMsg,wParam,lParam);
::SetWindowLong(m_hWnd, GWL_STYLE, style);
T* pThis=static_cast<T*>(this);
pThis->SetWindowPos(NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
// CWindowDC dc(m_hWnd);
// pThis->NcDraw(dc);
// LockWindowUpdate(FALSE);
return lRes;
}
LRESULT OnNcPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowDC dc(m_hWnd);
T* pThis=static_cast<T*>(this);
pThis->NcDraw(dc);
return NULL;
}
LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled=m_caption.OnAction(m_hWnd,wParam);
return !bHandled;
}
LRESULT OnNcLButtonUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
T* pThis=static_cast<T*>(this);
switch(wParam)
{
case HTCLOSE:
bHandled=pThis->CloseBtnPress();
break;
#ifdef DF_AUTO_HIDE_FEATURES
case HTPIN:
bHandled=pThis->PinBtnPress();
break;
#endif
default:
bHandled=FALSE;
}
return 0;
}
LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 0;
}
protected:
CCaption m_caption;
};
template <class T,
class TBase = CWindow,
class TDockingWinTraits = CEmptyTitleDockingWindowTraits>
class ATL_NO_VTABLE CTitleDockingWindowImpl
: public CTitleDockingWindowBaseImpl< T, TBase, TDockingWinTraits >
{
typedef CTitleDockingWindowBaseImpl< T, TBase, TDockingWinTraits > baseClass;
typedef CTitleDockingWindowImpl< T, TBase, TDockingWinTraits > thisClass;
public:
CTitleDockingWindowImpl()
{
m_pos.hdr.hBar=HNONDOCKBAR;
}
virtual bool Undock()
{
assert(IsDocking());
GetDockingPosition(&m_pos);
return baseClass::Undock();
}
virtual bool Hide()
{
bool bRes=true;
if(IsDocking())
{
bRes=GetDockingPosition(&m_pos);
assert(bRes);
if(bRes)
// bRes=Undock();
bRes=Float(&m_rcUndock,SWP_HIDEWINDOW);
assert(bRes);
}
else
m_pos.hdr.hBar=HNONDOCKBAR;
return (bRes && ShowWindow(SW_HIDE));
}
virtual bool Show()
{
bool bRes=true;
if(m_pos.hdr.hBar!=HNONDOCKBAR)
bRes=SetDockingPosition(&m_pos);
else
ShowWindow(SW_SHOW);
assert(bRes);
return bRes;
}
bool Toggle()
{
bool bRes=(static_cast<T*>(this)->IsWindowVisible()!=FALSE);
if(bRes)
{
Hide();
::SetFocus(::GetParent (m_hWnd));
}
else
Show();
return bRes;
}
bool GetDockingWindowPlacement(DFDOCKPOSEX* pHdr) const
{
bool bRes=baseClass::GetDockingWindowPlacement(pHdr);
pHdr->bVisible=static_cast<const T*>(this)->IsWindowVisible();
if( (!pHdr->bDocking
|| (!pHdr->bVisible) )
/*&& (m_pos.hdr.hBar!=HNONDOCKBAR)*/)
::CopyMemory(&pHdr->dockPos,&m_pos,sizeof(DFDOCKPOS));
return bRes;
}
bool SetDockingWindowPlacement(DFDOCKPOSEX* pHdr)
{
bool bRes=true;
pHdr->dockPos.hdr.hWnd=m_hWnd;
::CopyMemory(&m_pos,&(pHdr->dockPos),sizeof(DFDOCKPOS));
if(pHdr->bVisible)
bRes=baseClass::SetDockingWindowPlacement(pHdr);
else
{
if(IsDocking())
Undock();
::CopyRect(&m_rcUndock,&pHdr->rect);
bRes=(SetWindowPos(NULL,&m_rcUndock,SWP_NOZORDER | SWP_HIDEWINDOW |
SWP_NOACTIVATE )!=FALSE);
}
return bRes;
}
bool CanBeClosed(unsigned long /*param*/)
{
Hide();
return false;
}
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
LRESULT OnClose(UINT /*uMsg*/, WPARAM wParam, LPARAM/* lParam*/, BOOL& bHandled)
{
bHandled=!(static_cast<T*>(this)->CanBeClosed(wParam));
return 0;
}
LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(wParam==HTCAPTION)
{
if(IsDocking())
Float();
else
{
if(m_pos.hdr.hBar!=HNONDOCKBAR)
SetDockingPosition(&m_pos);
}
}
return 0;
}
protected:
DFDOCKPOS m_pos;
};
#define COMMAND_TOGGLE_MEMBER_HANDLER(id, member) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
{ \
member.Toggle(); \
}
//please don't use CStateKeeper class anymore!
//this class is obsolete and provided only for compatibility with previous versions.
//the CTitleDockingWindowImpl class provide all functionality of CStateKeeper
template<class T>
struct CStateKeeper : public T
{
};
//please don't use CTitleExDockingWindowImpl class anymore!
//this class is obsolete and provided only for compatibility with previous versions.
//the CTitleDockingWindowImpl class provide all functionality of CTitleExDockingWindowImpl
template <class T,
class TBase = CWindow,
class TDockingWinTraits = CEmptyTitleDockingWindowTraits>
struct ATL_NO_VTABLE CTitleExDockingWindowImpl : CTitleDockingWindowImpl< T, TBase, TDockingWinTraits >
{
};
}//namespace dockwins
#endif // __WTL_DW__DOCKINGWINDOW_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -