Click here to Skip to main content
15,896,063 members
Articles / Desktop Programming / MFC

Pretty WinAPI Class

Rate me:
Please Sign up or sign in to vote.
4.90/5 (36 votes)
23 May 20074 min read 96.4K   2.7K   80  
New library version that is not WTL/MFC dependent
/*
 * <F> CWinDock.cpp		1.0  
 *
 * Copyright 2003 Francisco Campos. All rights reserved.
 * BEYONDATA  PROPRIETARY. Use is subject to license terms. </F>
 *
 *			 \|||/
 *			 |o_o|
 *	----o00o-------o00o---      
 **/


#include "stdafx.h"




DockManager::DockManager()
{
	m_DockWindows.RemoveAll();
	m_Splits.RemoveAll();
	m_Aling=0;		
    m_lastAling=0;	
	m_Visible=TRUE;		
	m_MiniDock=NULL;		
  	m_Splitter=CRect(0,0,0,0);	
	m_OldSplitter=CRect(0,0,0,0);
	m_pParent=NULL;
	m_NumWins=0;
	m_NumSep=0;
	m_SplitMove=0;
	m_DragSplitter=FALSE;
	m_DragSplitterInside=FALSE;
}

DockManager::~DockManager()
{
	m_DockWindows.RemoveAll();
	m_Splits.RemoveAll();
	
}

BOOL DockManager::IsFloating()
{
	return m_Aling==BS_ALIGN_FLOAT;
}

BOOL DockManager::IsVertical()
{
	return (m_Aling== BS_ALIGN_LEFT) || (m_Aling== BS_ALIGN_RIGHT);
}

BOOL DockManager::IsHorz()
{
	return m_Aling == BS_ALIGN_BOTTOM;
}
BOOL DockManager::IsLeft()
{
	return m_Aling== BS_ALIGN_LEFT;
}
BOOL DockManager::IsRight()
{
	return m_Aling== BS_ALIGN_RIGHT;
}
/////////////////////////////////////////////////////////////////////////////
// DockManager message handlers


//****************************************************************************
BOOL DockManager::OnEraseBkgnd(HDC hDC) 
{
	// TODO: Add your message handler code here and/or call default
	CGDI pDC(hDC);
	if (m_NumWins == 0)
	{
		CBrush cbr;
		cbr.CreateSysColorBrush(COLOR_BTNFACE);
		CRect m_rect;
		GetClientRect(m_rect);
		pDC.FillRect(m_rect,&cbr);
		cbr.DeleteObject();
		
	}
	return TRUE;
}


BOOL DockManager::OnPaint(HDC hDC) 
{
	CRect rcClient;
	CPaintDC dc(GetSafeHwnd()); // device context for painting
	CBrush cbr;
	CRect m_rectDraw;
	cbr.CreateSolidBrush(CDrawLayer::GetRGBColorFace());
	GetClientRect(rcClient);
	CGDI		MemDC;
	CBitmap		m_BitmapMemDC;
	MemDC.CreateCompatibleDC(dc.m_hDC);
	m_BitmapMemDC.CreateCompatibleBitmap(dc.m_hDC,rcClient.Width(),rcClient.Height());	
	
	CBitmap *m_bitmapOld=new CBitmap(MemDC.SelectObject(&m_BitmapMemDC));
	MemDC.FillRect(&rcClient,&cbr);
		
	//paint routines

	dc.BitBlt(0,0,rcClient.Width(),rcClient.Height(),MemDC.m_hDC,
		      rcClient.left,rcClient.top,SRCCOPY);
	MemDC.SelectObject(m_bitmapOld);
	m_BitmapMemDC.DeleteObject();
	MemDC.DeleteDC();
	cbr.DeleteObject();
	m_bitmapOld->DeleteObject();
	delete m_bitmapOld;
	return TRUE;
}



BOOL DockManager::Create(DWORD dwStyle, const RECT& rect, CWin* pParentWnd, UINT nID) 
{
	// TODO: Add your specialized code here and/or call the base class
	m_pParent= pParentWnd;
	m_Aling=nID;
	LPCTSTR lpclassname=RegisterDefaultClass(NULL,WS_CHILD|WS_VISIBLE);
	return CWin::Create(lpclassname, _T(""), dwStyle, rect, pParentWnd->GetSafeHwnd(), nID);
}

int DockManager::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{

	// TODO: Add your specialized creation code here
	return 0;
}


BOOL DockManager::OnNcCalcSize(BOOL /*bCalcValidRects*/, LPNCCALCSIZE_PARAMS lpncsp)
{
	// adjust non-client area for border space
	//dependiendo de la alineacion se debe crear un peque�o borde
	switch(m_Aling)
	{
	case BS_ALIGN_LEFT:
		lpncsp->rgrc[0].right-=4;
		break;
	case BS_ALIGN_BOTTOM:
		lpncsp->rgrc[0].top+=4;
		break;
	case BS_ALIGN_RIGHT:
		lpncsp->rgrc[0].left+=1;
		break;
	}
	
	return TRUE;
}

CContainer* DockManager::PointIsInCaption(CPoint cp)
{
	int iNumW=GetNumVisibleWindows();
	
	for (int i = 0; i < iNumW; i++) //wich is the size real of the child windows
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		CRect rcW;
		pWin->GetWindowRect(rcW);
		if (pWin->IsWindowVisible())
		{
				rcW.bottom=rcW.top+18;
				if (rcW.PtInRect(cp))
					return (CContainer*)pWin;
		}
	}
	return NULL;

}

int DockManager::PointInDock(CPoint cp, CRect& rc, int& pos )
{
	int iNumW=GetNumVisibleWindows();
	
	for (int i = 0; i < iNumW; i++) //wich is the size real of the child windows
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		CRect rcW;
		pWin->GetWindowRect(rcW);
		if (pWin->IsWindowVisible())
		{
				//primero si es dock superior
			if (m_Aling== BS_ALIGN_LEFT || m_Aling== BS_ALIGN_RIGHT)
			{
				CRect rctop;
				rctop=rcW;
				rctop.top+=18;
                rctop.bottom=rctop.top+22;
				if (rctop.PtInRect(cp))
				{
					rc=rcW;
					pos=i;
					return 1;
				}
				//si es dock inferior
				rctop=rcW;
				rctop.top=rctop.bottom-22;
				if (rctop.PtInRect(cp))
				{
					rc=rcW;
					pos=i;
					return 2;
				}
			
			}
			else
			{
				CRect rctop;
				rctop=rcW;
				rctop.right=rctop.left+22;
				if (rctop.PtInRect(cp))
				{
					rc=rcW;
					pos=i;
					return 1;
				}
				//si es dock inferior
				rctop=rcW;
				rctop.left=rctop.right-22;
				if (rctop.PtInRect(cp))
				{
					rc=rcW;
					pos=i;
					return 2;
				}
			}

		}
	}
	return 0;

}
void DockManager::OnNcPaint(HRGN hRgn)
{
	// TODO: Add your message handler code here
	// Do not call CControlBar::OnNcPaint() for painting messages
	// Tomo la misma rutina que se desarrolla para la clase
	// CGuiToolBarWnd.
	CRect rcWindow;
	CRect rcClient;
	CGDI	dc(::GetWindowDC(GetSafeHwnd()));
	CGDI			m_dc;		//contexto de dispositivo en memoria
	CBitmap		m_bitmap;
	//la idea es tomar el area de la ventana y area  cliente , luego debemos
	//igualar el area de coordenadas de ventana al cliente
	GetWindowRect(&rcWindow);
	GetClientRect(&rcClient);
	ScreenToClient(rcWindow);
	
	
    ::OffsetRect(rcClient, -rcWindow.left,-rcWindow.top);
	::OffsetRect(rcWindow, -rcWindow.left,-rcWindow.top);
	
	m_dc.CreateCompatibleDC(dc.m_hDC);
	m_bitmap.CreateCompatibleBitmap(dc.m_hDC,rcWindow.Width(),rcWindow.Height());
	CBitmap m_OldBitmap((HBITMAP)m_dc.SelectObject(&m_bitmap));
	CBrush cb;
	cb.CreateSolidBrush(CDrawLayer::GetRGBColorFace());
	m_dc.FillRect(rcWindow, &cb);
	dc.IntersectClipRect(rcWindow);
    dc.ExcludeClipRect(rcClient);//asi evitamos el parpadeo
	dc.BitBlt(rcWindow.left,rcWindow.top,rcWindow.Width(),rcWindow.Height(),m_dc.m_hDC,0,0,SRCCOPY);
	m_dc.SelectObject(&m_OldBitmap);
	m_bitmap.DeleteObject();
	m_dc.DeleteDC();
	cb.DeleteObject ();
	dc.DeleteDC();
	
	
}

BOOL DockManager::OnLButtonUp(UINT nFlags, CPoint point)
{
	
	if (m_DragSplitter)
	{
		ReleaseCapture();
		m_DragSplitter=FALSE;
		DrawSppliter(m_Splitter);
		if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
		{

			if (abs(m_Splitter.left - m_ptStartPos.x)<= 2 ) return TRUE; 
		}
		else
		{
			if (abs(m_Splitter.top-m_ptStartPos.y)<=2)  return TRUE;
		}

		RecalLayout(TRUE);	
		return TRUE;
	}


	if (m_DragSplitterInside)
	{
	//	ScreenToClient(&point);
		DrawSppliterInside(	m_ptOldPos);
		ReleaseCapture();
		m_DragSplitterInside=FALSE;
		if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
		{

			if (abs(point.y - m_ptStartPos.y)<= 2 ) return TRUE; 
		}
		else
		{
			if (abs(point.x-m_ptStartPos.x)<=2)  return TRUE;
		}
		ResizeWindow(point);
		//RecalLayout(TRUE);				
	}

	return TRUE;
}

void DockManager::OnNcMouseMove(UINT nHitTest, CPoint point)
{
	Default();
}

void DockManager::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
	if (BS_SPLIT_VERT ==nHitTest || nHitTest ==BS_SPLIT_HORTZ)
	{
		if (!m_DragSplitterInside)
		{
			m_DragSplitterInside=TRUE;
			SetCapture();
			SetFocus();
			m_ptStartPos=point;
			ScreenToClient(&point);
			m_ptOldPos=point;
			DrawSppliterInside(point);
		}
		return;
	}

	if (!m_DragSplitter)
	{
		m_DragSplitter=TRUE;
		m_ptStartPos=point;
		SetCapture();
		SetFocus();
		DrawSppliter(m_Splitter);
		return;
	}

	//Default();	
}


void DockManager::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
	Default();
}

UINT DockManager::OnNcHitTest(CPoint cp)
{
	CRect rcWindow;
	GetWindowRect(rcWindow);
	if(m_Aling== BS_ALIGN_LEFT)
	{
		rcWindow.left=rcWindow.right-4;
		m_Splitter=rcWindow;
		if (rcWindow.PtInRect(cp))
			return BS_BORDER_RIGHT;
	}
	else if (m_Aling== BS_ALIGN_BOTTOM)
	{
		rcWindow.bottom=rcWindow.top+4;
		m_Splitter=rcWindow;
		if (rcWindow.PtInRect(cp))
			return BS_BORDER_TOP;
	}
	else if (m_Aling== BS_ALIGN_RIGHT)
	{
		rcWindow.right=rcWindow.left+4;
		m_Splitter=rcWindow;
		if (rcWindow.PtInRect(cp))
			return BS_BORDER_LEFT;
	}
	

	ScreenToClient(&cp);
	cp.y-=1;
	cp.x-=1;
	if(m_Aling== BS_ALIGN_LEFT || m_Aling== BS_ALIGN_RIGHT)
	{

		for( int i=0; i<m_NumSep; i++ )
		{
			
			if (m_Splits[i].PtInRect(cp))
			{
				m_Splitter=m_Splits[i];
				m_OldSplitter=m_Splitter;
				return BS_SPLIT_VERT;
			}
		}
	}

	if (m_Aling== BS_ALIGN_BOTTOM)
	{

		for( int i=0; i<m_NumSep; i++ )
		{
			if (m_Splits[i].PtInRect(cp))
			{
				m_Splitter=m_Splits[i];
				m_OldSplitter=m_Splitter;
				return BS_SPLIT_HORTZ;
			}
		}
	}
	
	return Default();
}

void DockManager::OnTimer(UINT nIDEvent)
{
	// TODO: Add your message handler code here and/or call default
	Default();
}

int  DockManager::GetNumChild()
{
	return m_DockWindows.GetSize();
}

void DockManager::RecalLayout(BOOL bReSize)
{

	// first ajust the docking bars in the frame window
	if (GetNumChild()<=0) 
	{
		ShowWindow(SW_HIDE);
		return;
	}
	if (bReSize)
	{
		
		if(m_Aling== BS_ALIGN_LEFT)
		{
			
			CRect rc,rcw,rcc;
			GetWindowRect(rc);
			GetClientRect(rcc);
			theApp->m_WinMain->GetClientRect(rcw);
			ClientToScreen(rcw);
			::OffsetRect(rcw, -rc.left,-rc.top);
		
			rc.right=m_Splitter.right;
			m_size.cx=rc.Width();
			m_size.cy=rc.Height();
			theApp->m_WinMain->ScreenToClient(rc);
			//SetWindowPos(NULL,rc,SWP_HIDEWINDOW);
			theApp->m_WinMain->UpdateFrame(FALSE);
		}

		if(m_Aling== BS_ALIGN_RIGHT)
		{
			CRect rc,rcw,rcc;
			this->GetWindowRect(rc);
			GetClientRect(rcc);
			theApp->m_WinMain->GetClientRect(rcw);
			if (m_Splitter.left < 0)
				rc.left+=m_Splitter.left;
			else
				rc.left=m_Splitter.left;
			theApp->m_WinMain->ScreenToClient(rc);
			m_size.cx=rc.Width();
			m_size.cy=rc.Height();
			//SetWindowPos(NULL,rc,SWP_HIDEWINDOW );
			theApp->m_WinMain->UpdateFrame(FALSE);
		}
		if(m_Aling== BS_ALIGN_BOTTOM)
		{
			CRect rc,rcw,rcc;
			this->GetWindowRect(rc);
			GetClientRect(rcc);
			theApp->m_WinMain->GetClientRect(rcw);
			ClientToScreen(rcw);
			::OffsetRect(rcw, -rc.left,-rc.top);
			if (m_Splitter.top < 0)
				rc.top+=m_Splitter.top;
			else
				rc.top=m_Splitter.top;
			theApp->m_WinMain->ScreenToClient(rc);
			m_size.cx=rc.Width();
			m_size.cy=rc.Height();
			//SetWindowPos(NULL,rc,SWP_HIDEWINDOW );
			theApp->m_WinMain->UpdateFrame(FALSE);
		}
	}
	else // now the child windows in the new container windows size
	{
		CalSizeWindow();
	}
}

int  DockManager::GetNumVisibleWindows()
{
	int iNumW=m_DockWindows.GetSize();
	int count=0;
	for (int i = 0; i < iNumW; i++)
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		if (!((CContainer*)pWin)->IsClosePane()) count++;
		
	}
	return count;
}

CContainer*  DockManager::GetWichContainerIsTheParent(HWND hWnd)
{
	int iNumW=m_DockWindows.GetSize();
	int count=0;
	for (int i = 0; i < iNumW; i++)
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		if (((CContainer*)pWin)->GetSafeHwnd()== hWnd)
			return (CContainer*)pWin; 
		
	}
	return NULL;
}

void DockManager::EveryWindowsInsert()
{
		int iSizeW=0;
		int iSizeH=0;
		int iSizeWDock=0;
		int iSizeHDock=0;
		int iNumW=GetNumVisibleWindows();
		int FirstVisible=GetFirstVisible();
		int LastVisible=GetLastVisible();
		if (FirstVisible == -1) return;
		m_Splits.RemoveAll();
		m_NumSep=0;
		CRect rcSplit;
		if (IsWindowVisible() && iNumW > 0)
		{
			CRect rcClient;
			GetClientRect(rcClient); //area client of the docking bar
			iSizeW=rcClient.Width()/iNumW; //size actual
			iSizeH=rcClient.Height()/iNumW;
		
			if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
			{
				if (rcClient.Width() < 4)
					rcClient.right=iSizeW;
			}else
			{
				if (rcClient.Height() < 4)
					rcClient.right=iSizeH;
			}
			CRect rcW=CRect(0,0,0,0);
			int  iContPos=0;
			HDWP hDWP = ::BeginDeferWindowPos(iNumW); 
			
			//Ok, we going to adjust all child window in the new docking bar size
			for (int i = FirstVisible; i <= LastVisible; i++)
			{
				CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
				CRect rcW=CRect(0,0,0,0);
				if (pWin->IsWindowVisible())
				{
					switch(m_Aling)
					{
					case BS_ALIGN_LEFT:
					case BS_ALIGN_RIGHT:
						pWin->GetWindowRect(rcW);
						ScreenToClient(rcW);
						if (m_Aling==BS_ALIGN_RIGHT)
							rcW.left=rcClient.left+2;
						else
							rcW.left=rcClient.left;
						rcW.right=rcClient.right;
						if (i==0) // si es la primera ventana hija donde esta la primera posicion del arriba
						{
							iContPos=rcClient.top;
							rcW.top=rcClient.top;
						}
						else
							rcW.top=iContPos; // si no, aqui se inicia la siguiente ventana.
						
						rcW.bottom=iSizeH;
						rcSplit=rcW;
						rcSplit.top=rcSplit.bottom;
						rcSplit.bottom=rcSplit.top+2;
						m_NumSep++;
						iContPos+=rcW.bottom+3;
						((CDockStruct*)m_DockWindows[i])->m_rectPost=rcW;
						DeferWindow(hDWP,pWin->GetSafeHwnd(),NULL,rcW,SWP_NOZORDER | SWP_NOACTIVATE||SWP_SHOWWINDOW);
						break;
					case BS_ALIGN_BOTTOM:
						pWin->GetWindowRect(rcW);
						ScreenToClient(rcW);
						rcW.top=rcClient.top;
						rcW.bottom=rcClient.bottom;
						if (i==0) 
						{
							iContPos=rcClient.left;
							rcW.left=rcClient.left;
						}
						else
							rcW.left=iContPos;
						
						rcW.right=iSizeW;
						rcSplit=rcW;
						rcSplit.left=rcSplit.right;
						rcSplit.right=rcSplit.left+2;
						m_Splits.InsertAt(m_NumSep,rcSplit);
						m_NumSep++;
						iContPos+=rcW.right+3;
						((CDockStruct*)m_DockWindows[i])->m_rectPost=rcW;
						DeferWindow(hDWP,pWin->GetSafeHwnd(),NULL,rcW,SWP_NOZORDER | SWP_NOACTIVATE||SWP_SHOWWINDOW);
						break;				
					}
					
				}
				
			}
			if (hDWP != NULL)
				::EndDeferWindowPos(hDWP);
		}

}

int DockManager::GetFirstVisible()
{

	int iNumW=m_DockWindows.GetSize();
	int count=0;
	for (int i = 0; i < iNumW; i++)
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		if (pWin->IsWindowVisible()) return i;
		
	}
	return -1;
}

int DockManager::GetLastVisible()
{

	int iNumW=m_DockWindows.GetSize();
	int count=0;
	for (int i = 0; i < iNumW; i++)
	{
		CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
		if (pWin->IsWindowVisible()) count= i;
		
	}
	return count;
}
void DockManager::CalSizeWindow()
{
		int iSizeW=0;
		int iSizeH=0;
		int iSizeWDock=0;
		int iSizeHDock=0;
		BOOL bGrow=FALSE;
		int  iDif=0;
		int iNumW=GetNumVisibleWindows();
		if (GetFirstVisible()== -1) return;
		m_Splits.RemoveAll();
		m_Splits.FreeExtra();
		m_NumSep=0;
		CRect rcSplit;
		int FirstVisible=GetFirstVisible();
		int LastVisible=GetLastVisible();
		if (IsWindowVisible() && iNumW > 0)
		{
			CRect rcClient;
			GetClientRect(rcClient); //area client of the docking bar
			iSizeW=rcClient.Width(); //size actual
			iSizeH=rcClient.Height();
			int iNumSeparador=0;
			for (int i =FirstVisible; i <= LastVisible; i++) //wich is the size real of the child windows
			{
				CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
				CRect rcW;
				pWin->GetWindowRect(rcW);
				if (pWin->IsWindowVisible())
				{
						iSizeWDock+=rcW.Width();
						iSizeHDock+=rcW.Height();
						iNumSeparador++;
				}
			}
			if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
			{
				if (rcClient.Width() < 4)
					rcClient.right=iSizeWDock;
			}else
			{
				if (rcClient.Height() < 4)
					rcClient.right=iSizeHDock;
			}

			if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
			{
				 
				 bGrow= ((iSizeH- ((iNumSeparador-1)*3)-1 )-iSizeHDock) < 0 ? FALSE: TRUE;
				 iDif= abs((iSizeH- ((iNumSeparador-1)*3)-1) -iSizeHDock);

			}
			else
			{
				 bGrow= ((iSizeW- ((iNumSeparador-1)*5)-1 )-iSizeWDock) < 0 ? FALSE: TRUE;
				 iDif= abs((iSizeW- ((iNumSeparador-1)*5)-1) -iSizeWDock);
				
			}

			CRect rcW=CRect(0,0,0,0);
			
			HDWP hDWP = ::BeginDeferWindowPos(GetNumVisibleWindows()); 
			
			//Ok, we going to adjust all child window in the new docking bar size
			if(iNumW ==1) // if it�s contains a only one window
			{
				rcW=rcClient;
				rcW.bottom-=1;
				iDif=0;
				((CDockStruct*)m_DockWindows[FirstVisible])->m_rectPost=rcW;
			}
			else
			{
				while(iDif > 0)
				{
					if (iDif <= 0)
						break;
					int  iContPos=0;
					int bFirst=TRUE;
					for (int i = FirstVisible; i <= LastVisible; i++)
					{
						CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
						CRect rcW=((CDockStruct*)m_DockWindows[i])->m_rectPost;
						if (pWin->IsWindowVisible())
						{
							switch(m_Aling)
							{
							case BS_ALIGN_LEFT:
							case BS_ALIGN_RIGHT:
								if (m_Aling==BS_ALIGN_RIGHT)
								{
									rcW.left=rcClient.left+2;
								}
								else
									rcW.left=rcClient.left;
								rcW.right=rcClient.right;
								if (i==0) // si es la primera ventana hija donde esta la primera posicion del arriba
								{
									iContPos=rcClient.top;
									rcW.top=rcClient.top;
								}
								else
								{
									if (iContPos >rcClient.top)
										rcW.top=iContPos; // si no, aqui se inicia la siguiente ventana.
									else
										rcW.top=rcClient.top;
								}
								if(iNumW ==1) // if it�s contains a only one window
								{
									if (bGrow)
										rcW.bottom+=iDif;
									else
										rcW.bottom-=iDif;
									iDif=0;
								}
								else
								{
									if (bGrow)
									{
										rcW.bottom+=1; 
										iDif--;
									}
									else
									{
										rcW.bottom-=1;
										iDif--;
									}
								}

								
								iContPos+=rcW.bottom+3;
								((CDockStruct*)m_DockWindows[i])->m_rectPost=rcW;
								
								break;
							case BS_ALIGN_BOTTOM:
								rcW.top=rcClient.top;
								rcW.bottom=rcClient.bottom;
								if (i==0) 
								{
									iContPos=rcClient.left;
									rcW.left=rcClient.left;
								}
								else
									rcW.left=iContPos;
								
								if(iNumW ==1) // if it�s contains a only one window
								{
									if (bGrow)
										rcW.right+=iDif;
									else
										rcW.right-=iDif;
									iDif=0;
								}
								else
								{
									if (bGrow)
									{
										rcW.right+=1; 
										iDif--;
									}
									else
									{
										rcW.right-=1;
										iDif--;
									}
								}
								
								iContPos+=rcW.right+5;
								((CDockStruct*)m_DockWindows[i])->m_rectPost=rcW;
								break;				
							}
							
						}
						
					}
					
				}
			}
			

				for (int i = FirstVisible; i <= LastVisible; i++)
				{
					CWin* pWin=((CDockStruct*)m_DockWindows[i])->m_WinDock;
					CRect rcW=((CDockStruct*)m_DockWindows[i])->m_rectPost;
					if (pWin->IsWindowVisible())
					{
						CRect rcWin;
						pWin->GetWindowRect(rcWin);
						if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
						{
							if (m_Aling==BS_ALIGN_RIGHT)
								rcW.left=rcClient.left+2;
							else
								rcW.left=rcClient.left;
							rcW.right=rcClient.right;
							rcSplit=rcW;
							rcSplit.top+=rcWin.Height()-2;
							rcSplit.bottom=rcSplit.top+3;
							//if (i< LastVisible)
							m_Splits.InsertAt(m_NumSep,rcSplit);
							m_NumSep++;
						}
						else
						{
							rcW.top=rcClient.top;
							rcW.bottom=rcClient.bottom;
							rcSplit=rcW;
							rcSplit.left+=rcWin.Width()-1;
							rcSplit.right=rcSplit.left+5;
							m_Splits.InsertAt(m_NumSep,rcSplit);
							m_NumSep++;
						}

						((CDockStruct*)m_DockWindows[i])->m_rectPost=rcW;
						
						DeferWindow(hDWP,pWin->GetSafeHwnd(),NULL,rcW,SWP_NOZORDER | SWP_NOACTIVATE);

					}
				}
			if (hDWP != NULL)
				::EndDeferWindowPos(hDWP);
		}

}

void DockManager::ResizeWindow(CPoint point)
{
		ClientToScreen(&point);
		int iNumW=GetNumVisibleWindows();
		if (m_Aling == BS_ALIGN_LEFT || m_Aling == BS_ALIGN_RIGHT)
		{
			CRect rc;
			CRect rcClient;
			if (abs(m_ptStartPos.y - abs(point.y)) < 1 )
			{
				SetCursorPos(m_ptStartPos.x,m_ptStartPos.y );
				return;
			}
			if (m_ptStartPos.y > point.y) //la ventana inferior se amplia, la superior o anterior se reduce
			{
				int nDif=0;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost;
				if (abs(rc.top - point.y) <= 22)
				{
					nDif=rc.Height()-23;
					rc.bottom=rc.top+23;
				}
				else
				{
					nDif=rc.bottom-point.y;
					rc.bottom=point.y;
					
				}
				rcClient.bottom-=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost=rcClient;
				int NextPos=rcClient.bottom+3;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost;
				rcClient.top=NextPos;
				rcClient.bottom=rc.Height()+nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost=rcClient;
			}
			else
			{
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost;
				rcClient.bottom=rc.Height();
				int nDif=0;
				if ( point.y >= rc.bottom-22)
				{
					nDif=rc.Height()-23;
					rc.top=rc.bottom-23;
				}
				else
				{
					nDif=point.y-rc.top;
					rc.top=point.y;
				}

				rcClient.top+=nDif;
				rcClient.bottom-=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost=rcClient;
				
				int NextPos=rcClient.top-3;
				
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost;
				rcClient.bottom+=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost=rcClient;
			}
		
			
		}
		else //the bottom window
		{
			CRect rc;
			CRect rcClient;
			if (abs(m_ptStartPos.y - abs(point.y)) < 1 )
			{
				SetCursorPos(m_ptStartPos.x,m_ptStartPos.y );
				return;
			}
			if (m_ptStartPos.y > point.y) //la ventana inferior se amplia, la superior o anterior se reduce
			{
				int nDif=0;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost;
				if (abs(rc.right - point.x) <= 22)
				{
					nDif=rc.Width()-23;
					rc.right=rc.left+23;
				}
				else
				{
					nDif=rc.right-point.x;
					rc.right=point.x;
					
				}
				rcClient.right-=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost=rcClient;
				int NextPos=rcClient.right+3;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost;
				rcClient.left=NextPos;
				rcClient.right=rc.Width()+nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost=rcClient;
			}
			else
			{
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost;
				rcClient.right=rc.Width();
				int nDif=0;
				if ( point.x >= rc.right-22)
				{
					nDif=rc.Width()-23;
					rc.left=rc.right-23;
				}
				else
				{
					nDif=point.x-rc.left;
					rc.left=point.x;
				}

				rcClient.left+=nDif;
				rcClient.right-=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove+1])->m_rectPost=rcClient;
				
				int NextPos=rcClient.left-3;
				
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_WinDock->GetWindowRect(rc);  
				rcClient=((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost;
				rcClient.right+=nDif;
				((CDockStruct*)m_DockWindows[m_SplitMove])->m_rectPost=rcClient;
			}
		
		}

		CalSizeWindow();
		CalSizeWindow();

}


CSize DockManager::Getsize()
{
	return m_size;
}

int DockManager::FindItem(HWND hWnd)
{
	for (int iCont=0; iCont< m_NumWins;iCont++)
	{
		CDockStruct* ct=(CDockStruct*) m_DockWindows[iCont];
		if (ct->m_WinDock->GetSafeHwnd() == hWnd)
		    return iCont;
	}
	return -1;

}

CWin*  DockManager::GetNumWnd(int m_numWin) 
{
        if (m_numWin > m_NumWins)
			return NULL;
		else
		{
			if (m_DockWindows.GetSize() < 1) return NULL;
			CWin* pw=((CDockStruct*) m_DockWindows [m_numWin])->m_WinDock;
			if (HIWORD(pw)== NULL) return NULL;
			else
			  return ((CDockStruct*) m_DockWindows [m_numWin])->m_WinDock;
		}
}



void DockManager::AddWindow(CWin* pParent,int nPos)
{
	if (!HIWORD(pParent))return;
	if (nPos == -1)
		m_DockWindows.SetAtGrow(m_NumWins,new CDockStruct(pParent));
	else{
		m_DockWindows.InsertAt(nPos,new CDockStruct(pParent));

	}
	pParent->ShowWindow(SW_SHOW);
	((CContainer*)pParent)->m_DOCKFLOAT=((CContainer*)pParent)->m_DOCKSITE=
	GetWindowLong(GetSafeHwnd(),GWL_ID);
	m_NumWins++;
	EveryWindowsInsert();
	RecalLayout(FALSE);
}

UINT DockManager::AddWindow(CDockPanelBase* pParent,UINT dlgCtrl,int nPos)
{

	if (dlgCtrl==NULL)
	{	
		CContainer* ctn= new CContainer;
		if (!ctn->Create(WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,pParent->GetDlgCtrlID()+1))
			return NULL;

		ctn->Addtab(pParent);
		pParent->SetParent(ctn);


		ctn->m_DOCKFLOAT=!BS_FLOATING;
		ctn->m_DOCKSITE=GetWindowLong(GetSafeHwnd(),GWL_ID);
		pParent->uAling=GetWindowLong(GetSafeHwnd(),GWL_ID);
		pParent->iLasPosition=m_NumWins;
		pParent->bIsPartOfTabbed=FALSE;
		pParent->bIsShow=TRUE;
		pParent->m_IdCtrlParent=NULL;	

		if (!HIWORD(pParent))return NULL;
		if (nPos == -1)
		{
			m_DockWindows.SetAtGrow(m_NumWins,new CDockStruct(ctn));
			m_NumWins++;
		}
		else{
			m_DockWindows.InsertAt(nPos,new CDockStruct(ctn));
		
		}
	}else
	{
		for( int i=0; i<m_DockWindows.GetSize(); i++ )
		{
			CDockStruct *pTab = (CDockStruct*)m_DockWindows.GetAt(i);
			CTab*  ctab= ((CContainer*)pTab->m_WinDock)->GetTab(0);
			if ( (UINT)ctab->pParent->GetDlgCtrlID() == dlgCtrl )
			{
				CContainer* pct=(CContainer*)pTab->m_WinDock;
				pParent->SetParent(pct);
				pParent->uAling=NULL;
				pParent->iLasPosition=m_NumWins;
				pParent->bIsPartOfTabbed=TRUE;
				pParent->bIsShow=TRUE;
				pParent->m_IdCtrlParent=dlgCtrl;	
				pct->Addtab(pParent);
				break;
			}
		}
		
	}

	pParent->ShowWindow(SW_SHOW);
	//((CContainer*)pParent)->m_DOCKFLOAT=((CContainer*)pParent)->m_DOCKSITE=
	//GetWindowLong(GetSafeHwnd(),GWL_ID);

	EveryWindowsInsert();
	RecalLayout(FALSE);
	return pParent->GetDlgCtrlID()+1;
}



void DockManager::DeleteWindow(int m_NumW)
{
	if (m_NumW < 0) return;
	if (m_NumW < m_NumWins)
	{
		CDockStruct* ctn=(CDockStruct*) m_DockWindows[m_NumW]; 	
		if (ctn)
			delete ctn;
		m_NumWins--;
		m_DockWindows.RemoveAt(m_NumW,1);
		EveryWindowsInsert();
	}
	
}

BOOL DockManager::OnSize(UINT nType, int cx, int cy) 
{
	//if (m_NumWins > 0)
	RecalLayout(FALSE);
	Invalidate();
	UpdateWindow();
	return TRUE;
}





void DockManager::OnMouseMove(UINT nHitTest, CPoint point)
{
	CPoint cp;
	GetCursorPos(&cp);
	if (GetCapture() != GetSafeHwnd())
		{
			m_DragSplitter=FALSE;
		}
	if (m_DragSplitter)
	{
		DrawSppliter(m_Splitter);
		//nuevos tama�os de la ventana
		if (IsVertical())
		{
			//ClientToScreen(&cp);
	
			m_Splitter.left=cp.x;
			m_Splitter.right=m_Splitter.left+4;

		}
		else
		{
	
			m_Splitter.top=cp.y;
			m_Splitter.bottom=m_Splitter.top+4;
		}
		DrawSppliter(m_Splitter);
		return;
	}
	ScreenToClient(&cp);
	if (m_DragSplitterInside)
	{
		
		DrawSppliterInside(m_ptOldPos);
		if (IsVertical())
		{
			//ClientToScreen(&cp);
	
			m_Splitter.left=cp.x;
			m_Splitter.right=m_Splitter.left+4;

		}
		else
		{
	
			m_Splitter.top=cp.y;
			m_Splitter.bottom=m_Splitter.top+4;
		}
		DrawSppliterInside(cp);
		m_ptOldPos=point;
		
		
	}
		
	//Default();
}

BOOL DockManager::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	
	Default();
	return TRUE;

}

BOOL DockManager::OnRButtonDown(UINT nFlags, CPoint point)
{
	Default();

	return TRUE;

}


int DockManager::OnDestroy()
{
	// Libera la memoria
    for( int i=0; i<m_NumWins; i++ )
    {
    CDockStruct *pTab = (CDockStruct*)m_DockWindows.GetAt(i);
    if( pTab )
        delete pTab;
    }
	return TRUE;

	// TODO: Add your message handler code here
}



void DockManager::DrawSppliter(CRect rc)
{

	CRect rcWindow;
	theApp->m_WinMain->GetWindowRect(rcWindow);
	CGDI pDC(theApp->m_WinMain->GetDCEx(NULL,DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE));
	CBrush* pBrush = CGDI::HalftGray();
    CBrush pBrushOld(pDC.SelectObject(pBrush));
	::OffsetRect(rc, -rcWindow.left,-rcWindow.top);
	//theApp->m_WinMain->GetClientRect(rcWindow);
	CRect rc1;
	GetClientRect (rc1);
	//::OffsetRect(rcWindow, -rcWindow.left,-rcWindow.top);
	
	//rc.OffsetRect(-rcWindow.TopLeft());
	if (IsVertical())
		pDC.PatBlt(rc.left, rc.top, rc.Width(), rc1.Height(), PATINVERT);
	else
		pDC.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
    pDC.SelectObject(&pBrushOld);
    theApp->m_WinMain->ReleaseDC(pDC.m_hDC);
	pBrush->DeleteObject();
	pBrushOld.DeleteObject();
	delete pBrush;

}

void DockManager::DrawSppliterInside(CPoint cp)
{
	CRect rc;
	GetClientRect(rc);
	CGDI pDC(this->GetDCEx(NULL,DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE));
	CBrush* pBrush = CGDI::HalftGray();
    CBrush pBrushOld(pDC.SelectObject(pBrush));

	if (IsVertical())
	{
		rc.top=cp.y;
		rc.bottom=cp.y+3;
		pDC.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
	}
	else
	{
		rc.left=cp.x;
		rc.right=cp.x+5;
		pDC.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
	}
    pDC.SelectObject(&pBrushOld);
	theApp->m_WinMain->ReleaseDC(pDC.m_hDC);
	pBrush->DeleteObject();
	pBrushOld.DeleteObject();
	delete pBrush;

}

BOOL DockManager::OnSetCursor(HWND hWnd, UINT nHitTest, UINT message)
{
	CPoint cp;
	GetCursorPos(&cp);
	CRect rcWindow;
	GetWindowRect(rcWindow);
	m_SplitMove=0;
	if(m_Aling== BS_ALIGN_LEFT)
	{
		rcWindow.left=rcWindow.right-2;
		if (rcWindow.PtInRect(cp))
		{
            SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(IDC_SIZEWE)));
			return TRUE;
		}
		
	}
	else if (m_Aling== BS_ALIGN_BOTTOM)
	{
		rcWindow.bottom=rcWindow.top+2;
		if (rcWindow.PtInRect(cp))
		{
			SetCursor(LoadCursor (NULL,MAKEINTRESOURCE(IDC_SIZENS)));
			return TRUE;
		}

		
	}
	else if (m_Aling== BS_ALIGN_RIGHT)
	{

		rcWindow.right=rcWindow.left+2;
		if (rcWindow.PtInRect(cp))
		{
			SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(IDC_SIZEWE)));
			return TRUE;
		}

		
	}
	ScreenToClient(&cp);
	cp.y-=1;
	cp.x-=1;
	if(m_Aling== BS_ALIGN_LEFT || m_Aling== BS_ALIGN_RIGHT)
	{

		for( int i=0; i<m_NumSep; i++ )
		{
			
			if (m_Splits[i].PtInRect(cp))
			{
				m_SplitMove=i;
				SetCursor(LoadCursor (NULL,MAKEINTRESOURCE(IDC_SIZENS)));
				return TRUE;
			}
		}
	}

	if (m_Aling== BS_ALIGN_BOTTOM)
	{

		for( int i=0; i<m_NumSep; i++ )
		{
			if (m_Splits[i].PtInRect(cp))
			{
				m_SplitMove=i;
				SetCursor(LoadCursor (NULL,MAKEINTRESOURCE(IDC_SIZEWE)));
				return TRUE;
			}
		}
	}
	
	SetCursor(LoadCursor (NULL,MAKEINTRESOURCE(IDC_ARROW)));	
	return TRUE;
	
}

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
Colombia Colombia
My name is Francisco Campos, A developer as you.I have the title of Engineer of Systems of the Universidad Autonoma de Colombia.My real Job Information Security officer, experience in security assessment, applications, and other related subjects.

Francisco.camposg@outlook.com

Comments and Discussions