// aplListCtrl.cpp: implementation of the CaplListCtrl class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AplGuiEx.h"
#include <aplAggr.h>

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

#define EDIT_CTRL_ID		31000
#define TIME_CTRL_ID		31001
#define COMBO_CTRL_ID		31002
#define EDIT_NUM_CTRL_ID	31003
#define DATE_CTRL_ID		31004
#define SPIN_CTRL_ID		31005
#define COMBO_TREE_CTRL_ID	31006

/////////////////////////////////////////////////////////////////////////////
// CaplListCtrl
IMPLEMENT_DYNAMIC(CaplListCtrl, CListCtrl)

CaplListCtrl::CaplListData::CHeaderItem::CHeaderItem()
{
	m_sName = "";
	m_iWidth = 10;
}

CaplListCtrl::CaplListData::CHeaderItem::~CHeaderItem()
{
}

CaplListCtrl::CaplListData::CRowItem::CRowItem()
{
	m_sText = "";
}

CaplListCtrl::CaplListData::CRowItem::~CRowItem()
{
}

CaplListCtrl::CaplListData::CRowData::CRowData()
{
}

CaplListCtrl::CaplListData::CRowData::~CRowData()
{
	int i;
	for(i=0; i<GetSize(); i++)
		delete m_pData[i];
}

CaplListCtrl::CaplListData::CaplListData()
{
}

CaplListCtrl::CaplListData::~CaplListData()
{
	int i;
	for(i=0; i<m_data.GetSize(); i++)
	{
		delete m_data[i];
	}
	for(i=0; i<m_header.GetSize(); i++)
	{
		delete m_header[i];
	}

	m_data.RemoveAll();
	m_header.RemoveAll();
}

bool CaplListCtrl::CaplListData::SaveData(CaplListCtrl *pList)
{
	int i, j, cnt;
	//заголовок
	TCHAR *pBuf = new TCHAR[1024];
	CHeaderCtrl *pHeader = pList->GetHeaderCtrl();
	HDITEM hdItem;
	
	hdItem.mask = HDI_TEXT|HDI_WIDTH|HDI_LPARAM;
	hdItem.pszText = pBuf;
	hdItem.cchTextMax = 1024;

	cnt = pHeader->GetItemCount();
	for(i=0; i<cnt; i++)
	{
		CHeaderItem *pItem = new CHeaderItem;
		pHeader->GetItem(i, &hdItem);
		pItem->m_iWidth = hdItem.cxy;
		pItem->m_sName = hdItem.pszText;
		pItem->m_dwData = hdItem.lParam;

		m_header.Add(pItem);
	}

	delete []pBuf;

	for(i=0; i<pList->GetItemCount(); i++)
	{
		CRowData* pRow = new CRowData;
		pRow->m_dwData = pList->GetItemData(i);
		for(j=0; j<cnt; j++)
		{
			CRowItem *pItem = new CRowItem;
			pItem->m_sText = pList->GetItemText(i, j);
			pItem->m_EditType = pList->GetColumnType(i, j);
			pRow->Add(pItem);
		}
		m_data.Add(pRow);
	}

	return true;
}

bool CaplListCtrl::CaplListData::RestoreData(CaplListCtrl *pList)
{
	int i, j, cnt;
	//заголовок
	pList->DeleteAllItems();
	while(pList->GetHeaderCtrl()->GetItemCount()>0)
		pList->DeleteColumn(0);

	cnt = m_header.GetSize();
	for(i=0; i<cnt; i++)
	{
		pList->InsertColumn(i, m_header[i]->m_sName, LVCFMT_LEFT, m_header[i]->m_iWidth);
	}
	
	for(i=0; i<m_data.GetSize(); i++)
	{
		pList->InsertItem(i, _T(""));
		pList->SetItemData(i, m_data[i]->m_dwData);
		for(j=0; j<cnt; j++)
		{
			pList->SetItemText(i, j, m_data[i]->GetAt(j)->m_sText);
			pList->SetItemEditType(m_data[i]->GetAt(j)->m_EditType);
		}
	}
	
	return true;
}

CaplListCtrl::CaplColTypes::CaplColTypes()
{
	Empty();
}

CaplListCtrl::CaplColTypes::CaplColTypes(const CaplColTypes &Val)
{
	*this = Val;
}

CaplListCtrl::CaplColTypes& CaplListCtrl::CaplColTypes::operator=(const CaplColTypes &Val)
{
	Empty();
	nCol = Val.nCol;
	nItem = Val.nItem;
	type = Val.type;

	MaxVal = Val.MaxVal;
	MinVal = Val.MinVal;

	int cnts, cntd, i;
	cnts = Val.m_Strings.GetSize();
	cntd = Val.m_Dwords.GetSize();
	if(cnts==cntd)
	{
		for(i=0; i<cnts; i++)
		{
			m_Strings.Add(Val.m_Strings[i]);
			m_Dwords.Add(Val.m_Dwords[i]);
		}
	}
	else
	{
		m_Strings.Append(Val.m_Strings);
	}

	m_check = Val.m_check;

	return *this;
}

bool CaplListCtrl::CaplColTypes::operator == (const aplEditTypes &Val)
{
	return type==Val;
}

void CaplListCtrl::CaplColTypes::Empty()
{
	nCol = -1;
	nItem = -1;
	type = aplNone;
	MinVal = 0;
	MaxVal = 999999;

	m_Dwords.RemoveAll();
	m_Strings.RemoveAll();

	m_check = aplCheckEmpty;
}

CaplListCtrl::CaplListCtrl()
	: m_bSetItemDataFromCmb(true)
	, m_bSendCmbSelChangeMsg(false)
	, m_EditCol(-1)
	, m_EditItem(-1)
	, m_bReadOnly(FALSE)
	, m_pWarningMessageWnd(NULL)
	, m_HeightCombobox(-1)
{}

CaplListCtrl::~CaplListCtrl()
{
	int i;
	for(i=0; i<m_ListDataArray.GetSize(); i++)
		delete m_ListDataArray[i];

	m_ListDataArray.RemoveAll();
}

BEGIN_MESSAGE_MAP(CaplListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CaplListCtrl)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclkCharacteristics)
	ON_NOTIFY_REFLECT(NM_SETFOCUS, OnSetFocus)
	ON_LC_CBN_SELCHANGE(COMBO_CTRL_ID, OnCBNSelchange)
	ON_LC_CBN_SELCHANGE(COMBO_TREE_CTRL_ID, OnCBNTreeSelchange)
	ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
	ON_WM_MOUSEWHEEL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CaplListCtrl message handlers
void CaplListCtrl::SetItemEditType(int item, int col, aplEditTypes type, CStringArray* StrArr, CDWordArray* DwArr, aplCheckValue check)
{
	ASSERT(item>-1);
	int cnt = m_columns.GetSize();
	int i;
	CaplColTypes ct;
	if(col>-1)
	{
		for(i=0; i<cnt; i++)
		{
			ct = m_columns[i];
			if(ct.nCol==col && ct.nItem == item)
			{
				ct.type = type;
				if(type!=aplEditSpinCtrl)
				{
					if(StrArr)
					{
						ct.m_Strings.RemoveAll();
						ct.m_Strings.Append(*StrArr);
					}
					if(DwArr)
					{
						ct.m_Dwords.RemoveAll();
						ct.m_Dwords.Append(*DwArr);
					}
					
				}
				else if(type==aplEditSpinCtrl)
				{
					if(DwArr)
					{
						if(DwArr->GetSize()>=2)
						{
							int i1, i2;
							i1 = (int)DwArr->GetAt(0);
							i2 = (int)DwArr->GetAt(1);
							ct.MinVal = i1;
							ct.MaxVal = i2;
						}
						else if(DwArr->GetSize()==1)
						{
							int i1;
							i1 = (int)DwArr->GetAt(0);
							ct.MinVal = 0;
							ct.MaxVal = i1;
						}
					}
				}
				m_columns.SetAt(i, ct);
				return;
			}
		}
	}
	else
	{
		for(i=0; i<cnt; i++)
		{
			ct = m_columns[i];
			if(ct.nItem == item)
				m_columns.RemoveAt(i--);
		}
	}
	ct.Empty();
	if(type!=aplEditSpinCtrl)
	{
		if(StrArr)
		{
			ct.m_Strings.RemoveAll();
			ct.m_Strings.Append(*StrArr);
		}
		if(DwArr)
		{
			ct.m_Dwords.RemoveAll();
			ct.m_Dwords.Append(*DwArr);
		}
		
	}
	else if(type==aplEditSpinCtrl)
	{
		if(DwArr)
		{
			if(DwArr->GetSize()>=2)
			{
				int i1, i2;
				i1 = (int)DwArr->GetAt(0);
				i2 = (int)DwArr->GetAt(1);
				ct.MinVal = i1;
				ct.MaxVal = i2;
			}
			else if(DwArr->GetSize()==1)
			{
				int i1;
				i1 = (int)DwArr->GetAt(0);
				ct.MinVal = 0;
				ct.MaxVal = i1;
			}
		}
	}

	ct.nCol = col;
	ct.nItem = item;
	ct.type = type;
	ct.m_check = check;
	m_columns.Add(ct);
}

void CaplListCtrl::SetItemEditType(CaplColTypes col_type)
{
	int cnt = m_columns.GetSize();
	int i;
	CaplColTypes ct;
	for(i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if(ct.nCol==col_type.nCol && ct.nItem == col_type.nItem)
		{
			ct = col_type;
			m_columns.SetAt(i, ct);
			return;
		}
	}

	m_columns.Add(col_type);
}


void CaplListCtrl::OnDblclkCharacteristics(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMLISTVIEW pNMListView = (LPNMLISTVIEW)pNMHDR;
	if(pNMListView->iItem<0) return;	
	if(pNMListView->iSubItem<0) return;

	if(m_columns.GetSize()>0)
		StartEdit(pNMListView->iItem, pNMListView->iSubItem);
	else
	{
		CWnd *pWnd = GetParent();
		if(pWnd && ::IsWindow(pWnd->m_hWnd))
		{
			NMLISTVIEW nmListView;
			memset(&nmListView, 0, sizeof(NMLISTVIEW));
			nmListView.hdr.idFrom = GetDlgCtrlID();
			nmListView.hdr.code = APL_LC_DEF_DBLCLK;
			nmListView.hdr.hwndFrom = m_hWnd;

			nmListView.iItem = pNMListView->iItem;
			nmListView.iSubItem = pNMListView->iSubItem;
			nmListView.ptAction = pNMListView->ptAction;

			pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
		}
	}

}

bool CaplListCtrl::EndEdit(bool bUpdate)
{
	CTime time;
	static bool bTesting = false;
	if(bTesting) return true;
	if(m_EditItem<0 || m_EditCol<0 || m_EditCtrl==aplNone) return false;

	bTesting = true;
	CString text, buf, msg;
	CWnd* pWnd = GetParent()/*GetParent()*/;
	
	if (pWnd && ::IsWindow(pWnd->m_hWnd) && bUpdate)
	{
		NMLISTVIEW nmListView;
		memset(&nmListView, 0, sizeof(NMLISTVIEW));
		nmListView.hdr.idFrom = GetDlgCtrlID();
		nmListView.hdr.code = APL_LC_BEFORE_END_EDIT_MESSAGE;
		nmListView.hdr.hwndFrom = m_hWnd;
		
		nmListView.iItem = m_EditItem;
		nmListView.iSubItem = m_EditCol;
	
		CString oText, nText;
		if(m_edit_ctrl.IsWindowVisible())
			m_edit_ctrl.GetWindowText(nText);
		else if(m_time_ctrl.IsWindowVisible())
			m_time_ctrl.GetWindowText(nText);
		else if(m_combo_ctrl.IsWindowVisible())
		{
			m_combo_ctrl.GetWindowText(nText);
			nmListView.lParam = m_combo_ctrl.GetCurSel();
		}
		else if(m_combo_tree_ctrl.IsWindowVisible())
		{
			nText = m_combo_tree_ctrl.GetWindowText();
			nmListView.lParam = (LPARAM)m_combo_tree_ctrl.GetCurSel();
		}
		else if(m_edit_num_ctrl.IsWindowVisible())
			m_edit_num_ctrl.GetWindowText(nText);
		else if(m_date_ctrl.IsWindowVisible())
			m_date_ctrl.GetWindowText(nText);

		oText = GetItemText(m_EditItem, m_EditCol);
		SetItemText(m_EditItem, m_EditCol, nText);
		if (pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView) != 0)
		{
			if(m_edit_ctrl.IsWindowVisible())
				m_edit_ctrl.SetFocus();
			else if(m_time_ctrl.IsWindowVisible())
				m_time_ctrl.SetFocus();
			else if(m_combo_ctrl.IsWindowVisible())
				m_combo_ctrl.SetFocus();
			else if(m_combo_tree_ctrl.IsWindowVisible())
				m_combo_tree_ctrl.SetFocus();
			else if(m_edit_num_ctrl.IsWindowVisible())
				m_edit_num_ctrl.SetFocus();
			else if(m_date_ctrl.IsWindowVisible())
				m_date_ctrl.SetFocus();
			SetItemText(m_EditItem, m_EditCol, oText);
			bTesting = false;
			return true;
		}
		SetItemText(m_EditItem, m_EditCol, oText);
	}

	if(m_edit_ctrl.IsWindowVisible())
	{
			m_edit_ctrl.GetWindowText(text);
			if(bUpdate)
			{
				if(m_EditCtrl==aplRealCtrl || m_EditCtrl==aplRealWithoutExpCtrl)
				{
					if(!TestCharactValue(text, false, msg, false))
					{
						m_edit_ctrl.SetFocus();
						SetErrorMessageText(msg);
						bTesting = false;
						return true;
					}
					if(m_EditCtrl==aplRealWithoutExpCtrl)
					{
						int find1 = text.Find(_T('e'));
						int find2 = text.Find(_T('E'));
						if( find1 != -1 || find2 != -1 )
						{
							m_edit_ctrl.SetFocus();
							//SetErrorMessageText( "The field value should not be written in exponential form!\nЗначение поля не должно быть записано в экспоненциальной форме!");
							SetErrorMessageText( APL_T("Значение поля не должно быть записано в экспоненциальной форме!"));
							bTesting = false;
							return true;
						}
					}
				}
				else if(m_EditCtrl==aplIntegerCtrl || m_EditCtrl==aplNaturalCtrl)
				{
					if(!IsInteger(text))
					{
						m_edit_ctrl.SetFocus();
						//SetErrorMessageText( "The field value must be an integer!\nЗначение поля должно быть целым числом!");
						SetErrorMessageText( APL_T("Значение поля должно быть целым числом!"));
						bTesting = false;
						return true;
					}
					if(m_EditCtrl==aplNaturalCtrl)
					{
						if(!IsPositive(text))
						{
							m_edit_ctrl.SetFocus();
							//SetErrorMessageText("The field value must be positive!\nЗначение поля должно быть положительным числом!");
							SetErrorMessageText(APL_T("Значение поля должно быть положительным числом!"));
							bTesting = false;
							return true;
						}
						int num = _atoi(text);
						if(num == 2147483647 && text != _T("2147483647") && text != _T("+2147483647"))
						{
							m_edit_ctrl.SetFocus();
							//SetErrorMessageText("The field value must be a number less than 2147483647!\nЗначение поля должно быть числом меньше 2147483647!");
							SetErrorMessageText(APL_T("Значение поля должно быть числом меньше 2147483647!"));
							bTesting = false;
							return true;
						}
					}
				}
				SetItemText(m_EditItem, m_EditCol, text);
			}
			m_edit_ctrl.ShowWindow(SW_HIDE);
			m_edit_ctrl.SetSel(0, -1);
			SetFocus();
	}
	else if(m_time_ctrl.IsWindowVisible())
	{
		m_time_ctrl.GetWindowText(text);
		if(bUpdate)
		{
			m_time_ctrl.SetFocus();
			if(!TestCharactValue(text, true, msg, false))
			{
				m_time_ctrl.SetFocus();
				SetErrorMessageText(msg);
				bTesting = false;
				return true;
			}
			SetItemText(m_EditItem, m_EditCol, text);
		}
		m_time_ctrl.ShowWindow(SW_HIDE);
		SetFocus();
	}
	else if(m_date_ctrl.IsWindowVisible())
	{
		if(GDT_VALID == m_date_ctrl.GetTime(time))
			m_date_ctrl.GetWindowText(text);
		else
			text.Empty();
		if(bUpdate)
			SetItemText(m_EditItem, m_EditCol, text);
		m_date_ctrl.ShowWindow(SW_HIDE);
		SetFocus();
	}
	else if(m_combo_ctrl.IsWindowVisible())
	{
		m_combo_ctrl.GetWindowText(text);
		if(bUpdate)
		{
			int ind = m_combo_ctrl.GetCurSel();
#if _MSC_VER >= 1400
			DWORD_PTR data;
#else
			DWORD data;
#endif
			data = m_combo_ctrl.GetItemData(ind);

			SetItemText(m_EditItem, m_EditCol, text);

			if (m_EditCtrl.m_Dwords.GetSize() > 0 && m_bSetItemDataFromCmb)
				SetItemData(m_EditItem, data);
		}
		m_combo_ctrl.ShowWindow(SW_HIDE);
		SetFocus();
	}
	else if(m_combo_tree_ctrl.IsWindowVisible())
	{
		text = m_combo_tree_ctrl.GetWindowText();
		if(bUpdate)
		{
			HTREEITEM hItem = m_combo_tree_ctrl.GetCurSel();
#if _MSC_VER >= 1400
			DWORD_PTR data;
#else
			DWORD data;
#endif
			data = m_combo_tree_ctrl.GetItemData(hItem);

			SetItemText(m_EditItem, m_EditCol, text);

			if (m_EditCtrl.m_Dwords.GetSize() > 0 && m_bSetItemDataFromCmb)
				SetItemData(m_EditItem, data);
		}
		m_combo_tree_ctrl.ShowWindow(SW_HIDE);
		SetFocus();
	}
	else if(m_edit_num_ctrl.IsWindowVisible())
	{
		m_edit_num_ctrl.GetWindowText(text);
		if(bUpdate)
			SetItemText(m_EditItem, m_EditCol, text);
		m_edit_num_ctrl.ShowWindow(SW_HIDE);
		m_spin_ctrl.ShowWindow(SW_HIDE);
		m_edit_num_ctrl.SetSel(0, -1);
		SetFocus();
	}
	
	if(pWnd && ::IsWindow(pWnd->m_hWnd) && bUpdate)
	{
		NMLISTVIEW nmListView;
		memset(&nmListView, 0, sizeof(NMLISTVIEW));
		nmListView.hdr.idFrom = GetDlgCtrlID();
		nmListView.hdr.code = APL_LC_AFTER_END_EDIT_MESSAGE;
		nmListView.hdr.hwndFrom = m_hWnd;
		
		nmListView.iItem = m_EditItem;
		nmListView.iSubItem = m_EditCol;
		
		pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
	}

	m_EditCol = -1;
	m_EditItem = -1;
	m_EditCtrl.Empty();
	m_sErrorText.Empty();
	bTesting = false;

	m_pWarningMessageWnd = NULL;
	m_ToolTipCtrl.DelTool(&m_edit_num_ctrl);
	m_ToolTipCtrl.DelTool(&m_edit_ctrl);
	m_ToolTipCtrl.DelTool(&m_combo_ctrl);
	m_ToolTipCtrl.DelTool(&m_combo_tree_ctrl);
	m_ToolTipCtrl.DelTool(&m_time_ctrl);

	ReleaseCapture();

	return true;
}

void CaplListCtrl::SetUseItemDataFromCmb( bool bUse /*= true*/ )
{
	m_bSetItemDataFromCmb = bUse;
}

void CaplListCtrl::SetSendCmbSelChangeMsg(bool bSend /*= true*/)
{
	m_bSendCmbSelChangeMsg = bSend;
}

CaplListCtrl::CaplColTypes CaplListCtrl::GetColumnType(int item, int col)
{
	CaplColTypes ct;
	int cnt =m_columns.GetSize();
	for(int i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if((ct.nCol==col || ct.nCol==-1) && ct.nItem==item)
			return ct;
	}
	ct.Empty();
	return ct;
}

BOOL CaplListCtrl::DestroyWindow() 
{
	if(::IsWindow(m_edit_ctrl.m_hWnd))
		m_edit_ctrl.DestroyWindow();
	if(::IsWindow(m_time_ctrl.m_hWnd))
		m_time_ctrl.DestroyWindow();
	if(::IsWindow(m_combo_ctrl.m_hWnd))
		m_combo_ctrl.DestroyWindow();
	if(::IsWindow(m_combo_tree_ctrl.m_hWnd))
		m_combo_tree_ctrl.DestroyWindow();
	if(::IsWindow(m_spin_ctrl.m_hWnd))
		m_spin_ctrl.DestroyWindow();
	if(::IsWindow(m_edit_num_ctrl.m_hWnd))
		m_edit_num_ctrl.DestroyWindow();
	
	return CListCtrl::DestroyWindow();
}

int CaplListCtrl::InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
{
	CaplColTypes ct;
	int cnt =m_columns.GetSize();
	for(int i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if(ct.nItem>=nItem)
		{
			ct.nItem++;
			m_columns.SetAt(i, ct);
		}
	}
	return CListCtrl::InsertItem(nMask, nItem, lpszItem, nState, nStateMask, nImage, lParam);
}

int CaplListCtrl::InsertItem(const LVITEM *pItem)
{
	CaplColTypes ct;
	int cnt =m_columns.GetSize();
	for(int i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if(ct.nItem>=pItem->iItem)
		{
			ct.nItem++;
			m_columns.SetAt(i, ct);
		}
	}
	return CListCtrl::InsertItem(pItem);
}

int CaplListCtrl::InsertItem(int nItem, LPCTSTR lpszItem)
{
	CaplColTypes ct;
	int cnt =m_columns.GetSize();
	for(int i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if(ct.nItem>=nItem)
		{
			ct.nItem++;
			m_columns.SetAt(i, ct);
		}
	}
	return CListCtrl::InsertItem(nItem, lpszItem);
}

int CaplListCtrl::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
	CaplColTypes ct;
	int cnt =m_columns.GetSize();
	for(int i=0; i<cnt; i++)
	{
		ct = m_columns[i];
		if(ct.nItem>=nItem)
		{
			ct.nItem++;
			m_columns.SetAt(i, ct);
		}
	}
	return CListCtrl::InsertItem(nItem, lpszItem, nImage);
}

void CaplListCtrl::SetReadOnly(BOOL bReadOnly)
{
	m_bReadOnly = bReadOnly;	
}

void CaplListCtrl::OnSetFocus(NMHDR* pNMHDR, LRESULT* pResult)
{
	EndEdit();
}

BOOL CaplListCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	UNREFERENCED_PARAMETER(nFlags);
	UNREFERENCED_PARAMETER(zDelta);
	UNREFERENCED_PARAMETER(pt);

	if (m_combo_tree_ctrl.IsWindowVisible())
	{
		m_combo_tree_ctrl.OnMouseWheel(nFlags, zDelta, pt);
		return 1;
	}
	else
		return 0;
}

void CaplListCtrl::OnCBNSelchange(NMHDR* pNMHDR, LRESULT* pResult)
{
	if (m_bSendCmbSelChangeMsg)
	{
		bool bUpdate = false;
		CWnd* pWnd = GetParent();

		if (pWnd && ::IsWindow(pWnd->m_hWnd))
		{
			NMLISTVIEW nmListView;
			memset(&nmListView, 0, sizeof(NMLISTVIEW));
			nmListView.hdr.idFrom = GetDlgCtrlID();
			nmListView.hdr.code = APL_LC_CBN_SELCHANGE;
			nmListView.hdr.hwndFrom = m_hWnd;
			nmListView.lParam = m_combo_ctrl.GetCurSel();

			nmListView.iItem = m_EditItem;
			nmListView.iSubItem = m_EditCol;

			LRESULT result = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
			if (result == 0)
				bUpdate = true;
		}

		EndEdit(bUpdate);
	}
}

void CaplListCtrl::OnCBNTreeSelchange(NMHDR* pNMHDR, LRESULT* pResult)
{
	if (m_bSendCmbSelChangeMsg)
	{
		bool bUpdate = false;
		CWnd* pWnd = GetParent();

		if (pWnd && ::IsWindow(pWnd->m_hWnd))
		{
			NMLISTVIEW nmListView;
			memset(&nmListView, 0, sizeof(NMLISTVIEW));
			nmListView.hdr.idFrom = GetDlgCtrlID();
			nmListView.hdr.code = APL_LC_CBN_SELCHANGE;
			nmListView.hdr.hwndFrom = m_hWnd;
			nmListView.lParam = (LPARAM)m_combo_tree_ctrl.GetCurSel();

			nmListView.iItem = m_EditItem;
			nmListView.iSubItem = m_EditCol;

			LRESULT result = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
			if (result == 0)
				bUpdate = true;
		}

		EndEdit(bUpdate);
	}
}

bool CaplListCtrl::StartEdit(int row, int col)
{
	if(row<0 || col<0) return false;
	if(m_bReadOnly) return false;
	COleDateTime codt;
// 	int i, cnt = m_columns.GetSize(); 
// 	for(i=0; i<cnt; i++) - цикл выполнялся всегда один раз, так что тут он явно лишний
// 	{
		CaplColTypes ct = GetColumnType(row, col);
		//начинаем редактировать наш элемент
		CRect rect;
		GetSubItemRect(row, col, LVIR_LABEL, rect);
		rect.DeflateRect(0, 0, 0, 0);
		CString text;
		text = GetItemText(row, col);

		switch(ct.type)
		{
		case aplTextCtrl:
		case aplRealCtrl:
		case aplRealWithoutExpCtrl:
		case aplIntegerCtrl:
		case aplNaturalCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}

				if(::IsWindow(m_edit_ctrl.m_hWnd))
				{
					m_edit_ctrl.MoveWindow(rect, FALSE);
					m_edit_ctrl.SetWindowText(text);
					m_edit_ctrl.SetSel(0,-1);
					m_edit_ctrl.ShowWindow(SW_SHOW);
					m_edit_ctrl.SetFocus();
					m_edit_ctrl.SetCapture();

					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplTimeCtrl:
			{
				if(::IsWindow(m_time_ctrl.m_hWnd))
				{
					m_time_ctrl.MoveWindow(rect, FALSE);
					m_time_ctrl.SetWindowText(text);
					m_time_ctrl.SetSel(0, -1);
					m_time_ctrl.ShowWindow(SW_SHOW);
					m_time_ctrl.SetFocus();
					m_time_ctrl.SetCapture();
					
					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplDateCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}

				m_date_ctrl.SetFormat(NULL);
				if(::IsWindow(m_date_ctrl.m_hWnd))
				{
					rect.DeflateRect(0, -4, 0, -4);
					m_date_ctrl.MoveWindow(rect, FALSE);
					aplString2Date(text,codt);
					m_date_ctrl.SetTime(codt);
					m_date_ctrl.ShowWindow(SW_SHOW);
					m_date_ctrl.SetFocus();
					m_date_ctrl.SetCapture();
					
					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplDateTimeCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}
				m_date_ctrl.SetFormat(_T("dd.MM.yyyy HH:mm"));
				if(::IsWindow(m_date_ctrl.m_hWnd))
				{
					rect.DeflateRect(0, -4, 0, -4);
					m_date_ctrl.MoveWindow(rect, FALSE);
					if(text.IsEmpty())
					{
						codt = COleDateTime::GetCurrentTime();
					}
					else
						codt.ParseDateTime(text);
					m_date_ctrl.SetTime(codt);
					m_date_ctrl.ShowWindow(SW_SHOW);
					m_date_ctrl.SetFocus();
					m_date_ctrl.SetCapture();
					
					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplComboCtrl:
		case aplComboWidthCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}

				if(::IsWindow(m_combo_ctrl.m_hWnd))
				{
					m_combo_ctrl.ResetContent();
					if( m_HeightCombobox != -1 )
						rect.bottom = rect.top + m_HeightCombobox;
					m_combo_ctrl.MoveWindow(rect, FALSE);
					int ind = 0, cnts, cntd, s;
					cnts = ct.m_Strings.GetSize();
					cntd = ct.m_Dwords.GetSize();
					if(cnts == cntd)
					{
						for (s=0; s<cnts; s++)
						{
							ind = m_combo_ctrl.AddString(ct.m_Strings[s]);
							m_combo_ctrl.SetItemData(ind, ct.m_Dwords[s]);
						}
					}
					else
					{
						for (s=0; s<cnts; s++)
							ind = m_combo_ctrl.AddString(ct.m_Strings[s]);
					}

					if( ct.type == aplComboWidthCtrl )
					{
						CString    str;
						CSize      sz;
						int        dx = 0;
						TEXTMETRIC tm;
						CDC*       pDC = m_combo_ctrl.GetDC();
						CFont*     pFont = m_combo_ctrl.GetFont();

						// Select the listbox font, save the old font
						CFont* pOldFont = pDC->SelectObject(pFont);
						// Get the text metrics for avg char width
						pDC->GetTextMetrics(&tm);

						for (int i = 0; i < m_combo_ctrl.GetCount(); i++)
						{
							m_combo_ctrl.GetLBText(i, str);
							sz = pDC->GetTextExtent(str);

							// Add the avg width to prevent clipping
							sz.cx += tm.tmAveCharWidth;

							if (sz.cx > dx)
								dx = sz.cx;
						}
						// Select the old font back into the DC
						pDC->SelectObject(pOldFont);
						m_combo_ctrl.ReleaseDC(pDC);

						// Adjust the width for the vertical scroll bar
						COMBOBOXINFO cbi;
						cbi.cbSize = sizeof(COMBOBOXINFO);
						if(m_combo_ctrl.GetComboBoxInfo(&cbi))
						{
							if(::IsWindow(cbi.hwndList))
							{
								SCROLLBARINFO sbi;
								sbi.cbSize = sizeof(SCROLLBARINFO);
								CWnd::FromHandle(cbi.hwndList)->GetScrollBarInfo(OBJID_VSCROLL, &sbi);
								if( !(sbi.rgstate[0]&STATE_SYSTEM_INVISIBLE) )
									dx += ::GetSystemMetrics(SM_CXVSCROLL);
							}
						}

						CRect list_rect;
						GetWindowRect(&list_rect);
						int sdx = ::GetSystemMetrics(SM_CXSCREEN) - rect.left - list_rect.left;
						if( dx < sdx ) sdx = dx;

						// Set the width of the list box so that every item is completely visible.
						m_combo_ctrl.SetDroppedWidth(sdx);
					}

					int cur = m_combo_ctrl.FindStringExact(-1, text);
					m_combo_ctrl.SetCurSel(cur > 0 ? cur : 0);
					m_combo_ctrl.ShowWindow(SW_SHOW);
					m_combo_ctrl.SetFocus();
					m_combo_ctrl.SetCapture();
					
					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplComboTreeCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}

				if(::IsWindow(m_combo_tree_ctrl.m_hWnd))
				{
					int i;
					m_combo_tree_ctrl.m_bFullWindowText = false;
					for( i = 0; i < m_FullWindowTextColumn.GetSize(); i++ )
					{
						if( m_FullWindowTextColumn[i] == col )
						{
							m_combo_tree_ctrl.m_bFullWindowText = true;
							break;
						}
					}
					CString CurStr = GetItemText(row, col);

					m_combo_tree_ctrl.ResetContent();
					if( m_HeightCombobox != -1 )
						m_combo_tree_ctrl.SetDroppedHeight(m_HeightCombobox);
					else
						m_combo_tree_ctrl.SetDroppedHeight(100);
					m_combo_tree_ctrl.MoveWindow(rect, FALSE);

					HTREEITEM hItem;
					int cnts = ct.m_Strings.GetSize();
					int cntd = ct.m_Dwords.GetSize();
					for( i = 0; i < cnts; i++ )
					{
						hItem = m_combo_tree_ctrl.AddString(ct.m_Strings[i]);
						if( cnts == cntd )
							m_combo_tree_ctrl.SetItemData(hItem, ct.m_Dwords[i]);

						if( !m_combo_tree_ctrl.m_bFullWindowText )
						{
							CString sFind = GetComboTreeDelimiter() + CurStr;
							int ind = ct.m_Strings[i].Find(sFind);
							if( ind != -1 )
							{
								if( sFind.GetLength()+ind == ct.m_Strings[i].GetLength() )
									CurStr = ct.m_Strings[i];
							}
						}
					}

					hItem = NULL;
					if( !CurStr.IsEmpty() )
						hItem = m_combo_tree_ctrl.SelectString(CurStr);
					if( !hItem )
					{
						hItem = m_combo_tree_ctrl.GetTree().GetRootItem();
						m_combo_tree_ctrl.GetLBText(hItem, CurStr);
						m_combo_tree_ctrl.SelectString(CurStr);
					}
					m_combo_tree_ctrl.ShowWindow(SW_SHOW);
					m_combo_tree_ctrl.SetFocus();
					m_combo_tree_ctrl.SetCapture();
					m_combo_tree_ctrl.SetSelectOnlyChilds(false);
					for( i = 0; i < m_OnlyLastSelectAnyItem.GetSize(); i++ )
					{
						if( m_OnlyLastSelectAnyItem[i] == col )
						{
							m_combo_tree_ctrl.SetSelectOnlyChilds();
							break;
						}
					}
					for( i = 0; i < m_FullWindowTextColumn.GetSize(); i++ )
					{
						if( m_FullWindowTextColumn[i] == col )
						{
							if( row == GetItemCount()-1 )
								m_combo_tree_ctrl.SetSelectOnlyChilds(false);
							break;
						}
					}

					m_EditCol = col;
					m_EditItem = row;
				}
			}
			break;
		case aplEditSpinCtrl:
			{
				{
					CWnd* pWnd = GetParent()/*GetParent()*/;
					if(pWnd && ::IsWindow(pWnd->m_hWnd))
					{
						NMLISTVIEW nmListView;
						memset(&nmListView, 0, sizeof(NMLISTVIEW));
						nmListView.hdr.idFrom = GetDlgCtrlID();
						nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
						nmListView.hdr.hwndFrom = m_hWnd;

						nmListView.iItem = row;
						nmListView.iSubItem = col;

						LRESULT lResult = pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
						if(lResult!=0)
							return false;
					}
				}

				if(::IsWindow(m_edit_num_ctrl.m_hWnd) && ::IsWindow(m_spin_ctrl.m_hWnd))
				{
					m_edit_num_ctrl.MoveWindow(rect, FALSE);
					m_edit_num_ctrl.SetWindowText(text);
					m_edit_num_ctrl.SetSel(0,-1);
					m_edit_num_ctrl.ShowWindow(SW_SHOW);
					m_spin_ctrl.SetBuddy(&m_edit_num_ctrl);
					m_spin_ctrl.ShowWindow(SW_SHOW);
					m_edit_num_ctrl.SetFocus();
					m_edit_num_ctrl.SetCapture();

					m_spin_ctrl.SetRange32(ct.MinVal, ct.MaxVal);
					
					m_EditCol = col;
					m_EditItem = row;
				}

			}
			break;
		case aplUser:
			{
				CWnd* pWnd = GetParent()/*GetParent()*/;
				if(pWnd && ::IsWindow(pWnd->m_hWnd))
				{
					NMLISTVIEW nmListView;
					memset(&nmListView, 0, sizeof(NMLISTVIEW));
					nmListView.hdr.idFrom = GetDlgCtrlID();
					nmListView.hdr.code = APL_LC_START_EDIT_MESSAGE;
					nmListView.hdr.hwndFrom = m_hWnd;
					
					nmListView.iItem = row;
					nmListView.iSubItem = col;
					
					pWnd->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmListView);
				}
			}
			break;
		default:
			break;
		}
		m_EditCtrl = ct;
// 		break;
// 	}
	return true;
}

BOOL CaplListCtrl::DeleteItem(int nItem)
{
	//Нам необходимо изменить индексы всех итемов после удаленного
	if(CListCtrl::DeleteItem(nItem))
	{
		int i;
		CaplColTypes colType;
		for(i=0; i<m_columns.GetSize(); i++)
		{
			colType = m_columns[i];
			if(colType.nItem==nItem)
				m_columns.RemoveAt(i--);
			else if(colType.nItem>nItem)
			{
				colType.nItem--;
				m_columns.SetAt(i, colType);
			}
		}
		return TRUE;
	}
	else
		return FALSE;
}

void CaplListCtrl::PreSubclassWindow() 
{
	if(!(GetExtendedStyle()&LVS_EX_FULLROWSELECT) || !(GetExtendedStyle()&LVS_EX_GRIDLINES))
		SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);

	SendMessage(TTM_TRACKACTIVATE);
	// TODO: Add your specialized creation code here
	if (!::IsWindow(m_edit_ctrl.m_hWnd))
	{
		// следует выставить стиль ES_MULTILINE, чтоб обрабатывать нажатие Enter в эдит-боксе...
		m_edit_ctrl.Create(WS_BORDER|ES_AUTOHSCROLL|WS_CHILD|ES_WANTRETURN|ES_MULTILINE, CRect(0,0,100,10), this, EDIT_CTRL_ID);
		m_edit_ctrl.SetFont(GetFont(), FALSE);
	}
	if(!::IsWindow(m_time_ctrl.m_hWnd))
	{
		m_time_ctrl.Create(WS_BORDER|ES_AUTOHSCROLL|WS_CHILD|ES_WANTRETURN|ES_MULTILINE, CRect(0,0,100,10), this, TIME_CTRL_ID);
		m_time_ctrl.SetFont(GetFont());
	}
	if(!::IsWindow(m_combo_ctrl.m_hWnd))
	{
		m_combo_ctrl.Create(WS_BORDER|WS_CHILD|CBS_DROPDOWNLIST|WS_VSCROLL, CRect(0,0,100,100), this, COMBO_CTRL_ID);
		m_combo_ctrl.SetFont(GetFont());
	}
	if(!::IsWindow(m_combo_tree_ctrl.m_hWnd))
	{
		m_combo_tree_ctrl.SetSelectOnlyChilds(true);
		m_combo_tree_ctrl.SetHasCheckboxes(FALSE); //Must set before tree is created
		m_combo_tree_ctrl.Create(CRect(0,0,100,100), 0, 0, this, COMBO_CTRL_ID);
		m_combo_tree_ctrl.SetFont(GetFont());
	}
	if(!::IsWindow(m_edit_num_ctrl.m_hWnd))
	{
		m_edit_num_ctrl.Create(WS_BORDER|ES_AUTOHSCROLL|ES_NUMBER|WS_CHILD|ES_WANTRETURN|ES_MULTILINE, CRect(0,0,100,10), this, EDIT_NUM_CTRL_ID);
		m_edit_num_ctrl.SetFont(GetFont(), FALSE);
	}
	if(!::IsWindow(m_date_ctrl.m_hWnd))
	{
		m_date_ctrl.Create(WS_BORDER|WS_CHILD|DTS_SHORTDATEFORMAT, CRect(0,0,100,10), this, DATE_CTRL_ID);
		m_date_ctrl.SetFont(GetFont(), FALSE);
		m_date_ctrl.SetTime(COleDateTime::GetCurrentTime());
	}
	if(!::IsWindow(m_spin_ctrl.m_hWnd))
	{
		m_spin_ctrl.Create(WS_CHILD|UDS_ARROWKEYS|UDS_SETBUDDYINT|UDS_ALIGNRIGHT, CRect(0,0,100,100), this, SPIN_CTRL_ID);
		m_spin_ctrl.SetFont(GetFont());
		m_spin_ctrl.SetRange(0, 32000);
	}
	if(!::IsWindow(m_ToolTipCtrl.m_hWnd))
	{
		m_ToolTipCtrl.Create(this, WS_POPUP|TTS_BALLOON|TTS_NOPREFIX|TTS_ALWAYSTIP);
		m_ToolTipCtrl.SetDelayTime(0);
	}

	EnableToolTips();
	
	CListCtrl::PreSubclassWindow();
}

int CaplListCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI ) const
{
	int nHit = CWnd::OnToolHitTest(point, pTI);
	
	static CString OldTitle;
	const CHeaderCtrl *pHeader = (CHeaderCtrl*)(GetDlgItem(0));

	if(pHeader)
	{

		#if _MFC_VER < 0x0700
			CToolTipCtrl* pTT = AfxGetThreadState()->m_pToolTip;
		#else
			CToolTipCtrl* pTT =AfxGetModuleState()->m_thread.GetDataNA()->m_pToolTip;
		#endif

		CRect rect;
		int i;
		CString buf;
		HDITEM HDItem;
		int cnt = pHeader->GetItemCount();
		int sp;

		HDItem.pszText = new TCHAR[1024];
		HDItem.cchTextMax = 1024;
		HDItem.mask = HDI_TEXT;
		memset(HDItem.pszText, 0, 1024);
		for(i=0; i<cnt; i++)
		{
			pHeader->GetItemRect(i, &rect);
			sp = GetScrollPos(SB_HORZ);
			rect.OffsetRect(-sp, 0);
			if(rect.PtInRect(point))
			{
				pHeader->GetItem(i, &HDItem);
				buf = HDItem.pszText;
				pTI->lpszText = new TCHAR[buf.GetLength()+1];
				pTI->uFlags &=~(TTF_CENTERTIP|TTF_ABSOLUTE);
				pTI->rect = rect;
				lstrcpy(pTI->lpszText, (LPCTSTR)buf);
				pTT->Update();
				if(OldTitle==buf)
				{
					nHit = 1;
					break;
				}
				else
				{
					OldTitle=buf;
					pTI->uId = 0;
					nHit = -1;
					break;
				}
			}
		}
		delete[] HDItem.pszText;
	}

	return nHit;
}

bool CaplListCtrl::SetErrorMessageText(LPCTSTR lpszText)
{
	m_sErrorText = lpszText;
	
	//CString sTitle =  "Invalid value (Недопустимое значение)";
	CString sTitle =  APL_T("Недопустимое значение");
	CRect r;
	
	if(m_EditCtrl==aplRealCtrl || m_EditCtrl==aplRealWithoutExpCtrl || m_EditCtrl==aplTextCtrl || m_EditCtrl==aplIntegerCtrl || m_EditCtrl==aplNaturalCtrl)
		m_pWarningMessageWnd = &m_edit_ctrl;
	else if(m_EditCtrl==aplTimeCtrl)
		m_pWarningMessageWnd = &m_time_ctrl;
	else if(m_EditCtrl==aplComboCtrl || m_EditCtrl==aplComboWidthCtrl)
		m_pWarningMessageWnd = &m_combo_ctrl;
	else if(m_EditCtrl==aplComboTreeCtrl)
		m_pWarningMessageWnd = &m_combo_tree_ctrl;
	else if(m_EditCtrl==aplEditSpinCtrl)
		m_pWarningMessageWnd = &m_edit_num_ctrl;
	else if(m_EditCtrl==aplDateCtrl)
		m_pWarningMessageWnd = &m_date_ctrl;
	else if(m_EditCtrl==aplDateTimeCtrl)
		m_pWarningMessageWnd = &m_date_ctrl;
	else
		return false;
	
	DWORD dwVer = GetDllVersion(_T("comctl32.dll"));
	if(dwVer>=PACKVERSION(5,0))
	{
		if(m_pWarningMessageWnd->IsKindOf(RUNTIME_CLASS(CEdit)))
		{
			CEdit *pEdit = (CEdit*)m_pWarningMessageWnd;
			CA2W conv("111222");
			if(pEdit->SendMessage(EM_SETCUEBANNER, (WPARAM)0, (LPARAM)conv.m_szBuffer))
				return true;
		}
		m_pWarningMessageWnd->GetWindowRect(&r);

		POINT t_pt;

		t_pt.x =  r.left+5;
		t_pt.y = r.top+5;
		::SetCursorPos(t_pt.x, t_pt.y);

		m_ToolTipCtrl.DelTool(m_pWarningMessageWnd);
		m_ToolTipCtrl.AddTool(m_pWarningMessageWnd, m_sErrorText);
		m_ToolTipCtrl.SendMessage(TTM_SETTITLE, TTI_ERROR, (LPARAM)(LPCTSTR)sTitle);
		m_ToolTipCtrl.SetWindowPos(m_pWarningMessageWnd, r.left+1, r.top+1, r.right, r.bottom, SWP_NOSIZE);
		m_ToolTipCtrl.SetDelayTime(0);
		m_ToolTipCtrl.SetDelayTime(TTDT_AUTOPOP, 2000);
		m_ToolTipCtrl.SetDelayTime(TTDT_RESHOW, 0);
	}
	else
	{
		AfxMessageBox(m_sErrorText, MB_OK|MB_ICONSTOP);
		return false;
	}
	
	return true;
}

BOOL CaplListCtrl::PreTranslateMessage(MSG* pMsg) 
{
	if(!m_sErrorText.IsEmpty() && m_pWarningMessageWnd)
	{
		m_ToolTipCtrl.RelayEvent(pMsg);
	}

	return CListCtrl::PreTranslateMessage(pMsg);
}

bool CaplListCtrl::SetItemBkColor(int nItem, int nSubItem, COLORREF color)
{
	bool bFind(false);
	for(int i=0; (i<m_items.GetSize()) && !bFind; ++i)
	{
		if(m_items[i].m_Item==nItem && m_items[i].m_SubItem==nSubItem)
		{
			m_items[i].m_BkColor = color;
			bFind = true;
		}
	}

	if (!bFind)
	{
		CaplItem item;
		item.m_BkColor = color;
		item.m_Item = nItem;
		item.m_SubItem = nSubItem;
		m_items.Add(item);
	}

	RedrawWindow();
	return true;
}

void CaplListCtrl::ResetItemBkColor(int nItem, int nSubItem)
{
	int i;
	for(i=0; i<m_items.GetSize(); i++)
	{
		if(m_items[i].m_Item==nItem && m_items[i].m_SubItem==nSubItem)
		{
			m_items.RemoveAt(i);
			RedrawWindow();
			return;
		}
	}
}

void CaplListCtrl::ClearModifiedItems()
{
	m_items.RemoveAll();
	RedrawWindow();
}

#if _MSC_VER >= 1400
DWORD_PTR CaplListCtrl::GetColData(int nItem, int nSubItem)
#else
DWORD CaplListCtrl::GetColData(int nItem, int nSubItem)
#endif
{
#if _MSC_VER >= 1400
	DWORD_PTR dwData = 0;
#else
	DWORD dwData = 0;
#endif

	int i;
	CaplColTypes colType;
	for (i = 0; i < m_columns.GetSize(); i++)
	{
		colType = m_columns[i];
		if (colType.nItem == nItem && colType.nCol == nSubItem)
		{
			CString sBuf = GetItemText(nItem, nSubItem);
			int iCur = colType.m_Strings.Find(sBuf);
			if (iCur == -1 && colType.type == aplComboTreeCtrl)
			{
				CString sFind = GetComboTreeDelimiter() + sBuf;
				for(int j = 0; j < colType.m_Strings.GetSize(); j++)
				{
					int ind = colType.m_Strings[j].Find(sFind);
					if(ind != -1)
					{
						if(sFind.GetLength()+ind == colType.m_Strings[j].GetLength())
						{
							iCur = j;
							break;
						}
					}
				}
			}

			if (iCur>-1 && colType.m_Dwords.GetSize()>iCur)
			{
				dwData = colType.m_Dwords[iCur];
			}
		}
	}

	return dwData;
}

void CaplListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);

	COLORREF oldTextColor;
	CRect rect;

	rect = lpDrawItemStruct->rcItem;
	if(lpDrawItemStruct->itemState&ODS_SELECTED)
	{
		if(IsWindowEnabled() && GetFocus()==this)
		{
			dc.FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
			oldTextColor = dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
		}
		else
		{
			dc.FillSolidRect(rect, ::GetSysColor(COLOR_MENU));
			oldTextColor = dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
		}
	}
	else
	{
		dc.FillSolidRect(rect, ::GetSysColor(COLOR_WINDOW));
		oldTextColor = dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
	}
	if(lpDrawItemStruct->itemState&ODS_FOCUS)
		dc.DrawFocusRect(rect);

	int i, cnt, j;
	for(j=0; j<m_items.GetSize(); j++)
	{
		if(m_items[j].m_Item==(int)lpDrawItemStruct->itemID && m_items[j].m_SubItem==-1)
			dc.FillSolidRect(rect, m_items[j].m_BkColor);
	}

	cnt = GetHeaderCtrl()->GetItemCount();
	for(i=0; i<cnt; i++)
	{
		GetSubItemRect(lpDrawItemStruct->itemID, i, LVIR_LABEL, rect);
		rect.DeflateRect(2, 0, 2, 0);
		for(j=0; j<m_items.GetSize(); j++)
		{
			if(m_items[j].m_Item==(int)lpDrawItemStruct->itemID && m_items[j].m_SubItem==i)
			{
				dc.FillSolidRect(rect, m_items[j].m_BkColor);
				break;
			}
		}
		dc.DrawText(GetItemText(lpDrawItemStruct->itemID, i), &rect, DT_LEFT);
	}
	dc.SetTextColor(oldTextColor);
	dc.Detach();
}

void CaplListCtrl::SetDateTimeChecked(bool b)
{
	m_date_ctrl.DestroyWindow();

	DWORD dwStyle = WS_BORDER | WS_CHILD | DTS_SHORTDATEFORMAT;
	if (b)
		dwStyle |= DTS_SHOWNONE;

	m_date_ctrl.Create(dwStyle, CRect(0,0,100,10), this, DATE_CTRL_ID);
}


bool CaplListCtrl::aplString2Date(CString &buf, COleDateTime &time)
{
	time.SetStatus(COleDateTime::null);
	if(buf.GetLength()<10) return false;
	int nYear,  nMonth,  nDay;

	nYear=_atoi(LPCTSTR(buf.Right(4)));

	// Тут может быть кроется ошибка, так как формат даты "28.10.2010"
	// четвертый символ - это 0, а не 1. В результате получаем номер месяца - "0"

	// [12/12/2011 lobanov] Лобанов для Акуленко в ответ на вышестоящий комментарий:
	// Что мешало эту хрень исправить блин год назад, из-за этого в период с октября по декабрь
	// каждого года этот контрол глючил при попытке редактировать поле даты.
	// КОММЕНТАРИИ ДОЛЖНЫ ОСТАВЛЯТЬ, МАТЬ ИХ, КОММЕНТАТОРЫ, А ПРОГРАММИСТЫ ОБЯЗАНЫ ПРАВИТЬ БАГИ!!! ИСПРАВЛЕНО!
	nMonth=_atoi(LPCTSTR(buf.Mid(3,2)));

	nDay=_atoi(LPCTSTR(buf.Left(2)));
	return time.SetDateTime(  nYear,  nMonth,  nDay,  0,  0,  0 ) == 0;
}

void CaplListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
	// TODO: Add your control notification handler code here
	if(pLVKeyDow->wVKey == VK_RETURN)
	{
		EndEdit();
	}
	
	*pResult = 0;
}

bool CaplListCtrl::SaveListData(LPCTSTR lpszName)
{
	int i;
	for(i=0; i<m_ListDataArray.GetSize(); i++)
	{
		if(m_ListDataArray[i]->m_sName.CompareNoCase(lpszName)==0)
		{
			delete m_ListDataArray[i];
			m_ListDataArray.RemoveAt(i);
			break;
		}
	}

	CaplListData *pLD = new CaplListData;
	pLD->m_sName = lpszName;
	m_ListDataArray.Add(pLD);
	return pLD->SaveData(this);
}

bool CaplListCtrl::RestoreListData(LPCTSTR lpszName)
{
	DeleteAllItems();
	int i;
	for(i=0; i<m_ListDataArray.GetSize(); i++)
	{
		if(m_ListDataArray[i]->m_sName.CompareNoCase(lpszName)==0)
		{
			return m_ListDataArray[i]->RestoreData(this);
		}
	}

	return false;
}

void CaplListCtrl::SetComboTreeDelimiter(CString delimiter)
{
	m_combo_tree_ctrl.SetDelimiter(delimiter);
}

CString CaplListCtrl::GetComboTreeDelimiter()
{
	return m_combo_tree_ctrl.GetDelimiter();
}

void CaplListCtrl::SetComboTreeFullWindowTextColumn(int col)
{
	m_FullWindowTextColumn.Add(col);
}

void CaplListCtrl::SetOnlyLastSelectAnyItem(int col)
{
	m_OnlyLastSelectAnyItem.Add(col);
}

BOOL CaplListCtrl::SetItemText( _In_ int nItem, _In_ int nSubItem, _In_z_ LPCTSTR lpszText )
{
	if (m_columns.GetSize() > nSubItem)
	{
		CaplColTypes colType = m_columns[nSubItem];
		if (colType.type == aplComboTreeCtrl)
		{
			int i;
			for( i = 0; i < m_FullWindowTextColumn.GetSize(); i++ )
			{
				if( m_FullWindowTextColumn[i] == nSubItem )
					break;
			}
			if (i == m_FullWindowTextColumn.GetSize())
			{
				CString str = lpszText;
				CString sDelimiter = GetComboTreeDelimiter();
				while( true )
				{
					int n = str.Find(sDelimiter);
					if( n != -1 )
						str = str.Right(str.GetLength()-n-sDelimiter.GetLength());
					else
						break;
				}
				return CListCtrl::SetItemText(nItem, nSubItem, str);
			}
		}
	}

	return CListCtrl::SetItemText(nItem, nSubItem, lpszText);
}
