Click here to Skip to main content
15,895,656 members
Articles / Desktop Programming / WTL

The Spring Computing Windows Controls

Rate me:
Please Sign up or sign in to vote.
4.27/5 (4 votes)
27 Sep 20014 min read 85.7K   2K   32  
A set of Win32 Windows controls.
#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__

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
Coming soon...

Comments and Discussions