f// aplTreeView.cpp : implementation file
//

#include "stdafx.h"
#include "apl_gui.h"

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

bool CaplTreeView::m_xp_mode=true;
bool CaplTreeView::m_ShowSelectedOverIcons=false;

COLORREF LightenColor(COLORREF col,double factor)
{
	if(factor>0.0&&factor<=1.0){
		BYTE red,green,blue,lightred,lightgreen,lightblue;
		red = GetRValue(col);
		green = GetGValue(col);
		blue = GetBValue(col);
		lightred = (BYTE)((factor*(255-red)) + red);
		lightgreen = (BYTE)((factor*(255-green)) + green);
		lightblue = (BYTE)((factor*(255-blue)) + blue);
		col = RGB(lightred,lightgreen,lightblue);
	}
	return(col);
}

const TCHAR KeyName[]=_T("Software\\CALS Centre \"Applied Logistic\"");
const TCHAR ValName[]=_T("XP_Tree");


/////////////////////////////////////////////////////////////////////////////
// CaplTreeView

IMPLEMENT_DYNCREATE(CaplTreeView, CTreeView)

BEGIN_MESSAGE_MAP(CaplTreeView, CTreeView)
	//{{AFX_MSG_MAP(CaplTreeView)
	ON_WM_LBUTTONDOWN()
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CaplTreeView construction/destruction

CaplTreeView::CaplTreeView()
{
	m_icon_width=0;
	m_default_font=0;
	m_bNoPaint=false;

	m_ToolTip.m_text_x_paragr=4;
	m_ToolTip.m_pFontWnd=this;

	int i;
	for(i=0;i<APL_TREE_CTRL_MAX_ICONS;i++) m_ImageLists[i]=0;
	for(i=0;i<APL_TREE_CTRL_MAX_ICONS;i++) m_ImagesHigh[i]=0;
	for(i=0;i<APL_TREE_CTRL_MAX_ICONS;i++) m_ImagesWidth[i]=0;

	m_bMultiSelect = false;
//	m_bWithCtrl = false;
	m_default_item_high=0;
}

CaplTreeView::~CaplTreeView()
{
}

/////////////////////////////////////////////////////////////////////////////
// CaplTreeView drawing

void CaplTreeView::OnDraw(CDC* pDC)
{
//	CAplTreeViewDoc* pDoc = GetDocument();
//	ASSERT_VALID(pDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CaplTreeView diagnostics

#ifdef _DEBUG
void CaplTreeView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CaplTreeView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CaplTreeView message handlers

//*********************************************************************************
void CaplTreeView::SetIconsSize(int cx, int cy)
{
	m_il_empty.Create(cx,cy,ILC_COLOR,2,2);
	GetTreeCtrl().SetImageList(&m_il_empty,LVSIL_STATE);
	m_icon_width=cx;
}
//*********************************************************************************
bool CaplTreeView::SetImageList(CImageList *il,int index)
{
	ASSERT(il!=0);
	if(il==0) return false;
	ASSERT(index<APL_TREE_CTRL_MAX_ICONS);
	if( (index<0) || (index>=APL_TREE_CTRL_MAX_ICONS)) return false;

	ASSERT(il->GetImageCount()>0);
	if(il->GetImageCount()<1) return false;
	
	IMAGEINFO imginfo;
	if(!il->GetImageInfo(0,&imginfo)) return false;

	m_ImageLists[index]=il;
	m_ImagesHigh[index]=imginfo.rcImage.bottom-imginfo.rcImage.top;
	m_ImagesWidth[index]=imginfo.rcImage.right-imginfo.rcImage.left;

	return true;	
}
//*********************************************************************************
void CaplTreeView::ResetFont()
{
	m_default_font=GetTreeCtrl().GetFont();
	if(0==m_default_item_high) m_default_item_high=GetTreeCtrl().GetItemHeight();
	ASSERT(m_default_font!=0);

	int i;
	for(i=0;i<8;i++) 
		m_fonts[i].DeleteObject();

	// Создание жирного, курсивного, зачеркнутого шрифтов и их комбинации
	LOGFONT LogFont;
	m_default_font->GetLogFont(&LogFont);

	//CaplDefWindowParam::Load();
	if(CaplDefWindowParam::m_font_face!=_T("")) CaplDefWindowParam::CopyFontFaceName(CaplDefWindowParam::m_font_face,LogFont.lfFaceName); 
	if(CaplDefWindowParam::m_font_size!=0)   LogFont.lfHeight=CaplDefWindowParam::m_font_size;
	if(CaplDefWindowParam::m_win_bk_color!=RGB(0,0,0)) GetTreeCtrl().SetBkColor(CaplDefWindowParam::m_win_bk_color);


	m_fonts[APL_FONT_DEFAULT].CreateFontIndirect(&LogFont);

	m_ToolTip.m_pFont=&(m_fonts[APL_FONT_DEFAULT]);

	//SetIconsSize(35,35);

	// Определение высоты Item-a
	int high=m_default_item_high;
	if(CaplDefWindowParam::m_font_face!=_T("") || CaplDefWindowParam::m_font_size!=0)
	{
		CDC *dc0=GetDC();
		if(0!=dc0)
		{
			CDC dc1; dc1.CreateCompatibleDC(dc0);
			RECT rect; rect.top=0; rect.bottom=1000; rect.left=0; rect.right=1000;
			CFont *oldfont=dc1.SelectObject(&(m_fonts[APL_FONT_DEFAULT]));
			dc1.DrawText(_T("A"),&rect,DT_LEFT|DT_SINGLELINE|DT_CALCRECT);
			dc1.SelectObject(oldfont);
			int h1=(rect.bottom-rect.top)+3;
			if(h1>high) high=h1;
			ReleaseDC(dc0);
		}
	}
	if(high!=GetTreeCtrl().GetItemHeight())GetTreeCtrl().SetItemHeight(high);


	LogFont.lfStrikeOut=TRUE;
	m_fonts[APL_FONT_STRIKEOUT].CreateFontIndirect(&LogFont);
		
	LogFont.lfItalic=TRUE;
	m_fonts[APL_FONT_ITALIC|APL_FONT_STRIKEOUT].CreateFontIndirect(&LogFont);
	
	LogFont.lfStrikeOut=FALSE;
	m_fonts[APL_FONT_ITALIC].CreateFontIndirect(&LogFont);
	
	LogFont.lfWeight=FW_BOLD;
	m_fonts[APL_FONT_BOLD|APL_FONT_ITALIC].CreateFontIndirect(&LogFont);

	LogFont.lfItalic=FALSE;
	m_fonts[APL_FONT_BOLD].CreateFontIndirect(&LogFont);
	
	LogFont.lfStrikeOut=TRUE;
	m_fonts[APL_FONT_BOLD|APL_FONT_STRIKEOUT].CreateFontIndirect(&LogFont);
	
	LogFont.lfItalic=TRUE;
	m_fonts[APL_FONT_BOLD|APL_FONT_ITALIC|APL_FONT_STRIKEOUT].CreateFontIndirect(&LogFont);
	
	//m_default_font->GetLogFont(&LogFont);
	//LogFont.lfWidth=8;
	//m_log_font.CreateFontIndirect(&LogFont);

	//SetFont(&(m_fonts[APL_FONT_BOLD|APL_FONT_ITALIC]));
	//SetFont(&(m_fonts[APL_FONT_DEFAULT]));
	//SetFont(&m_log_font);
	
	//SetTextColor(RGB(128,128,128));
	//COLORREF cr=GetBkColor();
	//SetTextColor(GetSysColor(COLOR_WINDOW));

}
//*********************************************************************************
void CaplTreeView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	HTREEITEM current, selected;
	bool isPressedCtrl, isPressedShift;
	GetAsyncKeyState(VK_SHIFT);
	GetAsyncKeyState(VK_CONTROL);
	if(m_bMultiSelect)
	{
		if(GetAsyncKeyState(VK_SHIFT)!=0) // 5 = MK_SHIFT
		{
			if(m_SelectedItems.GetSize() == 0)
				m_SelectedItems.Add(GetTreeCtrl().GetSelectedItem());
			isPressedShift = true;
			if(m_SelectedItems.GetSize()>1)
			{
				current = m_SelectedItems[0];
				m_SelectedItems.RemoveAll();
				m_SelectedItems.Add(current);
			}
		}
		else
			isPressedShift = false;
		if(GetAsyncKeyState(VK_CONTROL)!=0) // 9 = MK_CTRL
			isPressedCtrl = true;	
		else
			isPressedCtrl = false;
	}
	UINT flag=0;
	HTREEITEM hitem=GetTreeCtrl().HitTest(point,&flag);
	if(hitem!=0)// && (flag&TVHT_ONITEM))
	{
		if(m_bMultiSelect)
		{
			selected = hitem;
			ChangeSelectedArray(selected, isPressedCtrl, isPressedShift);
		}
		GetTreeCtrl().SelectItem(hitem);
		GetTreeCtrl().SelectDropTarget(hitem);
	}
	Invalidate();
	
	CTreeView::OnLButtonDown(nFlags, point);
}
//*********************************************************************************
int CaplTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	GetTreeCtrl().ModifyStyle(WS_VSCROLL,TVS_HASLINES|TVS_HASBUTTONS|/*TVS_SINGLEEXPAND|*/
		//TVS_FULLROWSELECT| 
		TVS_NOTOOLTIPS|
		TVS_LINESATROOT|TVS_SHOWSELALWAYS|WS_CHILD|WS_VISIBLE);

	ResetFont();	

	return 0;
}
//*********************************************************************************


void CaplTreeView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	if(m_bNoPaint)return;
	
	CDC memDC;
	memDC.CreateCompatibleDC(&dc);

	bool inArray = false;
	CRect rcClip, rcClient;
	dc.GetClipBox( &rcClip );
	GetClientRect(&rcClient);

	// Select a compatible bitmap into the memory DC
	CBitmap bitmap;
	bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );
	CBitmap* pOldBmp = memDC.SelectObject( &bitmap );
	
	// Set clip region to be same as that in paint DC
	CRgn rgn;
	rgn.CreateRectRgnIndirect( &rcClip );
	memDC.SelectClipRgn(&rgn);
	rgn.DeleteObject();

	
	// First let the control do its default drawing.
	CSize size0=memDC.GetWindowExt();
	CPoint pnt0=memDC.GetWindowOrg( ); 

	CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0);
	CSize size1=memDC.GetWindowExt();
	CPoint pnt1=memDC.GetWindowOrg( );

	int i, item_height=GetTreeCtrl().GetItemHeight();

	CRect rect,item_rect,text_rect,border_rect;
	CFont *lastfont=0;

	COLORREF clrBack=GetSysColor(COLOR_WINDOW);
	if(CaplDefWindowParam::m_win_bk_color!=RGB(0,0,0))clrBack=CaplDefWindowParam::m_win_bk_color;
	COLORREF clrText=GetSysColor(COLOR_HIGHLIGHTTEXT);
	COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
	COLORREF crSelectFill=LightenColor(crSelect,0.75);

	UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED;

	HTREEITEM hItem = GetTreeCtrl().GetFirstVisibleItem();
	HTREEITEM hDHItem=GetTreeCtrl().GetDropHilightItem();
	HTREEITEM hSelItem=GetTreeCtrl().GetSelectedItem();

	
	// Определение ширины станд. иконки
	int def_ico_width=0;
	CImageList *il=GetTreeCtrl().GetImageList(TVSIL_NORMAL);
	if(il!=0)
	{
		IMAGEINFO imginfo;
		if(il->GetImageInfo(0,&imginfo))
		{
			def_ico_width=imginfo.rcImage.right-imginfo.rcImage.left;
		}
	}
	CaplTreeItemData default_data;


	int iItemCount = GetTreeCtrl().GetVisibleCount() + 1;
	while(hItem && iItemCount--)
	{
		//Такая конструкция позволяет использовать в ItemData любые типы данных!!! Не ломать.
		CaplTreeItemData *data = dynamic_cast<CaplTreeItemData*>((CaplTreeItemDataFictive *)GetTreeCtrl().GetItemData(hItem));
		
		if(m_bMultiSelect)
			inArray = CheckInSelectedArray (hItem);	

		if(data==0)
			data=&default_data;

		// Определение ширины иконок
		int icons_width=0;
		for(i=0;i<APL_TREE_CTRL_MAX_ICONS;i++)
		{
			if(data->icons[i]>=0) 
				icons_width +=m_ImagesWidth[i];
		}

		GetTreeCtrl().GetItemRect(hItem, &rect, TRUE);
		rect.left-=m_icon_width;
		
		// Обработка одновременного отображения и одинарных и множеств. иконок
		if(icons_width>0 && m_icon_width==0)
		{
			rect.left-=(def_ico_width+3);
		}
	
		item_rect=rect;
		border_rect=rect;

		//Определение Шрифта
		CFont *cur_font=&(m_fonts[data->font_style]);
		if(cur_font!=lastfont) 
		{
			lastfont=cur_font;
			memDC.SelectObject(cur_font);
		}
		
		// Определение ширины текста
		int text_width=0;
		CString sItem = GetTreeCtrl().GetItemText(hItem);
		RECT text_rect=rect;
		memDC.DrawText(sItem,&text_rect,DT_LEFT|DT_SINGLELINE|DT_CALCRECT|DT_NOPREFIX);
		text_width=text_rect.right-text_rect.left;

		border_rect.right=border_rect.left+text_width+7;
		if(icons_width>0) border_rect.right+=icons_width+6;
		
		text_rect=border_rect;
		text_rect.left+=icons_width+3;
		if(icons_width>0) text_rect.left+=6;	

		// Рисование рамки и определение атрибутов текста
		UINT state=GetTreeCtrl().GetItemState( hItem, selflag );
		BOOL Draw;
		if((hItem==GetTreeCtrl().GetSelectedItem ()) && m_bMultiSelect)
		{
			//memDC.Draw3dRect(&focus,crSelect,crSelect);
			Draw = TRUE;
		}
		else Draw = FALSE;
		
		if((!m_bMultiSelect && ((hDHItem==hItem) || (state & TVIS_SELECTED))) ||
			(m_bMultiSelect && inArray))
		{
			// Выделенный объект
			// Очистка лишнего (если надо)
			if(border_rect.right<item_rect.right)
			{
				rect=item_rect; rect.left=border_rect.right;
				memDC.FillSolidRect(&rect,clrBack);
			}

			RECT ramka=border_rect;

			if(icons_width>0)
			{
				if(!m_ShowSelectedOverIcons)
				{
					ramka.left+=icons_width+4;
					RECT icorect=border_rect;
					icorect.right=ramka.left;
					memDC.FillSolidRect(&icorect,clrBack);
				}
			}
			

			if(m_xp_mode)
			{
				if(hDHItem==hItem || hDHItem==0 || inArray)
				{
					memDC.FillSolidRect(&ramka,crSelectFill);
					if(state & TVIS_SELECTED)
						memDC.Draw3dRect(&ramka,crSelect,crSelect);
					memDC.SetBkColor(crSelectFill);
				}
				else 
				{	
					memDC.FillSolidRect(&ramka,clrBack);
					memDC.Draw3dRect(&ramka,crSelect,crSelect);
					memDC.SetBkColor(clrBack);
				}
				memDC.SetTextColor(data->color);
				
			}
			else
			{
				if(icons_width<=0) memDC.FillSolidRect(&border_rect,crSelect);
				else
				{
					rect=border_rect;
					rect.right=text_rect.left-3;
					memDC.FillSolidRect(&rect,clrBack);
					rect.left=text_rect.left-2;
					rect.right=border_rect.right;
					memDC.FillSolidRect(&rect,crSelect);
				}
				memDC.SetBkColor(crSelect);
				memDC.SetTextColor(clrText);
			}
		}
		else
		{
			// не выделенный
			
				if(border_rect.right<item_rect.right) border_rect.right=item_rect.right;
					memDC.FillSolidRect(&border_rect,clrBack);
				if(Draw)
					memDC.Draw3dRect(&border_rect,crSelect,crSelect);	
				memDC.SetTextColor(data->color);
				memDC.SetBkColor(clrBack);
			
		}

		// Рисование item-а 
		int i, x=border_rect.left+3,y=border_rect.top;
		for(i=0;i<APL_TREE_CTRL_MAX_ICONS;i++)
		{
			if(m_ImageLists[i]==0) continue;
			int ico=data->icons[i];
			if(ico<0) continue;
			
			y=border_rect.top+((item_height-m_ImagesHigh[i])+1)/2;
			POINT pnt={x,y};
			m_ImageLists[i]->Draw(&memDC,ico,pnt,ILD_TRANSPARENT);//ILD_NORMAL);

			x+=m_ImagesWidth[i];
		}
		if(icons_width>0) rect.left=x+2;

		memDC.DrawText(sItem,&text_rect,DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
		data->m_text_rect=text_rect;

		hItem = GetTreeCtrl().GetNextVisibleItem(hItem);
	}


	dc.BitBlt(rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), &memDC, 
				rcClip.left, rcClip.top, SRCCOPY);

	memDC.SelectObject(pOldBmp);
	bitmap.DeleteObject();
	memDC.DeleteDC();
}
//*********************************************************************************
void CaplTreeView::OnInitialUpdate() 
{
	CTreeView::OnInitialUpdate();

}
//*********************************************************************************
void CaplTreeView::SaveXpMode()
{
	HKEY key;
	if(ERROR_SUCCESS==RegCreateKey(HKEY_CURRENT_USER,KeyName,&key))
	{
		DWORD val=0;
		if(m_xp_mode) val=1;
		RegSetValueEx(key,ValName,0,REG_DWORD,(BYTE *)(&val),sizeof(DWORD));
		RegCloseKey(key);
	}
}
void CaplTreeView::LoadXpMode()
{
	HKEY key;
	if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,KeyName,0, KEY_QUERY_VALUE,&key))
	{
		DWORD val=0,type=0,size=sizeof(DWORD);
		if(ERROR_SUCCESS==RegQueryValueEx (key,ValName,0,&type,(BYTE *)(&val),&size))
		{
			if(val!=0) m_xp_mode=true;
			else m_xp_mode=false;
		}
		RegCloseKey(key);
	}
}
//*********************************************************************************

LRESULT CaplTreeView::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(message==WM_SETREDRAW)
	{
		if(wParam==0)	
		{
			m_bNoPaint =true;
		}
		else  
			m_bNoPaint =false;
	}
	return CTreeView::DefWindowProc(message, wParam, lParam);
}

CaplTreeItemData *CaplTreeView::GetSelectedItemData()
{
	HTREEITEM hItem= GetTreeCtrl().GetSelectedItem();
	if(hItem == 0) return 0;
	
	return (CaplTreeItemData *)GetTreeCtrl().GetItemData(hItem);				
}

bool CaplTreeView::SetItemImage(HTREEITEM hItem, int image, int index/* =-1 */, bool update /* = true */)
{
	if(hItem==0) return false;
	CaplTreeItemData* tid = (CaplTreeItemData*)GetTreeCtrl().GetItemData(hItem);
	if(tid==0) return false;
	return tid->SetItemImage(image, index, update);
}

void CaplTreeView::OnMouseMove(UINT nFlags, CPoint point) 
{
	bool bNeedTestToolTip=true;
	if(m_ToolTip.IsShowed())
	{
		if(!m_TitledRect.PtInRect(point)) m_ToolTip.Hide();
		else 
			bNeedTestToolTip=false;
	}

	CTreeView::OnMouseMove(nFlags, point);

	if(bNeedTestToolTip)
	{	
		UINT flag=TVHT_ONITEMSTATEICON;
		HTREEITEM hitem=GetTreeCtrl().HitTest(point,&flag);
		if(hitem!=0)
		{
			CaplTreeItemData *td=(CaplTreeItemData *)(GetTreeCtrl().GetItemData(hitem));
			if(td!=0)
			{
				int text_width=0;
				CString sItem = GetTreeCtrl().GetItemText(hitem);
				UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED;
				UINT state=GetTreeCtrl().GetItemState( hitem, selflag );
				
				CRect ClientRect;
				GetClientRect(ClientRect);
				if (ClientRect.right<td->m_text_rect.right)
				{
					if( (td->m_text_rect.left<point.x) && (td->m_text_rect.right>point.x))
					{
						POINT p={td->m_text_rect.left,td->m_text_rect.top};
						ClientToScreen(&p);

						UINT state=GetTreeCtrl().GetItemState( hitem, selflag );
						if((state & TVIS_SELECTED))
						{
							if(m_xp_mode)
							{
								m_ToolTip.m_txt_color=::GetSysColor(COLOR_INFOTEXT);
								COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
								m_ToolTip.m_fon_color=LightenColor(crSelect,0.75);;
							}
							else
							{
								m_ToolTip.m_txt_color=::GetSysColor(COLOR_HIGHLIGHTTEXT);
								m_ToolTip.m_fon_color=::GetSysColor(COLOR_HIGHLIGHT);
							}
						}
						else
						{
							m_ToolTip.m_txt_color=::GetSysColor(COLOR_INFOTEXT);
							m_ToolTip.m_fon_color=::GetSysColor(COLOR_INFOBK);
						}
						m_ToolTip.Show(p.x-5,p.y, sItem);
					}
				}
			}
			
		}
	}

	TRACKMOUSEEVENT te;
	te.cbSize=sizeof(TRACKMOUSEEVENT);
	te.dwFlags=TME_LEAVE|TME_HOVER;
	te.hwndTrack=m_hWnd;
	te.dwHoverTime=HOVER_DEFAULT;
	BOOL b=::_TrackMouseEvent(&te);
}

BOOL CaplTreeView::PreTranslateMessage(MSG* pMsg) 
{
	if(pMsg!=0)
	{
		if(m_ToolTip.IsNeedHideOnMessage(pMsg->message))
			m_ToolTip.Hide();
	}
	return CTreeView::PreTranslateMessage(pMsg);
}


bool CaplTreeView::CheckInSelectedArray (HTREEITEM hItem)
{	
	for(int i=0; i<m_SelectedItems.GetSize(); i++)
	{
		if(m_SelectedItems.GetAt(i) == hItem)
			return true;
	}
	return false;
}

bool CaplTreeView::CheckForRange (HTREEITEM hItem, HTREEITEM selected)
{
	if(m_SelectedItems.GetSize()==0) return false;

	HTREEITEM last = m_SelectedItems[0];
	HTREEITEM current = GetTreeCtrl().GetRootItem();
	while(current)
	{
		if(((current==last) || (current==selected)) && (current==hItem))
			return true;
		if(current == last)
		{
			while(current!=selected)
			{
				if(current==hItem)
					return true;
				else
					current = GetNextItem(current);
			}
			if(current==hItem)
				return true;
			return false;
		}

		//aplDate2String(COleDateTime::GetCurrentTime(), buf);

		if(current==selected)
		{
			while(current!=last)
			{
				if(current==hItem)
					return true;
				else
					current = GetNextItem(current);
			}
			if(current==hItem)
				return true;
			return false;
		}

		current = GetNextItem(current);
	} 
	
	return false;
}

int CaplTreeView::GetCountOfSelect ()
{
	return m_SelectedItems.GetSize();
}

HTREEITEM CaplTreeView::GetSelectedInArray (int index)
{
	if(index<0 || index>=m_SelectedItems.GetSize()) return NULL;

	return m_SelectedItems[index];
}

int CaplTreeView::GetItemIndexInArray (HTREEITEM hItem)
{
	for(int i=0; i<m_SelectedItems.GetSize(); i++)
	{
		if(hItem == m_SelectedItems[i])
			return i;
	}
	return -1;
}

HTREEITEM CaplTreeView::GetNextItem(HTREEITEM hItem) 
{ 
    HTREEITEM hRes; 

    UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED;
	UINT state=GetTreeCtrl().GetItemState( hItem, selflag );
	
    if ((GetTreeCtrl().ItemHasChildren(hItem)) && (state & TVIS_EXPANDED)) 
		return GetTreeCtrl().GetChildItem(hItem); 
    while ((hRes = GetTreeCtrl().GetNextSiblingItem(hItem)) == NULL) 
    { 
        if ((hItem = GetTreeCtrl().GetParentItem(hItem)) == NULL) 
			return NULL; 
    } 
    return hRes; 
} 


void CaplTreeView::ChangeSelectedArray (HTREEITEM selected, bool isPressedCtrl, bool isPressedShift)
{
	UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED;
	UINT state;
	HTREEITEM hItem = GetTreeCtrl().GetRootItem ();				
	int iItemCount = GetTreeCtrl().GetVisibleCount() + 1;
	BOOL inArray, inRange;
	
	while(hItem)
	{
		state=GetTreeCtrl().GetItemState( hItem, selflag );
		inArray = CheckInSelectedArray (hItem);
		if((hItem==selected) && (isPressedCtrl) && (inArray))
			m_SelectedItems.RemoveAt(GetItemIndexInArray(hItem));
		else
		{
			if(m_SelectedItems.GetSize() != 0 && isPressedShift)
				inRange = CheckForRange(hItem,selected);
			if((isPressedCtrl && inArray && m_bMultiSelect) || (m_bMultiSelect && isPressedShift && inRange) || (hItem==selected))
			{			
				if(!isPressedCtrl && !isPressedShift)	// если нет Ctrl u Shift
				{
					m_SelectedItems.RemoveAll();
					m_SelectedItems.Add(hItem);
//					m_bWithCtrl = false;
				}
				if(isPressedShift && inRange && m_bMultiSelect)   // зажат Shift и hItem попадает в интервал выделения
				{
					if(!inArray)
					{
						m_SelectedItems.Add(hItem);
					}
//					m_bWithCtrl = false;
				}
				if(isPressedCtrl && !inArray && m_bMultiSelect)		// зажат Ctrl и его еще нет в массиве выделенных
				{
					m_SelectedItems.Add(hItem);	
//					m_bWithCtrl = true;
				}
			}
		}
		hItem = GetNextItem (hItem);
	}
}

bool CaplTreeView::GetMultiSelect ()
{
	return m_bMultiSelect;
}

void CaplTreeView::SetMultiSelect (bool bMultiSelect)
{
	m_bMultiSelect = bMultiSelect;
}

void CaplTreeView::CheckForExpand(NMHDR* pNMHDR, LRESULT* pResult)
{
	if(m_bMultiSelect)
	{
		HTREEITEM current = GetTreeCtrl().GetRootItem();
		CArray<HTREEITEM,HTREEITEM> TempSelect;
		while(current)
		{
			if(CheckInSelectedArray(current))
				TempSelect.Add(current);
			current = GetNextItem(current);
		}
		m_SelectedItems.RemoveAll ();
		for(int i=0; i<TempSelect.GetSize(); i++)
			m_SelectedItems.Add(TempSelect[i]);
	}
}

BOOL CaplTreeView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
	return TRUE;
	//return CTreeView::OnEraseBkgnd(pDC);
}
