www.pudn.com > clking_src.rar > GuiControlBar.cpp


//-----------------------------------------------------------------------// 
// This is a part of the GuiLib MFC Extention.							 //	 
// Autor  :  Francisco Campos											 // 
// (C) 2002 Francisco Campos  All rights reserved     // 
// This code is provided "as is", with absolutely no warranty expressed  // 
// or implied. Any use is at your own risk.								 //		 
// You must obtain the author's consent before you can include this code // 
// in a software library.												 // 
// If the source code in  this file is used in any application			 // 
// then acknowledgement must be made to the author of this program		 //	 
// fcampos@tutopia.com													 // 
//-----------------------------------------------------------------------// 
 
 
// GuiControlBar.cpp : implementation file 
 
 
#include "stdafx.h" 
#include "GuiControlBar.h" 
#include "GuiDockContext.h" 
#include "guicontrolbar.h" 
#include "GuiDrawLayer.h" 
#include "resource.h" 
#include "..\header\guicontrolbar.h" 
// CGuiControlBar 
 
IMPLEMENT_DYNAMIC(CGuiControlBar, CControlBar) 
CGuiControlBar::CGuiControlBar() 
{ 
	nGapGripper=20; 
	m_bActive=FALSE; 
	m_bOldActive=FALSE; 
	/*Modified By SunZhenyu 2003/6/21 
	m_sizeMinFloating=m_sizeVert=m_sizeHorz=CSize(200,100); 
	m_sizeHorzt=CSize(200,100); 
	m_sizeVertt=CSize(200,100); 
	*/ 
	m_sizeMinFloating=m_sizeVert=m_sizeHorz=CSize(210,400); 
	m_sizeHorzt=CSize(210,400); 
	m_sizeVertt=CSize(210,400); 
	m_pos=0; 
	m_Last=0; 
	m_bTracking=FALSE; 
	m_rcBorder=CRect(0,0,0,0); 
	m_rcOldBorder=CRect(0,0,0,0); 
	m_ptOld=CPoint(0,0); 
	m_sizeMinV=CSize(28,28); 
	m_sizeMinH=CSize(28,28); 
	m_Initialize=FALSE; 
	m_First=-1; 
	m_bForcepaint=FALSE; 
	m_stateBtn=NORMAL; 
	m_clrFondo=GuiDrawLayer::GetRGBColorFace(); 
	m_bSupportMultiView=FALSE; 
} 
 
CGuiControlBar::~CGuiControlBar() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CGuiControlBar, CControlBar) 
	ON_WM_CREATE() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_LBUTTONUP() 
	ON_WM_NCLBUTTONDOWN() 
	ON_WM_NCLBUTTONUP() 
	ON_WM_MOUSEMOVE() 
	ON_WM_NCPAINT() 
	ON_WM_NCCALCSIZE() 
	ON_WM_WINDOWPOSCHANGED() 
	ON_WM_PAINT() 
	ON_WM_LBUTTONDBLCLK() 
	ON_WM_NCLBUTTONDBLCLK() 
	ON_WM_NCHITTEST() 
	ON_WM_SETCURSOR() 
	ON_WM_SIZE() 
	ON_WM_NCMOUSEMOVE() 
	ON_WM_TIMER() 
	ON_COMMAND(WM_SHOWTITLE, OnShowTitle) 
	ON_WM_SYSCOLORCHANGE() 
	 
END_MESSAGE_MAP() 
 
 
 
// CGuiControlBar message handlers 
 
void CGuiControlBar::OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL /*bDisableIfNoHndler*/) 
{ 
	 
	CWnd* pFocus = GetFocus(); 
	m_bOldActive=(pFocus->GetSafeHwnd() && IsChild(pFocus)); 
	m_bForcepaint=TRUE; 
	if (!m_bActive && m_bOldActive) 
		OnActiveWindow(); 
	m_bForcepaint=FALSE; 
	 
 
} 
 
void CGuiControlBar::OnSysColorChange( ) 
{ 
	m_clrFondo=GuiDrawLayer::GetRGBColorFace(); 
	CControlBar::OnSysColorChange( ); 
	 
} 
 
BOOL CGuiControlBar::Create(LPCTSTR lpszWindowName, DWORD dwStyle,CWnd* pParentWnd, UINT nID) 
{ 
	// TODO: Add your specialized code here and/or call the base class 
	//gran parte del codigo se tomo como guia de clases MFC 
	ASSERT_VALID(pParentWnd);   // must have a parent 
	//en esta linea se verifica que la ventana debe disponer de un estilo fijo o dinamico 
	//pero no los dos.el estilo Dynamic permite cambiar el tamaño dela ventana mientras flota 
	//pero no cuando esta docking, el estilo fijo determina las columnas en que se disponen los 
	//componentes y permance asi. 
	ASSERT(!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC))); 
	// save the style 
	//en dwStyle debe asignarse un tipo de alineación por ejemplo CBRS_TOP,etc de lo contrario 
	//se generase un ASSERT al acambiar el Style 
	dwStyle|=CBRS_TOP; 
	m_dwStyle = (dwStyle & CBRS_ALL);//save the original style 
	dwStyle &= ~CBRS_ALL; 
	//en la siguiente instruccion el proposito que se busca es evitar el parpadeo  
	//cuando se refresca la ventana. 
	//WS_CLIPCHILDREN : recorta el area de las ventanas hijas cuando se dibuja sobre  
	//				 la ventana que la contiene. 
	//WS_CLIPSIBLING : cuando se recibe el mensaje paint se recorta el area de las otras ventanas 
	//				   hijas superpuestas, que estan fuera de la region.	 
	dwStyle |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN; 
	//con el estilo CS_DBLCLKS, lo que se busca es que al recibir un doble clic 
	//la ventana reaccione,ojo el problema es que esto lo hace solo con el area cliente.  
	LPCTSTR lpszClassName=::AfxRegisterWndClass(CS_DBLCLKS, 
												::LoadCursor(NULL,IDC_ARROW), 
												::GetSysColorBrush(COLOR_BTNFACE), 
												NULL); 
	//poque no se llama a CControlBar::Create, bueno, da igual llamar a cualquiera, CWnd o CControlBar 
	//esto debido a que CControlbar se deriva de CWnd y porque ademas CControlBar no sobrecarga el  
	//metodo Create, nosotros si porque tenemos que particularizar, cosas. 
	BOOL bResp= CWnd::Create(lpszClassName, lpszWindowName, dwStyle, CRect(0,0,0,0), pParentWnd, nID); 
	if (!bResp) return FALSE; 
	 
	return TRUE; 
} 
 
int CGuiControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 
	if (CControlBar::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	// TODO:  Add your specialized creation code here 
	//aqui es cuando llamamos a nuestra clase CGuiDockContext, de esta manera 
	//sobrecargamos el clase original que para nuestros propositos no nos sirve. 
	//porque ?, bueno porque me interesa que no se pegen las toolbar en el interior 
	//de las ventanas. 
	if (m_pDockContext==NULL) 
		m_pDockContext=new CGuiDockContext(this); 
	ASSERT(m_pDockContext); 
	m_CloseBtn.SetData(6,"Close"); 
	m_CloseBtn.SetImageList(IDB_DOCKBAR,9,10,RGB(255,0,255)); 
	return 0; 
} 
 
 
void CGuiControlBar::OnShowTitle() 
{ 
	ActiveCaption(); 
	SendMessage(WM_NCPAINT); 
} 
 
 
//esta funcion calcula el tamaño horizontal de la ventana,no importa si esta  
//docking a izquierda o derecha o arriba o abajo.Debemos disponer de un espacio equitativo entre todas 
//ventanas que se encuentren docking ya sea en una fila o columna. 
CSize CGuiControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) 
{ 
	//la funcion original toma el ancho o alto dependiendo del sentido que nos  
	//indica bHorz. 
	ASSERT_VALID(this); 
 
	if (IsFloating()) 
		return m_sizeMinFloating; 
	else 
	{ 
		//si bStrerch es TRUE significa que esta ventana no se puede hacer 
		//Docking 
		if (bStretch)  
		{ 
			if (bHorz) 
				return CSize(32767, m_sizeHorz.cy); 
			else 
				return CSize(m_sizeVert.cx, 32767); 
		} 
	} 
	 
	int Len=GetHiWid(); 
 
	int nWidth = GetWidthMax(); 
	int nMinSpace=0;//minimo espacio requerido con lo tamaños normales 
	int nMinimo=0;  //minimo espacio de los tamaños minimos 
	int nRealBars=0; 
	int m_First=GetFirstPos(); 
	 
	 
 
	for (int nPos = m_First; nPos <= m_Last; nPos++) 
	{ 
		CGuiControlBar* pBar = GetGuiControlBar(nPos,TRUE); 
		if (pBar== NULL) continue; 
		if (!pBar->IsVisible()) continue; 
		if (!pBar->IsKindOf(RUNTIME_CLASS(CGuiControlBar))) 
		{ 
			CPoint pt(GetMessagePos()); 
			m_pDockSite->FloatControlBar(pBar,pt); 
			continue; 
		} 
		if(IsVert()) 
			pBar->m_sizeVert.cx=nWidth; 
		else	 
			pBar->m_sizeHorz.cy=nWidth; //todas se hacen con el mismo ancho 
		nMinSpace+=IsVert() ? pBar->m_sizeVert.cy:pBar->m_sizeHorz.cx; //minimo espacio para alinear las barras 
		nRealBars++;	//cuantas barras realmente existen 
	} 
	 
	//si el tamaño de las barras en la fila es mayor que  
	//el espacio disponible, luego la solucion salomonica es  
	//repartir el espacio entre todas. 
	if (nRealBars == 1 ) 
	{ 
		if (bHorz) 
			return m_sizeHorz= CSize(Len,m_sizeHorz.cy); 
		else 
			return m_sizeVert=CSize(m_sizeVert.cx,Len); 
		 
	} 
	 
	 
 
	int nDif=Len-nMinSpace; 
	if (abs(nDif) !=0) 
	{ 
		BOOL bGrow=FALSE; 
		if (nDif > 0) 
			bGrow=TRUE; 
		nDif=abs(nDif); 
		while(nDif > 0) 
		{ 
			for (int nPos = m_First; nPos <= m_Last; nPos++) 
			{ 
				CGuiControlBar* pBar = GetGuiControlBar(nPos); 
				if (pBar== NULL) continue; 
				if(IsVert()) 
				{ 
					if(bGrow) 
						pBar->m_sizeVert.cy+=1; 
					else 
					{ 
						 
						if (pBar->m_sizeVert.cy-1 < pBar->m_sizeMinV.cy) 
							continue; 
						pBar->m_sizeVert.cy-=1; 
						 
					} 
				} 
				else 
				{ 
					if(bGrow) 
						pBar->m_sizeHorz.cx+=1; 
					else 
					{ 
						 
						if (pBar->m_sizeHorz.cx-1 < pBar->m_sizeMinH.cx) 
							continue; 
						pBar->m_sizeHorz.cx-=1; 
						 
					} 
					 
				} 
				 
				nDif--; 
				if(nDif==0) break; 
			} 
	 
		} 
 
	} 
	 
   //--reubicar las ventanas, sin esta rutina nada funciona 
  RecalWindowPos(); 
  
	if (IsHorz()) 
		return 	m_sizeHorz; 
	else 
		return 	m_sizeVert; 
} 
 
 
//esta rutina dispone de la posición en el Dockbar de la pila de  ventanas  
void CGuiControlBar::RecalWindowPos() 
{ 
	int m_First=GetFirstPos(); 
	int m_Last=GetLastPos(); 
	int m_This=m_pDockBar->FindBar(this); 
	 
	CRect rcWin=GetDockRect(); 
	int m_VertPos=0; 
	for(int i=m_First; i<= m_Last; i++) 
	{ 
		CGuiControlBar* pBar = GetGuiControlBar(i); 
		if (pBar == NULL) continue; 
		CRect rcBar; 
		pBar->GetWindowRect(rcBar); 
		rcBar.OffsetRect(-rcWin.TopLeft()); 
		if (IsVert()) 
		{ 
	 	 if (i==m_First)  
			rcBar.top=-2; 
		 else 
		 	rcBar.top=m_VertPos; 
		} 
		else 
		{ 
			if (i==m_First)  
				rcBar.left=-2; 
			else 
		 		rcBar.left=m_VertPos; 
		} 
		pBar->MoveWindow(rcBar); 
		m_VertPos+=IsVert()? rcBar.Height():rcBar.Width(); 
 
	} 
	m_pDockSite->RecalcLayout(); 
 
} 
 
CRect CGuiControlBar::GetDockRect() 
{ 
	CRect rcWin; 
	if (IsVert()) 
		if (IsLeft()) 
			m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rcWin); 
		else 
			m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_RIGHT)->GetWindowRect(rcWin); 
	else 
		if(IsBottom()) 
			m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_BOTTOM)->GetWindowRect(rcWin); 
		else 
			m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rcWin); 
	return rcWin; 
} 
 
 
 
int CGuiControlBar::GetWidthMax() 
{ 
	m_pos=m_pDockBar->FindBar(this); 
	m_Last=GetLastPos(); 
	int nWidth=0; 
	for (int nPos = GetFirstPos(); nPos <= m_Last; nPos++) 
	{ 
		CGuiControlBar* pBar = GetGuiControlBar(nPos); 
		if (pBar== NULL) continue; 
		nWidth=max(nWidth,IsVert() ? pBar->m_sizeVert.cx:pBar->m_sizeHorz.cy); 
	} 
	return nWidth; 
} 
 
 
 
CGuiControlBar* CGuiControlBar::GetGuiControlBar(int nPos,BOOL bAll) const 
{ 
	CGuiControlBar* pResult = (CGuiControlBar*)m_pDockBar->m_arrBars[nPos]; 
	if (bAll==FALSE) 
	{ 
		if (HIWORD(pResult) == NULL) return NULL; 
		else if (!pResult->IsVisible()) return NULL; 
		else if (!pResult->IsKindOf(RUNTIME_CLASS(CGuiControlBar))) return NULL; 
	} 
	else 
	{ 
		if (HIWORD(pResult) == NULL) 
		return NULL; 
	} 
	return pResult; 
} 
 
//En esta función se calcula el tamaño de la ventana cuando esta flotando 
//y gestionar cuando el mouse es presionado en las esquinas. 
//#define HTTOPLEFT           13 
//#define HTTOPRIGHT          14 
//#define HTBOTTOMLEFT        16 
//#define HTBOTTOMRIGHT       17 
 
 
CSize CGuiControlBar::CalcDynamicLayout(int nLength, DWORD nMode) 
{ 
 
	m_pDockSite->RecalcLayout(); 
 
	if (IsFloating()) 
	{ 
		// Enable diagonal arrow cursor for resizing 
		//m_sizeVert=m_sizeHorz=CSize(200,200); 
		GetParent()->GetParent()->ModifyStyle(MFS_4THICKFRAME|WS_CAPTION,0); 
	}  
	if (nMode & (LM_HORZDOCK | LM_VERTDOCK))  
	{ 
		m_pDockSite->DelayRecalcLayout(); 
		//obligar a reposicionar  la ventana, de lo contrario cuando vuelva de un doble click 
		//desde la ventana CMiniFrameWnd queda sin area cliente 
		SetWindowPos(NULL, 0, 0, 0, 0, 
			SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | 
			SWP_NOACTIVATE | SWP_FRAMECHANGED|SWP_NOREDRAW); 
	 	return CControlBar::CalcDynamicLayout(nLength, nMode); 
	} 
	if (nMode & LM_MRUWIDTH) 
        return  m_sizeMinFloating; 
 
    if (nMode & LM_COMMIT) 
        return  m_sizeMinFloating ; 
     
	if (IsFloating()) 
	{ 
 
		CRect	rcWin; 
		POINT	cpt; 
		GetCursorPos(&cpt); 
		GetParent()->GetParent()->GetWindowRect(&rcWin); 
		int nXOffset=0;int nYOffset=0; 
		switch (m_pDockContext->m_nHitTest) 
		{ 
 
			//------------------------------------------------------------------ 
			case HTLEFT: 
				m_pDockContext->m_rectFrameDragHorz= rcWin; 
				m_pDockContext->m_rectFrameDragHorz.left = cpt.x; 
				m_sizeMinFloating.cx = max(rcWin.right - cpt.x,32)-4 ; 
				m_sizeMinFloating.cy = max((rcWin.bottom -rcWin.top)-nGapGripper-5,32)+2 ; 
				return m_sizeMinFloating;		 
			break; 
			case HTTOP: 
				m_pDockContext->m_rectFrameDragHorz=rcWin; 
				m_pDockContext->m_rectFrameDragHorz.top = cpt.y; 
				m_sizeMinFloating.cx = max(rcWin.right-rcWin.left-2,32)-4 ; 
				m_sizeMinFloating.cy = max((rcWin.bottom -nGapGripper-cpt.y-3),32) ; 
				return m_sizeMinFloating;		 
			break; 
			case HTRIGHT: 
				m_pDockContext->m_rectFrameDragHorz=rcWin; 
				m_pDockContext->m_rectFrameDragHorz.right = cpt.x; 
				m_sizeMinFloating.cy = max(rcWin.bottom -rcWin.top-nGapGripper-3,32) ; 
				m_sizeMinFloating.cx = max(cpt.x-rcWin.left-4,32); 
				return m_sizeMinFloating;		 
			break; 
			case HTBOTTOM: 
				m_pDockContext->m_rectFrameDragHorz=rcWin; 
				m_sizeMinFloating.cy = max(cpt.y-rcWin.top -nGapGripper-3,32) ; 
				m_sizeMinFloating.cx = max(rcWin.right-rcWin.left-2,32)-4 ; 
				m_pDockContext->m_rectFrameDragHorz.bottom = cpt.y-4; 
				return m_sizeMinFloating; 
				break; 
			case HTTOPLEFT: 
				//--------------------------------------------------------- 
			//En este caso crece la ventana a izquierda y hacia arriba 
			//izquierda incrementa cx y top incrementa cy 
				m_sizeMinFloating.cx = max(rcWin.right - cpt.x,32)-3 ; 
				m_sizeMinFloating.cy = max(rcWin.bottom -nGapGripper-cpt.y,32)-2 ; 
				m_pDockContext->m_rectFrameDragHorz.top = cpt.y-1; 
				m_pDockContext->m_rectFrameDragHorz.left = cpt.x-2; 
 
				return m_sizeMinFloating;		 
				break; 
			case HTTOPRIGHT: 
				m_sizeMinFloating.cx = max(cpt.x-rcWin.left,32)-4 ; 
				m_sizeMinFloating.cy = max(rcWin.bottom -nGapGripper-cpt.y,32)-2 ; 
				m_pDockContext->m_rectFrameDragHorz.top = cpt.y-1; 
				m_pDockContext->m_rectFrameDragHorz.right = cpt.x-2; 
				return m_sizeMinFloating;		 
				break; 
			case HTBOTTOMLEFT: 
				m_sizeMinFloating.cx = max(rcWin.right - cpt.x,32)-4; 
				m_sizeMinFloating.cy = max(cpt.y-rcWin.top -nGapGripper,32)-2 ; 
				m_pDockContext->m_rectFrameDragHorz.top = rcWin.top; 
				m_pDockContext->m_rectFrameDragHorz.bottom = cpt.y-1; 
				m_pDockContext->m_rectFrameDragHorz.left = cpt.x-2; 
				return m_sizeMinFloating;		 
				break; 
			case HTBOTTOMRIGHT: 
				m_sizeMinFloating.cx = max(cpt.x-rcWin.left,32); 
				m_sizeMinFloating.cy = max(cpt.y-rcWin.top -nGapGripper,32) ; 
				m_pDockContext->m_rectFrameDragHorz.top = rcWin.top; 
				m_pDockContext->m_rectFrameDragHorz.bottom = cpt.y+1; 
				m_pDockContext->m_rectFrameDragHorz.right = cpt.x+2; 
				return m_sizeMinFloating;		 
				break; 
			 
		} 
		 
	} 
 
	if(nMode & LM_LENGTHY) 
		 m_sizeMinFloating.cy = max(nLength,32); 
	else 
	     m_sizeMinFloating.cx = max(nLength,32); 
	return m_sizeMinFloating; 
} 
 
void CGuiControlBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_pDockBar != NULL) 
		m_pDockContext->ToggleDocking(); 
	else 
		CWnd::OnLButtonDblClk(nFlags, point); 
} 
void CGuiControlBar::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
 
	CControlBar::OnLButtonDown(nFlags, point); 
} 
 
 
 
void CGuiControlBar::OnMouseMove( UINT nHitTest, CPoint point) 
{ 
	 
	if(m_bTracking) 
	{ 
		if (GetCapture() != this) 
		{ 
			//StopTracking(FALSE); 
			m_bTracking=FALSE; 
		} 
		 
		OnInvertTracker(m_rcBorder);			 
		//nuevos tamaños de la ventana 
		if (IsVert()) 
		{ 
			if (m_SideMove==HTLEFT || m_SideMove==HTRIGHT) 
			{ 
				m_rcBorder.left=point.x; 
				m_rcBorder.right=m_rcBorder.left+4; 
				 
			} 
			else 
			{ 
				m_rcBorder.top=point.y+26; 
				m_rcBorder.bottom=m_rcBorder.top+4; 
				 
			} 
		} 
		else 
		{ 
			if (m_SideMove==HTBOTTOM || m_SideMove==HTTOP) 
			{ 
				m_rcBorder.top=point.y+26; 
				m_rcBorder.bottom=m_rcBorder.top+4; 
				 
			} 
			else 
			{ 
				m_rcBorder.left=point.x; 
				m_rcBorder.right=m_rcBorder.left+4; 
				 
			} 
		} 
		 
		//-------------------------------------------------- 
		//se hacen iguales todos los tamaños 
		ClientToScreen(&point); 
		GetParentFrame()->ScreenToClient(&point); 
		m_ptActualPos=point; 
				 
		OnInvertTracker(m_rcBorder); 
		//SetEqualWidth(); 
		//----------------------------------------------- 
		 
		 
		 
	} 
	 
} 
 
 
//depende de la posicion se hace igual el tamanio del ancho o alto 
void CGuiControlBar::SetEqualWidth() 
{ 
 
	int nFirstPos=GetFirstPos(); 
	for (int nPos = nFirstPos; nPos <= m_Last; nPos++) 
	{ 
		CGuiControlBar* pBar = GetGuiControlBar(nPos); 
		if (pBar== NULL) continue; 
		if (IsHorz()) 
			pBar->m_sizeHorz.cy=m_sizeHorz.cy;//rcDockBar.Height(); 
		else 
			pBar->m_sizeVert.cx=m_sizeVert.cx; 
	} 
} 
 
int CGuiControlBar::GetHiWid() 
{ 
	CRect rcWin; 
	rcWin=GetDockRect(); 
	if (IsVert()) 
		return rcWin.Height() ; 
	else 
		return rcWin.Width() ; 
} 
 
 
//espero que funcione el truco 
//la idea es trabajar con coordenadas screen las dimensiones de los bordes del 
//dockBar, mas no con los movimientos internos. 
void CGuiControlBar::OnLButtonUp(UINT nFlags, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	CPoint ptTemp=point; 
	ClientToScreen(&ptTemp); 
	if (m_bTracking) 
	{ 
		ReleaseCapture(); 
		m_bTracking=FALSE; 
		OnInvertTracker(m_rcBorder); 
		m_pDockSite->UnlockWindowUpdate(); 
	 
		if (ptTemp ==m_ptStartPos) return; 
		 
		if (IsVert()) 
		{ 
			if (m_SideMove==HTLEFT) 
				m_sizeVert.cx-=point.x; 
			else if(m_SideMove==HTRIGHT) 
				m_sizeVert.cx=point.x; 
			else if(m_SideMove==HTTOP) 
				AjustReDinSize(point); 
		} 
		else 
		{ 
		   if (m_SideMove==HTBOTTOM) 
			   { 
				if (point.y < 0) 
					m_sizeHorz.cy+=abs(point.y); 
				else 
					m_sizeHorz.cy=point.y; 
			} 
			  
		   else if (m_SideMove==HTTOP) 
		   { 
			  if (point.y < 0) 
				  m_sizeHorz.cy+=abs(point.y)-12; 
			  else 
				  m_sizeHorz.cy-=abs(point.y)+12;	 
		   } 
			else if (m_SideMove==HTRIGHT) 
		   	   AjustReDinSize(point); 
		    	 
		} 
		 
		SetEqualWidth(); 
		 
	} 
	m_pDockSite->RecalcLayout(); 
	 
 
} 
 
//ajusta las ventanas a redimencionarlas verticalmente 
//se decrementa las anteriores ventanas a la actual y se  
//incrementan las posteriores. 
void CGuiControlBar::AjustReDinSize(CPoint point) 
{ 
	 
	int nFirstPos=GetFirstPos(); 
	int nLastPos=GetLastPos(); 
	int m_ThisPos=m_pDockBar->FindBar(this); 
	 
 
	ClientToScreen(&point); 
 
	//si la diferencia es negativa esta barra crece la anterior a esta disminuye 
	int nDif=0; 
	BOOL bGrow=FALSE; 
	 
	if (IsVert()) 
	{ 
		 nDif=m_ptStartPos.y- point.y; 
		 if (nDif > 0) 
			bGrow=TRUE; 
		  
		 if (bGrow) 
                m_sizeVert.cy+=abs(nDif)+4; 
		 else 
				m_sizeVert.cy-=abs(nDif); 
			 
	 	 if (nFirstPos == m_ThisPos)  
			return; 
	 
	} 
	else 
	{ 
		 nDif=m_ptStartPos.x- point.x; 
		 if (nDif < 0) 
			bGrow=TRUE; 
 
		 if (bGrow) 
				m_sizeHorz.cx+=abs(nDif); 
			else 
				m_sizeHorz.cx-=abs(nDif); 
			 
         if (nLastPos == m_ThisPos)  
			return; 
	} 
	 
	 
	if (IsVert()) 
		AjustVert(bGrow,nDif); 
	else 
		AjustHorz(bGrow,nDif); 
	 
	RecalWindowPos(); 
	 
 
	 
} 
	 
 
void CGuiControlBar::AjustVert(BOOL bGrow,int nDif) 
{ 
	int nFirstPos=GetFirstPos(); 
	int nLastPos=GetLastPos(); 
	int m_ThisPos=m_pDockBar->FindBar(this); 
 
	if(m_SideMove==HTTOP) 
	{ 
				 
		//Esta ventana crece las anteriores reducen su tamaño 
		 
		if (bGrow)	 
			{ 
				for (int i=m_ThisPos-1; i > 0; i--) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(i); 
					if (pBar== NULL) return; 
					if(IsVert()) 
					{ 
						if (pBar->m_sizeVert.cy-abs(nDif) < pBar->m_sizeMinV.cy) 
						{ 
							pBar->m_sizeVert.cy=pBar->m_sizeMinV.cy; 
							continue; 
						} 
						else 
						{ 
							pBar->m_sizeVert.cy-=abs(nDif); 
							break; 
						} 
					} 
				}//for 
					 
			}//bGrow 
			else	//este disminuye la anterior crece 
			{ 
				if (m_ThisPos-1 > 0) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(m_ThisPos-1); 
					if (pBar== NULL) return; 
					pBar->m_sizeVert.cy+=abs(nDif);  
					if(m_sizeVert.cy > m_sizeMinV.cy) 
						return; 
					else 
					  pBar->m_sizeVert.cy-=m_sizeMinV.cy;  
				} 
				for (int i=m_ThisPos+1; i >= m_Last; i++) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(i); 
					if (pBar== NULL) return; 
					if(IsVert()) 
					{ 
						if (pBar->m_sizeVert.cy-abs(nDif) < pBar->m_sizeMinV.cy) 
							continue; 
						else 
						{ 
							pBar->m_sizeVert.cy-=abs(nDif); 
							return; 
						} 
					} 
				}//for 
			} 
	} 
} 
 
 
void CGuiControlBar::AjustHorz(BOOL bGrow,int nDif) 
{ 
	int nFirstPos=GetFirstPos(); 
	int nLastPos=GetLastPos(); 
	int m_ThisPos=m_pDockBar->FindBar(this); 
 
	if(m_SideMove==HTRIGHT) 
	{ 
				 
		//Esta ventana crece las anteriores reducen su tamaño 
		 
		if (bGrow)	 
			{ 
				for (int i=m_ThisPos+1; i <= nLastPos; i++) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(i); 
					if (pBar== NULL) return; 
					if(IsHorz()) 
					{ 
						if (pBar->m_sizeHorz.cx-abs(nDif) < pBar->m_sizeMinH.cx) 
						{ 
							pBar->m_sizeHorz.cx=pBar->m_sizeMinH.cx; 
							continue; 
						} 
						else 
						{ 
							pBar->m_sizeHorz.cx-=abs(nDif); 
							break; 
						} 
					} 
				}//for 
					 
			}//bGrow 
			else	//este disminuye la anterior crece 
			{ 
			   if (m_ThisPos+1 <= m_Last) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(m_ThisPos+1); 
					if (pBar== NULL) return; 
					pBar->m_sizeHorz.cx+=abs(nDif);  
					if(m_sizeHorz.cx > m_sizeMinH.cx) 
						return; 
					else 
					  pBar->m_sizeHorz.cx+=abs(nDif);  
				} 
 
 
				for (int i=m_ThisPos-1; i >0; i--) 
				{ 
					CGuiControlBar* pBar = GetGuiControlBar(i); 
					if (pBar== NULL) return; 
					if(IsHorz()) 
					{ 
						if (pBar->m_sizeHorz.cx-abs(nDif) < pBar->m_sizeMinH.cx) 
							continue; 
						else 
						{ 
							pBar->m_sizeHorz.cx-=abs(nDif); 
							return; 
						} 
					} 
				}//for 
			} 
	} 
 
	 
} 
 
 
//---------------------------------------------------- 
//OnActiveWindow retira o asigna el foco a la ventana  
 
void CGuiControlBar::OnActiveWindow() 
{ 
	POSITION pos = m_pDockSite->m_listControlBars.GetHeadPosition(); 
	while (pos != NULL) 
	{ 
		CDockBar* pDockBar = (CDockBar*)m_pDockSite->m_listControlBars.GetNext(pos); 
		if (pDockBar->IsDockBar() && pDockBar->IsWindowVisible() && 
			(!pDockBar->m_bFloating )) 
			{ 
				int nNumBars=(int)pDockBar->m_arrBars.GetSize(); 
				for(int i=0; i< nNumBars;i++) 
				{ 
					CGuiControlBar* pBar = (CGuiControlBar*) pDockBar->m_arrBars[i]; 
					if (HIWORD(pBar) == NULL) continue; 
					if (!pBar->IsVisible()) continue; 
					if (!pBar->IsKindOf(RUNTIME_CLASS(CGuiControlBar))) continue; 
					if (pBar != this) 
					{ 
						pBar->m_bOldActive=FALSE; 
						pBar->m_bActive=FALSE; 
						pBar->m_bForcepaint=TRUE; 
						pBar->SendMessage(WM_NCPAINT); 
						pBar->m_bForcepaint=FALSE; 
					} 
					else 
					{ 
						m_bOldActive=m_bActive; 
						m_bActive=TRUE; 
						m_bForcepaint=TRUE; 
						SendMessage(WM_NCPAINT); 
						m_bForcepaint=FALSE; 
						 
 
					} 
				} 
			} 
	} 
} 
 
 
void CGuiControlBar::ActiveCaption() 
{ 
	CWnd* pFocus=SetFocus();	 
	if(pFocus->GetSafeHwnd()) 
		IsChild(pFocus); 
	m_bForcepaint=TRUE; 
	OnActiveWindow(); 
	m_bForcepaint=FALSE; 
 
} 
 
 
 
void CGuiControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	if (m_bTracking /*|| IsFloating()*/) 
        return; 
	 
	 
	  
	m_ptStartPos=point; 
	if( nHitTest == HTCAPTION || nHitTest == HTCLOSE)											 
		ActiveCaption(); 
	//---------para el boton---- 
	if( nHitTest == HTCLOSE)											 
	{ 
		m_stateBtn=PRESS; 
		SendMessage(WM_NCPAINT); 
		SetTimer(1,100,0); 
		 
		return; 
	} 
	//-------------------------- 
 
	if (m_pDockBar != NULL) 
	{ 
		 
		if (HTCAPTION == nHitTest) 
		{ 
			m_pDockContext->StartDrag(point); 
			m_sizeHorzt=m_sizeHorz; 
			m_sizeVertt=m_sizeVert; 
		} 
		if(!m_bTracking) 
		{ 
			if(m_rcBorder.PtInRect(point)) 
			{ 
				 
				m_pDockSite->LockWindowUpdate(); 
				OnInvertTracker(m_rcBorder); 
				 
				m_ptStartPos=point; 
				SetCapture(); 
				SetFocus(); 
			 
				m_bTracking=TRUE; 
				m_sizeHorzt=m_sizeHorz; 
				m_sizeVertt=m_sizeVert; 
				 
			} 
		} 
	} 
	CWnd::OnNcLButtonDown(nHitTest, point); 
	 
} 
 
void CGuiControlBar::OnNcLButtonUp(UINT nHitTest, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	CRect rc; 
	//------------------ para el boton 
	CRect rcT=m_rcCloseBtn; 
	ClientToScreen(rcT); 
	point.y+=23; 
	point.x+=5; 
	if (rcT.PtInRect(point)) 
	{ 
		 
		if (m_stateBtn ==PRESS) 
		{ 
			m_stateBtn=NORMAL; 
			KillTimer(1); 
			GetDockingFrame()->ShowControlBar(this, FALSE, FALSE); 
		} 
		//SendMessage(WM_NCPAINT); 
		return; 
			 
	} 
	//-------------------para el boton 
	 
	 
} 
 
void CGuiControlBar::OnNcPaint() 
{ 
	// 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; 
	CWindowDC	dc(this); 
	CDC			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); 
    rcClient.OffsetRect(-rcWindow.TopLeft()); 
    rcWindow.OffsetRect(-rcWindow.TopLeft()); 
  	 
	m_dc.CreateCompatibleDC(&dc); 
	m_bitmap.CreateCompatibleBitmap(&dc,rcWindow.Width(),rcWindow.Height()); 
	CBitmap *m_OldBitmap=m_dc.SelectObject(&m_bitmap); 
	//aqui debe utilizarse la brocha que define GuiDrawLayer, si no hacemos la siguiente 
	//linea usted vera un horrible color negro, a cambio del dibujo. 
	CBrush cb; 
	cb.CreateSolidBrush(m_clrFondo); 
	m_dc.FillRect(rcWindow, &cb); 
 
	DrawGripper(&m_dc,&rcWindow); 
	dc.IntersectClipRect(rcWindow); 
    dc.ExcludeClipRect(rcClient);//asi evitamos el parpadeo 
	dc.BitBlt(rcWindow.left,rcWindow.top,rcWindow.Width(),rcWindow.Height(),&m_dc,0,0,SRCCOPY); 
	ReleaseDC(&dc); 
	m_dc.SelectObject(m_OldBitmap); 
	m_bitmap.DeleteObject(); 
	m_dc.DeleteDC(); 
	 
		 
 
} 
 
void CGuiControlBar::DrawGripper(CDC* pDC,CRect* rc) 
{ 
	CRect gripper = rc; 
	gripper.top =3; 
	gripper.left+=4; 
	gripper.right-=IsVert()?6:4; 
	gripper.bottom =gripper.top +nGapGripper-3; 
	//si la ventana esta activa pintamos el caption o el area del titulo de color azul 	 
	if (IsFloating()) 
		m_bActive=TRUE; 
	 
	/* Modified By SunZhenyu 2003/6/21, Add the following line*/ 
	m_bActive = FALSE; 
	 
	if(!m_bActive) 
	{ 
		 
		CPen cp(PS_SOLID,1,::GetSysColor(COLOR_BTNSHADOW)); 
		CPen* cpold=pDC->SelectObject(&cp); 
		//linea superior 
		pDC->MoveTo(gripper.left+1,gripper.top); 
		pDC->LineTo(gripper.right,gripper.top); 
		//linea izquierda 
		pDC->MoveTo(gripper.left,gripper.top+1); 
		pDC->LineTo(gripper.left,gripper.bottom); 
		//linea inferior 
		pDC->MoveTo(gripper.left+1,gripper.bottom); 
		pDC->LineTo(gripper.right,gripper.bottom); 
		//linea derecha 
		pDC->MoveTo(gripper.right,gripper.top+1); 
		pDC->LineTo(gripper.right,gripper.bottom); 
		pDC->SelectObject(cpold); 
	} 
	else 
	{ 
		CBrush cb; 
		cb.CreateSolidBrush(::GetSysColor(COLOR_ACTIVECAPTION));//GuiDrawLayer::GetRGBCaptionXP()); 
		pDC->FillRect(gripper,&cb); 
	} 
	gripper.DeflateRect(1, 1); 
	CString m_caption; 
	GetWindowText(m_caption); 
	CFont m_cfont; 
 
	// Modified Bu SunZhenyu 
	if( !m_cfont.CreateStockObject( DEFAULT_GUI_FONT ) ) 
		m_cfont.CreateStockObject( ANSI_VAR_FONT ); 
	// m_cfont.CreateFont(-11,0,0,0,400,0,0,0,0,1,2,1,34,"Verdana"); 
		 
	CFont* m_fontOld=pDC->SelectObject(&m_cfont); 
	int nMode = pDC->SetBkMode(TRANSPARENT); 
	CSize SizeCad=pDC->GetTextExtent(m_caption); 
	CRect rCText=gripper; 
	rCText.top=6; 
	rCText.bottom =rCText.top+14; 
	 
	int cont=SizeCad.cx; 
	while(cont > 1 && gripper.Width() > 0) 
		{ 
			CSize coor=pDC->GetTextExtent(m_caption,m_caption.GetLength()); 
			if(coor.cx > gripper.Width()-10) 
			{ 
				m_caption=m_caption.Left(m_caption.GetLength()-1); 
			} 
			else 
				break; 
			cont--; 
				 
		} 
	if (gripper.Width() > 0	) 
	if (!m_bActive) 
		pDC->TextOut(rCText.left+3,rCText.top,m_caption); 
	else 
	{ 
		pDC->SetTextColor(RGB(255,255,255)); 
		pDC->TextOut(rCText.left+3,rCText.top,m_caption); 
	} 
	//CRect gripper; 
	//------------------------------------------------ 
	GetWindowRect( gripper ); 
	ScreenToClient( gripper ); 
	gripper.OffsetRect( -gripper.left, -gripper.top ); 
	gripper.left=gripper.right-20; 
	gripper.right-=7; 
	gripper.top+=6; 
	gripper.bottom=gripper.top+13; 
	m_rcCloseBtn=gripper; 
	//m_rcCloseBtn.left-=4; 
	//ClientToScreen(m_rcCloseBtn); 
	if(!m_bActive) 
	  m_CloseBtn.Paint(pDC,m_stateBtn,gripper,::GetSysColor(COLOR_BTNFACE)); 
	else 
	  m_CloseBtn.Paint(pDC,m_stateBtn,gripper,::GetSysColor(COLOR_ACTIVECAPTION)); 
	//------------------------------------------------ 
 	pDC->SetBkMode(nMode); 
	pDC->SelectObject(m_fontOld); 
	 
} 
 
//en esta función se calcula el area cliente que podra ser utilizado 
//por ventanas que deriven esta clase. 
void CGuiControlBar::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp) 
{ 
	// adjust non-client area for border space 
	lpncsp->rgrc[0].left +=!IsFloating()?5:2; 
	lpncsp->rgrc[0].top +=nGapGripper+3; 
	lpncsp->rgrc[0].right -=!IsFloating()?IsVert()?7:4:2; 
	lpncsp->rgrc[0].bottom -=!IsFloating()?3:2; 
	 
} 
 
 
//Aqui la idea es verificar que si se da clic sobre otra ventana de este tipo 
//automaticamente emita un mensaje eliminando el caption que la identifica como 
//ventana default. 
 
void CGuiControlBar::OnWindowPosChanged(WINDOWPOS* lpwndpos) 
{ 
	CRect rc; 
	GetClientRect(rc); 
	nDockBarAling = GetParent()->GetDlgCtrlID(); 
	//envie un recalculo del area cliente solo si el tamaño ha sido  
	//cambiado, de lo contrario permanezca igual 
	lpwndpos->flags |= SWP_FRAMECHANGED; 
	CControlBar::OnWindowPosChanged(lpwndpos); 
 
	CWnd* pWnd = GetWindow(GW_CHILD); 
	if (!m_bSupportMultiView) 
	{ 
        if (pWnd != NULL) 
        { 
            pWnd->MoveWindow(rc); 
            ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL); 
		} 
	} 
	else 
	{ 
		while (pWnd != NULL) 
        { 
            if (pWnd->IsWindowVisible()) 
			{ 
				pWnd->MoveWindow(rc); 
				break; 
			} 
            pWnd=pWnd->GetWindow(GW_HWNDNEXT); 
		} 
	} 
} 
 
 
//este conjunto de clases nos indican el estado de la ventana 
//en un momento determinado 
 
BOOL CGuiControlBar::IsLeft() 
{ 
	if (nDockBarAling == AFX_IDW_DOCKBAR_LEFT)	return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsRight() 
{ 
	if (nDockBarAling == AFX_IDW_DOCKBAR_RIGHT)	return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsTop() 
{ 
	if (nDockBarAling == AFX_IDW_DOCKBAR_TOP) return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsBottom() 
{ 
	if (nDockBarAling == AFX_IDW_DOCKBAR_BOTTOM) return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsVert() 
{ 
	if (IsLeft() || IsRight())	return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsHorz() 
{ 
	if (IsTop() || IsBottom())	return TRUE; 
	return FALSE; 
} 
 
BOOL CGuiControlBar::IsFloating() 
{ 
	if (nDockBarAling == AFX_IDW_DOCKBAR_FLOAT)	return TRUE; 
	return FALSE; 
 
} 
void CGuiControlBar::OnPaint() 
{ 
	CPaintDC dc(this); // device context for painting 
	m_pDockSite->RecalcLayout();//si quita esto se tiene problemas     
 
	// TODO: Add your message handler code here 
	// Do not call CControlBar::OnPaint() for painting messages 
} 
 
 
UINT CGuiControlBar::OnNcHitTest(CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	CRect rcWindow; 
	//no se convierte las coordenadas de pantalla porque el punto 
	//entregado por esta función esta dado en el mismo sentido. 
	GetWindowRect(rcWindow); 
	int it=0; 
//	if (IsFloating()) 
//        return CControlBar::OnNcHitTest(point); 
	CRect rcT=m_rcCloseBtn; 
	ClientToScreen(rcT); 
	CPoint pt=point; 
	pt.y+=23; 
	pt.x+=5; 
	//pt.Offset(-rcT.left,-rcT.top); 
	if (rcT.PtInRect(pt)) 
		return HTCLOSE; 
	CRect rcTemp; 
	for (int i=0; i< 4; i++) 
	{ 
		rcTemp=rcWindow; 
		if (i== 0)		//left 
		{ 
			it=	rcTemp.left; 
			it+=4; 
			rcTemp.right=it; 
			m_rcBorder=rcTemp; 
			if (rcTemp.PtInRect(point)) 
				if(IsLegal(HTLEFT)) return m_SideMove=HTLEFT; 
		} 
		if (i==1)  //top 
		{ 
			it=	rcTemp.top; 
			it+=4; 
			rcTemp.bottom=it; 
			m_rcBorder=rcTemp; 
			if (rcTemp.PtInRect(point)) 
				 if(IsLegal(HTTOP)) return m_SideMove=HTTOP ;			 
		} 
		if (i==2)  //right 
		{ 
			it=	rcTemp.right; 
			it-=4; 
			rcTemp.left=it; 
			m_rcBorder=rcTemp; 
			if (rcTemp.PtInRect(point)) 
				if (IsLegal(HTRIGHT)) return m_SideMove=HTRIGHT;			 
		} 
		if (i==3)  //bottom 
		{ 
			it=	rcTemp.bottom; 
			it-=4; 
			rcTemp.top=it; 
			m_rcBorder=rcTemp; 
			if (rcTemp.PtInRect(point)) 
				if (IsLegal(HTBOTTOM))return m_SideMove=HTBOTTOM;			 
		} 
 
	} 
	it=0; 
	rcTemp=rcWindow; 
	it=	rcTemp.top+nGapGripper; 
	rcTemp.bottom=it; 
	if (rcTemp.PtInRect(point)) 
		return m_SideMove=HTCAPTION; 
	 
	return CControlBar::OnNcHitTest(point); 
} 
 
//----------------------------------------------------------- 
//aqui se verifica que las coordenadas de cambio de tamaño 
//sean las correctas 
 
BOOL CGuiControlBar::IsLegal(UINT uAlin) 
{ 
	m_First=GetFirstPos(); 
//	if (IsFloating()) return FALSE; 
	switch(uAlin) 
	{ 
		case HTLEFT: 
			if (IsHorz() && m_pos >0 && (m_pos != m_Last && m_pos != m_First)) return TRUE; 
			if (IsVert() && m_pos <= m_Last && IsRight() ) return TRUE; 
			return FALSE; 
			break; 
		case HTTOP: 
			if (m_pos != m_First && IsVert()) return TRUE; 
			if (IsHorz() && m_pos <= m_Last && IsBottom() ) return TRUE; 
			return FALSE; 
			break; 
		case HTRIGHT: 
			if (m_pos <= m_Last && IsVert() && IsLeft() ) return TRUE; 
			if (IsHorz() && m_pos >0 &&  m_pos != m_Last) return TRUE; 
			return FALSE; 
		case HTBOTTOM: 
			if ((m_pos != m_Last && m_pos != m_First) && IsHorz() && IsBottom()) return TRUE; 
			if (m_pos <= m_Last && IsHorz() && IsTop()) return TRUE; 
			//if (IsVert() && m_pos >0 ) return TRUE; 
			return FALSE; 
			break; 
	} 
	return FALSE; 
} 
 
 
 
//---------------------------------------------- 
//debemos obtener cuantas barras existen en esta columnas 
//porque si intentamos obtener el conteo con la funciones de dockbar 
//siempre obtendremos nuestra actual barra mas otra de otra fila, por lo que 
//el conteo es incorrecto, luego despues de nuestra barra la siguiente nula 
//es el final de esta fila. 
 
int CGuiControlBar::GetLastPos() 
{ 
	 
	int nNumBars=(int)m_pDockBar->m_arrBars.GetSize(); 
	int m_pos=m_pDockBar->FindBar(this); 
	for(int i=m_pos+1; i< nNumBars;i++) 
	{ 
		if (m_pDockBar->m_arrBars[i]== NULL) 
		    return i-1;	 
	} 
	return -1; 
} 
 
//-------------------------------------------- 
//esta rutina funciona algo parecido a la anterior 
//con la diferencia que ahora se parte desde la posicion 
//que indetifica m_pos hacia atraz hasta encontrar el nulo 
int CGuiControlBar::GetFirstPos() 
{ 
	int m_pos=m_pDockBar->FindBar(this); 
	for(int i=m_pos; i>=0;i--) 
	{ 
		if (m_pDockBar->m_arrBars[i]== NULL) 
		    return i+1;	 
	} 
	return -1; 
 
} 
 
 
 
//------------------------------------------------------------------------ 
 
BOOL CGuiControlBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{ 
	// TODO: Add your message handler code here and/or call default 
	if (IsFloating()) return 0; 
	CPoint ptCursor; 
	::GetCursorPos (&ptCursor); 
	if(nHitTest == HTLEFT ||nHitTest == HTRIGHT) 
		SetCursor(AfxGetApp ()->LoadCursor (AFX_IDC_HSPLITBAR)); 
	else if(nHitTest == HTTOP ||nHitTest == HTBOTTOM) 
		SetCursor(AfxGetApp ()->LoadCursor (AFX_IDC_VSPLITBAR)); 
	else 
		return CControlBar::OnSetCursor(pWnd, nHitTest, message); 
	return 1; 
} 
 
 
 
void CGuiControlBar::OnInvertTracker(const CRect& rect) 
{ 
	ASSERT_VALID(this); 
	ASSERT(!rect.IsRectEmpty()); 
		 
	CRect rcWin=GetDockRect(); 
	 
	CDC *pDC = m_pDockSite->GetDCEx(NULL, 
        DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE); 
	CRect rcBar; 
	GetWindowRect(rcBar); 
	if (IsVert())  //el sentido de las barras es vertical 
	{ 
 
		 
		 
		if (m_SideMove==HTLEFT || m_SideMove==HTRIGHT) //el mouse esta en el borde izquierdo o derecho 
		{ 
			rcWin.OffsetRect(-rect.left,-rect.top); 
			rcWin.top+=10; 
			rcWin.left=rect.left+2; 
			rcWin.right=rect.right+2; 
		} 
		else  //el mouse esta el borde de arriba pero de una barra vertical 
		{ 
			rcBar.OffsetRect(-rect.TopLeft()); 
			rcWin=rcBar; 
			if (IsLeft() || IsRight())   //a la izquierda 
			{ 
				 
				rcWin.top=rect.top-2; 
				rcWin.bottom=rect.bottom-2; 
			} 
			// 
			 
		} 
	} 
	else  //el sentido de las barras es horizontal 
	{ 
		 
		if (m_SideMove==HTTOP || m_SideMove==HTBOTTOM) //el mouse esta en el borde de arriba o abajo 
		{ 
			rcWin.OffsetRect(-rect.left,-rect.top); 
			rcWin.top=rect.top-2; 
			rcWin.bottom=rect.bottom-2; 
		} 
		else		//el mouse esta en el borde derecho 
		{ 
			rcBar.OffsetRect(-rect.TopLeft()); 
			rcWin=rcBar; 
			if (IsBottom() || IsTop())	//abajo 
			{		 
				rcWin.left=rect.left+2; 
				rcWin.right=rect.right+2; 
			} 
		} 
	} 
	ClientToScreen(&rcWin); 
	GetParentFrame()->ScreenToClient(&rcWin); 
	// invert the brush pattern (looks just like frame window sizing) 
	CBrush* pBrush = CDC::GetHalftoneBrush(); 
	HBRUSH hOldBrush = NULL; 
	if (pBrush != NULL) 
		hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject); 
	pDC->PatBlt(rcWin.left, rcWin.top, rcWin.Width(), rcWin.Height(), PATINVERT); 
	if (hOldBrush != NULL) 
		SelectObject(pDC->m_hDC, hOldBrush); 
	m_pDockSite->ReleaseDC(pDC); 
} 
 
 
void CGuiControlBar::OnSize(UINT nType, int cx, int cy) 
{ 
//	CControlBar::OnSize(nType, cx, cy); 
	CWnd* pWnd = GetWindow(GW_CHILD); 
	if (!m_bSupportMultiView) 
	{ 
        if (pWnd != NULL) 
        { 
            pWnd->MoveWindow(0, 0, cx, cy); 
            ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL); 
		} 
	} 
	else 
	{ 
		while (pWnd != NULL) 
        { 
            if (pWnd->IsWindowVisible()) 
			{ 
				pWnd->MoveWindow(0, 0, cx, cy); 
				break; 
			} 
            pWnd=pWnd->GetWindow(GW_HWNDNEXT); 
		} 
	} 
	//m_pDockSite->RecalcLayout(); 
	// TODO: Add your message handler code here 
} 
void CGuiControlBar::SetColorFondo(COLORREF clrFondo) 
{ 
	m_clrFondo=clrFondo; 
	 
} 
 
//enum State{NORMAL=0,OVER=1,PRESS=2}; 
 
 
CGuiControlBarButton::CGuiControlBarButton() 
{ 
	bTypeButton=GUINORMAL; 
	m_bEnabled=TRUE; 
} 
 
 
CGuiControlBarButton::~CGuiControlBarButton() 
{ 
 
} 
 
void CGuiControlBarButton::SetTypeButton(GuiType bTypeb) 
{ 
	bTypeButton=bTypeb; 
} 
 
 
void CGuiControlBarButton::SetEnabled(BOOL bEnabled) 
{ 
	m_bEnabled=bEnabled; 
} 
 
void CGuiControlBarButton::Paint(CDC* pDC,int st,CRect rc,COLORREF clrFondo) 
{ 
	CBrush cb; 
	if(bTypeButton==GUINORMAL)  
		cb.CreateSolidBrush(clrFondo); 
	else 
	{ 
		if (m_bEnabled) 
			if (st == OVER) 
				cb.CreateSolidBrush(GuiDrawLayer::GetRGBFondoXP()); 
			else if(st == PRESS) 
				cb.CreateSolidBrush(GuiDrawLayer::GetRGBPressBXP()); 
			else 
				cb.CreateSolidBrush(GuiDrawLayer::GetRGBColorFace()); 
	} 
 
	if (m_bEnabled) 
	{ 
		pDC->FillRect(rc,&cb); 
		if (st == OVER) 
			pDC->Draw3dRect(rc,bTypeButton==GUINORMAL?::GetSysColor(COLOR_BTNHIGHLIGHT):GuiDrawLayer::GetRGBCaptionXP(), 
							   bTypeButton==GUINORMAL?::GetSysColor(COLOR_BTNSHADOW):GuiDrawLayer::GetRGBCaptionXP()); 
		if (st == PRESS) 
			pDC->Draw3dRect(rc,bTypeButton==GUINORMAL?::GetSysColor(COLOR_BTNSHADOW):GuiDrawLayer::GetRGBCaptionXP(), 
			bTypeButton==GUINORMAL?::GetSysColor(COLOR_BTNHIGHLIGHT):GuiDrawLayer::GetRGBCaptionXP()); 
	} 
	if(bTypeButton==GUINORMAL)  
		m_imgList.Draw(pDC,clrFondo == ::GetSysColor(COLOR_ACTIVECAPTION)? m_nIcon+1:m_nIcon,  
						CPoint(rc.left+1,rc.top+2), ILD_TRANSPARENT);				 
	else 
	{ 
		if (m_bEnabled) 
			m_imgList.Draw(pDC,m_nIcon, CPoint(rc.left+1,rc.top+1), ILD_TRANSPARENT);				 
		else 
		{ 
			HICON m_Icon=m_imgList.ExtractIcon(m_nIcon); 
			ICONINFO bm; 
			ZeroMemory(&bm, sizeof(ICONINFO)); 
			::GetIconInfo(m_Icon,&bm); 
			CSize m_SizeImage =CSize((BYTE)(bm.xHotspot*2),(BYTE)(bm.yHotspot*2)); 
			pDC->DrawState(CPoint(rc.left+1,rc.top+1),m_SizeImage,m_Icon,DSS_MONO,CBrush (GuiDrawLayer::GetRGBColorShadow())); 
		} 
	} 
} 
 
void CGuiControlBarButton::SetData(int nIcon,LPCTSTR lpMsg) 
{ 
	m_nIcon=nIcon; 
	m_lpMsg=lpMsg; 
} 
 
void  CGuiControlBarButton::SetImageList(UINT nBitmapID, int cx, int nGrow, COLORREF crMask) 
{ 
	CBitmap cbmp; 
	BITMAP bmp; 
	m_imgList.Create(nBitmapID,cx,nGrow,crMask); 
	cbmp.LoadBitmap(nBitmapID); 
	cbmp.GetBitmap(&bmp); 
	m_imgList.Add(&cbmp,crMask); 
 
} 
 
 
void CGuiControlBar::OnNcMouseMove(UINT nHitTest, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
	if (m_stateBtn != NORMAL) return; 
	if (nHitTest == HTCLOSE) 
	{ 
		m_stateBtn=OVER; 
		SetTimer(1,100,0); 
	} 
	SendMessage(WM_NCPAINT); 
	CControlBar::OnNcMouseMove(nHitTest, point); 
} 
 
void CGuiControlBar::OnTimer(UINT nIDEvent) 
{ 
	// TODO: Add your message handler code here and/or call default 
	if (m_stateBtn==NORMAL) return; 
	CRect rc; 
	CPoint pt(GetMessagePos()); 
	 
	CRect rcT=m_rcCloseBtn; 
	ClientToScreen(rcT); 
	pt.y+=23; 
	pt.x+=5; 
	if (!rcT.PtInRect(pt)) 
	{ 
		m_stateBtn=NORMAL; 
		KillTimer(1); 
		SendMessage(WM_NCPAINT); 		 
	} 
	CControlBar::OnTimer(nIDEvent); 
} 
 
void CGuiControlBar::OnNcLButtonDblClk(UINT nFlags, CPoint point) 
{ 
	if(m_pDockBar != NULL) 
	{ 
 
		m_pDockContext->ToggleDocking(); 
		m_rcOldBorder=CRect(0,0,0,0); 
				 
	}	 
}