⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wndfrmpkg.h

📁 一款最完整的工业组态软源代码
💻 H
📖 第 1 页 / 共 3 页
字号:
// 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.

#ifndef __WTL_DW__WNDFRMPKG_H__
#define __WTL_DW__WNDFRMPKG_H__

#pragma once

#ifndef __ATLMISC_H__
        #error WndFrmPkg.h requires atlmisc.h to be included first
#endif

#include <memory>
#include "ssec.h"
#include "DDTracker.h"
#ifdef USE_BOOST
#include<boost/smart_ptr.hpp>
#endif

namespace dockwins{

class CWndFrame
{
public:
	typedef long position;
	typedef long distance;

	class CCmp
	{
	public:
		CCmp(HWND hWnd)	:m_hWnd(hWnd)
		{
		}
		bool operator ()(const CWndFrame& frame) const
		{
			return (frame.hwnd() == m_hWnd);
		}
	protected:
		HWND m_hWnd;
	};

	CWndFrame(position pos=0,HWND hWnd=NULL)
		:m_hWnd(hWnd),m_pos(pos)
	{
	}

	HWND hwnd() const
	{
		return m_hWnd;
	}

	operator position() const
	{
		return (position)m_pos;
	}

	CWndFrame& operator += (position val)
	{
		m_pos+=val;
		return *this;
	}
	CWndFrame& operator -= (position val)
	{
		m_pos-=val;
		return *this;
	}

	CWndFrame& operator = (position pos)
	{
		m_pos=pos;
		return *this;
	}

	CWndFrame& operator = (double pos)
	{
		m_pos=pos;
		return *this;
	}

	double get_real()
	{
		return m_pos;
	}

	HDWP DeferFramePos(HDWP hdwp,long x1,long y1,long x2,long y2) const
	{
		return ::DeferWindowPos(hdwp,hwnd(),
								NULL,
								x1,y1,
								x2-x1,y2-y1,
								SWP_NOZORDER | SWP_NOACTIVATE);
	}
	void GetMinMaxInfo(LPMINMAXINFO pMinMaxInfo) const
	{
		::SendMessage(m_hWnd,WM_GETMINMAXINFO,NULL,reinterpret_cast<LPARAM>(pMinMaxInfo));
	}
	distance MinDistance() const
	{
		DFMHDR dockHdr;
		dockHdr.code=DC_GETMINDIST;
		dockHdr.hWnd=m_hWnd;
		dockHdr.hBar=::GetParent(m_hWnd);
		assert(::IsWindow(dockHdr.hBar));
		return static_cast<distance>(::SendMessage(dockHdr.hBar,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(&dockHdr)));
	}
protected:
	double m_pos;
	mutable HWND m_hWnd;
};

//template<class T,const T::distance TMinDist=0>
//struct CWndFrameTraits : ssec::spraits<T, T::position, T::distance/*,TMinDist*/>
//{
//	typedef ssec::spraits<T,position,position/*,TMinDist*/> baseClass;
//	static distance min_distance(const T& x)
//	{
//		const distance dist=TMinDist;
//		return dist+x.MinDistance();
//	}
//
//};

template< class TFrame = CWndFrame , class TTraits = CDockingFrameTraits>
class CWndFramesPackageBase
{
	typedef typename TFrame CFrame;
	typedef typename TTraits CTraits;
	typedef typename CTraits::CSplitterBar	CSplitterBar;
	typedef CWndFramesPackageBase<CFrame,TTraits> thisClass;
protected:
	enum {splitterSize=CSplitterBar::sbThickness};
	typedef typename CFrame::position	position;

#if _MSC_VER >= 1310
	template<class T,const typename T::distance TMinDist=0>
#else
	template<class T,const T::distance TMinDist=0>
#endif
	struct CWndFrameTraits : ssec::spraits<T, typename T::position, typename T::distance/*,TMinDist*/>
	{
		typedef ssec::spraits<T,position,position/*,TMinDist*/> baseClass;
		static distance min_distance(const T& x)
		{
			const distance dist=TMinDist;
			return dist+x.MinDistance();
		}

	};
	typedef CWndFrameTraits<CFrame,splitterSize> CFrameTraits;
	typedef ssec::ssection<CFrame,CFrameTraits> CFrames;

	typedef typename CFrames::iterator				iterator;
	typedef typename CFrames::reverse_iterator		reverse_iterator;
	typedef typename CFrames::const_iterator			const_iterator;
	typedef typename CFrames::const_reverse_iterator	const_reverse_iterator;

	typedef ssec::bounds_type<position> CBounds;
protected:
	struct CEmbeddedSplitterBar : public CSplitterBar
	{
		CEmbeddedSplitterBar(bool bHorizontal,position vertex,const CRect& rcClient)
				:CSplitterBar(bHorizontal)
		{
            if(IsHorizontal())
            {
                    top=vertex;
                    bottom=top+GetThickness();
                    left=rcClient.left;
                    right=rcClient.right;
            }
            else
            {
                    left=vertex;
                    right=left+GetThickness();
                    top=rcClient.top;
                    bottom=rcClient.bottom;
            }

		}
	};
	class CEmbeddedSplitterBarPainter
	{
	public:
		CEmbeddedSplitterBarPainter(CDC& dc,bool bHorizontal,const CRect& rc)
			:m_dc(dc),m_rc(rc),m_bHorizontal(bHorizontal)
		{
		}
		void operator()(const CFrame& ref) const
		{
			CEmbeddedSplitterBar splitter(m_bHorizontal,ref,m_rc);
			splitter.Draw(m_dc);
		}
	protected:
		const	CRect& m_rc;
		bool	m_bHorizontal;
		CDC&	m_dc;
	};

	class CSplitterMoveTrackerBase : public IDDTracker//CDDTrackerBaseT<CSizeTrackerBase>
	{
	protected:
		void SetPosition()
		{
			assert(m_bounds.bind(m_pos)==m_pos);
			m_frames.set_position(m_i,m_pos);
			m_owner.Arrange(m_rc);
			m_wnd.RedrawWindow(&m_rc,NULL,RDW_INVALIDATE | RDW_UPDATENOW);
		}
	public:
		CSplitterMoveTrackerBase(HWND hWnd,thisClass& owner,const CPoint& pt,const CRect& rc)
			:m_wnd(hWnd),m_owner(owner),m_frames(owner.m_frames),m_rc(rc)
		{
			position pos=owner.IsHorizontal() ? pt.x : pt.y;
			m_i=m_frames.locate(pos);
			if(m_i!=m_frames.end())
			{
				m_pos=(*m_i);
				m_offset=pos-m_pos;
				m_frames.get_effective_bounds(m_i,m_bounds);
			}
		}
		operator iterator() const
		{
			return m_i;
		}
        void OnMove(long x, long y)
        {
			position pos = m_owner.IsHorizontal() ? x : y;
			pos=m_bounds.bind(pos-m_offset);
			if(pos!=m_pos)
			{
				m_pos=pos;
				Move();
			}
		}
		virtual void Move()=0;

	protected:
		thisClass&		m_owner;
		CFrames&		m_frames;
		iterator		m_i;
		CBounds			m_bounds;
		position		m_pos;
		position		m_offset;
		const CRect&	m_rc;
		CWindow			m_wnd;
	};

	friend class CSplitterMoveTrackerBase;

	class CSplitterMoveTrackerFull : public CSplitterMoveTrackerBase
	{
	public:
		CSplitterMoveTrackerFull(HWND hWnd,thisClass& owner,const CPoint& pt,const CRect& rc)
			:CSplitterMoveTrackerBase(hWnd,owner,pt,rc)
		{
		}
		void Move()
		{
			SetPosition();
		}
	};

	class CSplitterMoveTrackerGhost : public CSplitterMoveTrackerBase
	{
		typedef CEmbeddedSplitterBar CSplitterBar;
        typedef CSimpleSplitterBarSlider<CSplitterBar> CSlider;
	public:
		CSplitterMoveTrackerGhost(HWND hWnd,thisClass& owner,
									const CPoint& pt,const CRect& rc)
			:CSplitterMoveTrackerBase(hWnd,owner,pt,rc),
			  m_dc(::GetWindowDC(NULL)),m_splitter(!owner.IsHorizontal(),m_pos,rc),m_slider(m_splitter)
		{
			CPoint point(rc.TopLeft ());
			::ClientToScreen(hWnd,&point);
			CSize offset(point.x-rc.left,point.y-rc.top);
			m_splitter+=offset;
			m_ghOffset=owner.IsHorizontal()
									?offset.cx
									:offset.cy;
		}
        void BeginDrag()
        {
            m_splitter.DrawGhostBar(m_dc);
        }
        void EndDrag(bool bCanceled)
        {
            m_splitter.CleanGhostBar(m_dc);
            if(!bCanceled)
                SetPosition();
        }
		void Move()
		{
			m_splitter.CleanGhostBar(m_dc);
			m_slider=m_pos+m_ghOffset;
			m_splitter.DrawGhostBar(m_dc);
		}

	protected:
		position		m_ghOffset;
		CSplitterBar	m_splitter;
		CSlider			m_slider;
		CDC				m_dc;
	};
	template<long add=0>
	class CMinMaxInfoAccumulator
	{
		typedef LPMINMAXINFO (*CFunPtr)(MINMAXINFO& mmInfo,LPMINMAXINFO pMinMaxInfo);
	public:
		CMinMaxInfoAccumulator(bool bHorizontal)
		{
			m_pFun=bHorizontal ? &MinMaxInfoH : &MinMaxInfoV;
		}
		LPMINMAXINFO operator() (LPMINMAXINFO pMinMaxInfo,const CFrame& x) const
		{
			MINMAXINFO mmInfo;
			ZeroMemory(&mmInfo,sizeof(MINMAXINFO));
			x.GetMinMaxInfo(&mmInfo);
			return (*m_pFun)(mmInfo,pMinMaxInfo);
		}
	protected:
		static LPMINMAXINFO MinMaxInfoH(MINMAXINFO& mmInfo,LPMINMAXINFO pMinMaxInfo)
		{
			if(pMinMaxInfo->ptMinTrackSize.y<mmInfo.ptMinTrackSize.y)
				pMinMaxInfo->ptMinTrackSize.y=mmInfo.ptMinTrackSize.y;
			pMinMaxInfo->ptMinTrackSize.x+=mmInfo.ptMinTrackSize.x+add;
			return pMinMaxInfo;
		}
		static LPMINMAXINFO MinMaxInfoV(MINMAXINFO& mmInfo,LPMINMAXINFO pMinMaxInfo)
		{
			if(pMinMaxInfo->ptMinTrackSize.x<mmInfo.ptMinTrackSize.x)
				pMinMaxInfo->ptMinTrackSize.x=mmInfo.ptMinTrackSize.x;
			pMinMaxInfo->ptMinTrackSize.y+=mmInfo.ptMinTrackSize.y+add;
			return pMinMaxInfo;
		}
	protected:
		CFunPtr	m_pFun;
	};
protected:
    bool ArrangeH(const CRect& rc)
    {
        HDWP hdwp=reinterpret_cast<HDWP>(TRUE);
        const_iterator begin=m_frames.begin();
        const_iterator end=m_frames.end();
        if(begin!=end)
        {
            hdwp=BeginDeferWindowPos(m_frames.size());
            const_iterator next=begin;
            while((hdwp!=NULL)&&(++next!=end))
            {
                long x=(*begin)+splitterSize;
                hdwp=begin->DeferFramePos(hdwp,
											x,
											rc.top,
											(*next),
											rc.bottom);
                begin=next;
            }
            if(hdwp!=NULL)
            {
                long x=(*begin)+splitterSize;
                hdwp=begin->DeferFramePos(hdwp,
											x,
											rc.top,
											rc.right,
											rc.bottom);
                if(hdwp)
					hdwp=reinterpret_cast<HDWP>(EndDeferWindowPos(hdwp));
            }
        }
        return hdwp!=NULL;
    }

    bool ArrangeV(const CRect& rc)
    {
        HDWP hdwp=reinterpret_cast<HDWP>(TRUE);
        const_iterator begin=m_frames.begin();
        const_iterator end=m_frames.end();
        if(begin!=end)
        {
            hdwp=BeginDeferWindowPos(m_frames.size());
            const_iterator next=begin;
            while((hdwp!=NULL)&&(++next!=end))
            {
                long y=(*begin)+splitterSize;
                hdwp=begin->DeferFramePos(hdwp,
											rc.left,
											y,
											rc.right,
											(*next));
                begin=next;
            }
            if(hdwp!=NULL)
            {
                long y=(*begin)+splitterSize;
                hdwp=begin->DeferFramePos(hdwp,
											rc.left,
											y,
											rc.right,
											rc.bottom);
                if(hdwp)
					hdwp=reinterpret_cast<HDWP>(EndDeferWindowPos(hdwp));
            }
        }
        return hdwp!=NULL;
    }
    bool Arrange(const CRect& rcClient)
    {
		bool bRes;
		if(IsHorizontal())
			bRes=ArrangeH(rcClient);
		else
			bRes=ArrangeV(rcClient);
		return bRes;
    }

	CWndFramesPackageBase(bool bHorizontal)
		:m_bHorizontal(bHorizontal),m_frames(0,0)
	{
	}
public:
	bool IsHorizontal() const
	{
		return m_bHorizontal;
	}

	void SetOrientation(bool bHorizontal)
	{
		m_bHorizontal=bHorizontal;
	}

	HCURSOR GetCursor(const CPoint& pt,const CRect& rc) const
	{
		HCURSOR hCursor=NULL;
		position pos=IsHorizontal() ?pt.x :pt.y;
		const_iterator i=m_frames.locate(pos);
		if(i!=m_frames.end())
		{
			CEmbeddedSplitterBar splitter(!IsHorizontal(),(*i),rc);
			hCursor=splitter.GetCursor(pt);
		}
		return hCursor;
	}
/*
	bool StartSliding(HWND hWnd,const CPoint& pt,const CRect& rc,bool bGhostMove)
	{
		std::auto_ptr<CSplitterMoveTrackerBase> pTracker;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -