// 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.
#if !defined(AFX_DOCKINGFRAME_H__00E099AA_F8A4_40A6_8368_4FF0870CC58D__INCLUDED_)
#define AFX_DOCKINGFRAME_H__00E099AA_F8A4_40A6_8368_4FF0870CC58D__INCLUDED_
#include <atlframe.h>
#include <DockMisc.h>
#include <PackageWindow.h>
namespace dockwins{
/////////////////CDockingFrameImplBase
template <class T, class TBase,class TWinTraits = CDockingFrameTraits >
class ATL_NO_VTABLE CDockingFrameImplBase : public TBase
{
typedef CDockingFrameImplBase<T,TBase,TWinTraits> thisClass;
typedef TBase baseClass;
typedef TWinTraits CTraits;
typedef CTraits::CSplitterBar CSplitterBar;
typedef CPackageWindowFrame<CTraits> CPackageFrame;
typedef CSubWndFramesPackage<CPackageFrame,CTraits> CWndPackage;
typedef CDockingBarStyle CStyle;
public:
CDockingFrameImplBase()
:m_vPackage(false),m_hPackage(true)
{
}
CStyle GetStyle() const
{
return m_style;
}
CStyle SetStyle(const CStyle& style)
{
CStyle prevStyle=m_style;
m_style=style;
return prevStyle;
}
void ApplySystemSettings()
{
if(!m_style.IgnoreSystemSettings())
{
BOOL bFullDrag;
BOOL bRes=::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bFullDrag, 0);
if(bRes&&(m_style.GhostDrag()==(bFullDrag!=FALSE)))
{
CStyle style=m_style;
style.Set(CStyle::mskGhostDrag,bFullDrag ? CStyle::sFullDrag : CStyle::sGhostDrag);
SetStyle(style);
m_vPackage.SystemSettingsChange();
m_hPackage.SystemSettingsChange();
}
}
}
bool InitializeDockingFrame(CStyle style=CStyle::sUseSysSettings)
{
SetStyle(style);
T* pThis = static_cast<T*>(this);
pThis->ApplySystemSettings();
pThis->UpdateLayout();
m_vPackage.Insert(&m_hPackage,m_vPackage);
m_vPackage.UpdateLayout(m_vPackage);
m_hPackage.Insert(&m_hWndClient,m_vPackage);
return true;
}
void UpdateLayout(BOOL bResizeBars = TRUE)
{
CRect rc;
GetClientRect(&rc);
UpdateBarsPosition(rc, bResizeBars);
m_vPackage.UpdateLayout(rc);
}
void Draw(CDC& dc)
{
m_vPackage.Draw(dc);
m_hPackage.Draw(dc);
}
HCURSOR GetCursor(const CPoint& pt)
{
HCURSOR hCursor=NULL;
if(m_hPackage.PtInRect(pt))
hCursor=m_hPackage.GetCursor(pt);
else
{
if(m_vPackage.PtInRect(pt))
hCursor=m_vPackage.GetCursor(pt);
}
return hCursor;
}
bool StartSliding(const CPoint& pt)
{
bool bRes;
if(m_hPackage.PtInRect(pt))
bRes=m_hPackage.StartSliding(m_hWnd,pt,m_style.GhostDrag());
else
bRes=m_vPackage.StartSliding(m_hWnd,pt,m_style.GhostDrag());
if(bRes)
RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW |
((m_hWndClient==NULL)?RDW_ERASE:0));
return bRes;
}
bool AdjustDragRect(DFDOCKRECT* pHdr)
{
CRect rc;
GetClientRect(&rc);
int limit=rc.Width()/3;
if(pHdr->rect.right-pHdr->rect.left>limit)
pHdr->rect.right=pHdr->rect.left+limit;
limit=GetSystemMetrics(SM_CXMIN);
if(pHdr->rect.right-pHdr->rect.left<limit)
pHdr->rect.right=pHdr->rect.left+limit;
limit=rc.Height()/3;
if(pHdr->rect.bottom-pHdr->rect.top>limit)
pHdr->rect.bottom=pHdr->rect.top+limit;
limit=GetSystemMetrics(SM_CYMIN);
if(pHdr->rect.bottom-pHdr->rect.top<limit)
pHdr->rect.bottom=pHdr->rect.top+limit;
return true;
}
LRESULT AcceptDock(DFDOCKRECT* pHdr)
{
ScreenToClient(&(pHdr->rect));
pHdr->hdr.hBar=m_hWnd;
LRESULT lRes=m_vPackage.AcceptDock(pHdr);
if(!lRes)
pHdr->hdr.hBar=HNONDOCKBAR;
ClientToScreen(&(pHdr->rect));
return lRes;
}
LRESULT Dock(DFDOCKRECT* pHdr)
{
LRESULT lRes=FALSE;
ScreenToClient(&(pHdr->rect));
if(m_hPackage.PtInRect(CPoint(pHdr->rect.left,pHdr->rect.top))
&&
!((pHdr->rect.right-pHdr->rect.left==m_vPackage.Width())
&& pHdr->rect.left ==m_vPackage.left) )
lRes=m_hPackage.Dock(pHdr);
else
lRes=m_vPackage.Dock(pHdr);
ClientToScreen(&(pHdr->rect));
RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW |
((m_hWndClient==NULL)?RDW_ERASE:0));
return lRes;
}
LRESULT Undock(DFMHDR* pHdr)
{
bool bRes;
assert(::IsWindow(pHdr->hWnd));
if(CDockingBarStyle::GetStyle(pHdr->hWnd).IsHorizontal())
bRes=m_vPackage.Undock(pHdr,NULL);
else
bRes=m_hPackage.Undock(pHdr,m_hWndClient);
RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW |
((m_hWndClient==NULL)?RDW_ERASE:0));
return bRes;
}
template<class T>
bool DockWindow(T& dockWnd,CDockingSide side,unsigned long nBar,float fPctPos,unsigned long nWidth, unsigned long nHeight)
{
if(dockWnd.IsDocking())
dockWnd.Undock();
DFDOCKPOS dockHdr;
dockHdr.hdr.hWnd=dockWnd.m_hWnd;
dockHdr.hdr.hBar=m_hWnd;
dockHdr.hdr.code=DC_SETDOCKPOSITION;
dockHdr.dwDockSide=side;
dockHdr.nBar=nBar;
dockHdr.fPctPos=fPctPos;
dockHdr.nWidth=nWidth;
dockHdr.nHeight=nHeight;
return SetDockingPosition(&dockHdr);
}
bool SetDockingPosition(DFDOCKPOS* pHdr)
{
assert(pHdr->hdr.hWnd);
bool bRes;
CDockingSide side(pHdr->dwDockSide);
if(side.IsHorizontal())
bRes=m_hPackage.SetDockingPosition(pHdr,m_hWndClient);
else
bRes=m_vPackage.SetDockingPosition(pHdr,NULL);
RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW |
((m_hWndClient==NULL)?RDW_ERASE:0));
return bRes;
}
bool GetDockingPosition(DFDOCKPOS* pHdr) const
{
pHdr->dwDockSide=CDockingSide::sBottom;
bool bRes=m_vPackage.GetDockingPosition(pHdr,NULL);
if(!bRes)
{
pHdr->dwDockSide=CDockingSide::sRight;
bRes=m_hPackage.GetDockingPosition(pHdr,m_hWndClient);
}
return bRes;
}
protected:
////////////////messages handlers//////////////////////
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_SETCURSOR,OnSetCursor)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
/////////////////////
MESSAGE_HANDLER(WMDF_DOCK,OnDock)
MESSAGE_HANDLER(WMDF_STYLE,OnStyle)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
T* pThis=static_cast<T*>(this);
pThis->InitializeDockingFrame();
bHandled=FALSE;
return NULL;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pThis=static_cast<T*>(this);
pThis->ApplySystemSettings();
return NULL;
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pThis=static_cast<T*>(this);
CPaintDC dc(pThis->m_hWnd);
pThis->Draw(dc);
return 0;
}
LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return DefWindowProc(uMsg,wParam,lParam);
}
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pThis = static_cast<T*>(this);
if((HWND)wParam == pThis->m_hWnd && LOWORD(lParam) == HTCLIENT)
{
DWORD dwPos = ::GetMessagePos();
CPoint pt(GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos));
pThis->ScreenToClient(&pt);
HCURSOR hCursor=pThis->GetCursor(pt);
bHandled=(hCursor!=NULL);
if(bHandled)
SetCursor(hCursor);
return bHandled;
}
bHandled = FALSE;
return 0;
}
LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
CPoint pt( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
T* pThis = static_cast<T*>(this);
bHandled=pThis->StartSliding(pt);
return !bHandled;
}
LRESULT OnDock(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRes=FALSE;
T* pThis=static_cast<T*>(this);
DFMHDR* pHdr=reinterpret_cast<DFMHDR*>(lParam);
switch(pHdr->code)
{
case DC_ADJUSTDRAGRECT:
lRes=pThis->AdjustDragRect(reinterpret_cast<DFDOCKRECT*>(pHdr));
break;
case DC_ACCEPT:
lRes=pThis->AcceptDock(reinterpret_cast<DFDOCKRECT*>(pHdr));
break;
case DC_DOCK:
lRes=pThis->Dock(reinterpret_cast<DFDOCKRECT*>(pHdr));
break;
case DC_UNDOCK:
lRes=pThis->Undock(pHdr);
break;
case DC_SETDOCKPOSITION:
lRes=pThis->SetDockingPosition(reinterpret_cast<DFDOCKPOS*>(pHdr));
break;
case DC_GETDOCKPOSITION:
lRes=pThis->GetDockingPosition(reinterpret_cast<DFDOCKPOS*>(pHdr));
break;
}
return lRes;
}
LRESULT OnStyle(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRes;
T* pThis=static_cast<T*>(this);
if(LOWORD(wParam))
lRes=pThis->SetStyle(lParam/*,HIWORD(wParam)==TRUE*/);
else
lRes=pThis->GetStyle();
return lRes;
}
protected:
CStyle m_style;
CWndPackage m_vPackage;
CWndPackage m_hPackage;
CRect m_rcClient;
};
typedef CDockingFrameTraitsT< CSimpleSplitterBarEx<6>,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,0> CDockingSiteTraits;
/////////////////CDockingSiteBasement
template <class T, class TBase = CWindow, class TWinTraits = CDockingSiteTraits>
class ATL_NO_VTABLE CDockingSiteBasement : public CWindowImpl<T, TBase, TWinTraits >
{
typedef CDockingSiteBasement<T, TBase, TWinTraits > thisClass;
public:
DECLARE_WND_CLASS(NULL)
CDockingSiteBasement():m_hWndClient(NULL)
{
}
protected:
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
END_MSG_MAP()
LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(wParam != SIZE_MINIMIZED)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
bHandled = FALSE;
return 1;
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_hWndClient != NULL)
return 1;
bHandled = FALSE;
return 0;
}
protected:
HWND m_hWndClient;
};
/////////////////CDockingSiteImpl
template < class T,
class TBase = CWindow,
class TWinTraits = CDockingSiteTraits,
class TBaseImpl = CDockingSiteBasement<T,TBase,TWinTraits> >
class CDockingSiteImpl:
public CDockingFrameImplBase< T, TBaseImpl ,TWinTraits >
{
typedef CDockingSiteImpl<T,TBase,TWinTraits,TBaseImpl> thisClass;
typedef CDockingFrameImplBase< T, TBaseImpl ,TWinTraits > baseClass;
public:
DECLARE_WND_CLASS(_T("CDockingSiteImpl"))
void UpdateLayout(BOOL bResizeBars = TRUE)
{
bResizeBars;// avoid level 4 warning
CRect rc;
T* pT = static_cast<T*>(this);
pT->GetClientRect(&rc);
m_vPackage.UpdateLayout(rc);
}
};
/////////////////CDockingFrameImpl
template < class T,
class TBase = CWindow,
class TWinTraits = CDockingFrameTraits >
class ATL_NO_VTABLE CDockingFrameImpl:
public CDockingFrameImplBase< T, CFrameWindowImpl< T ,TBase, TWinTraits> ,TWinTraits >
{
public:
DECLARE_WND_CLASS(_T("CDockingFrameImpl"))
};
/////////////////CMIDIDockingFrameImpl
template <class T,
class TBase = CMDIWindow,
class TWinTraits = CDockingFrameTraits >
class ATL_NO_VTABLE CMDIDockingFrameImpl :
public CDockingFrameImplBase< T, CMDIFrameWindowImpl< T ,TBase, TWinTraits> ,TWinTraits >
{
public:
DECLARE_WND_CLASS(_T("CMDIDockingFrameImpl"))
};
}//namespace dockwins
#endif // !defined(AFX_DOCKINGFRAME_H__00E099AA_F8A4_40A6_8368_4FF0870CC58D__INCLUDED_)