#ifndef __ATLSPCTLW_H__
#define __ATLSPCTLW_H__
#pragma once
#ifndef __cplusplus
#error atlspctlw.h requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLSPCTL_H__
#error atlspctlw.h requires atlspctl.h to be included first
#endif
/////////////////////////////////////////////////////////////////////////////
// Forward declarations
template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class CCaptionBarWindowImpl;
template <class T> class CCaptionBarWindow;
/////////////////////////////////////////////////////////////////////////////
// CCaptionBarWindowImpl
template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CCaptionBarWindowImpl : public CWindowImpl<T, TBase, TWinTraits>
{
public:
DECLARE_WND_CLASS(NULL)
// Constants
enum {
m_cySpacing = 5,
m_cchTitle = 128
};
// Data members
CCaptionBarCtrl m_captionBar;
HWND m_hWndClient;
TCHAR m_pszTitle[m_cchTitle];
// Constructor
CCaptionBarWindowImpl() : m_hWndClient(0)
{
m_pszTitle[0] = 0;
}
// Attributes
CCaptionBarCtrl& GetCaptionBarCtrl()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(::IsWindow(m_captionBar.m_hWnd));
return m_captionBar;
}
HWND SetClient(HWND hWnd)
{
HWND hWndOldClient = m_hWndClient;
m_hWndClient = hWnd;
if(m_hWnd != NULL) {
T* pT = static_cast<T*>(this);
pT->RecalcLayout();
}
return hWndOldClient;
}
// Implementation
HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR pszTitle = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0U)
{
ATLASSERT(m_hWnd == NULL);
if (pszTitle != 0)
lstrcpyn(m_pszTitle, pszTitle, m_cchTitle);
if (rect.m_lpRect == NULL || rect.m_lpRect == &TBase::rcDefault)
::GetClientRect(hWndParent, rect.m_lpRect);
return CWindowImpl<T, TBase, TWinTraits>::Create(hWndParent, *rect.m_lpRect, NULL, dwStyle, dwExStyle, nID);
}
// Message Handlers
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
m_captionBar.Create(m_hWnd, NULL, m_pszTitle, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS);
return 0L;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(wParam != SIZE_MINIMIZED) {
T* pT = static_cast<T*>(this);
pT->RecalcLayout();
}
return 0L;
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
return 1L; // no further processing
}
LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
if(m_hWndClient != NULL && ::IsWindowVisible(m_hWndClient))
::SetFocus(m_hWndClient);
bHandled = FALSE;
return 1L;
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC hDC(m_hWnd);
RECT rect;
GetClientRect(&rect);
// Offset client dimensions
RECT rectCB;
m_captionBar.GetClientRect(&rectCB);
rect.top += rectCB.bottom - rectCB.top;
// Draw gap
CRect rectSpacing = rect;
rectSpacing.bottom = rectSpacing.top + m_cySpacing;
rect.top += m_cySpacing;
hDC.FillRect(&rectSpacing, (HBRUSH)LongToPtr(COLOR_BTNFACE + 1));
// Draw pane
if (m_hWndClient == NULL) {
T* pT = static_cast<T*>(this);
pT->DrawPane(hDC.m_hDC, rect);
}
return 0L;
}
LRESULT OnCaptionBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
pT->RecalcLayout();
return 0L;
}
// Message Map
BEGIN_MSG_MAP(CCaptionBarWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
NOTIFY_CODE_HANDLER(CBN_AUTOSIZE, OnCaptionBarAutoSize)
FORWARD_NOTIFICATIONS()
END_MSG_MAP()
// Overridables
public:
void RecalcLayout()
{
RECT rect;
GetClientRect(&rect);
// position bar and offset client dimensions
m_captionBar.SendMessage(WM_SIZE, 0, 0);
RECT rectCB;
m_captionBar.GetWindowRect(&rectCB);
rect.top += rectCB.bottom - rectCB.top;
rect.top += m_cySpacing;
// resize client window
if(m_hWndClient != NULL) {
::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
}
// called only if pane is empty
void DrawPane(CDCHandle hDC, const CRect& rect)
{
CRect rcPane = rect;
if((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
hDC.DrawEdge(&rcPane, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
hDC.FillRect(&rcPane, (HBRUSH)LongToPtr(COLOR_APPWORKSPACE + 1));
}
};
template <class T>
class CCaptionBarWindow : public CCaptionBarWindowImpl<T>
{
public:
DECLARE_WND_CLASS(NULL)
};
#endif // __ATLSPCTLW_H__