//////////////////////////////////////////////////////////////////////
//
// Разработчик: Алексей Фёдоров aka АЛьФ, mailto: alf@dorex.ru
//
//////////////////////////////////////////////////////////////////////

// MySuperGrid.cpp : implementation file
//

#include "stdafx.h"
//#include "supergrid.h"
#include "MySuperGrid.h"
#include "ComboInListView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CMySuperGrid

extern HINSTANCE hDllInstance;
extern CBkEndUI * pBkEndUI;

IMPLEMENT_DYNAMIC(CMySuperGrid, CSuperGridCtrl)

CMySuperGrid::CMySuperGrid()
{
	m_bDrag = FALSE;
	m_pTable = NULL;
}

void ClearVT(CValueTable* pTable)
{
	if(pTable)
	{
		int n = pTable->GetRowCount();
		for(int i=0; i<n; i++)
		{
			CValue val = pTable->GetValue(0,i);
			CBLContext* pTblCont = val.GetContext();
			if(pTblCont)
				if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
					ClearVT(((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable());
		}
		pTable->Clear(TRUE);
	}

}

CMySuperGrid::~CMySuperGrid()
{
	m_FullRedraw = TRUE;
	DeleteAll();
	try{
		ClearVT(m_pTable);
	}catch(...) {
	};
	m_image.DeleteImageList();
}


BEGIN_MESSAGE_MAP(CMySuperGrid, CSuperGridCtrl)
	//{{AFX_MSG_MAP(CMySuperGrid)
	ON_WM_CREATE()
	ON_WM_NCDESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMySuperGrid message handlers

void CMySuperGrid::OnNcDestroy(void)
{
	CSuperGridCtrl::OnNcDestroy();
	delete this;
}

int CMySuperGrid::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CSuperGridCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	/////////////////////
	//remember this	
	///////////////////
	if(!m_image.Create(16,15,ILC_MASK,4,0))
		return -1;
	HBITMAP hBitmap;
	hBitmap = ::LoadBitmap(hDllInstance,MAKEINTRESOURCE(IDB_BITMAPTREE));
	m_image.Add(CBitmap::FromHandle(hBitmap), RGB(0x00,0x80,0x80));
	::DeleteObject(hBitmap);

	SetImageList(&m_image, LVSIL_SMALL);
	CImageList *pImageList = GetImageList(LVSIL_SMALL);
	if(pImageList)
		ImageList_GetIconSize(pImageList->m_hImageList, &m_cxImage, &m_cyImage);
	else
		return -1;
	
	return 0;
}

void CMySuperGrid::SetOptions(int ShowHGrid, int ShowVGrid, int ShowTGrid)
{
	if(ShowHGrid > 0)
		m_bShowHGrid = true;
	else if(ShowHGrid == 0)
		m_bShowHGrid = false;

	if(ShowVGrid > 0)
		m_bShowVGrid = true;
	else if(ShowVGrid == 0)
		m_bShowVGrid = false;

	if(ShowTGrid > 0)
		m_bShowTGrid = true;
	else if(ShowTGrid == 0)
		m_bShowTGrid = false;
}

void CMySuperGrid::DeleteChildren(CTreeItem * pTreeItem)
{
	if(!IsCollapsed(pTreeItem))
		Collapse(pTreeItem);
	if(ItemHasChildren(pTreeItem))
	{
		POSITION pos = pTreeItem->m_listChild.GetHeadPosition();
		while (pos != NULL)
		{
			CTreeItem* pChildItem = (CTreeItem *)pTreeItem->m_listChild.GetNext(pos);
			DeleteChildren(pChildItem);
			int nChildIndex = NodeToIndex(pChildItem);
			if(nChildIndex >=0) DeleteItem(nChildIndex);
		}
		pTreeItem->m_listChild.RemoveAll();
	}
}

int CMySuperGrid::GetRealColumnNum(int num)
{
	if(num == 1)
		return 3;
	int n = m_pTable->GetColumnCount();
	int vx = 1;
	for(int x = 3; x < n; x++)
	{
		CVTColumn* pCol = m_pTable->GetColumn(x);
		if(pCol)
			if(pCol->GetVisible())
			{
				vx++;
				if(vx == num)
					return x+1;
			}
	}
	return 0;
}

BOOL CMySuperGrid::SetValueByPath(CString stPath, int num, CValue& setValue)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		if(num>pTable->GetColumnCount())
		{
			CString strErr = "";
			strErr.Format("Номер колонки (%d) превышает количество колонок в таблице (%d).",num,pTable->GetColumnCount());
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return FALSE;
		}
		//num = GetRealColumnNum(num);
		if(num<=0)
		{
			CString strErr = "";
			strErr.Format("Неверный номер колонки: %d.",num);
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return FALSE;
		}
		int i = 0;
		i = atoi(stPath);
		CTreeItem* pTreeItem = NULL;
		if(i > 0)
		{
			int m = GetRootCount();
			for(int f = 0; f < m; f++)
			{
				pTreeItem = GetRootItem(f);
				if(pTreeItem->m_nIndexVT == i) break;
				pTreeItem = NULL;
			}
		}

		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			if(i>pTable->GetRowCount())
			{
				CString strErr = "";
				strErr.Format("Номер строки (%d) превышает количество строк в таблице (%d).",i,pTable->GetRowCount());
				CBLModule::RaiseExtRuntimeError(strErr,0);
				return FALSE;
			}
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();
				pTable = NULL;

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
					if(pTreeItem) pTreeItem = pTreeItem->GetTreeItem(i);
				}
				else
				{
					return FALSE;
				}
			}
			else
			{
				pTable->SetValue(setValue,num-1,i-1);
				if(pTreeItem)
				{
					CVTColumn* pCol = pTable->GetColumn(num-1);
					CString st = "";
					BOOL bViewAsImage = FALSE;
					if(pCol)
					{
						CString strFormat = pCol->GetFormat();
						if(!strFormat.IsEmpty())
						{
							CBLModule* pCurMod = CBLModule::GetExecutedModule();
							if(pCurMod)
								st = pCurMod->FormatValue(setValue, strFormat);
						}
						bViewAsImage = pCol->GetViewAsImage();
					}
					if(st.IsEmpty())
						st = setValue.Format();

					CItemInfo* pItemInfo = GetData(pTreeItem);
					if(pItemInfo)
					{
						if(num == 1) // вложенная таблица
						{
							// удаляем старые
							DeleteChildren(pTreeItem);
							// добавляем новые
							CValueTable* pTable1 = NULL;
							CBLContext* pTblCont = setValue.GetContext();

							if(pTblCont)
								if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
									pTable1 = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

							if(pTable1) FillTable(pTreeItem, pTable1);
						}
						else if(num == 2) // номер пиктограммы
						{
							int picNum = setValue.GetNumeric();
							if(picNum > 0)
								pItemInfo->SetImage(picNum+3);
							else
								pItemInfo->SetImage(-1);
						}
						else if(num == 3) // наименование ветки
						{
							pItemInfo->SetItemText(st);
							SetItemText(NodeToIndex(pTreeItem), 0, st);
						}
						else if(num > 3)
						{
							int n = m_pTable->GetColumnCount();
							if(n < num) num = n;
							int numvis = num - 3;
							for(int x = 3; x < num; x++)
							{
								CVTColumn* pCol = m_pTable->GetColumn(x);
								if(pCol)
									if(!pCol->GetVisible())
										numvis --;
							}
							if(numvis > 0)
							{
								int iSubItemImageOffset = pItemInfo->GetSubItemImageOffset(numvis-1);
								if(iSubItemImageOffset != -1)
								{
									pItemInfo->SetSubItemImage(numvis-1, 3 + setValue.GetNumeric() + iSubItemImageOffset);
								}
								else
								{
									pItemInfo->SetSubItemText(numvis-1,st);
									pItemInfo->SetSubItemImage(numvis-1, -1);
									SetItemText(NodeToIndex(pTreeItem), numvis, st);
								}
							}
						}
						UpdateData(pTreeItem, pItemInfo);
						FillColors(pTreeItem, pTable, i-1);
						RedrawItems(NodeToIndex(pTreeItem),NodeToIndex(pTreeItem));
					}
				}
				i = 0;
			}
		}
	}
	else
		return FALSE;

	return TRUE;
}

void CMySuperGrid::ExpandNodeByPath(CString stPath)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		int i = 0;
		i = atoi(stPath);
		CTreeItem* pTreeItem = NULL;
		if(i > 0)
		{
			int m = GetRootCount();
			for(int f = 0; f < m; f++)
			{
				pTreeItem = GetRootItem(f);
				if(pTreeItem->m_nIndexVT == i) break;
				pTreeItem = NULL;
			}
		}

		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();
				pTable = NULL;

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
					if(pTreeItem) pTreeItem = pTreeItem->GetTreeItem(i);
				}
				else
					return;
			}
			else
			{
				if(pTreeItem)
				{
					int nSize = GetIndent(pTreeItem);
					CTreeItem** ppParentArray = new CTreeItem*[nSize];
					CTreeItem *pChild = pTreeItem;
					int i=0;
					while(i<nSize)
					{
						CTreeItem *pParent = GetParentItem(pChild);
						
						//if(IsRoot(pParent)) break;
						if(pParent == NULL) break;
						if(!IsCollapsed(pParent)) break;
						pChild = pParent;
						ppParentArray[i] = pChild;
						i++;
					}

					for(int x=i; x > 0; x--)
					{
						CTreeItem *pParent = ppParentArray[x-1];
						Expand(pParent, NodeToIndex(pParent));
					}
					delete [] ppParentArray;
					Expand(pTreeItem, NodeToIndex(pTreeItem));
				}
				i = 0;
			}
		}
	}
}

void CMySuperGrid::CollapseNodeByPath(CString stPath)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		int i = 0;
		i = atoi(stPath);
		CTreeItem* pTreeItem = NULL;
		if(i > 0)
		{
			int m = GetRootCount();
			for(int f = 0; f < m; f++)
			{
				pTreeItem = GetRootItem(f);
				if(pTreeItem->m_nIndexVT == i) break;
				pTreeItem = NULL;
			}
		}

		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();
				pTable = NULL;

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
					if(pTreeItem) pTreeItem = pTreeItem->GetTreeItem(i);
				}
				else
					return;
			}
			else
			{
				if(pTreeItem)
				{
					Collapse(pTreeItem);
				}
				i = 0;
			}
		}
	}
}

BOOL CMySuperGrid::IsGroupByPath(CString stPath)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		int i = 0;
		i = atoi(stPath);
		CTreeItem* pTreeItem = NULL;
		if(i > 0)
		{
			int m = GetRootCount();
			for(int f = 0; f < m; f++)
			{
				pTreeItem = GetRootItem(f);
				if(pTreeItem->m_nIndexVT == i) break;
				pTreeItem = NULL;
			}
		}

		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();
				pTable = NULL;

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
					if(pTreeItem) pTreeItem = pTreeItem->GetTreeItem(i);
				}
				else
					return FALSE;
			}
			else
			{
				if(pTreeItem)
				{
					// здесь код метода
					return ItemHasChildren(pTreeItem);
				}
				i = 0;
			}
		}
	}
	return FALSE;
}

void CMySuperGrid::SetCurrentByPath(CString stPath)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		int i = 0;
		i = atoi(stPath);
		CTreeItem* pTreeItem = NULL;
		if(i > 0)
		{
			int m = GetRootCount();
			for(int f = 0; f < m; f++)
			{
				pTreeItem = GetRootItem(f);
				if(pTreeItem->m_nIndexVT == i) break;
				pTreeItem = NULL;
			}
		}

		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();
				pTable = NULL;

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
					if(pTreeItem) pTreeItem = pTreeItem->GetTreeItem(i);
				}
				else
					return;
			}
			else
			{
				if(pTreeItem)
				{
					// сначала раскроем дерево
					int nSize = GetIndent(pTreeItem);
					CTreeItem** ppParentArray = new CTreeItem*[nSize];
					CTreeItem *pChild = pTreeItem;
					int i=0;
					while(i<nSize)
					{
						CTreeItem *pParent = GetParentItem(pChild);
						
						//if(IsRoot(pParent)) break;
						if(pParent == NULL) break;
						if(!IsCollapsed(pParent)) break;
						pChild = pParent;
						ppParentArray[i] = pChild;
						i++;
					}

					for(int x=i; x > 0; x--)
					{
						CTreeItem *pParent = ppParentArray[x-1];
						Expand(pParent, NodeToIndex(pParent));
					}
					delete [] ppParentArray;
					//Expand(pTreeItem, NodeToIndex(pTreeItem));
					//теперь установим текущим
					SelectNode(pTreeItem);
				}
				i = 0;
			}
		}
	}
}

void CMySuperGrid::GetValueByPath(CString stPath, int num, CValue& retValue)
{
	if(m_pTable)
	{
		CValueTable* pTable = m_pTable;
		if(num>pTable->GetColumnCount())
		{
			CString strErr = "";
			strErr.Format("Номер колонки (%d) превышает количество колонок в таблице (%d).",num,pTable->GetColumnCount());
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return;
		}
		//num = GetRealColumnNum(num);
		if(num<=0)
		{
			CString strErr = "";
			strErr.Format("Неверный номер колонки: %d.",num);
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return;
		}
		int i = 0;
		i = atoi(stPath);
		int n = 0;
		CValue val;
		CValue valNULL;
		while(i > 0)
		{
			n = stPath.Find("/",0);
			if(n >=0 )
			{
				if(i>pTable->GetRowCount())
				{
					CString strErr = "";
					strErr.Format("Номер строки (%d) превышает количество строк в таблице (%d).",i,pTable->GetRowCount());
					CBLModule::RaiseExtRuntimeError(strErr,0);
					return;
				}
				val = pTable->GetValue(0,i-1);
				CBLContext* pTblCont = val.GetContext();

				if(pTblCont)
					if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
						pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();

				if(pTable)
				{
					stPath = stPath.Mid(n+1);
					i = atoi(stPath);
				}
				else
				{
					retValue = valNULL;
					i = 0;
				}
			}
			else
			{
				if(i>pTable->GetRowCount())
				{
					CString strErr = "";
					strErr.Format("Номер строки (%d) превышает количество строк в таблице (%d).",i,pTable->GetRowCount());
					CBLModule::RaiseExtRuntimeError(strErr,0);
					return;
				}
				retValue = pTable->GetValue(num-1,i-1);
				i = 0;
			}
		}
	}
}

CString CMySuperGrid::GetColumnName(int num)
{
	if(m_pTable)
	{
		if(num>m_pTable->GetColumnCount())
		{
			CString strErr = "";
			strErr.Format("Номер колонки (%d) превышает количество колонок в таблице (%d).",num,m_pTable->GetColumnCount());
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return "";
		}
		//num = GetRealColumnNum(num);
		if(num<=0)
		{
			CString strErr = "";
			strErr.Format("Неверный номер колонки: %d.",num);
			CBLModule::RaiseExtRuntimeError(strErr,0);
			return "";
		}
		CVTColumn* pCol = m_pTable->GetColumn(num-1);
		if(pCol)
			return pCol->GetCode();
	}
	return "";
}

CString CMySuperGrid::GetCurrentItemIndex()
{
	CString ret = "";
	int cur = GetSelectedItem();
	if(cur>=0)
	{
		CString retTemp = "";
		CTreeItem* pTreeItem = GetTreeItem(cur);
		if(pTreeItem)
		{
			retTemp.Format("%d",GetCurIndexVT(pTreeItem));
			ret = retTemp;
			int num = -1;
			while(pTreeItem)
			{
				pTreeItem = GetParentItem(pTreeItem);
				if(pTreeItem)
				{
					num = GetCurIndexVT(pTreeItem);
					//retTemp.Format("%d",(cur - num));
					//cur = num;
					retTemp.Format("%d",num);
					cur = GetCurIndex(pTreeItem);
					if(ret.IsEmpty())
						ret = retTemp;
					else
						ret = retTemp + "/" + ret;
				}
			}
		}
	}

	return ret;
}

long CMySuperGrid::GetCurrentColumn()
{
	long lCurCol = IndexToOrder(GetCurSubItem())+1;
	return lCurCol;
}

BOOL CMySuperGrid::FillColors(CTreeItem * pTreeItem, CValueTable* pTable, int y)
{
	if(pTable == NULL)
		pTable = m_pTable;
	
	int n = pTable->GetColumnCount();
	int m = pTable->GetRowCount();
	CValue val;
	
	int bufFontSet;
	int bufFont;
	int bufBrush;
	int bufCount;
	int bufIndent;
	COLORREF st_fontCol = COLORREF(-1);
	COLORREF st_brushCol = COLORREF(-1);
	COLORREF fontCol = COLORREF(-1);
	COLORREF brushCol = COLORREF(-1);
	COLORREF fontColS = COLORREF(-1);
	COLORREF brushColS = COLORREF(-1);
	DWORD fontSet = 0;
	DWORD fontSetS = 0;
	int CountCol = -1;
	int IndentCol = 0;
	CString st_buf;
	char ** endptr = NULL;
	const char * ptr = NULL;
	BOOL bUseColor = FALSE;
	int i;
	CItemInfo* lpItemInfo = pTreeItem->m_lpNodeInfo;
	
	val = pTable->GetValue(1,y);

	int vx = 0;
	st_fontCol = st_brushCol = fontCol = brushCol = fontColS = brushColS = COLORREF(-1);
	fontSet = fontSetS = 0;
	CountCol = -1;
	IndentCol = 0;
	
	for(int x = 2; x < n; x++)
	{
		CVTColumn* pCol = m_pTable->GetColumn(x);
		if(pCol)
		{
			CString strFormat = pCol->GetFormat();
			val = pTable->GetValue(x,y);
			CString stItem = "";
			if(strFormat.IsEmpty())
				stItem = val.Format();
			else
			{
				CBLModule* pCurMod = CBLModule::GetExecutedModule();
				if(pCurMod)
					stItem = pCurMod->FormatValue(val, strFormat);
				else
					stItem = val.Format();
			}
			
			if(x == 2)
			{
				lpItemInfo->SetItemStyle();
				vx++;
			}
			else if(pCol->GetVisible())
			{
				vx++;
				if(vx>1) lpItemInfo->SetSubItemStyle(vx-2);
			}
			
			st_buf = stItem;
			
			if(!st_buf.IsEmpty())
			{
				st_buf.MakeUpper();
				
				bufFontSet = st_buf.Find("FONTSET_S[",0);
				if(bufFontSet >= 0)
				{
					bufFontSet += 10;
					if(st_buf.Mid(bufFontSet, 4) =="NONE")
						fontSetS = 0;
					else
						fontSetS = (DWORD)atol(st_buf.Mid(bufFontSet));
					CountCol = -1;
					IndentCol = 0;
				}
				bufFontSet = st_buf.Find("FONTSET[",0);
				if(bufFontSet >= 0)
				{
					bufFontSet += 8;
					if(st_buf.Mid(bufFontSet, 4) =="NONE")
						fontSet = 0;
					else
						fontSet = (DWORD)atol(st_buf.Mid(bufFontSet));
					CountCol = -1;
					IndentCol = 0;
				}
				
				bufFont = st_buf.Find("FONT_S[",0);
				if(bufFont >= 0)
				{
					bufFont += 7;
					if(st_buf.Mid(bufFont, 4) =="NONE")
						fontColS = st_fontCol;
					else
					{
						ptr = st_buf.Mid(bufFont);
						endptr = (char**)&ptr;
						fontColS = strtol(ptr,endptr,0);
					}
					CountCol = -1;
					IndentCol = 0;
				}
				bufFont = st_buf.Find("FONT[",0);
				if(bufFont >= 0)
				{
					bufFont += 5;
					if(st_buf.Mid(bufFont, 4) =="NONE")
						fontCol = st_fontCol;
					else
					{
						ptr = st_buf.Mid(bufFont);
						endptr = (char**)&ptr;
						fontCol = strtol(ptr,endptr,0);
					}
					CountCol = -1;
					IndentCol = 0;
				}
				
				bufBrush = st_buf.Find("BRUSH_S[",0);
				if(bufBrush >= 0)
				{
					bufBrush += 8;
					if(st_buf.Mid(bufBrush, 4) =="NONE")
						brushColS = st_brushCol;
					else
					{
						ptr = st_buf.Mid(bufBrush);
						endptr = (char**)&ptr;
						brushColS = strtol(ptr,endptr,0);
					}
					CountCol = -1;
					IndentCol = 0;
				}
				bufBrush = st_buf.Find("BRUSH[",0);
				if(bufBrush >= 0)
				{
					bufBrush += 6;
					if(st_buf.Mid(bufBrush, 4) =="NONE")
						brushCol = st_brushCol;
					else
					{
						ptr = st_buf.Mid(bufBrush);
						endptr = (char**)&ptr;
						brushCol = strtol(ptr,endptr,0);
					}
					CountCol = -1;
					IndentCol = 0;
				}
				
				bufCount = st_buf.Find("COUNT[",0);
				if(bufCount >= 0)
				{
					bufCount += 6;
					if(st_buf.Mid(bufCount, 4) =="NONE")
						CountCol = -1;
					else
						CountCol = atoi(st_buf.Mid(bufCount))+1;
					IndentCol = 0;
				}
				
				bufIndent = st_buf.Find("INDENT[",0);
				if(bufIndent >= 0)
				{
					bufIndent += 7;
					if(st_buf.Mid(bufIndent, 4) =="NONE")
						IndentCol = 0;
					else
						IndentCol = atoi(st_buf.Mid(bufIndent));
				}
			}
	
			if(IndentCol>0)
			{
				IndentCol--;
				//bUseColor = FALSE;
			}
			else
			{
				if(IndentCol<0)
				{
					if(CountCol>0)
					{
						CountCol--;
						for(i = IndentCol; i < 0 && CountCol > 0; i++)
						{
							if(-i<=vx)
							{
								if(-i < vx)
									lpItemInfo->SetSubItemStyle(vx+i-1,
																TRUE,
																brushCol,
																fontCol,
																brushColS,
																fontColS,
																fontSet,
																fontSetS);
								else if(vx == -i)
									lpItemInfo->SetItemStyle(TRUE,
															brushCol,
															fontCol,
															brushColS,
															fontColS,
															fontSet,
															fontSetS);
								
							}
							CountCol--;
						}
						if(CountCol<=0)
						{
							st_fontCol = 
								st_brushCol = 
								fontCol = 
								brushCol = 
								fontColS = 
								brushColS = COLORREF(-1);
							fontSet = fontSetS = 0;
							CountCol = -1;
						}
					}
					else
					{
						if(-IndentCol > vx)
							IndentCol = -vx;
						for(i = IndentCol; i < 0; i++)
						{
							if(i < -1)
								lpItemInfo->SetSubItemStyle(vx+i,
															TRUE,
															brushCol,
															fontCol,
															brushColS,
															fontColS,
															fontSet,
															fontSetS);
							else
								lpItemInfo->SetItemStyle(TRUE,
														brushCol,
														fontCol,
														brushColS,
														fontColS,
														fontSet,
														fontSetS);
						}
					}
					IndentCol = 0;
				}
				
				if(CountCol>0) CountCol--;
				if(CountCol == 0)
				{
					fontCol = st_fontCol;
					brushCol = st_brushCol;
					fontSet = 0;
					CountCol--;
				}
				else if((CountCol>0) || (CountCol == -1))
				{
					if((vx > 1) && (pCol->GetVisible()))
						lpItemInfo->SetSubItemStyle(vx-2,
													TRUE,
													brushCol,
													fontCol,
													brushColS,
													fontColS,
													fontSet,
													fontSetS);
					else if(x == 2)
						lpItemInfo->SetItemStyle(TRUE,
												brushCol,
												fontCol,
												brushColS,
												fontColS,
												fontSet,
												fontSetS);
				}			
			}
		}
	}
	return TRUE;
}

BOOL CMySuperGrid::FillTable(CTreeItem * pRoot, CValueTable* pTable)
{
	if(pTable == NULL)
		pTable = m_pTable;
	
	int n = pTable->GetColumnCount();
	int m = pTable->GetRowCount();
	CValue val;
	
	int bufFontSet;
	int bufFont;
	int bufBrush;
	int bufCount;
	int bufIndent;
	COLORREF st_fontCol = COLORREF(-1);
	COLORREF st_brushCol = COLORREF(-1);
	COLORREF fontCol = COLORREF(-1);
	COLORREF brushCol = COLORREF(-1);
	COLORREF fontColS = COLORREF(-1);
	COLORREF brushColS = COLORREF(-1);
	DWORD fontSet = 0;
	DWORD fontSetS = 0;
	int CountCol = -1;
	int IndentCol = 0;
	CString st_buf;
	char ** endptr = NULL;
	const char * ptr = NULL;
	BOOL bUseColor = FALSE;
	int i;
	
	for(int y = 0; y < m; y++)
	{
		CItemInfo* lpItemInfo = new CItemInfo();
		val = pTable->GetValue(1,y);
		int picNum = val.GetNumeric();
		CImageList *pImageList = GetImageList(LVSIL_SMALL);
		if((pImageList == NULL) || (picNum > (pImageList->GetImageCount() - 4)))
			picNum = 0;
		
		if(picNum > 0)
			lpItemInfo->SetImage(picNum+3);

		int vx = 0;
		st_fontCol = st_brushCol = fontCol = brushCol = fontColS = brushColS = COLORREF(-1);
		fontSet = fontSetS = 0;
		CountCol = -1;
		IndentCol = 0;
		
		for(int x = 2; x < n; x++)
		{
			CVTColumn* pCol = m_pTable->GetColumn(x);
			if(pCol)
			{
				CString strFormat = pCol->GetFormat();
				val = pTable->GetValue(x,y);
				CString stItem = "";
				if(strFormat.IsEmpty())
					stItem = val.Format();
				else
				{
					CBLModule* pCurMod = CBLModule::GetExecutedModule();
					if(pCurMod)
						stItem = pCurMod->FormatValue(val, strFormat);
					else
						stItem = val.Format();
				}
				
				if(x == 2)
				{
					lpItemInfo->SetItemText(stItem);
					lpItemInfo->SetItemStyle();
					vx++;
				}
				else if(pCol->GetVisible())
				{
					vx++;
					int iSubItem = 0;
					if(pCol->GetViewAsImage())
					{
						lpItemInfo->AddSubItemText("");
						iSubItem = lpItemInfo->GetItemCount()-1;
						lpItemInfo->SetSubItemImage(iSubItem,3+val.GetNumeric()+pCol->GetImageOffset());
						lpItemInfo->SetSubItemImageOffset(iSubItem,pCol->GetImageOffset());
					}
					else
					{
						lpItemInfo->AddSubItemText(stItem);
						iSubItem = lpItemInfo->GetItemCount()-1;
						lpItemInfo->SetSubItemImage(iSubItem,-1);
						lpItemInfo->SetSubItemImageOffset(iSubItem,-1);
					}
					lpItemInfo->SetSubItemStyle(iSubItem);
				}
				
				st_buf = stItem;
				
				if(!st_buf.IsEmpty())
				{
					st_buf.MakeUpper();
					
					bufFontSet = st_buf.Find("FONTSET_S[",0);
					if(bufFontSet >= 0)
					{
						bufFontSet += 10;
						if(st_buf.Mid(bufFontSet, 4) =="NONE")
							fontSetS = 0;
						else
							fontSetS = (DWORD)atol(st_buf.Mid(bufFontSet));
						CountCol = -1;
						IndentCol = 0;
					}
					bufFontSet = st_buf.Find("FONTSET[",0);
					if(bufFontSet >= 0)
					{
						bufFontSet += 8;
						if(st_buf.Mid(bufFontSet, 4) =="NONE")
							fontSet = 0;
						else
							fontSet = (DWORD)atol(st_buf.Mid(bufFontSet));
						CountCol = -1;
						IndentCol = 0;
					}
					
					bufFont = st_buf.Find("FONT_S[",0);
					if(bufFont >= 0)
					{
						bufFont += 7;
						if(st_buf.Mid(bufFont, 4) =="NONE")
							fontColS = st_fontCol;
						else
						{
							ptr = st_buf.Mid(bufFont);
							endptr = (char**)&ptr;
							fontColS = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}
					bufFont = st_buf.Find("FONT[",0);
					if(bufFont >= 0)
					{
						bufFont += 5;
						if(st_buf.Mid(bufFont, 4) =="NONE")
							fontCol = st_fontCol;
						else
						{
							ptr = st_buf.Mid(bufFont);
							endptr = (char**)&ptr;
							fontCol = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}
					
					bufBrush = st_buf.Find("BRUSH_S[",0);
					if(bufBrush >= 0)
					{
						bufBrush += 8;
						if(st_buf.Mid(bufBrush, 4) =="NONE")
							brushColS = st_brushCol;
						else
						{
							ptr = st_buf.Mid(bufBrush);
							endptr = (char**)&ptr;
							brushColS = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}
					bufBrush = st_buf.Find("BRUSH[",0);
					if(bufBrush >= 0)
					{
						bufBrush += 6;
						if(st_buf.Mid(bufBrush, 4) =="NONE")
							brushCol = st_brushCol;
						else
						{
							ptr = st_buf.Mid(bufBrush);
							endptr = (char**)&ptr;
							brushCol = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}
					
					bufCount = st_buf.Find("COUNT[",0);
					if(bufCount >= 0)
					{
						bufCount += 6;
						if(st_buf.Mid(bufCount, 4) =="NONE")
							CountCol = -1;
						else
							CountCol = atoi(st_buf.Mid(bufCount))+1;
						IndentCol = 0;
					}
					
					bufIndent = st_buf.Find("INDENT[",0);
					if(bufIndent >= 0)
					{
						bufIndent += 7;
						if(st_buf.Mid(bufIndent, 4) =="NONE")
							IndentCol = 0;
						else
							IndentCol = atoi(st_buf.Mid(bufIndent));
					}
				}
		
				if(IndentCol>0)
				{
					IndentCol--;
					//bUseColor = FALSE;
				}
				else
				{
					if(IndentCol<0)
					{
						if(CountCol>0)
						{
							CountCol--;
							for(i = IndentCol; i < 0 && CountCol > 0; i++)
							{
								if(-i<=vx)
								{
									if(-i < vx)
										lpItemInfo->SetSubItemStyle(vx+i-1,
																	TRUE,
																	brushCol,
																	fontCol,
																	brushColS,
																	fontColS,
																	fontSet,
																	fontSetS);
									else if(vx == -i)
										lpItemInfo->SetItemStyle(TRUE,
																brushCol,
																fontCol,
																brushColS,
																fontColS,
																fontSet,
																fontSetS);
									
								}
								CountCol--;
							}
							if(CountCol<=0)
							{
								st_fontCol = 
									st_brushCol = 
									fontCol = 
									brushCol = 
									fontColS = 
									brushColS = COLORREF(-1);
								fontSet = fontSetS = 0;
								CountCol = -1;
							}
						}
						else
						{
							if(-IndentCol > vx)
								IndentCol = -vx;
							for(i = IndentCol; i < 0; i++)
							{
								if(i < -1)
									lpItemInfo->SetSubItemStyle(vx+i,
																TRUE,
																brushCol,
																fontCol,
																brushColS,
																fontColS,
																fontSet,
																fontSetS);
								else
									lpItemInfo->SetItemStyle(TRUE,
															brushCol,
															fontCol,
															brushColS,
															fontColS,
															fontSet,
															fontSetS);
							}
						}
						IndentCol = 0;
					}
					
					if(CountCol>0) CountCol--;
					if(CountCol == 0)
					{
						fontCol = st_fontCol;
						brushCol = st_brushCol;
						fontSet = 0;
						CountCol--;
					}
					else if((CountCol>0) || (CountCol == -1))
					{
						if((vx > 1) && (pCol->GetVisible()))
							lpItemInfo->SetSubItemStyle(vx-2,
														TRUE,
														brushCol,
														fontCol,
														brushColS,
														fontColS,
														fontSet,
														fontSetS);
						else if(x == 2)
							lpItemInfo->SetItemStyle(TRUE,
													brushCol,
													fontCol,
													brushColS,
													fontColS,
													fontSet,
													fontSetS);
					}			
				}
			}
		}
		
		CTreeItem * pNewRoot = NULL;
		if(pRoot)
			pNewRoot = InsertItem(pRoot, lpItemInfo);
		else
			pNewRoot = InsertRootItem(lpItemInfo);
		
		SetCurIndexVT(pNewRoot,y+1);
		
		val = pTable->GetValue(0,y);
		CValueTable* pTable1 = NULL;
		CBLContext* pTblCont = val.GetContext();
		
		if(pTblCont)
			if(CString("CValueTableContext") == pTblCont->GetRuntimeClass()->m_lpszClassName)
				pTable1 = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();
			
			if(pTable1) FillTable(pNewRoot, pTable1);
	}
	return TRUE;
}

void CMySuperGrid::InitializeGrid()
{
	/*
	ExtendedStyle support:
	LVS_EX_TRACKSELECT
	LVS_EX_GRIDLINES
	LVS_EX_FLATSB
	LVS_EX_CHECKBOXES
	LVS_EX_FLATSB
	all other ExStyles are not supported...buhhh and you call your self a windows-developer :(
	*/

	SetRedraw(0);
	m_FullRedraw = TRUE;
	DeleteAll();
	while(GetNumCol()) DeleteColumn(0);

	SetExtendedStyle(GetExtendedStyle()|LVS_EX_GRIDLINES); //|LVS_EX_CHECKBOXES

	if(m_pTable)
	{
		int n = m_pTable->GetColumnCount();
		int m = m_pTable->GetRowCount();
		LV_COLUMN   lvColumn;
		//initialize the columns
		lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
		lvColumn.fmt = LVCFMT_LEFT;
		lvColumn.cx = 200;
		int iFullCX = 0;
		int vx = 0;
		for(int x = 2; x < n; x++)
		{
			CVTColumn* pCol = m_pTable->GetColumn(x);
			if(pCol)
				if(pCol->GetVisible())
				{
					if(pCol->GetAlign() == 2)
						lvColumn.fmt = LVCFMT_RIGHT;
					else
						lvColumn.fmt = LVCFMT_LEFT;

					CString st = pCol->GetTitle();
					lvColumn.pszText = (char*)(LPCSTR)st;
					int w = pCol->GetWidth();
					if(w)
					{
						CSize cSize;
						cSize.cx = 0;
						cSize.cy = 0;
						cSize = GetDC()->GetTextExtent(_T(" "),1);
						lvColumn.cx = cSize.cx*w;
					}
					else
						lvColumn.cx = 150;
					iFullCX += lvColumn.cx;
					InsertColumn(vx++,&lvColumn);
				}
		}
		CRect wndRect;
		GetWindowRect(wndRect);
		int w = wndRect.Width() - 20;
		if(iFullCX < w)
		{
			for(x = 0; x < vx; x++)
			{
				int cx = GetColumnWidth(x);
				cx = (cx*w/iFullCX);
				SetColumnWidth(x, cx);
			}
		}
		FillTable();
	}
	m_FullRedraw = FALSE;
	SetRedraw(1);
	InvalidateRect(NULL);
	UpdateWindow();

}


//helper function to copy CItemInfo used when drag/drop you must override this this function to suit your own CItemInfo class
CItemInfo* CMySuperGrid::CopyData(CItemInfo* lpSrc)
{
	ASSERT(lpSrc!=NULL);
	CItemInfo* lpDest = new CItemInfo;
	//well okay I put all the copy thing in one function, located in CItemInfo class, 
	//so you should check out this function, remember to modify this function each time you add new data to CItemInfo class.
	lpDest->CopyObjects(lpSrc);
	return lpDest;
}


//override, like red!
COLORREF CMySuperGrid::GetCellRGB()
{
	return RGB(10,10,200);//RGB(192,0,0);
}


//this is my override of GetIcon, override this to set what ever icon suits you
int CMySuperGrid::GetIcon(const CTreeItem* pItem)
{
	if(pItem!=NULL)
	{
		int n = GetData(pItem)->GetImage();
		if(n!=-1)
			return n;
		
		int iImage = 0;
		if(ItemHasChildren(pItem))
		{
			IsCollapsed(pItem) ? iImage = 1/*close icon*/:iImage = 0;/*open icon*/
		}
		else
			iImage = 2;//doc icon
		return iImage;
	}
	return 0;
}



//override
void CMySuperGrid::OnUpdateListViewItem(CTreeItem* lpItem, LV_ITEM *plvItem)
{
	CSuperGridCtrl::OnUpdateListViewItem(lpItem, plvItem);
}

BOOL CMySuperGrid::OnItemLButtonDown(LVHITTESTINFO& ht)
{
	return CSuperGridCtrl::OnItemLButtonDown(ht);
}

//override called when OnLButtondown
void CMySuperGrid::OnControlLButtonDown(UINT nFlags, CPoint point, LVHITTESTINFO& ht)
{
	//CSuperGridCtrl::OnControlLButtonDown(nFlags, point, ht);
}



BOOL CMySuperGrid::OnVkReturn()
{
	BOOL bResult=FALSE;
	int iItem = GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);
	if( GetCurSubItem() != -1 && iItem != -1)
	{
		CTreeItem*pSelItem = GetTreeItem(iItem);
		if(pSelItem!=NULL)
		{	
			CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
			int iSubItem = Header_OrderToIndex(pHeader->m_hWnd, GetCurSubItem());
			CItemInfo* pInfo = GetData(pSelItem);
			CItemInfo::CONTROLTYPE ctrlType;
			if(pInfo->GetControlType(iSubItem-1, ctrlType))
			{	
				switch(ctrlType)
				{
					/*put in your own control here*/
					case pInfo->CONTROLTYPE::datecontrol:break;
					case pInfo->CONTROLTYPE::spinbutton:break;
					case pInfo->CONTROLTYPE::dropdownlistviewwhatevercontrol:break;
					case pInfo->CONTROLTYPE::combobox: 
						{

							CStringList* list=NULL;
							pInfo->GetListData(iSubItem-1, list);
							CComboBox * pList = ShowList(iItem, iSubItem, list);
							bResult=TRUE; //I'll handle it from here
						}break;
					default:break;
				}
			}
		}
	}
	return bResult;
}





#define IDC_COMBOBOXINLISTVIEW 0x1235
CComboBox* CMySuperGrid::ShowList(int nItem, int nCol, CStringList *lstItems)
{
	CString strFind = GetItemText(nItem, nCol);

	//basic code start
	CRect rect;
	int offset = 0;
	// Make sure that the item is visible
	if( !EnsureVisible(nItem, TRUE)) return NULL;
	GetSubItemRect(nItem, nCol, LVIR_BOUNDS, rect);
	// Now scroll if we need to expose the column
	CRect rcClient;
	GetClientRect(rcClient);
	if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
	{
		CSize size;
		size.cx = offset + rect.left;
		size.cy = 0;
		Scroll(size);
		rect.left -= size.cx;
	}
	
	rect.left += offset;	
	rect.right = rect.left + GetColumnWidth(nCol);
	if(rect.right > rcClient.right) 
	   rect.right = rcClient.right;
	//basic code end

	rect.bottom += 10 * rect.Height();//dropdown area
	
	DWORD dwStyle =  WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL|CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL;
	CComboBox *pList = new CComboInListView(nItem, nCol, lstItems);
	pList->Create(dwStyle, rect, this, IDC_COMBOBOXINLISTVIEW);
	pList->ModifyStyleEx(0,WS_EX_CLIENTEDGE);//can we tell at all
	pList->SetHorizontalExtent(CalcHorzExtent(pList, lstItems));
	pList->ShowDropDown();
	pList->SelectString(-1, strFind.GetBuffer(1));
	// The returned pointer should not be saved
	return pList;
}



int CMySuperGrid::CalcHorzExtent(CWnd* pWnd, CStringList *pList)
{
	int nExtent=0;
	if(pWnd!=NULL)
	{
		CDC* pDC = pWnd->GetDC();
		HFONT hFont = (HFONT)pWnd->SendMessage(WM_GETFONT); //why not pWnd->GetFont();..I like the send thing alot and
		CFont *pFont = CFont::FromHandle(hFont);			//this way I get to use this function..cool :)
		if(pFont!=NULL)										//ya what ever makes me happy,.right :}
		{
			CFont* pOldFont = pDC->SelectObject(pFont);
			CSize newExtent;
			POSITION pos = pList->GetHeadPosition();
			while(pos != NULL)
			{
				CString str(pList->GetNext(pos));
				newExtent = pDC->GetTextExtent(str);
				newExtent.cx += 6;
				if (newExtent.cx > nExtent)
				{
					nExtent = newExtent.cx;
				}
			}
			pDC->SelectObject(pOldFont);
		}
		pWnd->ReleaseDC(pDC);
	}
	return nExtent;
}



//this is just one way to search items...strItem must match and then all subitems must be
//a match before returning the node
//the search function here search all nodes regardless if collapsed or expanded
CMySuperGrid::CTreeItem* CMySuperGrid::Search(CString strItem,...)
{
	if(!GetItemCount())
		return NULL;

	va_list args;
	va_start(args, strItem);
	int nCount=0;
	
	for(;;)
	{
		LPCTSTR lpsz = va_arg(args, LPCTSTR);
		if(lpsz==NULL)
			break;
	   nCount++;
	}


	POSITION pos = GetRootHeadPosition();
	while(pos != NULL)
	{
		CTreeItem *pParent = (CTreeItem*)GetNextRoot(pos); 
		CTreeItem *pItem = pParent;
		CItemInfo* lp = GetData(pParent);
		CString strData = lp->GetItemText();
		if(strData==strItem)//must be a match before going further...suit you self
		{
			va_start(args, strItem);
			int nResult=0;
			for(int i=0; i<nCount;i++)
			{
				LPCTSTR lpsz = va_arg(args, LPCTSTR);   
				for(int nCol=0; nCol < lp->GetItemCount(); nCol++)
				{
					CString str = lp->GetSubItem(nCol);
					if(!str.CompareNoCase(lpsz))
					{
						nResult++;
						break;
					}
				}	
			}
			va_end(args);
			if(nCount==nResult)//all args was found return node
				return pParent;
		}

		//GetNext ....loop through all children 
		for(;;)
		{
			CTreeItem *pCur = GetNext(pParent, pItem, TRUE, FALSE/*regardless of the item are hidden or not, set to TRUE if only visible items must be included in the search*/);	  
			if(!IsChildOf(pParent, pCur))
				break;
			else
			if(pCur==pItem)
				break;
			CItemInfo* lp = GetData(pCur);
			CString strData = lp->GetItemText();
			if(strData==strItem)//must be a match before going further
			{
				va_start(args, strItem);
				int nResult=0;
				for(int i=0; i<nCount;i++)
				{
					LPCTSTR lpsz = va_arg(args, LPCTSTR);   
					for(int nCol=0; nCol < lp->GetItemCount(); nCol++)
					{
						CString str = lp->GetSubItem(nCol);
						if(!str.CompareNoCase(lpsz))
						{
							nResult++;
							break;
						}
					}	
				}
				va_end(args);
				if(nCount==nResult)//all args was found return node
					return pCur;
			}
			pItem=pCur;//next;
		}
	}	
	return NULL;
}



void CMySuperGrid::SortData()
{
	int nIndex = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
	if(nIndex==-1)
		return;

	CTreeItem *pItem = reinterpret_cast<CTreeItem*>(GetItemData(nIndex));

	if(AfxMessageBox("Sort all children(Yes)\nor just sort rootitems(No)",MB_YESNO)==IDYES)
		Sort(pItem, TRUE);			
	else
		Sort(pItem, FALSE);			
	//do a simple refresh thing
	if(ItemHasChildren(pItem))
	{
		SetRedraw(0);
		Collapse(pItem);
		Expand(pItem, nIndex);
		SetRedraw(1);
	}
}



//another search thing
CMySuperGrid::CTreeItem* CMySuperGrid::SearchEx(CTreeItem *pStartPosition, CString strItem)
{
	CItemInfo* lp = GetData(pStartPosition);
	//if(lp->GetCheck()) another condition here maybe
	CString strData = lp->GetItemText();
	if(strData==strItem)
	{
		return pStartPosition;
	}

	const int nChildren = NumChildren(pStartPosition);
	if (nChildren > 0)
	{
		POSITION pos = GetHeadPosition(pStartPosition);
		while (pos)
		{
			CTreeItem *pChild = GetNextChild(pStartPosition, pos);
			CItemInfo* lp = GetData(pChild);
			CString strData = lp->GetItemText();
			if(strData==strItem)
			{
				return pChild;
			}
		}
	}

	POSITION pos = GetHeadPosition(pStartPosition);
	while (pos)
	{
		CTreeItem *pChild = GetNextChild(pStartPosition, pos);
		CItemInfo* lp = GetData(pChild);
		CString strData = lp->GetItemText();
		if(strData==strItem)
		{
			return pChild;
		}

		pChild = SearchEx(pChild, strItem);
		if(pChild!=NULL)
			return pChild;
	}
	return NULL;
}





BOOL CMySuperGrid::OnDeleteItem(CTreeItem* pItem, int nIndex)
{
	return FALSE;
}


BOOL CMySuperGrid::OnItemExpanding(CTreeItem *pItem, int iItem)
{
	CValue vCurrentItem = GetItemIndex(pItem);
	CValue vFSO = 1;
	CValue *lArray[2] = {&vCurrentItem, &vFSO};
	CallModuleProc("ПриРазворачиванииУзла","OnItemExpanding",2,lArray);

	return (long(vFSO.GetNumeric()) != 0L);
}


BOOL CMySuperGrid::OnItemExpanded(CTreeItem* pItem, int iItem)
{
	CValue vCurrentItem = GetItemIndex(pItem);
	CValue vFSO = 1;
	CValue *lArray[2] = {&vCurrentItem, &vFSO};
	CallModuleProc("ПослеРазворачиванияУзла","OnItemExpanded",2,lArray);

	return (long(vFSO.GetNumeric()) != 0L);
}


BOOL CMySuperGrid::OnCollapsing(CTreeItem *pItem)
{
	CValue vCurrentItem = GetItemIndex(pItem);
	CValue vFSO = 1;
	CValue *lArray[2] = {&vCurrentItem, &vFSO};
	CallModuleProc("ПриСворачиванииУзла","OnItemCollapsing",2,lArray);

	return (long(vFSO.GetNumeric()) != 0L);
}



BOOL CMySuperGrid::OnItemCollapsed(CTreeItem *pItem)
{
	CValue vCurrentItem = GetItemIndex(pItem);
	CValue vFSO = 1;
	CValue *lArray[2] = {&vCurrentItem, &vFSO};
	CallModuleProc("ПослеСворачиванияУзла","OnItemCollapsed",2,lArray);

	return (long(vFSO.GetNumeric()) != 0L);
}


CImageList *CMySuperGrid::CreateDragImageEx(int nItem)
{
		if(m_bDrag)
			return CSuperGridCtrl::CreateDragImageEx(GetDragItem());
		else
			return NULL;
}



void CMySuperGrid::_DeleteAll()
{
	DeleteAll();//call CSuperGridCtrl::DeleteAll();

	//add some new data
	CItemInfo* lp = new CItemInfo();
	lp->SetImage(4);
	//add item text
	lp->SetItemText(_T("New data"));
	//Create root item
	CTreeItem * pRoot = InsertRootItem(lp);//previous we call CreateTreeCtrl(lp)
	if( pRoot == NULL )
		return;
	//insert items	
	int nCol = GetNumCol();
	for(int i=0; i < nCol; i++)
	{
		CItemInfo* lpItemInfo = new CItemInfo();
		CString strItem;
		strItem.Format(_T("Item %d"),i);
		//add items text
		lpItemInfo->SetItemText(strItem);
		//add subitem text
		for(int y=0;y < nCol-1; y++) 
		{
			CString str;
			str.Format(_T("subItem %d of %s"),y,lpItemInfo->GetItemText());
			lpItemInfo->AddSubItemText(str);
			lpItemInfo->AddSubItemText(str);
		}
		//insert the iteminfo with ParentPtr
		CTreeItem* pParent = InsertItem(pRoot, lpItemInfo);
		//other nodes
		if(i%nCol)
		{
			CTreeItem* pParent1=NULL;
			CTreeItem* pParent2=NULL;
			for(int x=0; x < nCol; x++)
			{
				CItemInfo* lpItemInfo = new CItemInfo();
				CString strItem;
				strItem.Format(_T("Item %d"),x);
				lpItemInfo->SetItemText(strItem);
				for(int z=0; z < nCol-1; z++) 
				{
					CString str;
					str.Format(_T("subItem %d of %s"),z, lpItemInfo->GetItemText());
					lpItemInfo->AddSubItemText(str);
				}
				pParent1 = InsertItem(pParent, lpItemInfo);
				
			}
		}
	}
	//expand one level
	Expand(pRoot, 0 /*listview index 0*/); 
	UINT uflag = LVIS_SELECTED | LVIS_FOCUSED;
	SetItemState(0, uflag, uflag);


}
