Click here to Skip to main content
15,886,518 members
Articles / Programming Languages / C++

Writing Win32 Apps with C++ only classes (part 3)

Rate me:
Please Sign up or sign in to vote.
4.76/5 (14 votes)
20 Jun 2004CPOL26 min read 68.9K   979   56  
C++ classes and wrappers to write W32 apps without MFC, ATL or other (part 3).
//DockMan.h

// does area management
#pragma once

#include "NLib/RegisterTypes.h"

namespace GE_{namespace NWin{
	//temporary window hide
	struct STmpWndHide
	{
	private:
		HWND _hwnd;
		bool _bShow;
	public:
		STmpWndHide(HWND hWnd)
		{	_hwnd = hWnd; _bShow = 0!=ShowWindow(hWnd, SW_HIDE); }
		~STmpWndHide()
		{	ShowWindow(_hwnd, (_bShow)? SW_SHOW: SW_HIDE); }
	};
	
	//child window, atoadapting itself to a given area
	interface IAutoLayout
	{
		//redo the layout. modify the ractangle to the remaining area 
		virtual void DoLayout(LPRECT lprc, HWND hMoving)=0;
		virtual S_Sides::e_side GetSideAlignment()=0;
	};

	//toplevel window, handling layouts
	interface ILayoutManager
	{
		virtual void RedoLayout(HWND hMoving)=0;
		struct Autonotify: public NUtil::SNmHdr<Autonotify>
		{//sent as notification to require layout recomputation
			LPRECT _lprc; //poiter to the ayout rectangle
			//pass the initial rectangle, return as the remaining part
			HWND _hwndMoving; //the window that causes the layout
		};

		static ILayoutManager* Get(HWND hWnd);
	};

	//Giving to  a window the capability to dock bars around
	class EDockBar:
		public EWnd,
		public IAutoLayout,
		public S_Sides
	{
	public:
		//a window docked to this bar
		struct XElem: 
			public EWnd,
			public S_Sides
		{
			SPlace _plPlacement; //the obtained placement
			SPlace _plWantedHorz; //the wanted placement
			SPlace _plWantedVert;
			SPlace _plWantedFloat;
			SPlace& _plWanted(e_side side)
			{	return isHorz(side)? _plWantedHorz: isVert(side)? _plWantedVert: _plWantedFloat; }
			e_side _sdLastDocked;
			UINT _nDragging;
			SPoint _pntBegin; 
			EDockBar* _pBeginParent;
			
			XElem();
			virtual ~XElem() { Detach(); }

			LRESULT OnNcLButtonDown(UINT hit, SPoint& point, bool& bHandled);
			LRESULT OnMouseMove(UINT flag, SPoint& point, bool& bHandled);
			LRESULT OnLButtonUp(UINT flag, SPoint& point, bool& bHandled);
			LRESULT OnNcLButtonDblClk(UINT hittest, SPoint& point, bool& bHandled);

			BEGIN_MSG_MAP(XElem)
				GE_WM_NCLBUTTONDOWN(OnNcLButtonDown)
				GE_WM_MOUSEMOVE(OnMouseMove)
				GE_WM_LBUTTONUP(OnLButtonUp)
				GE_WM_NCLBUTTONDBLCLK(OnNcLButtonDblClk)
				GE_FORWARD_COMMANDS(GetParent(*this))
			END_MSG_MAP()
		};

		typedef XElem* PElem;
		typedef std::list<PElem> TLstElem;

	protected:
		e_side _side;
		TLstElem _lstElem;

	protected:
		void DoInnerLayout(LPRECT lprc, HWND hMoving);

		LRESULT OnParentNotifyDestroy(UINT nID, HWND hChild, bool& bHandled);
	public:
		virtual void DoLayout(LPRECT lprc, HWND hMoving);
		virtual S_Sides::e_side GetSideAlignment() { return _side; }

		HWND Create(HINSTANCE hInst, e_side side, HWND hParent);
		void AddElement(HWND hWnd, LPCRECT lpPlacement);
		void RemoveElement(HWND hWnd);
	public:
		BEGIN_MSG_MAP(EDockBar)
			GE_WM_PARENTNOTIFY_DESTROY(OnParentNotifyDestroy)
			GE_FORWARD_COMMANDS(GetParent(*this))
		END_MSG_MAP()

		//EWnd overrides
		virtual ~EDockBar() { Detach(); }
	};
	
	//Giving a window the capability to fill an area
	class EClientWnd:
		public EWnd,
		public IAutoLayout
	{
	public:
		//IAutoayout
		virtual void DoLayout(LPRECT lprc, HWND hMoving);
		virtual S_Sides::e_side GetSideAlignment() { return S_Sides::sd_inside;}
		//EWnd
		virtual void OnAddRef(TRefCount* pRC);
		virtual void OnRelease(TRefCount* pRC);
	public:
		BEGIN_MSG_MAP(EClientWnd)
		END_MSG_MAP()
	};
	
	//translating sizing into layout management
	struct XLayoutProvider:
		public EWnd,
		public ILayoutManager
	{
	private:
		SRect _rcFree;
		bool _bDoingLayout;
	public:
		LPCRECT GetFreeRect() const { return _rcFree; }
		LRESULT OnSize(UINT flags, const NWin::SSize& sz, bool& bHandled);
		LRESULT OnEraseBkg(HDC hDC, bool& bHandled);

		XLayoutProvider() { _bDoingLayout = false; }
		virtual ~XLayoutProvider() { Detach(); }

		BEGIN_MSG_MAP(XLayoutProvider)
			GE_WM_SIZE(OnSize)
			GE_WM_ERASEBKGND(OnEraseBkg)
		END_MSG_MAP()

		//ILayoutManager
		virtual void RedoLayout(HWND hMoving);

		//helper
		static XLayoutProvider* Get(HWND hWnd); //gets or create a CLayoutprovider for a given HWND
	};



	//giving a frame the capability to hav a client and dockbars
	class EDockBarManager:
		public EWnd,
		public S_Sides
	{
	private:
		EClientWnd _clientwindow;
		EDockBar _barleft, _bartop, _barright, _barbottom;
		EDockBar& bar(e_side side) { return (&_barleft)[side];}
	protected:
		LRESULT OnILayoutManagerAutonotify(int nID, ILayoutManager::Autonotify& nm, bool& bHandled);
	public:
		EDockBarManager();

		BEGIN_MSG_MAP(EDockFrameWnd)
			GE_FORWARD_COMMANDS(_clientwindow)
			GE_NOTIFY_CODE_REGISTREDHANDLER(OnILayoutManagerAutonotify, ILayoutManager::Autonotify)
		END_MSG_MAP()

		void SetClient(HWND hWndClient);
		void SetBars(f_sides flg = -1); //all bars
		void DockElement(HWND hwnd, e_side side, LPCRECT lprcPlacement=NULL)
		{	if (!!bar(side)) bar(side).AddElement(hwnd, lprcPlacement); }
		void UndockRemoveElement(HWND hWnd)
		{	_barleft.RemoveElement(hWnd); _bartop.RemoveElement(hWnd); _barright.RemoveElement(hWnd); _barbottom.RemoveElement(hWnd); }

		//EWnd overrides
		virtual ~EDockBarManager() { Detach(); }
	};
}}


#ifdef GE_FORCEINLINE
#include "DockMan.cpp"
#endif

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Italy Italy
Born and living in Milan (Italy), I'm an engineer in electronics actually working in the ICT department of an important oil/gas & energy company as responsible for planning and engineering of ICT infrastructures.
Interested in programming since the '70s, today I still define architectures for the ICT, deploying dedicated specific client application for engineering purposes, working with C++, MFC, STL, and recently also C# and D.

Comments and Discussions