'"True'" Dynamic Splitter Bar

If you want to implement splitter window in your MFC based application that redraws its panes dynamically (like Microsoft Windows Explorer does when you have IE4.0 installed) then you can use my simple class CDynSplitterWnd. Dragging CDynSplitterWnd splitter bar does not show a hatched line, instead it immediately redraws itself at a new position as well as forces all its panes to redraw themselves.

To implement CDynSplitterWnd window simply:

1. Change declaration of your splitter window instances to be instances of the CDynSplitterWnd class rather than CSplitterWnd class.

2. Or derive your own CSplitterWnd based classes (if you have them) from CDynSplitterWnd instead, and don't forget about BEGIN_MESSAGE_MAP(CYourSplitterWnd, CDynSplitterWnd) macro.

CDynSplitterWnd works best for the "1column 2 rows static splitter" situation. If you have MFC dynamic splitters create them with SIZE sizeMin parameter in CSplitterWnd ::Create(...) function set to CSize(1,1) or CSize(0,0).

// DynSplitterWnd.h file
//
class CDynSplitterWnd : public CSplitterWnd
{
	// Construction
	public:
		CDynSplitterWnd();
		
		// Attributes
	public:
		BOOL	IsDynamic()
			
		{ return m_bDynSplit; }
		void	SetDynamic(BOOL bDynSplit = TRUE) 
		{ m_bDynSplit = bDynSplit; }
		
		// Operations
	public:
		
		// Overrides
		// ClassWizard generated virtual function overrides
		//{{AFX_VIRTUAL(CDynSplitterWnd)
		virtual void OnInvertTracker(const CRect& rect);
		virtual void StartTracking(int ht);
		virtual void StopTracking(BOOL bAccept);
		//}}AFX_VIRTUAL
		
		// Implementation
	public:
		virtual ~CDynSplitterWnd();
		
	protected:
		CPoint  m_OldPoint;
		BOOL	m_bDynSplit;
		
		enum HitTestValue
		{
			noHit                   = 0,
				vSplitterBox            = 1,
				hSplitterBox            = 2,
				bothSplitterBox         = 3,        // just for
				keyboard
				vSplitterBar1           = 101,
				vSplitterBar15          = 115,
				hSplitterBar1           = 201,
				hSplitterBar15          = 215,
				splitterIntersection1   = 301,
				splitterIntersection225 = 525
		};
		
		
		// Generated message map functions
	protected:
		//{{AFX_MSG(CDynSplitterWnd)
		afx_msg void OnMouseMove(UINT nFlags, CPoint point);
		//}}AFX_MSG
		DECLARE_MESSAGE_MAP()
};

#include "stdafx.h"
#include <afxext.h>
#include "DynSplitterWnd.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CX_BORDER	1
#define CY_BORDER	1

#define FAR_POINT_XY		-10000



////////////////////////////////////////////////////////////////////////
/////
// CDynSplitterWnd

CDynSplitterWnd::CDynSplitterWnd() 
:m_OldPoint(FAR_POINT_XY,FAR_POINT_XY),
m_bDynSplit(TRUE)
{
}

CDynSplitterWnd::~CDynSplitterWnd()
{
}


void CDynSplitterWnd::OnInvertTracker(const CRect& rect)
{
	if(!m_bDynSplit)
		CSplitterWnd::OnInvertTracker(rect);
	else
		return;
}

void CDynSplitterWnd::StartTracking(int ht)
{
	if(!m_bDynSplit)
	{
		CSplitterWnd::StartTracking(ht);
		return;
	}
	
	ASSERT_VALID(this);
	if (ht == noHit)
		return;
	
	// GetHitRect will restrict 'm_rectLimit' as appropriate
	GetInsideRect(m_rectLimit);
	
	if (ht >= splitterIntersection1 && ht <=
		splitterIntersection225)
	{
		// split two directions (two tracking
		rectangles)
			int row = (ht - splitterIntersection1) / 15;
		int col = (ht - splitterIntersection1) % 15;
		
		GetHitRect(row + vSplitterBar1, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(col + hSplitterBar1, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset;
	}
	else if (ht == bothSplitterBox)
	{
		// hit on splitter boxes (for keyboard)
		GetHitRect(vSplitterBox, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(hSplitterBox, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset;
		
		// center it
		m_rectTracker.OffsetRect(0,
			m_rectLimit.Height()/2);
		m_rectTracker2.OffsetRect(m_rectLimit.Width()/2,
			0);
	}
	else
	{
		// only hit one bar
		GetHitRect(ht, m_rectTracker);
	}
	
	// steal focus and capture
	SetCapture();
	
	// set tracking state and appropriate cursor
	m_bTracking = TRUE;
	m_htTrack = ht;
	SetSplitCursor(ht);
}


void CDynSplitterWnd::StopTracking(BOOL bAccept)
{
	ASSERT_VALID(this);
	
	if (!m_bTracking)
		return;
	
	ReleaseCapture();
	
	// erase tracker rectangle
	OnInvertTracker(m_rectTracker);
	if (m_bTracking2)
		OnInvertTracker(m_rectTracker2);
	m_bTracking = m_bTracking2 = FALSE;
	
	// save old active view
	CWnd* pOldActiveView = GetActivePane();
	
	// m_rectTracker is set to the new splitter position
	(without border)
		// (so, adjust relative to where the border will be)
		m_rectTracker.OffsetRect(-CX_BORDER , -CY_BORDER);
	m_rectTracker2.OffsetRect(-CX_BORDER, -CY_BORDER);
	
	if (bAccept)
	{
		if (m_htTrack == vSplitterBox)
		{
			SplitRow(m_rectTracker.top);
		}
		else if (m_htTrack >= vSplitterBar1 && m_htTrack
			<= vSplitterBar15)
		{
			// set row height
			TrackRowSize(m_rectTracker.top,
				m_htTrack - vSplitterBar1);
			RecalcLayout();
		}
		else if (m_htTrack == hSplitterBox)
		{
			SplitColumn(m_rectTracker.left);
		}
		else if (m_htTrack >= hSplitterBar1 && m_htTrack
			<= hSplitterBar15)
		{
			// set column width
			TrackColumnSize(m_rectTracker.left,
				m_htTrack - hSplitterBar1);
			RecalcLayout();
		}
		else if (m_htTrack >= splitterIntersection1 &&
			m_htTrack <= splitterIntersection225)
		{
			// set row height and column width
			int row = (m_htTrack -
				splitterIntersection1) / 15;
			int col = (m_htTrack -
				splitterIntersection1) % 15;
			
			TrackRowSize(m_rectTracker.top, row);
			TrackColumnSize(m_rectTracker2.left,
				col);
			RecalcLayout();
		}
		else if (m_htTrack == bothSplitterBox)
		{
			// rectTracker is vSplitter (splits
			rows)
				// rectTracker2 is hSplitter (splits
				cols)
				SplitRow(m_rectTracker.top);
			SplitColumn(m_rectTracker2.left);
		}
	}
	
	if ( (pOldActiveView == GetActivePane()) &&
		(pOldActiveView != NULL)
		)
		SetActivePane(-1, -1, pOldActiveView);
	// re-activate
}


BEGIN_MESSAGE_MAP(CDynSplitterWnd, CSplitterWnd)
//{{AFX_MSG_MAP(CDynSplitterWnd)
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()



////////////////////////////////////////////////////////////////////////
/////
// CDynSplitterWnd message handlers


void CDynSplitterWnd::OnMouseMove(UINT nFlags, CPoint pt) 
{
	if(!m_bDynSplit)
	{
		CSplitterWnd::OnMouseMove(nFlags, pt);
		return;
	}
	
	if (GetCapture() != this)
		StopTracking(FALSE);
	
	if (m_bTracking)
	{
		// move tracker to current cursor position
		pt.Offset(m_ptTrackOffset); // pt is the upper
		right of hit detect
			// limit the point to the valid split range
			if (pt.y < m_rectLimit.top)
				pt.y = m_rectLimit.top;
			else if (pt.y > m_rectLimit.bottom)
				pt.y = m_rectLimit.bottom;
			if (pt.x < m_rectLimit.left)
				pt.x = m_rectLimit.left;
			else if (pt.x > m_rectLimit.right)
				pt.x = m_rectLimit.right;
			
			if (m_htTrack == vSplitterBox ||
				m_htTrack >= vSplitterBar1 && m_htTrack
				<= vSplitterBar15)
			{
				if (m_rectTracker.top != pt.y)
				{
					OnInvertTracker(m_rectTracker);
					m_rectTracker.OffsetRect(0, pt.y
						- m_rectTracker.top);
					OnInvertTracker(m_rectTracker);
				}
			}
			else if (m_htTrack == hSplitterBox ||
				m_htTrack >= hSplitterBar1 && m_htTrack
				<= hSplitterBar15)
			{
				if (m_rectTracker.left != pt.x)
				{
					OnInvertTracker(m_rectTracker);
					m_rectTracker.OffsetRect(pt.x -
						m_rectTracker.left, 0);
					OnInvertTracker(m_rectTracker);
				}
			}
			else if (m_htTrack == bothSplitterBox ||
				(m_htTrack >= splitterIntersection1 &&
				m_htTrack <= splitterIntersection225))
			{
				if (m_rectTracker.top != pt.y)
				{
					OnInvertTracker(m_rectTracker);
					m_rectTracker.OffsetRect(0, pt.y
						- m_rectTracker.top);
					OnInvertTracker(m_rectTracker);
				}
				if (m_rectTracker2.left != pt.x)
				{
					OnInvertTracker(m_rectTracker2);
					m_rectTracker2.OffsetRect(pt.x -
						m_rectTracker2.left, 0);
					OnInvertTracker(m_rectTracker2);
				}
			}
			
			OnLButtonUp(MK_LBUTTON,pt);
			OnLButtonDown(MK_LBUTTON,pt);
			if(m_OldPoint != pt)
			{
				RedrawWindow(NULL, NULL, RDW_ALLCHILDREN
					| RDW_UPDATENOW);
				m_OldPoint = pt;
			}
	}
	else
	{
		// simply hit-test and set appropriate cursor
		int ht = HitTest(pt);
		SetSplitCursor(ht);
	}
}

Download file 52K

Updated 4 April 1998



Comments

  • Specifically what other people actually does with regards to nike and moreover what youwant to do completely different.

    Posted by icoppyapedcap on 04/22/2013 06:11pm

    EbpWuqMxyCow [url=http://www.adidasgekiyasu.biz/]adidas originals[/url]TudIybNqfWts [url=http://www.nikegekiyasu.biz/]nike[/url]WdoAxgNbmSdp BhuKfbXnqSem[url=http://www.guccisayihujp.biz/]グッチ バッグ[/url]OtpXacZqhEss [url=http://www.guccisayihujp.biz/【グッチ】レディース財布-c-5.html]gucci 財布[/url]JuvFpaAuxBod [url=http://www.guccisayihujp.biz/【グッチ】レディース長財布-c-6.html]グッチ 財布 新作[/url]VczDijBjbToj [url=http://www.guccisayihujp.biz/【グッチ】ショルダーバッグ-c-2.html]gucci アウトレット[/url]XlcCdoOykMup OuhVufCxtQxz [url=http://www.chloesayihujp.biz/]chloe 財布[/url] RfdHweAiwNse [url=http://www.chloesayihujp.biz/クロエ-長財布-c-3.html]クロエ 長財布[/url] VdtGudVrwMth [url=http://www.chloesayihujp.biz/クロエ-ハンドバッグ-c-2.html]chloe バッグ[/url] WuiKrnMraQci GpuMwnZeyEbi [url=http://www.chanelsayihujp.biz/]シャネル[/url] KivRfbKoxVsj [url=http://www.chanelsayihujp.biz/シャネル財布-c-9.html]chanel 財布[/url]TzlEmjSusDse [url=http://www.chanelsayihujp.biz/シャネル-ショルダーバッグ-c-1.html]シャネル マトラッセ[/url]YlqEapWhzZhb

    Reply
  • Cannot print from second view

    Posted by Legacy on 08/11/1999 12:00am

    Originally posted by: Vicky

    In View2, printing options are disabled. This happens in the second view which is not created by AppWizard. How to enable the printing?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • When it comes to desktops – physical or virtual – it's all about the applications. Cloud-hosted virtual desktops are growing fast because you get local data center-class security and 24x7 access with the complete personalization and flexibility of your own desktop. Organizations make five common mistakes when it comes to planning and implementing their application management strategy. This eBook tells you what they are and how to avoid them, and offers real-life case studies on customers who didn't …

  • Today's competitive marketplace requires the organization to frequently release and deploy applications at the pace of user demands, with reduced cost, risk, and increased quality. This book defines the basics of application release and deployment, and provides best practices for implementation with resources for a deeper dive. Inside you will find: The business and technical drivers behind automated application release and deployment. Evaluation guides for application release and deployment solutions. …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds