
/*------------------------------------------------------------------------------*
 * File Name:GridControl.h														*
 * Creation: CPY 6/12/2003														*
 * Purpose: OriginC Header file for general vsFlexGrid control					*
 * Copyright (c) Originlab Corp. 2003, 2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	ML 1/21/2004 QA70-5871 			OLECONTROL_DLGINIT_RESOURCE_LANGUAGE		*
 *  Danice 2/16/04 v8.0821 			ADD_SOME_ACCESS_FUNCTION					*
 *	CPY 2/24/04 v7.5826 QA70-6032 	TREE_CONTROL_BASE_CLASS						*
 *  Danice 3/29/04 v8.0844b 		CHANGE_PARA_ORDER_ROW_COL					*
 *	TD 3-23-04 QA70-6053 			PICTURE_IN_OC								*
 *	YuI 3/24/04 v7.5846 QA70-6118	NEW_DATA_SELECTOR_TOOL						*
 *	Frank 5/12/04 v8.0872 			ADD_FOLDER_WITHOUT_PAGE						*
 *  Danice 17/05/04 QA70-6232 		PRO_ONLY_MASK_FOR_SOME_FEATURE				*
 *	CPY 5/25/04 v7.5878 			FO_ADD_PROFILE_DUE_TO_SLOW_LAUNCH			*
 *  Danice 31/05/04 v8.0881			REMOVE_PRO_INFO								*
 *	Frank 24/6/04	v8.0895			FO_ADD_SET_SELECT_ROW_COLLAPSE_STATE		*
 *  Danice 7/2/04 v8.0899			ROW_HEIGH_SETTING							*
 *  Danice 7/14/04 QA70-6631 v8.0905 TREE_BRANCH_COLLAPSED_DEFAULT				*
 *  SY 07/27/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL		*
 *	Frank  7/28/04 			v8.0105 COLLAPSED_BRANCE_WITHOUT_LEAF_NODES			*
 *	Frank 8/3/04	v8.0109			GET_SELECT_ROW_COLLAPSE_STATE				*
 *  Danice 9/13/04 QA70-6891 v8.0132b SUPPORT_GRID_VIEW							*
 *  Danice 9/28/04 QA70-6631 v8.0140 TREE_BRANCH_COLLAPSED_IMPROVEMENT			*
 *	Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION				*
 *	Frank 11/12/04 v8.0162 QA70-6086   ADD_CHECK_STOP_ATTRIBUTE					*
 *  Danice 11/13/04 v8.0162 CORRECT_ENUM_PROBLEM								*
 *  Danice 11/14/04 v8.0162 ADD_GRID_FORMAT_SETTING								*
 *  Danice 11/15/04 QA70-7169 v8.0163 TREE_ROW_SHOW_ALTERNATE_COLORS			*
 *  Danice 12/9/04 QA70-6891 v8.0172 ADD_CELL_COLOR_CONTROL						*
 *  Danice 12/16/04 v8.0175 ADD_TREENODE_FROM_ROW								*
 *	Frank 1/27/05  ALWAYS_NEED_SET_ALL_COLLAPSED_IN_INIT						*
 *  DG 3/16/05 v8.0204 ADD_SIMPLE_TREENODE										*
 *	AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB									*
 *	Frank 3/18/05 v8.0206 ADD_ADDTREENODES_REPLACE_OF_CONTROL_VALUE				*
 *	AW 03/18/05 QA80-7522 v8.0206 MORE_ON_ADD_TREE_NODE_TO_LST_GRID				*
 *	Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE						*
 *  DG 3/22/05 v8.0208 ENABLE_SCROLLBARS_SETTINGS								*
 *  DG 4/20/05 v8.0223 REWRITE_TREE_GET_NODE									*
 *  DG 4/27/05 QA70-7581 v8.0227 TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG				*
 *  Frank 6/24/05 DELETE_SPECIAL_ROW											*
 *  Frank 	7/4/05 SET_GRID_SORT_AND_EDITABLE									*
 *	Jasmine 10/20/05 ADD_SEL_CELL												*
 *	Jasmine 01/05/07 ADD_GET_COL_VALUE											*
 *	Jasmine 06/08/07 UPDATE_SIMPLE_TREE_MODIFICATION							*
 *	Folger 06/12/07 ADD_SET_COL_DATA_TYPE										*
 *	Jasmine 06/14/07 SET_CELL_STATE												*
 *	CPY 6/14/07 SCRIPT_SAMPLE_DLG_SWITCHING_LOCATION_AUTOMATION_ERR				*
 *	Jasmine 07/6/07 CANCEL_GRID_SELECTION										*
 *	CPY 5/4/08 QA70-11504 DIRECT_VC_SET_CELLS									*
 *	Jasmine 10/15/08 MUST_USE_ISSELECT_TO_REMOVE_SELECTION_IN_LISTBOX_CASE		*
 *	Sophy 11/12/2008 SUPPORT_CONTEXT_MENU_COMMAND_TO_UPDATE_PARAM_GRID_CONTROL	*
 *	Jasmine 11/25/08 v8.0979 QA80-12304 SHOULD_ALSO_CHECK_HAS_ENOUGH_ROW_COL	*
 * Kenny 04/27/2009 QA80-13519-P3 COL_BROWSER_DLG_SHOULD_REMEMBER_COLUMN_WIDTH	*
 * Kenny 05/05/2009 FIX_BUG_FOR_SET_COL_WIDTH_OVER_BOUND						*
 * Sim 06-02-2009 QA80-4584 EXTRACT_WKS_SUPPORT_AUTO_UPDATE						*
 *	Hong 07/17/09 QA80-11468 IMPROVE_NLFIT_PARAMS_GRID_UPDATE_SPEED				*
 *	ML CPY 1/28/2010 VSFLEXGRID_NEEDS_IDENTIFIER_FOR_RANOREX					*
 *	TD ML 04-13-2010 QA85-15312 ICON_OVERLAYS_IN_GRIDCONTROL					*
 *	Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID		*
 *	Kenny 04/27/2010 QA80-15357 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID	*
 *	Folger 05/26/10 ORG-120 DATA_DISPLAY_DIALOG_IMPROVEMENT						*
 *	Hong 05/27/10 ORG-131 MATRIX_ADD_GENERAL_LABEL_SUPPORT_AS_WKSHEET			*
 *	Kenny 06/13/2010 ORG-305-P2 GRIDCONTROL_IS_COLLAPSED_FUNCTION_RETURN_WRONG_VALUE*
 *	Folger 07/12/10 ORG-515-P1 COPY_PASTE_WHOLE_COLUMN_IN_NLFIT_SHOULD_ONLY_HANDLE_VISIBLE
 *------------------------------------------------------------------------------*/

#ifndef _GRID_CONTROL_H_
#define _GRID_CONTROL_H_

/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
#include <TreeEditor.h>
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#include <vsFlexGrid.h>
#include <OC_Res.h>
#include "ResizeControl.h"
#include "DataIDs.h"
#include "ocTE.h"		///DG ADD_SIMPLE_TREENODE

#define _DBINT2(_STR, _INT1, _INT2) 		//printf("%s [%d, %d]\n", _STR, _INT1, _INT2);
#define _DBINT3(_STR, _INT1, _INT2, _INT3)	//printf("%s [%d, %d] %d\n", _STR, _INT1, _INT2, _INT3);
#define _DBINT(_STR, _INT)					//out_int(_STR, _INT);
#define _DBSTR(_STR)						//out_str(_STR);
#define _DBPRINTF(_FMT, _ARG)				//printf(_FMT, _ARG);
#define _DBMEMBER(_STR1, _STR2)				//printf("%s::%s\n", _STR1, _STR2);



enum {
	GCSETFONT_NOT_JAPANESE = 0x01,
	GCSETFONT_NOT_OTHER_LANG = 0x02,
	GCSETFONT_HARD_CODE	= 0x04, //--- CPY 10/6/09 LT_CUSTOM_MENU_JUNK_J_MENU_NAMES_IN_GRID
};

#define NUM_EDIT_COL_ALIGNMENTS 3

#define NOT_SET_STOP_LEVEL -1   /// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB



class GridControl : public ResizeControl
{
public:
	GridControl() : ResizeControl()
	{
		_DBSTR("calling GridControl constructor");
		m_bMouseDownToggleCheck = true;//---- CPY 7/5/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE

		m_bReady = false;/// SY 07/27/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	}
	~GridControl()
	{
		_DBSTR("calling GridControl Destructor");
	}
//---- ML CPY 1/28/2010 VSFLEXGRID_NEEDS_IDENTIFIER_FOR_RANOREX
protected:
	BOOL SetCtrlID(int nResID, LPCSTR lpcszName)
	{
		Control* pCntrl = GetControl();
		if(pCntrl && nResID)
		{
			HWND hGrid = pCntrl->GetSafeHwnd();
			SetWindowText(hGrid, lpcszName);
			// better not to touch the controlID, per Marko, as we don't know when problem will crop up in which OS
		//	uint uID = MAKELONG(nResID, VSFLEX_CTRL_ID_HWORD);// vsFlex just use WindowProc as cntrol ID which is random, but we assume hiword !=0
		//	SetWindowLong(hGrid, GWL_ID, uID);
			return true;
		}
		return false;
	}
public:
//----
	//void Init(int nID, Dialog& dlg)
	//void Init(int nID, WndContainer& dlg)	///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
	void Init(int nID, WndContainer& dlg, WndContainer* pParentDlg = NULL)
	{
		//InitControl(nID, dlg);	///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
		InitControl(nID, dlg, pParentDlg);
		
		Control* pCntrl = GetControl();
		if(pCntrl)
		{
			/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
			TreeGridControl		gridCntrl 	= dlg.GetDlgItem(nID);
			ASSERT(gridCntrl);
			m_flx = gridCntrl.GetGridCtrlInterface();
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
			/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
			m_flx = pCntrl->GetActiveXControl();
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__ /// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		}
		
		SetFont();
		//---- ML CPY 1/28/2010 VSFLEXGRID_NEEDS_IDENTIFIER_FOR_RANOREX
		if(nID > 0)
		{
			string strName = "OLVSFLEX_" + (string)nID;
			SetCtrlID(nID, strName);
		}
		//----
		
//		m_flx.FormatString = lpcszColHeadings;
//		m_flx.Cols = nCols;
		m_flx.Rows = 1;
		m_flx.FixedRows = 1;
		
		m_flx.FixedCols = 0;//hide the Row heading
		m_flx.ExtendLastCol = true;
		
		m_nHaldGridLineWidth = m_flx.GridLineWidth/2;
		
		m_nLastRow = -1;
		m_nLastCol = -1;
		m_bReady = false;//CPY 9/1/05 SET_READY_FROM_BASE_CLASS_ONLY
	}
	bool HasRows()
	{
		int nRows = m_flx.Rows - m_flx.FixedRows;
		return nRows > 0? true:false;
	}	
	
	void	SetColHeader(string strColHeaders)
	{
		m_flx.FormatString = strColHeaders;	
	}	
	
	//---- CPY 11/14/05 LOOSE_DATALIST_BETTER_SHOW_WITHOUT_LAST_COL_TOO_WIDE
	void SetExtendLastCol(bool bSet)
	{
		m_flx.ExtendLastCol = bSet;
	}
	//----
	
	///Jasmine 10/20/05 ADD_SEL_CELL
	void SelCell(int nRow, int nCol, bool bSelLast = false) // -1 to sel last row
	{
		if(bSelLast || nRow>=m_flx.Rows || nCol>=m_flx.Cols)
		{
			nRow = m_flx.Rows-1;
			nCol = m_flx.Cols-1;
		}
		
		m_flx.Row = nRow;
		m_flx.Col = nCol;
		
		if(nRow >= 0 && nCol >= 0)
		{
			m_flx.ShowCell(nRow, nCol);
		}
	}
	///End ADD_SEL_CELL
	
	///Danice 2/16/04 v8.0821 ADD_SOME_ACCESS_FUNCTION
	//bool 	SetupRowsCols(int nFixedCols = 0, int nFixedRows = 1,  int nCols = 1, int nRows = -1)	///Danice 3/29/04 v8.0844b CHANGE_PARA_ORDER_ROW_COL
	bool 	SetupRowsCols(int nFixedRows = 1, int nFixedCols = 0,  int nRows = -1, int nCols = 1)
	{
		///---DG 3/23/05 check invalid input
		bool bRet=true;
		if(nFixedRows<0 || nFixedCols<0 || nCols<0)
		{
			if(0 > nFixedRows)
				nFixedRows=0;
			if(0 > nFixedCols)
				nFixedCols=0;
			if(0 > nCols)
				nCols=nFixedCols;
			
			bRet=false;
			error_report("Invalid Rows or Cols input");
		}
		///---end
		
		m_flx.Cols 	=	nCols;
		//if(-1 == nRows)	///DG 3/23/05
		if(0 > nRows)
			nRows = nFixedRows;
		m_flx.Rows 	= 	nRows;
		m_flx.FixedCols = 	nFixedCols;
		m_flx.FixedRows = 	nFixedRows;
		return bRet;
	}
	void 	AddCol(int iCol = 1) {m_flx.Cols = m_flx.Cols + iCol;}
	int 	GetCols() {return m_flx.Cols;}
	int		GetRows() {return m_flx.Rows;}
	void 	SetCols(int nCols, bool bKeepFixedCols = true) {int nn = bKeepFixedCols? m_flx.FixedCols + nCols:nCols; m_flx.Cols = nn;}
	void	SetRows(int nRows, bool bKeepFixedRows = true) {int nn = bKeepFixedRows? m_flx.FixedRows + nRows:nRows; m_flx.Rows = nn;}
	//---- CPY 11/12/04 SHARE_PARAMS_USE_HIDE_INSTEAD_OF_INSERT_DEL
	void SetAlternateRowColors(uint nAlternateColor=-1)
	{
		if(-1 == nAlternateColor)
			nAlternateColor = RGB(0xF0,0xF0,0xF0);
		m_flx.BackColorAlternate = nAlternateColor;
	}

	int	GetColOffset() {return m_flx.FixedCols;}
	int	GetRowOffset() {return m_flx.FixedRows;}
	///Vinden 5/8/2008 v8.0857 ADD_FUNCTION
	int GetNumRows(){return GetRows()-GetRowOffset();}
	int GetNumCols(){return GetCols()-GetColOffset();}
	///End ADD_FUNCTION
	bool GetRowValues(int nRow, vector<string>& vsVals, int nCol1 = 0)
	{
		if(nRow < 0)//GetRowOffset())	///Jasmine 03/07/07 should be able to get fixed row value
			return false;
		if(nRow >= GetRows())
			return false;
		vsVals.SetSize(0);
		string	strRet ;
		for(int nCol = nCol1 ; nCol < GetCols(); nCol++ )
		{
			strRet = GetCell(nRow, nCol);
			vsVals.Add(strRet);
		}
		return true;
	}
	///Jasmine 01/05/07 ADD_GET_COL_VALUE
	bool GetColValues(int nCol, vector<string>& vsVals, int nRow1 = 0)
	{
		if(nCol < 0)//GetColOffset())	///Jasmine 03/07/07 should be able to get fixed col value
			return false;
		if(nCol >= GetCols())
			return false;
		vsVals.SetSize(0);
		string	strRet ;
		for(int nRow = nRow1 ; nRow < GetRows(); nRow++ )
		{
			strRet = GetCell(nRow, nCol);
			vsVals.Add(strRet);
		}
		return true;
	}
	///End ADD_GET_COL_VALUE
	bool SetFixedRowValues(int nRow, const vector<string> &vsVals, int nCol1 = 0, bool bExpand = false)
	{
		int nColsInData = vsVals.GetSize();
		int nLastCol = nCol1 + nColsInData - 1;
		if(!CheckConvertCol(nLastCol, bExpand))
			return false;
		for(int nCol = nCol1 + GetColOffset(), nn = 0; nCol < GetCols(); nCol++, nn++ )
		{
			if(nn < nColsInData)
				SetCell(vsVals[nn], flexcpText, nRow, nCol);
		}
		return true;
	}
	bool SetRowValues(int nRow, const vector<string> &vsVals, int nCol1 = 0, bool bExpand = false)
	{
		if(nRow < 0)
			return SetFixedRowValues(0, vsVals, nCol1, bExpand);
		
		if(!CheckConvertRow(nRow, bExpand))
			return false;
		int nColsInData = vsVals.GetSize();
		int nLastCol = nCol1 + nColsInData - 1;
		if(!CheckConvertCol(nLastCol, bExpand))
			return false;
		for(int nCol = nCol1 + GetColOffset(), nn = 0; nCol < GetCols(); nCol++, nn++ )
		{
			if(nn < nColsInData)
			{
				SetCell(vsVals[nn], flexcpText, nRow, nCol);
			}
		}
		return true;
	}
	bool SetColValues(int nCol, const vector<string> &vsVals, int nRow1 = 0, bool bExpand = false)
	{
		if(!CheckConvertCol(nCol, bExpand))
			return false;
		int nRowsInData = vsVals.GetSize();
		int nLastRow = nRow1 + nRowsInData - 1;
		if(!CheckConvertRow(nLastRow, bExpand))
			return false;
		for(int nRow = nRow1 + GetRowOffset(), nn = 0; nRow < GetRows(); nRow++, nn++ )
		{
			if(nn < nRowsInData)
			{
				SetCell(vsVals[nn], flexcpText, nRow, nCol);
			}
		}
		return true;
	}
	// convert from 0 offset col index into actual grid index, option to expand as well
	bool CheckConvertCol(int& nCol, bool bExpand)
	{
		if(nCol < 0)
			return false;
		
		nCol += GetColOffset();
		
		if(nCol >= GetCols())
		{
			if(!bExpand)
				return false;
			m_flx.Cols = nCol + 1;
		}
		return true;
	}
	// convert from 0 offset row index into actual grid index, option to expand as well
	bool CheckConvertRow(int& nRow, bool bExpand)
	{
		if(nRow < 0)
			return false;
		
		nRow += GetRowOffset();
		
		if(nRow >= GetRows())
		{
			if(!bExpand)
				return false;
			m_flx.Rows = nRow + 1;
		}
		return true;
	}
	bool SetFixedColAlignment(int nCol, int nAlignment, bool bExpand = false)
	{
		/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		/*
		if(nCol < 0) // set all
		{
			for(int nc = m_flx.FixedCols; nc < m_flx.Cols; nc++)
				m_flx.FixedAlignment(nc) = nAlignment;
			
			return true;
		}
		if(!CheckConvertCol(nCol, bExpand))
			return false;
		*/
		int			nCount = 1;
		if ( nCol < 0 )
		{
			nCol = m_flx.FixedCols;
			nCount = m_flx.Cols - nCol;
		}
		else if ( !CheckConvertCol(nCol, bExpand) )
			return false;
		
		for ( int nIndex = nCol; nCount > 0; nCount--, nIndex++ )
		{
			SetFixedAlignment(nCol, nAlignment);
		}
		/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		return true;
	}
	bool SetColAlignment(int nCol, int nAlignment, bool bExpand = false)
	{
		/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		/*
		if(nCol < 0) // set all
		{
			for(int nc = m_flx.FixedCols; nc < m_flx.Cols; nc++)
				m_flx.ColAlignment(nc) = nAlignment;
			
			return true;
		}
		if(!CheckConvertCol(nCol, bExpand))
			return false;
		
		m_flx.ColAlignment(nCol) = nAlignment;
		*/
		int			nCount = 1;
		if ( nCol < 0 )
		{
			nCol = m_flx.FixedCols;
			nCount = m_flx.Cols - nCol;
		}
		else if ( !CheckConvertCol(nCol, bExpand) )
			return false;
		
		for ( int nIndex = nCol; nCount > 0; nCount--, nIndex++ )
		{
		#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
			m_flx.SetColAlignment(nCol, nAlignment);
		#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
			m_flx.ColAlignment(nCol) = nAlignment;
		#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		}
		/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		return true;
	}
	bool SetColHeading(int nCol, LPCSTR lpcsz, bool bExpand = false)
	{
		if(!CheckConvertCol(nCol, bExpand))
			return false;
		if(lpcsz)
		{
			if(GetRowOffset() < 1)
				m_flx.FixedRows = 1;
		}
		SetCell(lpcsz, flexcpText, 0, nCol);
		return true;
	}
	bool SetRowHeading(int nRow, LPCSTR lpcsz, bool bExpand = false)
	{
		if(!CheckConvertRow(nRow, bExpand))
			return false;
		if(lpcsz)
		{
			if(GetColOffset() < 1)
				m_flx.FixedCols = 1;
		}
		SetCell(lpcsz, flexcpText, nRow, 0);
		return true;
	}
	bool SetMergeCol(int nCol, BOOL bSet = true, bool bExpand = false)
	{
		if(!CheckConvertCol(nCol, bExpand))
			return false;
		if(bSet)
			m_flx.MergeCells = flexMergeFree;//flexMergeRestrictAll;
		
		/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		m_flx.SetMergeCol(nCol, bSet);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		m_flx.MergeCol(nCol) = bSet;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__ /// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		return true;
	}
	bool SetMergeRow(int nRow, BOOL bSet = true, bool bExpand = false)
	{
		if(bSet)
			m_flx.MergeCells = flexMergeFree;//flexMergeRestrictAll;
		if(nRow < 0)
			nRow = 0;
		else if(!CheckConvertRow(nRow, bExpand))
			return false;

		/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		m_flx.SetMergeRow(nRow, bSet);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		m_flx.MergeRow(nRow) = bSet;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__ /// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
		return true;
	}
			
	//---- end SHARE_PARAMS_USE_HIDE_INSTEAD_OF_INSERT_DEL
	///---Frank	4/15/05 CONFUS_OF_VARIABLE_NAME_DOUBLE			
	void SetRowHeaderValues(LPCSTR lpcszVal = NULL )
	{
		for(int nRow = GetRowOffset(); nRow < GetRows(); nRow++)
			SetCell(nRow, 0, lpcszVal);
	}	
	///---End CONFUS_OF_VARIABLE_NAME_DOUBLE			
	///Danice ADD_GRID_FORMAT_SETTING
	int SetSelection(int nSelMode)
	{
		int nOldMode=m_flx.SelectionMode;
		m_flx.SelectionMode=nSelMode;
		return nOldMode;
	}
	bool SetAllowSelection(bool bAllow=true)
	{
		bool bOldVal=m_flx.AllowSelection;
		m_flx.AllowSelection=bAllow;
		return bOldVal;
	}
	int SetOutlineBar(int nOutlineBar)
	{
		int nOldVal=m_flx.OutlineBar;
		m_flx.OutlineBar=nOutlineBar;
		return nOldVal;
	}
	int SetGridLines(int nGridLines)
	{
		int nOldVal=m_flx.GridLines;
		m_flx.GridLines=nGridLines;
		return nOldVal;
	}
	///DG ENABLE_SCROLLBARS_SETTINGS : for fb filter
	int SetScrollBars(int nScrollBars)
	{
		int nOldVal=m_flx.ScrollBars;
		m_flx.ScrollBars=nScrollBars;
		return nOldVal;
	}
	///end ADD_GRID_FORMAT_SETTING
	///------Frank 	7/4/05 SET_GRID_SORT_AND_EDITABLE
	int SetExplorerBar(int nExplorerBar )
	{
		int nOldVal=m_flx.ExplorerBar;
		m_flx.ExplorerBar=nExplorerBar;
		return nOldVal;		
	}
	int SetEditable(int nEditable = flexEDNone)
	{
		int nOldVal=m_flx.Editable;
		m_flx.Editable = nEditable;
		return nOldVal;		
	}
	///------End SET_GRID_SORT_AND_EDITABLE
	bool 	InsertRow(bool bNoSelAddToEnd = true)
	{
		if( m_flx.Row < 1 )	//If no select row
			if(bNoSelAddToEnd)
				m_flx.Rows += 1;
			else
				return false;
		else
			m_flx.AddItem("", m_flx.Row);
		return true;
	}
	///------Frank 6/24/05 DELETE_SPECIAL_ROW
	/*
	bool 	DeleteRow()
	{
		if( m_flx.Row < 1 )	//No row exist, return
			return FALSE;
		m_flx.RemoveItem(m_flx.Row);
		return TRUE;
	}
	*/
	bool 	DeleteRow(int nRow= -1)
	{
		if(nRow == -1) //If default, delete the seleted row
			nRow = m_flx.Row;
		
		///Iris 7/13/05 cannot use 1 here since the first row number will be diff when have col header or not
		//if(nRow< 1 || !IsInGrid(nRow, 0) )	//No row exist, return
		if(nRow < m_flx.FixedRows || !IsInGrid(nRow, 0) )
			return FALSE;
		
		m_flx.RemoveItem(nRow);
		return TRUE;
	}
	///------End DELETE_SPECIAL_ROW

	///------ Folger 05/26/10 ORG-120 DATA_DISPLAY_DIALOG_IMPROVEMENT
	#define		GET_COLUMN_POSITION_AND_NUMBER_COLUMNS(_nCol, _nCols) \
				if ( _nCol < 0 ) \
					_nCol = m_flx.Col; \
				\
				int		_nCols = m_flx.Cols; \
				if ( _nCol < 0 || _nCol >= _nCols ) \
					return FALSE;

	BOOL	DeleteCol(int nCol = -1)
	{
		GET_COLUMN_POSITION_AND_NUMBER_COLUMNS(nCol, nCols)
		
		SetColPosition(nCol, nCols - 1);
		m_flx.Cols = nCols - 1;
		return TRUE;
	}

	BOOL	InsertCol(int nCol = -1)
	{
		GET_COLUMN_POSITION_AND_NUMBER_COLUMNS(nCol, nCols)

		m_flx.Cols = nCols + 1;
		SetColPosition(nCols, nCol);
		return TRUE;
	}

	BOOL	SetColPosition(int nCol, int nPos)
	{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.SetColPosition(nCol, nPos);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.ColPosition(nCol) = nPos;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	}
	///------ End DATA_DISPLAY_DIALOG_IMPROVEMENT	
	
	BOOL 	SetGridFont(int iFont)	
	{
		int iFontSize;
		m_flx.FontName = GetFontName(iFont, &iFontSize);
		return TRUE;
	}
	void 	SetOwnerDraw(int iOwnerDrawSettings = flexODNone) {m_flx.OwnerDraw = iOwnerDrawSettings;}
	void	SetFinishEditing(bool bFinish = true) {m_flx.FinishEditing(bFinish);}
	///END ADD_SOME_ACCESS_FUNCTION
	
	// nx, ny in screen pixels
	// return false if not inside grid data area
	bool FindCell(int nx, int ny, int& nRow, int& nCol)
	{
		if(nx < 0 || ny < 0) // from keyboard
			return false;
		ScreenToClient(nx, ny);
		for(nCol = m_flx.LeftCol; nCol <= m_flx.RightCol; nCol++)
		{
			for(nRow = m_flx.TopRow; nRow <= m_flx.BottomRow; nRow++)
			{
				if(isInCell(nx, ny, nRow, nCol))
					return true;
			}
		}
		return false;
	}
	// return row number if found otherwise return -1
	///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION	
	///Add one argument of start row to find .
	//int FindRow(LPCSTR lpcszRowText, int nCol = 0, bool bCaseSensitive = false, bool bFullmatch = true)
	int FindRow(LPCSTR lpcszRowText, int nCol = 0, bool bCaseSensitive = false, bool bFullmatch = true, int nStartRow = -1)
	{
		/*
		for(int nRow = m_flx.FixedRows; nRow < m_flx.Rows; nRow++)
		{
			string strTemp = m_flx.Cell(flexcpText, nRow, nCol);
			if(bCaseSensitive && strTemp.Compare(lpcszRowText) == 0)
				return nRow;
			if(!bCaseSensitive && strTemp.CompareNoCase(lpcszRowText) == 0)
				return nRow;
		}
		*/
		///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION	
		if( nStartRow<0 )
			nStartRow =  m_flx.FixedRows;
		return m_flx.FindRow(lpcszRowText, nStartRow, nCol, bCaseSensitive, bFullmatch);
		//return m_flx.FindRow(lpcszRowText, m_flx.FixedRows, nCol, bCaseSensitive, bFullmatch);
		///End   REMEMBER_LAST_USE_FUNCTION	
	}
	//---- CPY 5/24/07 XF_INFO_NEED_FASTER_LOADING added vnInfo
	/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	/*
	DWORD GetRowData(int nRow)
	{
		DWORD dw = GetRowData(nRow);
		return dw;
	}
	///Jasmine 06/14/07 SET_CELL_STATE
	bool SetRowData(int nRow, DWORD dw)
	{
		SetRowData(nRow, dw);
		return true;
	}
	*/
	/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	///End SET_CELL_STATE
	//----
		
	int FindRow(DWORD dwData)
	{
		int nRowRet = m_flx.FindRow(dwData, m_flx.FixedRows, -1);
		if(nRowRet < 0)
		{
			for(int nRow = m_flx.FixedRows; nRow < m_flx.Rows; nRow++)
			{
				/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
				//DWORD dw = m_flx.RowData(nRow);
				DWORD dw = GetRowData(nRow);
				/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
				//printf("%d: %d\n", nRow, dw);
				if(dw == dwData)
					return nRow;
			}
		}
		return nRowRet;
	}		
	// return false if not selected
	// this function is used to obtained screen location of selected cell
	bool GetSelCell(int& nx, int& ny, int& nRow, int& nCol)
	{
		bool bRet = false;
		RECT rect;
		if(m_flx.Row >= 0 && m_flx.Col >= 0)
		{
			nRow = m_flx.Row;
			nCol = m_flx.Col;
			getCellRect(nRow, nCol, rect);
			bRet = true;
		}
		else
		{
			getCellRect(m_flx.TopRow, m_flx.LeftCol, rect);
			nRow = -1;
			nCol = -1;
		}
		nx = RECT_X(rect); nx = XTwipsToPixels(nx);
		ny = RECT_Y(rect); ny = YTwipsToPixels(ny);
		ClientToScreen(nx, ny);
		return bRet;
	}
	/////////////////////////////////////////////
	/////////////////////////////////////////////
	// return false if same location as last call
	bool GetMouseCell(int& nRow, int& nCol)
	{
		nRow = m_flx.MouseRow;
		nCol = m_flx.MouseCol;
		if(nRow == m_nLastRow && nCol == m_nLastCol)
			return false;

		m_nLastRow = nRow;
		m_nLastCol = nCol;
		return true;
	}
	bool GetMousePixel(float X, float Y, int& nRow, int& nCol, int& nx, int& ny)
	{
		nRow = m_flx.MouseRow;
		nCol = m_flx.MouseCol;
		nx = XTwipsToPixels(X);
		ny = YTwipsToPixels(Y);
		ClientToScreen(nx, ny);
		if(nRow < 0 || nCol < 0)
			return false;
		return true;
	}
	///Sophy 11/12/2008 SUPPORT_CONTEXT_MENU_COMMAND_TO_UPDATE_PARAM_GRID_CONTROL
	bool IsMouseOnHeader()
	{
		int nRow, nCol;
		GetMouseCell( nRow, nCol );
		
		if( nRow >= 0 && nRow < GetRowOffset() || nCol >= 0 && nCol < GetColOffset() )
			return true;
		
		return false
	}
	///end SUPPORT_CONTEXT_MENU_COMMAND_TO_UPDATE_PARAM_GRID_CONTROL
	//for given pixel location, find best interpretation on grid, nx and ny both [in] and [out]
	// if ny/nx < 0, then we will need to look at grid Current position for location info
	bool ConvertPixelLocation(int& nRow, int& nCol, int& nx, int& ny)
	{
		// for now, only consider
		return false;
	}	
	
	/// Iris 5/07/2008 ADD_CLASS_FOR_COL_LIST
	////Alternate background color with [0] as the first row to use shading
	//vnGroupBegs[0] > 0 like 4
	//vnGroupBegs[1] might be 8
	
	bool ShowAlternateGroups(const vector<int> &vnGroupBegins)
    { 
    	/// Iris 5/17/2008 	Vinden's logic is too complex so rewrite. Not test since not second group now, m_pNLParamsMngr->GetGroupingRowsBegin always return 0.
    	/*
		int nRows=GetNumRows();
		int nCols=GetNumCols();
			
	    vector<int> vnGroup;
	    int  nSum=0;//use to count the rows which have been add to vnGroup
	    int nSize=vnGroupBegs.GetSize( );
	 	for(int ii=0;ii<nSize;ii++)
	 	{
	 		if(vnGroupBegs[ii]+1<=nRows)
	 		{
	 			if(ii==0)
	 			   vnGroup.Add(vnGroupBegs[ii]);
	 			else
	 			   vnGroup.Add(vnGroupBegs[ii]-vnGroupBegs[ii-1]);
	 			nSum+=vnGroup[ii];
	 		}
	 		else
	 			break;
	 	}
	 	if(nSum<nRows)
	 		vnGroup.Add(nRows-nSum);
	    
	 	int nGroups=vnGroup.GetSize();
	    int nRowIndex=GetRowOffset();
		for(int nGroup=0;nGroup<nGroups;nGroup++)
		{
			uint nColor=(0==nGroup%2)?COLOR_WHITE : RGB(230,230,230);
			
			int nNumOfOneGroup=vnGroup[nGroup];
			int nNumRows=(nRows>nNumOfOneGroup)?nNumOfOneGroup:nRows;
			
			for(int ii=0;ii<nNumRows;ii++)
			{
				for(int nCol=0;nCol<nCols;nCol++)
					SetCellProperty(flexcpBackColor, nColor, nRowIndex, nCol);
				nRowIndex++;
			}
		}  
		*/
	    int 	nRowIndex = GetRowOffset();
	    int		nRows = GetNumRows();
	    int		nCols = GetNumCols();
	    
		vnGroupBegins.InsertAt(0, 0); // vnGroupBegins begin from the second group, because the first group always begin from 0
		///Sophy 15/7/2008 FIX_RUNTIME_ERROR_WHEN_FIT_WITH_MULTIPLE_DATASETS
		//for(int nGroup = 0; nGroup < vnGroupBegins.GetSize() + 1; nGroup++)
		int nSize = vnGroupBegins.GetSize();
		for(int nGroup = 0; nGroup < nSize; nGroup++)
		///end FIX_RUNTIME_ERROR_WHEN_FIT_WITH_MULTIPLE_DATASETS
		{
			uint 	nColor=(0==nGroup%2)?COLOR_WHITE : RGB(230,230,230);
			///Sophy 15/7/2008 FIX_RUNTIME_ERROR_WHEN_FIT_WITH_MULTIPLE_DATASETS
			//int 	nNumOfOneGroup = vnGroupBegins[nGroup+1] - vnGroupBegins[nGroup] - 1;
			//if( nRowIndex + nNumOfOneGroup > nRows )
				//nNumOfOneGroup = nRows - nRowIndex;
			int 	nNumOfOneGroup;
			if( nGroup < nSize - 1 )
				nNumOfOneGroup = vnGroupBegins[nGroup+1] - vnGroupBegins[nGroup];
			else
				nNumOfOneGroup = nRows - nRowIndex + 1;
			///end FIX_RUNTIME_ERROR_WHEN_FIT_WITH_MULTIPLE_DATASETS
			
			/// Hong 07/17/09 QA80-11468 IMPROVE_NLFIT_PARAMS_GRID_UPDATE_SPEED
			/*
			for(int ii=0; ii < nNumOfOneGroup; ii++)
			{
				for(int nCol = 0; nCol < GetNumCols(); nCol++)
					SetCellProperty(flexcpBackColor, nColor, nRowIndex, nCol);
				nRowIndex++;
			}
			*/
			int			nR1 = nRowIndex, nR2 = nR1 + nNumOfOneGroup - 1;
			int			nC1 = 0, nC2 = nC1 + nCols - 1;
			SetCellProperty(flexcpBackColor, nColor, nR1, nC1, &nR2, &nC2);
			nRowIndex = nR2 + 1;
			/// end IMPROVE_NLFIT_PARAMS_GRID_UPDATE_SPEED
		}		
		return true;
    }
    
	bool ShowRows(vector<bool>&vbShows)
	{
		int nRows=GetNumRows();
		if( vbShows.GetSize() >nRows)
		{
			vbShows.SetSize(nRows);
		}
		for(int nn = 0; nn < vbShows.GetSize(); nn++)
		{
			int		nRow = GetRowOffset() + nn;
			bool	bHide = !vbShows[nn];
			if( !HideRow(nRow, bHide) )
				return false;
		}
		return true;
	}
	
	bool GetRowsHide(vector<int> &vnHides)
	{
		vnHides.SetSize(0);
		if(GetRows() <= GetRowOffset())
		{
			return false;// gird is empty
		}
		
		/// Iris 10/28/2008 v8.0962 QA80-12401-P2 FIX_SHOW_LAST_HIDDEN_ROW_AFTER_QUICK_SET_IF_REPLICA
		//for( int nRow = GetRowOffset(); nRow < GetNumRows(); nRow++)
		for( int nRow = GetRowOffset(); nRow < GetRows(); nRow++)
		///end FIX_SHOW_LAST_HIDDEN_ROW_AFTER_QUICK_SET_IF_REPLICA
		{
			vnHides.Add( IsRowHidden(nRow) );
		}
		return true;
	}
	
	bool ShowCols(vector<bool>& vbShows)
	{
		int	nCols =GetNumCols();
		if( vbShows.GetSize() > nCols )
		{
			vbShows.SetSize(nCols);
		}
		
		for(int nn = 0; nn < vbShows.GetSize(); nn++)
		{
			int		nCol = GetColOffset() + nn;
			bool	bHide = !vbShows[nn];  //CPY 5/11/08 was bHide = vbShows[nn] which is obviously wrong
			if( !HideCol(nCol, bHide) )
				return false;
		}
		return true;
	}
	///end ADD_CLASS_FOR_COL_LIST
	
	bool HideRow(int nRow = -1, bool bHide = true)
	{
		if(nRow < 0) // to all
		{
			for(int ii = 0; ii < m_flx.Rows; ii++)
				SetIsRowHidden(ii, bHide);
			
			return true;
		}
		if(nRow >= m_flx.Rows)
			return false;

		SetIsRowHidden(nRow, bHide);
		return true;
	}
	bool HideCol(int nCol = -1, bool bHide = true)
	{
		if(nCol < 0) // to all
		{
			for(int ii = 0; ii < m_flx.Cols; ii++)
				SetIsColHidden(ii, bHide);
			
			return true;
		}
		if(nCol >= m_flx.Cols)
			return false;

		SetIsColHidden(nCol, bHide);
		return true;
	}
	bool IsColHidden(int nCol)
	{
		if(nCol < 0 || nCol >= m_flx.Cols)
			return false;
		
		return GetIsColHidden(nCol);
	}
	///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION
	bool IsRowHidden(int nRow)
	{
		if(nRow < 0 || nRow >= m_flx.Rows)
			return false;
		
		return GetIsRowHidden(nRow);
	}
	///End  REMEMBER_LAST_USE_FUNCTION
	bool IsColHeadingRow(int nRow)
	{
		return (nRow < m_flx.FixedRows)? true:false;
	}
	bool IsInGrid(int nRow, int nCol)
	{
		if(nRow < 0 || nRow >= m_flx.Rows)
			return false;
		if(nCol < 0 || nCol >= m_flx.Cols)
			return false;
		return true;
	}
	int GetRowRange(int& nRow1, int& nRow2)
	{
		nRow1 = m_flx.FixedRows;
		nRow2 = m_flx.Rows-1;
		return m_flx.Rows;
	}
	bool SetCheck(int nRow, int nCol, bool bCheck)
	{
		_DBINT3("Enter SetCheck", nRow, nCol, GetCheck(nRow, nCol));
		if(!IsInGrid(nRow, nCol))
			return false;
		SetCell(bCheck? flexChecked: flexUnchecked, flexcpChecked, nRow, nCol);
		_DBINT3("Exit SetCheck", nRow, nCol, GetCheck(nRow, nCol));
		return true;
	}		
	bool GetCheck(int nRow, int nCol)
	{
		if(!IsInGrid(nRow, nCol))
			return false;
		
		int nVal = GetCell(flexcpChecked, nRow, nCol);
		bool bCheck = flexUnchecked == nVal? 0:1;
		return bCheck;
	}		
	DWORD GetCellData(int nRow, int nCol)
	{
		if(!IsInGrid(nRow, nCol))
			return 0;
		
		DWORD dw = GetCell(flexcpData, nRow, nCol);
		return dw;
	}
	bool SetCellData(int nRow, int nCol, DWORD dwData)
	{
		if(!IsInGrid(nRow, nCol))
			return false;
		SetCell(dwData, flexcpData, nRow, nCol);
		return true;
	}
	string GetCell(int nRow, int nCol)
	{
		string strRet;
		if(!IsInGrid(nRow, nCol))
			return strRet;
		//---- CPY 11/12/04 SHARE_PARAMS_USE_HIDE_INSTEAD_OF_INSERT_DEL
		//int nVal = m_flx.Cell(flexcpChecked, nRow, nCol);// cannot use COM in == test directly
		//if(nVal != flexNoCheckbox)
		int nVal;
		if(IsCheckBoxCell(nRow, nCol, &nVal))
			strRet = flexChecked == nVal? "1" : "0";
		else
		//----		
			strRet = GetCell(flexcpText, nRow, nCol);
		return strRet;
	}
	//---- CPY 5/4/08 QA70-11504 DIRECT_VC_SET_CELLS
	bool SetCells(const vector<string>& vs, int nRowCol, bool bCol=true)
	{
		Control* pCntrl = GetControl();
		HWND hGrid = pCntrl->GetSafeHwnd();
		HWND hWnd = GetDlgSafeHwnd();
		return octe_set_cells(hWnd, hGrid, &vs, nRowCol, bCol);
	}

	///------ Folger 07/12/10 ORG-515-P1 COPY_PASTE_WHOLE_COLUMN_IN_NLFIT_SHOULD_ONLY_HANDLE_VISIBLE
	BOOL	GetRowsShow(vector<int>& vn, BOOL bIncludeOffset = FALSE)
	{
		BOOL	bRet = octe_get_rows_show(GetDlgSafeHwnd(), GetControl()->GetSafeHwnd(), &vn);
		if ( !bIncludeOffset )
		{
			vn -= GetRowOffset();
			while ( vn.GetSize() > 0 && vn[0] < 0 )
				vn.RemoveAt(0);
		}
		return bRet;
	}

	BOOL	GetColsShow(vector<int>& vn, BOOL bIncludeOffset = FALSE)
	{
		BOOL	bRet = octe_get_cols_show(GetDlgSafeHwnd(), GetControl()->GetSafeHwnd(), &vn);
		if ( !bIncludeOffset )
		{
			vn -= GetColOffset();
			while ( vn.GetSize() > 0 && vn[0] < 0 )
				vn.RemoveAt(0);
		}
		return bRet;
	}
	///------ End COPY_PASTE_WHOLE_COLUMN_IN_NLFIT_SHOULD_ONLY_HANDLE_VISIBLE

	/*
	//alternative code that loops in OC
	// will be used for Testing only
	bool SetCol(const vector<string>& vs, int nCol)
	{
		for(int ii = m_flx.FixedRows; ii < m_flx.Rows; ii++)
		{
			int jj = ii - m_flx.FixedRows;
			if(jj >= vs.GetSize())
				break;
			SetCell(ii, nCol, vs[jj]);
		}
		return true;
	}*/
	bool CheckExpandRows(int nLastDataRow)
	{
		int nRow = nLastDataRow;
		
		return CheckConvertRow(nRow, true);
	}
	//---- end DIRECT_VC_SET_CELLS
	bool SetCell(int nRow, int nCol, const string& str)
	{
		if(!IsInGrid(nRow, nCol))
			return false;
					
		//---- CPY 11/12/04 SHARE_PARAMS_USE_HIDE_INSTEAD_OF_INSERT_DEL
		//int nVal = m_flx.Cell(flexcpChecked, nRow, nCol);// cannot use COM in == test directly
		//if(nVal != flexNoCheckbox)
		if(IsCheckBoxCell(nRow, nCol))
			///m_flx.Cell(flexcpChecked, nRow, nCol) = atoi(str) > 0? flexChecked: flexUnchecked;
			SetCheck(nRow, nCol, (atoi(str) > 0));
		else
		//----		
		SetCell(str, flexcpText, nRow, nCol);
		return true;
	}
	bool SetCell(int nRow, int nCol, int nVal)
	{
		string strTemp = nVal;
		return SetCell(nRow, nCol, strTemp);
	}
	///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION
	bool SetCell(int nRow, int nCol, double dVal, string strFormat = "*")
	{
		string strTemp = ftoa(dVal,strFormat );
		return SetCell(nRow, nCol, strTemp);
	}
	///End  REMEMBER_LAST_USE_FUNCTION
	/// TD 3-23-04 QA70-6053 PICTURE_IN_OC
	/// TD ML 04-13-2010 QA85-15312 ICON_OVERLAYS_IN_GRIDCONTROL
	//bool SetCellIcon(int nRow, int nCol, int nResID, int nModule, BOOL bSmall = TRUE)
	bool SetCellIcon(int nRow, int nCol, int nResID, int nModule, BOOL bSmall = TRUE, int nOverlayResId = 0)
	/// end ICON_OVERLAYS_IN_GRIDCONTROL
	{
		bool bRet = false; 
		
		HINSTANCE hinstOrg =  GetModuleHandle(nModule);
		if(!hinstOrg)
			return bRet;
		
		HICON hIcon = NULL;
		{
			char *lpcszID = (char*)nResID;
			int nSize = bSmall ? 16 : 0;
			/// TD ML 04-13-2010 QA85-15312 ICON_OVERLAYS_IN_GRIDCONTROL
			//hIcon = LoadImage(hinstOrg, lpcszID, IMAGE_ICON, nSize, nSize, LR_DEFAULTCOLOR);
			HICON hIconBase = LoadImage(hinstOrg, lpcszID, IMAGE_ICON, nSize, nSize, LR_DEFAULTCOLOR);
			BOOL bUsingOverlayedIcon = FALSE;
			if(nOverlayResId > 0)
			{
				char *lpcszIDOverLay = (char*)nOverlayResId;
				HICON hIconOverLay = LoadImage(hinstOrg, lpcszIDOverLay, IMAGE_ICON, nSize, nSize, LR_DEFAULTCOLOR);
				if(hIconOverLay)
				{
					bUsingOverlayedIcon = TRUE;
					hIcon = okutil_CreateOvelayedIcon(hIconBase, hIconOverLay, bSmall ? 16 : 32);  //Note when bSmall is false, overlayed icon size is assumed to be 32
				}
			}
			if(!bUsingOverlayedIcon)
			{
				hIcon = hIconBase;
			}
			/// end ICON_OVERLAYS_IN_GRIDCONTROL

		}
		if(!hIcon)
			return bRet;;
		
		PictureHolder ph;
		
		if(ph.CreateFromIcon(hIcon, TRUE))
			bRet = SetCellPicture(nRow, nCol, ph);
		
		return bRet;
	}
	//------- CPY TD 11-30-04 QA70-6582 ADD_COMBO_IMAGE_TO_RIGHT_OF_EDIT_CELL
	bool SetCellBitmap(int nRow, int nCol, int nResID, int nModule, int nAlignment = DISPLAY_LEFT)
	{
		HINSTANCE hInst = NULL;
		if(nModule)
		{
			hInst = GetModuleHandle(nModule);
			if(!hInst)
				return false;
		}
		char *lpcszID = (char*)nResID;
		HBITMAP hBmp = LoadBitmap(hInst, lpcszID);
		PictureHolder pict;
		
		if(pict.CreateFromBitmap(hBmp, TRUE))
		{
			SetCellPicture(nRow, nCol, pict);
			SetCell(GetVsFlexAlignment(nAlignment), flexcpPictureAlignment, nRow, nCol);
			return true;
		}
		return false;
	}
	int GetVsFlexAlignment(int nDisplayJustification)
	{
		int  nAligns[NUM_EDIT_COL_ALIGNMENTS] = {flexPicAlignLeftCenter, flexPicAlignCenterCenter, flexPicAlignRightCenter};
		if(nDisplayJustification >= 0 && nDisplayJustification < NUM_EDIT_COL_ALIGNMENTS)
			return nAligns[nDisplayJustification];
		
		return flexPicAlignRightCenter;
	}
	//-------
	bool SetCellPicture(int nRow, int nCol, PictureHolder &pict)
	{
		_VARIANT vtPic;
		vtPic = pict;
		SetCell(vtPic, flexcpPicture, nRow, nCol);
		return TRUE;
	}
	/// end PICTURE_IN_OC
	bool SetBold(int nRow, int nCol, bool bSet = true) {return SetCellState(nRow, nCol, bSet);}
	bool SetItalic(int nRow, int nCol, bool bSet = true) {return SetCellState(nRow, nCol, bSet, flexcpFontItalic);}
	bool IsItalic(int nRow, int nCol) {return IsCellState(nRow, nCol, flexcpFontItalic);}
	bool IsBold(int nRow, int nCol) {return IsCellState(nRow, nCol);}
	// nCol = -1 to set all cols, return last state of last col
	// nRow = -1 to set all rows, reutrn last state of last row
	// otherwise return last state of the specified cell
	bool SetCellState(int nRow, int nCol, bool bSet = true, int nStateType = flexcpFontBold)
	{
		if(nCol < 0)
		{
			bool bRet = false;
			for(int ii = 0; ii < m_flx.Cols; ii++)
				bRet = SetCellState(nRow, ii, bSet, nStateType);
			
			return bRet;
		}
		if(nRow < 0)
		{
			bool bRet = false;
			for(int ii = 0; ii < m_flx.Rows; ii++)
				bRet = SetCellState(ii, nCol, bSet, nStateType);
			
			return bRet;
		}
		if(!IsInGrid(nRow, nCol))
			return false;
		bool bWasBold = GetCell(nStateType, nRow, nCol);
		SetCell(bSet, nStateType, nRow, nCol);
		return bWasBold;
	}
	bool IsCellState(int nRow, int nCol, int nStateType = flexcpFontBold)
	{
		if(!IsInGrid(nRow, nCol))
			return false;
		bool bIsBold = GetCell(nStateType, nRow, nCol);
		return bIsBold;
	}
	bool IsEnable() 
	{
		bool bEnable = m_flx.Enabled;
		return bEnable;
	}
	bool SetEnable(bool bSet = true)
	{
		bool bOldVal = IsEnable();
		m_flx.Enabled = bSet;
		return bOldVal;
	}
	/*
	void SetColHeading(int nCol, LPCSTR lpcszText)
	{
		if(nCol >= 0)
			//m_flx.Cell(flexcpText, 0, nCol) = lpcszText;
			m_flx.TextMatrix(0, nCol) = lpcszText;
	}
	*/
	///Danice ADD_CELL_COLOR_CONTROL
	void SetCellColor(int nRow, int nCol, uint nForeColor, uint nBackColor=-1)
	{
		SetCell(nForeColor, flexcpForeColor, nRow, nCol);
		if(-1 != nBackColor)
			SetCell(nBackColor, flexcpBackColor, nRow, nCol);
	}
	///---Sim 06-02-2009 QA80-4584 EXTRACT_WKS_SUPPORT_AUTO_UPDATE
#ifdef EXTRACT_WKS_SUPPORT_AUTO_UPDATE
	void GetCellColor(int nRow, int nCol, uint *pnForeColor = NULL, uint *pnBackColor = NULL)
	{
		if ( pnForeColor )
			*pnForeColor = GetCell(flexcpForeColor, nRow, nCol);
		if ( pnBackColor )
			*pnBackColor = GetCell(flexcpBackColor, nRow, nCol);
	}
#endif // EXTRACT_WKS_SUPPORT_AUTO_UPDATE	
	///---END QA80-4584 EXTRACT_WKS_SUPPORT_AUTO_UPDATE
	
    /// Iris 11/16/05  
	//SetCellProperty(0, 0, FlexcpAlignment, JUSTIFICATION_MULTILINE): set the cell support multiple line
	//see vsFlex Help to get more propertySettings and more format
	///Vinden 8/5/2008 v8.0857 MOVE_FUNCTION_FROM_GRIDLISTCONTROL_TO_GRIDCONTROL
	/// Hong 07/17/09 QA80-11468 IMPROVE_NLFIT_PARAMS_GRID_UPDATE_SPEED
	/*
	void SetCellProperty(int nPropertySettings, int nFormat, int nRow = 0, int nCol = 0)
	{
		m_flx.Cell(nPropertySettings, nRow, nCol) = nFormat; //JUSTIFICATION_MULTILINE;

	}
	*/
	void SetCellProperty(int nPropertySettings, int nFormat, int nRow1 = 0, int nCol1 = 0, int* pnRow2 = NULL, int* pnCol2 = NULL)
	{
		// Hong, from ducoment of vsflex, "The default value for Row2 and Col2 is Row1 and Col1"
		int			nRow2 = pnRow2 ? *pnRow2 : nRow1;
		int			nCol2 = pnCol2 ? *pnCol2 : nCol1;
		SetCell(nFormat, nPropertySettings, nRow1, nCol1, nRow2, nCol2);
	}
	///End MOVE_FUNCTION_FROM_GRIDLISTCONTROL_TO_GRIDCONTROL
	///end ADD_CELL_COLOR_CONTROL
	
protected:
	 // assume format str in standard form, and we convert into new str with localization if needed
	int GetFormatStrAsArray(LPCSTR lpcszHeadings, vector<string>& vsHeadings, LPCSTR lpcszCategory = NULL, bool bCvtToLocal = true)
	{
		string strHeadings = lpcszHeadings;
		int nCount = strHeadings.GetTokens(vsHeadings, '|');
		if(!bCvtToLocal)
			return nCount;
		ASSERT(vsHeadings.GetSize() == nCount);
		for(int ii = 0; ii < nCount; ii++)
		{
			vsHeadings[ii] = _LC(vsHeadings[ii], lpcszCategory);
		}
		return nCount;
	}
	void SetFormatStrLocal(LPCSTR lpcszHeadings, LPCSTR lpcszCategory = NULL)
	{
		vector<string> vsHeadings;
		int nSize = GetFormatStrAsArray(lpcszHeadings, vsHeadings, lpcszCategory);
		ASSERT(vsHeadings.GetSize() == nSize);
		string strFormat;
		for(int ii = 0; ii < nSize; ii++)
		{
			if(ii > 0)
				strFormat += "|";
			strFormat += vsHeadings[ii];
		}
		m_flx.FormatString = strFormat;
	}

public:		//expose LoadHideCols & SaveHideCols
	
	void LoadHideCols(LPCSTR lpcszDlgName, LPCSTR lpcszValName, vector<byte>* pvbColsDefault = NULL) // from registry
	{
		m_strHideColsRegValName = lpcszValName;
		m_strHideColsRegDlgName = lpcszDlgName;
		vector<byte> vbCols;
		if(load_default_checkboxes(m_strHideColsRegDlgName, vbCols, m_strHideColsRegValName))
			SetHiddenCols(vbCols);
		else if(pvbColsDefault)
			SetHiddenCols(*pvbColsDefault);
	}
	void SaveHideCols() // to registry
	{
		if(m_strHideColsRegValName.IsEmpty() || m_strHideColsRegDlgName.IsEmpty())
			return;
		
		vector<byte> vbCols;
		GetHiddenCols(vbCols);
		save_default_checkboxes(m_strHideColsRegDlgName, vbCols, m_strHideColsRegValName);
	}
	
   //--- CPY 12/22/04 QA70-5890
protected:
	// bSkipLeafs = true, we only consider top level branch, all subbranch are not considered
	//bool IsBranchRow(int nRow, bool bSkipLeafs = true)	///DG 1/20/05 : argument name SkipLeafs is not right
	bool IsBranchRow(int nRow, bool bOnlyTopLevelIsBranch = true)
	{
		//--- CPY 6/14/07 SCRIPT_SAMPLE_DLG_SWITCHING_LOCATION_AUTOMATION_ERR
		int nRows = m_flx.Rows;
		if(nRow >= nRows)
		{
			printf("grid IsBranchRow asking for %d when total is only %d\n",nRow, nRows);
			return true; // not sure which way is better, caller shoudl really take care of this
		}
		//---
		int nRet = GetIsSubtotal(nRow);
		if(0 == nRet)
			return false;
		// for some reason, nRet is always -1
		int nLevel = GetRowOutlineLevel(nRow);
		if(bOnlyTopLevelIsBranch && nLevel > 0)
			return false;
		//_DBINT3("---------The nRow/branch/Level = ", nRow, nRet, nLevel)
		
		if( nRow +1 < m_flx.Rows )
		{
			int nLevel1 = GetRowOutlineLevel(nRow+1);
			//_DBINT("---------The Next Row Level = ", nLevel1)

			if( nLevel + 1 == nLevel1 )
				return true;
		}
		
		return false;
	}

	bool IsCheckBoxCell(int nRow, int nCol, int* pnVal = NULL)
	{
		int nVal = GetCell(flexcpChecked, nRow, nCol);// cannot use COM in == test directly
		if(nVal != flexNoCheckbox)
		{
			if(pnVal)
				*pnVal = nVal;
			return true;
		}
		
		return false;
	}
	
private:
	//---

	//--- CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP move all m_cntrl and m_wndDlg related code to base class from GridControl
public:
	//virtual 
	int	GetPanelHeight(bool bGetMin = false)
	{
		return 50;
	}
	//virtual 
	int GetPanelWidth(bool bGetMin = false)
	{
		return 150;
	}
	//virtual 
	int GetMinHeight(bool bKeepFunctional = false) 
	{
		if(bKeepFunctional) // Min height that is still good to use the grid
			return YTwipsToPixels(m_nRowHeight * 4);
		
		return ResizeControl::GetMinHeight(bKeepFunctional);
	}
	//virtual 
	int GetMaxHeight(bool bKeepFunctional = false)
	{
		if(bKeepFunctional) // Min height that is still good to use the grid
			return YTwipsToPixels(m_nRowHeight * 6);
			
		return ResizeControl::GetMaxHeight(bKeepFunctional);
	}
	//---
	
	//----- CPY 12/20/04 GET_BASE_ROW_HEIGHT
	int GetBaseRowHeight(double dFactor = 1.0)
	{
		int nSingleLineRowHeight = 0.5 + m_nRowHeight * dFactor;
		return nSingleLineRowHeight;
	}
	//-----
private:
	string m_strHideColsRegValName;
	string m_strHideColsRegDlgName;
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
	// local helper functions
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
	
	// nx ny in Twips in client coordinates
	bool isInCell(int nx, int ny, int nRow, int nCol)
	{
		/// Hong 09/06/07 v8.0696 SHOULD_CHECK_IF_NO_CELL
		if ( m_flx.TopRow == m_flx.BottomRow && m_flx.LeftCol == m_flx.RightCol )
			return false;
		/// end SHOULD_CHECK_IF_NO_CELL
		RECT rect;
		if(!getCellRect(nRow, nCol, rect))
			return false;
		if(nx >= rect.left && nx <= rect.right && ny >= rect.top && ny <= rect.bottom)
			return true;
		
		return false;
	}
	bool	getCellRect(int nRow, int nCol, RECT& rect)
	{
		//if(nRow < 0 || nCol < 0)	///Jasmine 11/25/08 v8.0979 QA80-12304 SHOULD_ALSO_CHECK_HAS_ENOUGH_ROW_COL
		if( !IsInGrid(nRow, nCol) )
			return false;
	
		rect.left = GetCell(flexcpLeft, nRow, nCol);
		rect.top = 	GetCell(flexcpTop, nRow, nCol);
		rect.right = rect.left + GetCell(flexcpWidth, nRow, nCol);
		rect.bottom = rect.top + GetCell(flexcpHeight, nRow, nCol);
		return true;
	}
	
	/////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////
		
private:
	int	m_nLastRow;
	int m_nLastCol;
	bool m_bMouseDownToggleCheck; //CPY 5/20/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE
	//---------- SY 07/27/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	bool m_bReady;
protected:
	void SetReadyFlag(bool bReady) //CPY 9/1/05 SET_READY_FROM_BASE_CLASS_ONLY
	{
		m_bReady = bReady; 
	}
public:
	bool IsReady() { return m_bReady;}
	//void SetReady(bool bReady = true) {m_bReady = bReady;}	///DG 3/15/05 FB_SPEED_UP_LOADING_MECHANISM
	void SetReady(bool bReady = true, bool bRDBuffered = true)
	{
		m_bReady = bReady;
		if(m_bReady)
		{
			SetRedraw(bRDBuffered ? flexRDBuffered : flexRDDirect);
		}
		else
			SetRedraw(flexRDNone);
	}
	void SetRedraw(int nMode)
	{
		m_flx.Redraw = nMode;
	}
	void ResizeAllRows(int nExtraPixcels = 0);

private:
	//---------- end GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	
	int	toggleCheck(int nVal)
	{
		_DBINT("old check value = ", nVal)
		
		switch(nVal)
		{
		case flexChecked:
			return flexUnchecked;
		case flexUnchecked:
			return flexChecked;
		case flexTSChecked:
			return flexTSUnchecked;
		case flexTSUnchecked:
			return flexTSChecked;
		}
		ASSERT(FALSE);
		return flexTSGrayed;
	}
	
	void resizeAllCols(int nExtraPixcels = 8, int nColOffset = 0)
	{
		bool bAllColSameWidth = false;
		int nExtra = PixelsToTwips(nExtraPixcels);
		
		/// SY 07/28/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
		///	m_flx.AutoSize(0, m_flx.Cols - 1, bAllColSameWidth, nExtra);
		m_flx.AutoSizeMode = flexAutoSizeColWidth;//CPY 7/29/04
		m_flx.AutoSize(nColOffset, m_flx.Cols - 1, bAllColSameWidth, nExtra);
		/// end GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	}
	bool is_WindowJapanese()
	{
		int nCharSet;
		string str = get_system_font_name(GSFI_TYPE_DEFAULT, &nCharSet);
		if(SHIFTJIS_CHARSET == nCharSet)
			return true;
		
		/// ML 1/21/2004 QA70-5871 OLECONTROL_DLGINIT_RESOURCE_LANGUAGE
		// Check the system var for Japanese:
		double		resLang = 0;
		LT_get_var("@RL", &resLang);
		int			nresLang = nint(resLang);
		if (ORESLANG_JAPANESE == nresLang)
			return true;
		/// end OLECONTROL_DLGINIT_RESOURCE_LANGUAGE
		
		return false;
	}
public:	
	virtual string GetRuntimeClass()
	{
		return "GridControl";
	}
	void SetFont()
	{
		/// ML 2/2/2004 QA70-5871 SETTING_FONT_IN_GRIDCONTROL_ORIGINC_FOR_JAPANESE
		setFontLang();	 // old codes removed
		/// end SETTING_FONT_IN_GRIDCONTROL_ORIGINC_FOR_JAPANESE

		m_nFontSize = m_flx.CellFontSize;
		
		/// YuI 3/24/04 v7.5846 QA70-6118 NEW_DATA_SELECTOR_TOOL
		// this code prohibits calling SetFont twice during control life which is not nice
		// so I change code that m_nRowHeight does not get changed if SetFont has been called before
		//	m_nRowHeight= m_flx.RowHeight(0);
		if( 0 == m_nRowHeight )
			m_nRowHeight= GetRowHeight(0);
		/// end NEW_DATA_SELECTOR_TOOL
	}	
	virtual void ClearAll() 
	{
		m_flx.Rows = m_flx.FixedRows;
	}
	//OnAfterEdit call base method first 
	virtual void OnAfterEdit(int nRow, int nCol) 
	{
		_DBMEMBER("GridControl", "OnAfterEdit");
		_DBINT3("OnAfterEdit bToggleCheck [row:col] =", nRow, nCol, m_bMouseDownToggleCheck);
		
		m_bMouseDownToggleCheck = false;//---- CPY 5/20/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE

		/// Bill 07/15/2010 ORG-576-S1 MOVE_TO_NEXT_ROW_IF_USER_PRESS_ENTER
		if ( GetKeyState(VK_RETURN) < 0 && nRow + 1 < GetRows() )
			SelCell(nRow + 1, nCol);
		/// End MOVE_TO_NEXT_ROW_IF_USER_PRESS_ENTER
	}

	
	// OnBeforeMouseDown call base class method last	
	void OnBeforeMouseDown(short nButton, short nShift, float X, float Y, BOOL* pCancel)
	{
		_DBMEMBER("GridControl", "OnBeforeMouseDown");
		int iRow = m_flx.MouseRow;
		int iCol = m_flx.MouseCol;
		if(iRow < 0 || iCol < 0)
		{
			*pCancel = TRUE;
			return;
		}
		//---- CPY 5/20/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE
		//int nVal = m_flx.Cell(flexcpChecked, iRow, iCol);// cannot use COM in == test directly
		int nVal;
		_DBINT("------------------- OnBeforeMouseDown bToggleCheck = ", m_bMouseDownToggleCheck);
		if(m_bMouseDownToggleCheck && IsCheckBoxCell(iRow, iCol, &nVal))//nVal != flexNoCheckbox)
		{
			nVal = toggleCheck(nVal);
			SetCell(nVal, flexcpChecked, iRow, iCol);//bWasCheck? flexUnchecked : flexChecked;
			_DBINT3("calling OnAfterEdit from OnBeforeMouseDown [nR:nC] nNewCheck",iRow, iCol, nVal)
			
			OnAfterEdit(iRow, iCol);
		}
		m_bMouseDownToggleCheck = true;
		//---- end CPY 5/20/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE
	}
	
	//nMaxColSizeFactor = 0 will not consider max col width
	// nMaxColSizeFactor = 2 will set each col no bigger then 1/2 the width of the control width
	void ResizeCols(int nMaxColSizeFactor = 0, int nExtraPixcels = 8, int nColWidthMinPixcels = 0, int nColOffset = 0)
	{
		int nMaxColWidth = 0;
		
		if(nMaxColSizeFactor)
		{
			RECT rect;
			GetWindowRect(rect);
			nMaxColWidth = PixelsToTwips(RECT_WIDTH(rect)/(double)nMaxColSizeFactor);
		}
		m_flx.ColWidthMax = nMaxColWidth;
		
		if(nColWidthMinPixcels) ///---- CPY SY 07/28/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
			m_flx.ColWidthMin = PixelsToTwips(nColWidthMinPixcels); 	
		else if(nMaxColWidth)
			m_flx.ColWidthMin = PixelsToTwips(5); // ,min width

		resizeAllCols(nExtraPixcels, nColOffset);

	}
	// min col by row height as a factor, max col by screen width as a divider
	void ResizeCols(double dbMinColRowFactor, double dbMaxColDivScreen, int nExtraPixcels = 8, int nColWidthMinPixcels = 0, int nColOffset = 0)
	{
		///---- CPY SY 07/28/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
		//m_flx.ColWidthMin = 0.5 + m_nRowHeight * dbMinColRowFactor;
		if(nColWidthMinPixcels)
			m_flx.ColWidthMin = PixelsToTwips(nColWidthMinPixcels);
		else
			m_flx.ColWidthMin = 0.5 + m_nRowHeight * dbMinColRowFactor;
		///-----
		
		int nScreenW = PixelsToTwips(GetSystemMetrics(SM_CXSCREEN));
		m_flx.ColWidthMax = 0.5 + nScreenW /dbMaxColDivScreen;

		resizeAllCols(nExtraPixcels, nColOffset);
	}
	void ResizeCols(const vector<double>& vdColWidthPercent)
	{
		m_flx.ColWidthMin = PixelsToTwips(5);
		int nSetColNum = vdColWidthPercent.GetSize();
		for(int iCol=0; iCol<m_flx.Cols && iCol<nSetColNum; iCol++)
			SetColWidth(iCol, m_flx.ClientWidth * vdColWidthPercent[iCol]);
	}
	
	int XTwipsToPixels(int nx)	{return TwipsToPixels(nx);}
	int YTwipsToPixels(int ny)	{return TwipsToPixels(ny, false);}

	void	GridToDlgOffsets(int& dx, int &dy)
	{
		RECT rectGrid;
		GetRect(rectGrid);
	
		dx = rectGrid.left;
		dy = rectGrid.top;
	}
	bool	GetCellRect(int iRow, int iCol, RECT& rect, bool bCvtToFrame = true, bool bCvtToScree = false)
	{
		if(!getCellRect(iRow, iCol, rect))
			return false;
	
		rect.left = XTwipsToPixels(rect.left);
		rect.top = 	YTwipsToPixels(rect.top);
		rect.right = XTwipsToPixels(rect.right);
		rect.bottom = YTwipsToPixels(rect.bottom);
		InflateRect(&rect, -m_nHaldGridLineWidth, -m_nHaldGridLineWidth);
		
		if(bCvtToFrame) // convert
		{
			int dx, dy;
			GridToDlgOffsets(dx, dy);
			OffsetRect(&rect, dx, dy);
		}
		if(bCvtToScree)
		{
			ClientToScreen(rect);
		}
		return true;
	}
	void GetGridSize(int& nx, int& ny);	//--- CPY 7/29/04 FIT_LR_DLG_NOT_VISIBLE_DUE_TO_NEG_GRID_HEIGHT, moved to GetNBox.c

	void ClientToScreen(int &nx, int &ny, bool bCvtToFrame = true)
	{
		RECT rect;
		rect.left = rect.right = nx;
		rect.top = rect.bottom = ny;
		if(bCvtToFrame)
		{
			int dx, dy;
			GridToDlgOffsets(dx, dy);
			OffsetRect(&rect, dx, dy);
		}
		ClientToScreen(rect);
		nx = rect.left;
		ny = rect.top;
	}
	void ScreenToClient(int &nx, int &ny, bool bCvtToTwips = true, bool bCvtToFrame = true)
	{
		RECT rect;
		rect.left = rect.right = nx;
		rect.top = rect.bottom = ny;
		ScreenToClient(rect);
		if(bCvtToFrame)
		{
			int dx, dy;
			GridToDlgOffsets(dx, dy);
			OffsetRect(&rect, -dx, -dy);
		}		
		nx = rect.left;
		ny = rect.top;
		if(bCvtToTwips)
		{
			nx = PixelsToTwips(nx);
			ny = PixelsToTwips(ny, false);
		}
	}
	// nx ny in Twips in clint coordinates
	virtual void GetHiddenCols(vector<byte>& vbCols)
	{
		vbCols.SetSize(0);
		for(int nCol = 0; nCol < m_flx.Cols; nCol++)
		{
			vbCols.Add(IsColHidden(nCol));
		}
	}
	virtual void SetHiddenCols(const vector<byte>& vbCols, bool bDefault = true)
	{
		for(int nCol = 0; nCol < m_flx.Cols; nCol++)
		{
			bool bHide = bDefault;
			if(nCol < vbCols.GetSize())
				bHide = vbCols[nCol];
			HideCol(nCol, bHide);
		}
	}

	///------ Folger 06/10/10 ORG-120 DATA_DISPLAY_DIALOG_IMPROVEMENT
	BOOL	MoveItemDown(int nRow)
	{
		if ( nRow < GetRows() - 1 )
		{
			SetRowPosition(nRow, nRow + 1);
			m_flx.Row = nRow + 1;
			return TRUE;
		}
		return FALSE;
	}
	
	BOOL	MoveItemUp(int nRow)
	{
		if ( nRow > 0 )
		{
			SetRowPosition(nRow, nRow - 1);
			m_flx.Row = nRow - 1;
			return TRUE;
		}
		return FALSE;
	}

	BOOL		SetRowPosition(int nRow, int nPos)
	{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.SetRowPosition(nRow, nPos);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.RowPosition(nRow) = nPos;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	}
	///------ End DATA_DISPLAY_DIALOG_IMPROVEMENT
	
private:
	/// ML 2/2/2004 QA70-5871 SETTING_FONT_IN_GRIDCONTROL_ORIGINC_FOR_JAPANESE
	bool setFontLang()
	{
		// Check the system var for Japanese:
		double		rSF = 0;
		LT_get_var("@RLJ", &rSF);
		int			nSF = nint(rSF);
		
		if(is_WindowJapanese())
		{
			if (nSF & GCSETFONT_NOT_JAPANESE)
				return false;
			int nFontSize;
			//--- CPY 10/6/09 LT_CUSTOM_MENU_JUNK_J_MENU_NAMES_IN_GRID
			if(nSF & GCSETFONT_HARD_CODE)
			{
				m_flx.FontName = "Lucida Sans Unicode";
				nFontSize = 9;
			}
			else
			{
			//---			
				m_flx.FontName = GetFontName(ORIGIN_MENU_FONT,&nFontSize);
				if(nFontSize < 0) // convert to pt
				{
					double vv = - PixelsToTwips(nFontSize);
					vv = vv * 72.0 / 1440.0;
					nFontSize = 0.5 + vv;
				}
			}
			m_flx.FontSize = nFontSize;
		}
		else
		{
			if (nSF & GCSETFONT_NOT_OTHER_LANG)
				return false;
			
			/// TD 1-16-04 QA70-5824 v7.58100 SPLITTER_CONTROL_IN_DDK 
			string strFontName = FontName();
			if(!strFontName.IsEmpty())
			{
				m_flx.FontName = strFontName;
				m_flx.FontSize = FontSize();
			}
			/// end SPLITTER_CONTROL_IN_DDK 
		}
		return true;
	}
	/// end SETTING_FONT_IN_GRIDCONTROL_ORIGINC_FOR_JAPANESE
	
protected:
	/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	wxGirdInterface		m_flx;
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	Object		m_flx;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__ /// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	int			m_nRowHeight;
	int 		m_nFontSize;
	int			m_nHaldGridLineWidth;
	
	
	
/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
public:
	_VARIANT	GetCell(CellPropertySettings settings, int nRow, int nCol);
	
	void		SetCell(_VARIANT var, CellPropertySettings settings, int nRow, int nCol);
	void		SetCell(_VARIANT var, CellPropertySettings settings, int nRow1, int nCol1, int nRow2, int nCol2);
	
	string		GetTextMatrix(int nRow, int nCol);
	void		SetTextMatrix(int nRow, int nCol, LPCSTR lpszVal);
	
	_VARIANT	GetRowData(int nRow);
	void		SetRowData(int nRow, _VARIANT var);

	void		SetColComboList(long Col, string strCombo);
	void		SetComboIndex(long index);
	long		GetComboIndex();
	//---	Jacky 09/03/10 IMPLEMENT_WXGRID
	//void		SetComboItem(long index, string strVal);
	//---	end IMPLEMENT_WXGRID
	string		GetComboItem(long index);

	bool		GetIsSelected(long Row);
	void		SetIsSelected(long Row, bool bSel);

	int			GetColDataType(long Col);
	void		SetColDataType(long Col, int nType);

	bool		GetIsSubtotal(long Row);
	void		SetIsSubtotal(long Row, bool bVal);
	long		GetRowOutlineLevel(long Row);
	void		SetRowOutlineLevel(long Row, long nLevel);

	long		GetSelectedRow(long index);

	void		SetColWidth(long Col, int nWidth);
	int			GetColWidth(long Col);
	int			GetRowHeight(long Row);
	void		SetRowHeight(long Row, int nHeight);

	bool		GetIsRowHidden(long Row);
	void		SetIsRowHidden(long Row, bool bVal);
	bool		GetIsColHidden(long Col);
	void		SetIsColHidden(long Col, bool bVal);

	int			GetColAlignment(long Col);
	int			GetFixedAlignment(long Col);
/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID

	/// Kenny 04/27/2010 QA80-15357 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	void		SetFixedAlignment(long Col, int nMode);

	int			GetColFormat(long Col);
	void		SetColFormat(long Col, string strFormat);
	/// End QA80-15357 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
	
	/// Hong 05/27/10 ORG-131 MATRIX_ADD_GENERAL_LABEL_SUPPORT_AS_WKSHEET
	void		SetResizeMode(int nMode);
	int			GetResizeMode();
	/// end MATRIX_ADD_GENERAL_LABEL_SUPPORT_AS_WKSHEET
};



// a vsFlexGrid that is used like a list control
class GridListControl : public GridControl
{
public:
	//void Init(int nID, WndContainer& dlg)	///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
	void Init(int nID, WndContainer& dlg, WndContainer* pParentDlg = NULL)
	{
		//GridControl::Init(nID, dlg); ///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
		GridControl::Init(nID, dlg, pParentDlg);
		
		m_flx.SelectionMode = flexSelectionByRow;
		m_flx.AllowSelection = false;
		//m_flx.ExplorerBar = flexExSortShow;
		m_flx.AllowUserResizing = flexResizeColumns;
	}
	// return false if no change, otherwise check if sel consistent, otherwise set to specified row/col
	bool CheckSelRow(int nRow, bool bOnlyInsideGrid = true)
	{
		if(bOnlyInsideGrid && nRow < 0)
			return false;
		
		if(m_flx.SelectionMode == flexSelectionListBox)
		{
			//--- CPY 8/19/03
			if(SHIFT_DOWN || CNTRL_DOWN)
				return false;
			//---
			int nNumSelected = m_flx.SelectedRows;

			for(int ii = 0; ii < nNumSelected; ii++)
			{
				if( nRow == GetSelectedRow(ii) )
					return false;
			}
		}
		else
		{
			if(m_flx.Row == nRow)
				return false;
		}
		
		m_flx.Row = nRow;
		return true;
	}
	
	/// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB
	///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
	//bool AddSimpleTreeNodes(TreeNode& tr, int nStopLevel=-1, LPCSTR lpcszStopAttribute=NULL, bool bCollapseAll = true)
	bool AddSimpleTreeNodes(TreeNode& tr,int nStopLevel=-1, LPCSTR lpcszStopAttribute = NULL,bool bCollapseAll = TRUE,
							bool bStopAtLastBranch = false,int nLevel =-1, int nCols = 0, int *pnFromRow=NULL)
	///End APPLY_ADDTREENODES_WITH_NEW_RULE		
	{
		Control* pCntrl = GetControl();
		HWND hGrid = pCntrl->GetSafeHwnd();
		HWND hWnd = GetDlgSafeHwnd();
		DWORD dwCntrl = bCollapseAll? 0:TEAT_OPEN;// TEAT_OPEN will be faster
		return octe_add_tree(&tr, hWnd, hGrid, nStopLevel, lpcszStopAttribute);
	}
	//----- CPY 6/7/2007 GET_HAS_SCRIPT_INFO_FROM_MAP
	///Jasmine 06/08/07 UPDATE_SIMPLE_TREE_MODIFICATION
	void UpdateSimpleTree(TreeNode& tr, int nFromRow = -1)
	{
		SetReady(false);
		if(-1 == nFromRow)
			ClearAll();
		AddTreeNode(tr, -1, NULL, TEAT_CHK_ADD_ICONS|TEAT_CHK_ADD_ROW_DATA, nFromRow); 
	///End UPDATE_SIMPLE_TREE_MODIFICATION
		SetReady(true);
	}
	//-----
	///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
	//virtual void UpdateList(TreeNode& tr, LPCSTR lpcszStopAttribute = NULL, int nStopLevel = NOT_SET_STOP_LEVEL, bool bCollapseAll = TRUE)
	virtual void UpdateList(TreeNode& tr, LPCSTR lpcszStopAttribute = NULL, int nStopLevel = NOT_SET_STOP_LEVEL,
							bool bCollapseAll = TRUE, bool bStopAtLastBranch = false,int nLevel =-1,
							int nCols = 0, int *pnFromRow=NULL)
	///End APPLY_ADDTREENODES_WITH_NEW_RULE		
	{
		SetReady(false);
		ClearAll();
		///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
		//AddSimpleTreeNodes(tr, nStopLevel, lpcszStopAttribute, bCollapseAll);
		AddSimpleTreeNodes(tr, nStopLevel, lpcszStopAttribute, bCollapseAll, bStopAtLastBranch, nLevel,
							nCols, pnFromRow);
		///End APPLY_ADDTREENODES_WITH_NEW_RULE		
		SetReady(true);
	}
	
	/// END CENTERLIZE_CODES_IN_FB
	/// AW 03/18/05 QA80-7522 v8.0206 MORE_ON_ADD_TREE_NODE_TO_LST_GRID
	bool AddTreeNode(TreeNode& trSrc, int nStopLevel = -1, LPCSTR lpcszStopAttribute = NULL, DWORD dwCntrl = 0, int nFromRow = -1)
	{
		Control* pCntrl = GetControl();
		HWND hGrid = pCntrl->GetSafeHwnd();
		HWND hWnd = GetDlgSafeHwnd();
		return octe_add_tree(&trSrc, hWnd, hGrid, nStopLevel, lpcszStopAttribute, dwCntrl, nFromRow);
	}
	/// END MORE_ON_ADD_TREE_NODE_TO_LST_GRID
	
	bool GetSelRows(vector<uint>& vnRows)
	{
		vnRows.SetSize(0);// empty first
		//--- CPY 6/14/07 SCRIPT_SAMPLE_DLG_SWITCHING_LOCATION_AUTOMATION_ERR
		if(m_flx.Rows <= m_flx.FixedRows)
		{
			//out_str("grid is empty, cannot have any selection");
			return false;
		}
		//---
		if(m_flx.SelectionMode == flexSelectionListBox)
		{
			int nNumSelected = m_flx.SelectedRows;
			if(nNumSelected > 0)
			{
				int nRow;
				for(int ii = 0; ii < nNumSelected; ii++)
				{
					/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
					nRow = m_flx.GetSelectedRow(ii);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
					/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
					nRow = m_flx.SelectedRow(ii);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__ /// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
					vnRows.Add(nRow);
				}
				return true;
			}
		}
		else
		{
			if(m_flx.Col >= 0)
			{
				int nSel = m_flx.Row;
				if(nSel >= m_flx.FixedRows)
				{
					vnRows.Add(nSel);
					return true;
				}
			}
		}
		return false;
	}
	
	
	void RemoveSelection()
	{
		if(m_flx.SelectionMode == flexSelectionListBox)	///Jasmine 10/15/08 MUST_USE_ISSELECT_TO_REMOVE_SELECTION_IN_LISTBOX_CASE
		{
			vector<uint> vnRows;
			if( GetSelRows(vnRows) )
				CancelSelRows(vnRows);
		}
		
		m_flx.Col = 0;
		m_flx.Row = -1;
	}
	//----- CPY 7/29/04 I moved the following two functions to GetNBox.c
	// vn = [out] array of 1 = collapsed and 0 = open of all outline nodes
	// return -1 if not applicable, otherwise return number of branches
	int GetCollapsed(vector<byte>& vn, bool bOnlyTopLevelIsBranch = true );
	// CPY 1/28/05 SET_COLLAPSED_NULL_VEC_FOR_TRUE_TO_ALL
	bool SetCollapsed(const vector<byte>& vn, bool bOnlyTopLevelIsBranch = true  );
	//-----
	//------- CPY 8/27/04 QA70-5890 v8.0125 BRANCH_ALLOW_CHECKBOX
	/*
	///Frank 24/6/04	v8.0895	FO_ADD_SET_SELECT_ROW_COLLAPSE_STATE	
	bool SetSelectRowCollapsed(int nRow, byte nState)
	{
		if(m_flx.OutlineBar == flexOutlineBarNone)
			return false;
		if(nRow < m_flx.Rows && nRow > 0)
		{
			m_flx.IsCollapsed(nRow) = nState;
		}
		return true;
	}
	///Frank 8/3/04	v8.0109			GET_SELECT_ROW_COLLAPSE_STATE	
	///Frank 8/3/04	Add this function because we need get select row collapsed state when double click the row,
	//It is pair of  SetSelectRowCollapsed function, use together when user want to change the selete row collapsed state.
	byte GetSelectRowCollapsed(int nRow)
	{
		if(m_flx.OutlineBar == flexOutlineBarNone)
			return 4;
		if(nRow < m_flx.Rows && nRow > 0)
		{
			return m_flx.IsCollapsed(nRow);
		}
		return 3;
	}
	//End	GET_SELECT_ROW_COLLAPSE_STATE	
	*/
	/// Kenny 06/13/2010 ORG-305-P2 GRIDCONTROL_IS_COLLAPSED_FUNCTION_RETURN_WRONG_VALUE
	//bool		GetIsCollapsed(long nRow)
	int			GetIsCollapsed(long nRow)
	/// End ORG-305-P2 GRIDCONTROL_IS_COLLAPSED_FUNCTION_RETURN_WRONG_VALUE
	{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.GetIsCollapsed(nRow);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.IsCollapsed(nRow);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	}

	bool SetIsCollapsed(int nRow, int nState = flexOutlineCollapsed)
	{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.SetIsCollapsed(nRow, nState);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
		return m_flx.IsCollapsed(nRow) = nState;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	}

	bool SetCollapsed(int nRow, bool bIsCollasped = true);
	int GetCollapsed(int nRow); //return -1 if not applicable, otherwise 1 = collapsed, 0 = expended
	//--------
	//End	FO_ADD_SET_SELECT_ROW_COLLAPSE_STATE
	////Frank 1/27/05  ALWAYS_NEED_SET_ALL_COLLAPSED_IN_INIT
	void SetAllCollapsed(bool bIsCollasped = true)
	{
		if(bIsCollasped)
		{
			SetCollapsed(NULL, false);
			return;
		}
		
		int		nRow = GetRows();
		vector<byte>	vecCollapsed(nRow);
		vecCollapsed = bIsCollasped;
		SetCollapsed(vecCollapsed, false);
	}
	////End  ALWAYS_NEED_SET_ALL_COLLAPSED_IN_INIT
	///Danice TREE_BRANCH_COLLAPSED_IMPROVEMENT : Move from GridTreeControl, SetCollapsed() use
	int	GetLevel(int nSelRow) 
	{
		if(nSelRow >= m_flx.Rows || nSelRow < 0)
			return -1;
		return GetRowOutlineLevel(nSelRow);
	}
	int GetParent(int nRow)
	{
		int nLevel=GetLevel(nRow);
		if(0 > nLevel)
			return -1;
		for(int ii=nRow-1; ii>=0; ii--)
		{
			if(1==nLevel-GetLevel(ii))
				return ii;
		}
		return -1;
	}
	///end TREE_BRANCH_COLLAPSED_IMPROVEMENT
protected:
	///Kenny 04/27/2009 QA80-13519-P3 COL_BROWSER_DLG_SHOULD_REMEMBER_COLUMN_WIDTH, these functions are moved from GridTableControl.h except Get/SetDlgName and InitColsWidthFromReg
	string GetDlgName() { return m_strDlgName; }

	void SetDlgName(LPCSTR lpcszDlgName) { m_strDlgName = lpcszDlgName; }

	BOOL InitColsWidthFromReg()
	{
		vector<uint> vnColsWidth;
		if( LoadColsWidthFromReg( vnColsWidth ) )
		{
			SetColsWidth( vnColsWidth );
			return TRUE;
		}
		return FALSE;
	}

	virtual string	GetClassName() { return "GridListControl"; }

	string GetDlgNameForRegistry()
	{
		return GetDlgName() + "\\" + GetClassName();
	}
	string	GetRegKeyName( LPCSTR lpcszBasic, int nGroup = -1 )
	{
		string	strKeyName( lpcszBasic );
		if( nGroup >= 0 )
		{
			strKeyName += "_Group" + ( nGroup + 1 );
		}
		return	strKeyName;
	}
	bool	LoadColsWidthFromReg( vector<uint>& vnColWidth)
	{
		string			strDlgName = GetDlgNameForRegistry();
		string			strKeyName = GetRegKeyName( "ColWidth");
		string			strColsWidth;
		vector<string>	vsColWidth;
		bool			bRet;


		if( bRet = dlg_load_registry( strDlgName, strKeyName, strColsWidth) )
		{
			strColsWidth.GetTokens( vsColWidth, '|');
			convert_string_vector_to_uint_vector( vsColWidth, vnColWidth );
		}

		return bRet;
	}
	bool	SaveColsWidthToReg()
	{
		string			strDlgName = GetDlgNameForRegistry();
		string			strKeyName = GetRegKeyName( "ColWidth" );
		vector<uint>	vnColsWidth;
		vector<string>	vsColsWidth;
		string			strColsWidth;

		int nCols = GetNumCols();
		if( 0 == nCols )
			return false;

		vnColsWidth.SetSize( nCols );
		for( int ii = 0; ii < nCols; ii++)
			vnColsWidth[ii] = GetColWidth( ii );

		convert_uint_vector_to_string_vector( vnColsWidth, vsColsWidth);
		strColsWidth.SetTokens( vsColsWidth, '|' );
		dlg_save_to_registry( strDlgName, strKeyName, strColsWidth );

		return true;
	}
	void	SetColsWidth( const vector<uint>& vnColsWidth)
	{
		int	nCols = GetNumCols();
		///Kenny 05/05/2009 FIX_BUG_FOR_SET_COL_WIDTH_OVER_BOUND
		//ASSERT( vnColsWidth.GetSize() == nCols );
		const int nColsWidthSize = vnColsWidth.GetSize();
		ASSERT( nColsWidthSize == nCols );
		if (nColsWidthSize < nCols)
			nCols = nColsWidthSize;
		///End FIX_BUG_FOR_SET_COL_WIDTH_OVER_BOUND

		for( int ii = 0; ii < nCols; ii++)
			SetColWidth( ii, vnColsWidth[ii]);

		return;
	}
	///End QA80-13519-P3 COL_BROWSER_DLG_SHOULD_REMEMBER_COLUMN_WIDTH
	
	bool	InitColsShowHiddenFromReg(LPCSTR lpcszSectionName = "ColHidden")
	{
		string strVal;
		vector vHidden;
		if( dlg_load_registry(GetDlgNameForRegistry(), lpcszSectionName, strVal) && !strVal.IsEmpty() )
		{
			strVal.GetTokens(vHidden, '|');
		}
	
		for( int ii=0; ii<vHidden.GetSize(); ++ii )
		{			
			if( ii < GetNumCols() )
				SetIsColHidden( ii, vHidden[ii] );
		}
		return (vHidden.GetSize() > 0);
	}
	
	void	SaveColsShowHiddenToReg(LPCSTR lpcszSectionName = "ColHidden")
	{
		string str;
		for(int nn = 0; nn < GetNumCols(); nn++)
		{
			int nHidden = GetIsColHidden(nn);
			str += (string)nHidden + "|";
		}
		str.TrimRight("|");
		dlg_save_to_registry(GetDlgNameForRegistry(), lpcszSectionName, str);		
	}
	
public:
	///end TREE_ROW_SHOW_ALTERNATE_COLORS
	bool GetSelItems(int nCol, vector<string>& vsItems)
	{
		vector<uint> vnRows;
		vsItems.SetSize(0);
		string strTemp;
		if(GetSelRows(vnRows))
		{
			for(int ii = 0; ii < vnRows.GetSize(); ii++)
			{
				strTemp = GetCell(flexcpText, vnRows[ii], nCol);
				vsItems.Add(strTemp);
			}
			return true;
		}
		return false;
	}
	// return -1 if none selected, reutrn 1st sel Row if multiple
	int  GetSelectedRow()
	{
		vector<uint> vnRows;
		if(GetSelRows(vnRows))
			return vnRows[0];
		
		return -1;
	}
	//---Jasmine 12/17/08 comment update
	//-1 to hide the selection, except SelectionMode = flexSelectionListBox(see RemoveSelection)
	//---
	void SelRow(int nRow, bool bSelLast = false) 
	{
		if(bSelLast || nRow>=m_flx.Rows)
			nRow = m_flx.Rows-1;
		
		m_flx.Row = nRow;
		
		if(nRow >= 0)
		{
			m_flx.ShowCell(nRow, 0);
		}
	}
	bool SelRows(const vector<int> nRows)
	{
		if(nRows.GetSize() == 1)
		{
			SelRow(nRows[0]);
			return true;
		}
		if(m_flx.SelectionMode != flexSelectionListBox)
			return false;
		m_flx.Row = -1;
		for(int ii = 0; ii < nRows.GetSize(); ii++)
			SetIsSelected(nRows[ii], true);

		return true;
	}
	///Jasmine 07/6/07 CANCEL_GRID_SELECTION
	void CancelSelRows(const vector<int> vnRows)
	{	
		for(int ii = 0; ii < vnRows.GetSize(); ii++)
			SetIsSelected(vnRows[ii], false);
	}
	///End CANCEL_GRID_SELECTION
	//virtual 
	string GetRuntimeClass()
	{
		return "GridListControl";
	}
	
	
	/// Iris 11/16/05 
	//SetCellProperty(0, 0, FlexcpAlignment, JUSTIFICATION_MULTILINE): set the cell support multiple line
	//see vsFlex Help to get more propertySettings and more format
	
	///Vinden 8/5/2008 v8.0857 MOVE_FUNCTION_FROM_GRIDLISTCONTROL_TO_GRIDCONTROL
	/*
	void SetCellProperty(int nPropertySettings, int nFormat, int nRow = 0, int nCol = 0)
	{
		m_flx.Cell(nPropertySettings, nRow, nCol) = nFormat; //JUSTIFICATION_MULTILINE;

	}
	*/
	///End MOVE_FUNCTION_FROM_GRIDLISTCONTROL_TO_GRIDCONTROL
private:
	//CPY 7/29/04, the reason this is needed is because some how IsSubTotal is always returnning true
	//Frank  7/28/04 v8.0105  COLLAPSED_BRANCE_WITHOUT_LEAF_NODES
	bool isBranch(int nRow, bool bOnlyTopLevelIsBranch = true)
	{
		//--- CPY 12/22/04 QA70-5890 
		//if(!m_flx.IsSubtotal(nRow))
		//	return false; // CPY, it some how never gets here, we need to see why later
		return IsBranchRow(nRow, bOnlyTopLevelIsBranch);
		//---
		/*
		if(bSkipLeafs )
		{
			if(nRow+1 < m_flx.Rows)
			{
				int nRet = m_flx.RowOutlineLevel(nRow);
				int nRet2 = m_flx.RowOutlineLevel(nRow+1);
				if(nRet2 != nRet+1 )
					 return false;
			}
		};
		return true;
		*/
	}
	//End  COLLAPSED_BRANCE_WITHOUT_LEAF_NODES
///Kenny 04/27/2009 QA80-13519-P3 COL_BROWSER_DLG_SHOULD_REMEMBER_COLUMN_WIDTH
private:
	string m_strDlgName;
///End QA80-13519-P3 COL_BROWSER_DLG_SHOULD_REMEMBER_COLUMN_WIDTH
};

///DG REWRITE_TREE_GET_NODE
/*
// dwCntrl for AddTreeNodes
enum {
	ATRN_SKIP_LEAFS 			= 0x00010000,
	ATRN_STOP_LEVEL 			= 0x00020000, // use lobyte to indicate level to stop, 1 = show up to 1st child branch
	ATRN_SHOW_FOLDER_ONLY		= 0x00040000,	///Danice CORRECT_ENUM_PROBLEM
	ATRN_CHECK_STOP_ATTRIBUTE 	= 0x00080000, 
	ATRN_LAST_ENTRY,
};
*/
///end REWRITE_TREE_GET_NODE

//--------- CPY 2/24/04 v7.5826 QA70-6032 TREE_CONTROL_BASE_CLASS
class  GridTreeControl: public GridListControl
{
public:
	//void Init(int nID, WndContainer& dlg, bool bSubBranch = true)	///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
	void Init(int nID, WndContainer& dlg, bool bSubBranch = true, WndContainer* pParentDlg = NULL)
	{
		//GridListControl::Init(nID, dlg); ///DG TREE_CTRL_IN_PROPERTYPAGE_NEED_MSG
		GridListControl::Init(nID, dlg, pParentDlg);
		
		m_flx.Rows = 0;
		m_flx.FixedRows = 0;//hide the Col heading
		m_flx.Cols = 1;
		m_flx.FixedCols = 0;//hide the Row heading
		m_flx.SelectionMode = flexSelectionFree;//flexSelectionByRow;			//Forces selections to span entire rows.
		m_flx.AllowSelection = false;
		m_flx.GridLines = flexGridNone;
		m_flx.Editable = flexEDNone;

		//SetAlternateRowColors();
		m_flx.ExtendLastCol = true;
		if(bSubBranch)
		{
			m_bIsOutlineTree = true;
			m_flx.OutlineCol = 0;
			m_flx.OutlineBar = flexOutlineBarSimpleLeaf;
			m_flx.MergeCells = flexMergeSpill;
		}		
		else
			//m_bIsOutlineTree = false;	///Danice 9/17/04 SUPPORT_GRID_VIEW : by default: tree view
			m_bIsOutlineTree = true;


		RemoveSelection();
	}
	//virtual 
	string GetRuntimeClass()
	{
		return "GridTreeControl";
	}
protected:
	//---- WKBOOK_SHOW_ACTIVE_SHEETIN_ORGANIZER
	// return number of rows that are set by this call
	// loop through each row and turn bold on/off by matching Data ID stored inrow
	// we meed to use dwID that are only 16 bits in size
	//Danice 11/13/04 : By now, only vector<string> support Find, so use this for temp
	int SetBoldByRowData(vector<string> vsIDs, bool bBold=true, bool bResetAll=true)
	{
		int nTotalBold=0;
		string strRowData;
		for(int jj=0; jj<m_flx.Rows; jj++)
		{
			strRowData = GetRowData(jj);
			if(-1 != vsIDs.Find(strRowData))
			{
				SetBold(jj, 0, bBold);
				nTotalBold++;
			}
			else if(bResetAll)
				SetBold(jj, 0, !bBold);
		}
		return nTotalBold;
	}
	//-----
	///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
	/// YuI 3/24/04 v7.5846 QA70-6118 NEW_DATA_SELECTOR_TOOL
	/*
	void	addDataRangeNode(TreeNode& tr, DWORD dwCntrl, int nLevel)
	{
		if(nLevel >= 0)
			//addTreeRow(tr, nLevel, dwCntrl, true);
		
		PageBase pg = Project.Pages();
		foreach(TreeNode cNode in tr.Children)
		{
			AddTreeNodes(cNode, dwCntrl, nLevel+1);
		}
	}
	*/
	/// end NEW_DATA_SELECTOR_TOOL
	
	///DG REWRITE_TREE_GET_NODE : don't know what this function is used for, it seems useless.
	/*
	void	addDataRangeNode(TreeNode& tr, int nStopLevel=-1, LPCSTR lpcszStopAttribute=NULL, 
						bool bCollapseAll = true, bool bStopAtLastBranch = false,int nLevel =-1,
						int *pnFromRow=NULL, int nCols = 0)
	{
		if(nLevel >= 0)
			addTreeRow(tr, nLevel, true, pnFromRow, nCols);
		
		PageBase pg = Project.Pages();
		foreach(TreeNode cNode in tr.Children)
		{
			AddTreeNodes(cNode, nStopLevel, lpcszStopAttribute,  bCollapseAll , bStopAtLastBranch, nLevel+1,pnFromRow,nCols);
		}
	}
	*/
	///end REWRITE_TREE_GET_NODE
	
	///End APPLY_ADDTREENODES_WITH_NEW_RULE		
public:
	///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
	/// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB
	// move to base class
	/*
	///DG ADD_SIMPLE_TREENODE
	bool AddSimpleTreeNodes(TreeNode& tr, int nStopLevel=-1, LPCSTR lpcszStopAttribute=NULL, bool bCollapseAll = true)
	{
		Control* pCntrl = GetControl();
		HWND hGrid = pCntrl->GetSafeHwnd();
		HWND hWnd = GetDlgSafeHwnd();
		DWORD dwCntrl = bCollapseAll? 0:TEAT_OPEN;// TEAT_OPEN will be faster
		return octe_add_tree(&tr, hWnd, hGrid, nStopLevel, lpcszStopAttribute);
	}
	///end ADD_SIMPLE_TREENODE
	*/
	/// END CENTERLIZE_CODES_IN_FB
	
	/*
		Add TreeNode to Grid control, you can special the adding treenode's stop level, all collapse state, and so on.
	Parameters:
		tr=[Input]TreeNode to be add to Grid control.
		dwCntrl=[Input]  This parameter have many use, can be :
						if dwCntrl & ATRN_STOP_LEVEL = true, will add the treenode of the level count LOBYTE(dwCntrl);
						if dwCntrl & ATRN_SHOW_FOLDER_ONLY = true, will add folder treenode only, this feature just use in PM, the treenode's STR_DISPLAY_ATTRIB 
						attribute should equal to IDI_FOLDER_CLOSED. 
						if dwCntrl & ATRN_SKIP_LEAFS = true, will add treenode's branch to Grid control and skip leaves.
						(dwCntrl & 0x000F) = nCols;
		lpcstrAttrib = [input] the attribute will check to stop, if not NULL and dwCntrl & ATRN_CHECK_STOP_ATTRIBUTE = true, 
						will stop adding treenode when meet the treenode with attribute of lpcstrAttrib
						
		nLevel = [input] the level of the treenode will be add.
		pnFromRow = [input]	the start row of the treenode will be add.
	Return:
		return true if work, else false. 		
	*/
	//bool AddTreeNodes(TreeNode& tr, DWORD dwCntrl = 0, int nLevel = -1) ///Danice ADD_TREENODE_FROM_ROW
	//CPY 3/19/05 GETN_TREE_BROKEN please note that (dwCntrl & 0x000F) = nCols
//	bool AddTreeNodes(TreeNode& tr, DWORD dwCntrl = 0, int nLevel = -1, int *pnFromRow=NULL, LPCSTR lpcstrAttrib=NULL)
//	{
//		///Danice 31/05/04 v8.0881 REMOVE_PRO_INFO
//		/*
//		///Danice QA70-6232 PRO_ONLY_MASK_FOR_SOME_FEATURE
//		int nDataId;
//		//----- CPY 5/25/04 v7.5878 FO_ADD_PROFILE_DUE_TO_SLOW_LAUNCH
//		// after using Profiler, I found is_pro_version is a slow function
//		//if(!is_pro_version())
//		//{
//			//if(tr.GetAttribute(STR_DATAID_ATTRIB, nDataId) && (IDST_MASK_PRO_ONLY & nDataId))
//			//{
//				//return true;
//			//}
//		//}
//		if(tr.GetAttribute(STR_DATAID_ATTRIB, nDataId) && (IDST_MASK_PRO_ONLY & nDataId) && !is_pro_version())
//		{
//			return true;
//		}
//		//-----
//		///END PRO_ONLY_MASK_FOR_SOME_FEATURE
//		*/
//		///END REMOVE_PRO_INFO
//		
//		/// AW 03/18/05 QA80-7522 v8.0206 MORE_ON_ADD_TREE_NODE_TO_LST_GRID
//		/*
//		BOOL 	bCheckStop = (dwCntrl & ATRN_STOP_LEVEL) ? TRUE : FALSE;
//		///Frank 11/12/04 ADD_CHECK_STOP_ATTRIBUTE
//		///If the attribute exist and need to check it, will add the node , but stop from this.
//		BOOL	bChcekStopAttribute = (dwCntrl & ATRN_CHECK_STOP_ATTRIBUTE) ? TRUE : FALSE;
//		bool	bStopAttribute = false;
//		if(bChcekStopAttribute && NULL != lpcstrAttrib)
//		{
//			string strTemp;
//			if(tr.GetAttribute(lpcstrAttrib, strTemp))
//				bStopAttribute = true;/////if bChcekStopAttribute == false, mean tr not need to display.
//		}
//		///End ADD_CHECK_STOP_ATTRIBUTE
//		
//		int 	nStopLevel = LOBYTE(dwCntrl);
//		int 	nCnt = tr.GetNodeCount();
//		//if(!bCheckStop || nLevel <= nStopLevel)
//		if(!bCheckStop || nLevel <= nStopLevel)
//		{
//			/// Frank 5/12/04 v8.0872 ADD_FOLDER_WITHOUT_PAGE
//			//if(nCnt < 1 && !(dwCntrl & ATRN_SHOW_FOLDER_ONLY))	///Danice CORRECT_ENUM_PROBLEM
//			if(nCnt < 1 && (dwCntrl & ATRN_SHOW_FOLDER_ONLY))
//			{
//				int intFolderID;
//				tr.GetAttribute(STR_DISPLAY_ATTRIB, intFolderID);
//				if( intFolderID == IDI_FOLDER_CLOSED)
//					addTreeRow(tr, nLevel, dwCntrl, false, pnFromRow);
//				return true;
//			}
//			///end ADD_FOLDER_WITHOUT_PAGE
//			
//			if(nCnt < 1) // no children, add leaf
//			{
//				if(!(dwCntrl & ATRN_SKIP_LEAFS))
//					addTreeRow(tr, nLevel, dwCntrl, false, pnFromRow);
//			}
//			else
//			/// YuI 3/24/04 v7.5846 QA70-6118 NEW_DATA_SELECTOR_TOOL
//			if( tr.ID == TRGP_DATA_RANGE )
//				addDataRangeNode(tr, dwCntrl, nLevel);
//			else
//			/// end NEW_DATA_SELECTOR_TOOL	
//			{
//				if(nLevel >= 0)
//					addTreeRow(tr, nLevel, dwCntrl, true, pnFromRow);
//				
//				///Frank 11/12/04 ADD_CHECK_STOP_ATTRIBUTE
//				if(!bStopAttribute)
//				///End ADD_CHECK_STOP_ATTRIBUTE
//					foreach(TreeNode cNode in tr.Children)
//					{
//						AddTreeNodes(cNode, dwCntrl, nLevel+1, pnFromRow, lpcstrAttrib);
//					}
//			}
//		}
//		return true;
//		*/
//		
//		DWORD dwNewCntrl = 0;
//		int 	nStopLevel = -1;
//		int nFromRow = -1;
//		if ( dwCntrl & ATRN_SKIP_LEAFS || dwCntrl & ATRN_SHOW_FOLDER_ONLY )
//			dwNewCntrl |= TEAT_SKIP_LEAFS;
//		if ( -1 != nLevel )
//			dwNewCntrl |= TEAT_NOT_SHOW_ROOT;
//		if ( NULL != pnFromRow )
//			nFromRow = *pnFromRow;	
//		nStopLevel = LOBYTE(dwCntrl);
//		bool bOK = AddTreeNode(tr, nStopLevel, lpcstrAttrib, dwNewCntrl, nFromRow);
//		ASSERT(true == bOK );
//		return bOK;
//		/// END MORE_ON_ADD_TREE_NODE_TO_LST_GRID
//
//	}
	///End APPLY_ADDTREENODES_WITH_NEW_RULE		
	//---- CPY 3/19/05 GETN_TREE_BROKEN
	// this function is in conflict with existing code, so must not be exposed
	///Frank 3/18/05 v8.0206 ADD_ADDTREENODES_REPLACE_OF_CONTROL_VALUE		
	/*
		Add TreeNode to Grid control, you can special the adding treenode's stop level, all collapse state, and so on.
	Parameters:
		tr=[Input]TreeNode to be add to Grid control.
		nStopLevel=[Input] how many level you want to add to Grid control of the treenode, if nStopLevel =0, mean 
		just add first level of the treenode; default is -1, mean whole treenode to Grid control.
		lpcszStopAttribute = [input] Use with bStopAtLastBranch, have 4 case:
			1: if no NULL, and bStopAtLastBranch = false, will stop adding treenode when meet the treenode with 
			attribute of lpcszStopAttribute; 
			2: if no NULL, and bStopAtLastBranch = true, will just add treenode if the treenode's STR_DISPLAY_ATTRIB 
			attribute equal to IDI_FOLDER_CLOSED. 
			3: if NULL, bStopAtLastBranch = true, will add treenode to Grid control and skip leaves.
			4: if NULL, and bStopAtLastBranch = false, do nothing.
		bCollapseAll = [input] Set all collapse, True of yes, false of no.
		bStopAtLastBranch =[input] 	See lpcszStopAttribute description.
		nLevel = [input] the level of the treenode will be add.
		nCols = [input]	= 0 if no need to add extra cols.
		pnFromRow = [input]	the start row of the treenode will be add.
	Return:
		return true if work, else false. 		
	*/
	///DG REWRITE_TREE_GET_NODE
	/*
	bool AddTreeNodes(TreeNode& tr, int nStopLevel=-1, LPCSTR lpcszStopAttribute=NULL, 
						bool bCollapseAll = true, bool bStopAtLastBranch = false,int nLevel =-1,
						int *pnFromRow=NULL, int nCols = 0)
	{
		if(!tr.IsValid())
			return false;
		
		string strStopAttribute(lpcszStopAttribute);
		///If the attribute exist and need to check it, will add the node , but stop from this.
		bool	bStopAttribute = false;
		//if(lpcszStopAttribute != NULL && !bStopAtLastBranch)
		if( !strStopAttribute.IsEmpty() && !bStopAtLastBranch)
		{
			string strTemp;
			//if(tr.GetAttribute(lpcszStopAttribute, strTemp))
			if(tr.GetAttribute(strStopAttribute, strTemp))
				bStopAttribute = true;//if bStopAttribute == false, mean tr's branch not need to display.
		}
		
		if( nStopLevel < 0 || nLevel <= nStopLevel)
		{

			
			if(tr.GetNodeCount() < 1 )
			{
				///Add leaf node.
								
				///If bStopAtLastBranch = true and lpcszStopAttribute == NULL, just skip the leaves node.
				///If bStopAttribute = true, add the row directly, because leaf node have not branch, so not need consider the branch ;
				if(!bStopAtLastBranch)
					addTreeRow(tr, nLevel, false, pnFromRow, nCols);
				else
				{
					//if(lpcszStopAttribute != NULL)
					if( !strStopAttribute.IsEmpty() )
					{
						///If bStopAtLastBranch = true and lpcszStopAttribute != NULL, will just add folder, need to check the node's attribute is folder or not
						int intFolderID;
						tr.GetAttribute(STR_DISPLAY_ATTRIB, intFolderID);
						if( intFolderID == IDI_FOLDER_CLOSED)
							addTreeRow(tr, nLevel, false, pnFromRow, nCols);
					}
					return true;
				}
			}
			else
			{
				if(nLevel >= 0)
					addTreeRow(tr, nLevel, true, pnFromRow, nCols);
				
				if(!bStopAttribute)
					foreach(TreeNode cNode in tr.Children)
					{
						//AddTreeNodes(cNode, dwCntrl, nLevel+1, pnFromRow, lpcstrAttrib);
						AddTreeNodes(cNode, nStopLevel, lpcszStopAttribute,  bCollapseAll , 
									bStopAtLastBranch ,nLevel + 1, pnFromRow, nCols);
					}
			}
		}
		if(bCollapseAll)
		{
			int nRow = m_flx.Rows;
			SetCollapsed(nRow, true); ///Frank 3/20/05. Can't set the row Collapsed directly, I dont know why.
		}


		return true;
	}
	///End ADD_ADDTREENODES_REPLACE_OF_CONTROL_VALUE
	//--- end CPY 3/19/05 GETN_TREE_BROKEN
	*/
public:
	///DG 4/18/05 : it seems we have nothing to do with bCollapseAll in OC level
	bool AddTreeNodes(TreeNode& tr, DWORD dwCntrl=0, LPCSTR lpcszAttribute=NULL, 
						int nLevel = -1, int *pnFromRow = NULL, 
						bool bCollapseAll = true, int nCols = 0)
	{
		if(!tr.IsValid())
			return false;
		
		bool	bCheckStop				= dwCntrl & ATRN_STOP_LEVEL ? true : false;
		int 	nStopLevel 				= bCheckStop ? (int)LOBYTE(dwCntrl) : -1;
		bool 	bUseAttributeAsStop 	= dwCntrl & ATRN_LOOP_MARDED_NODE_ONLY ? false : true;
		bool 	bSkipLeaf 				= dwCntrl & ATRN_SKIP_LEAFS ? true : false;
		
		string strTemp = lpcszAttribute;
		bool bHasAttribute = !strTemp.IsEmpty();
		if( nStopLevel < 0 || nLevel <= nStopLevel)
		{
			if(-1 != nLevel && !bUseAttributeAsStop && bHasAttribute && !tr.GetAttribute(lpcszAttribute, strTemp))
				return true; //we don't check top root node "OriginStorage", or use attribute as continue but don't meet attribute node
			if(tr.GetNodeCount() < 1 )
			{
				///Add leaf node.
				if(!bSkipLeaf)
					addTreeRow(tr, nLevel, false, pnFromRow, nCols);
			}
			else
			{
				if(nLevel >= 0)	//ignore the top node "OriginStorage"
					addTreeRow(tr, nLevel, true, pnFromRow, nCols);
				
				if(!bUseAttributeAsStop || !bHasAttribute || !tr.GetAttribute(lpcszAttribute, strTemp))
					foreach(TreeNode cNode in tr.Children) //don't meet stop attribute or just ignore this checking
					{
						AddTreeNodes(cNode, dwCntrl, lpcszAttribute, nLevel+1, pnFromRow, bCollapseAll, nCols);
					}
			}
		}
		///DG 4/18/05 : can't set it this way in oc
		/*
		if(bCollapseAll)
		{
			int nRow = m_flx.Rows;
			SetCollapsed(nRow, true); ///Frank 3/20/05. Can't set the row Collapsed directly, I dont know why.
		}
		*/
		///end
		return true;
	}
	///end REWRITE_TREE_GET_NODE
	
	bool IsTreeView() { return m_bIsOutlineTree;}
	void SetTreeView(bool bTreeView=true) { m_bIsOutlineTree=bTreeView; }	///Danice SUPPORT_GRID_VIEW
	
private:
	//CPY 7/28/04, the is not needed
	/*
	/// SY 07/28/2004 QA70-6719 v8.0105 GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	void setGridColWidthInChars(int nCol, int nChars, int FixedWidthGridFont)
	{
		if( nCol >= m_flx.Cols )
			return;
		// set grid column width in chars
		int iTwips = PixelsToTwips(FixedWidthGridFont * nChars);
		
		if( iTwips > m_flx.ColWidth(nCol) )
			m_flx.ColWidth(nCol) = iTwips;
	}
	/// end GETN_AUTO_RESIZE_WIDTH_WITH_LONG_LABEL
	*/
	//--CPY 7/28/04, move this to GetNBox.c
	/*
		Add Tree row to Grid control, you can special the adding treenode's stop level, all collapse state, and so on.
	Parameters:
		tr=[Input]TreeNode to be add to Grid control.
		bIsBranch=[Input] If true, will set the row as branch.
		nCol = 
		nLevel = [input] the level of the treenode will be add.
		pnFromRow = [input]	the start row of the treenode will be add.
	Return:
		return true if work, else false. 		
	*/
	///Frank 3/20/05 v8.0207 APPLY_ADDTREENODES_WITH_NEW_RULE		
	//void addTreeRow(TreeNode& cNode, int nLevel, DWORD dwCntrl, bool bIsBranch = false, int *pnFromRow=NULL); ///Danice ADD_TREENODE_FROM_ROW
	void addTreeRow(TreeNode& cNode, int nLevel, bool bIsBranch = false, int *pnFromRow=NULL, int nCol = 0); ///Danice ADD_TREENODE_FROM_ROW
	///End APPLY_ADDTREENODES_WITH_NEW_RULE		
	
/// TD 3-30-04 QA70-6053 PICTURE_IN_OC
private:
	bool setCellIcon(TreeNode& cNode, int nRow, int nCol)
	{
		int nDisplayAttrib = 0;
		if(cNode.GetAttribute(STR_DISPLAY_ATTRIB, nDisplayAttrib))
		{
			//if(isDisplayIcon(nDisplayAttrib))	///Jasmine 01/06/10 QA81-14909 more and more icons are added, and SetCellIcon can skip the invalid id
			{
				/// TD ML 04-13-2010 QA85-15312 ICON_OVERLAYS_IN_GRIDCONTROL
				//return SetCellIcon(nRow, nCol, nDisplayAttrib, MODULE_ORIGIN);
				int nOverlayAttrib = 0;
				cNode.GetAttribute(STR_OVERLAY_ATTRIB, nOverlayAttrib);
				return SetCellIcon(nRow, nCol, nDisplayAttrib, MODULE_ORIGIN, TRUE, nOverlayAttrib);
				/// end ICON_OVERLAYS_IN_GRIDCONTROL
			}


		}
		return false;
	}
	
	/*bool isDisplayIcon(int nDisplayAttrib, int nModuleID  = MODULE_ORIGIN)
	{	
		if(MODULE_ORIGIN == nModuleID)
		{
			if(IDI_FOLDER_CLOSED == nDisplayAttrib)
				return true;
			
			if(IDR_WORKSHEETTYPE_V8 <= nDisplayAttrib || IDR_NOTESTYPE >= nDisplayAttrib)
				return true;
		}
		
		return false;
	}*/
	
/// end PICTURE_IN_OC

private:
	bool	m_bIsOutlineTree;
};
//--------- end CPY 2/24/04 v7.5826 QA70-6032 TREE_CONTROL_BASE_CLASS

/// Hong QA80-15357 03/31/10 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
_VARIANT	GridControl::GetCell(CellPropertySettings settings, int nRow, int nCol)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetCell(settings, nRow, nCol);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.Cell(settings, nRow, nCol);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

void		GridControl::SetCell(_VARIANT var, CellPropertySettings settings, int nRow, int nCol)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetCell(var, settings, nRow, nCol);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.Cell(settings, nRow, nCol) = var;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

void		GridControl::SetCell(_VARIANT var, CellPropertySettings settings, int nRow1, int nCol1, int nRow2, int nCol2)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetCell(var, settings, nRow1, nCol1, nRow2, nCol2);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.Cell(settings, nRow1, nCol1, nRow2, nCol2) = var;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__

}

string		GridControl::GetTextMatrix(int nRow, int nCol)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetTextMatrix(nRow, nCol);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.TextMatrix(nRow, nCol);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__

}
void		GridControl::SetTextMatrix(int nRow, int nCol, LPCSTR lpszVal)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetTextMatrix(nRow, nCol, lpszVal);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.TextMatrix(nRow, nCol) = lpszVal;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

_VARIANT		GridControl::GetRowData(int nRow)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetRowData(nRow);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.RowData(nRow);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__

}

void		GridControl::SetRowData(int nRow, _VARIANT var)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetRowData(nRow, var);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.RowData(nRow) = var;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
/// end REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID

void		GridControl::SetColComboList(long Col, string strCombo)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetColComboList(Col, strCombo);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.ColComboList(Col) = strCombo;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
//---	Jacky 09/03/10 IMPLEMENT_WXGRID
//void		GridControl::SetComboItem(long index, string strVal)
//{
//#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	//m_flx.SetComboItem(index, strVal);
//#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	//m_flx.ComboItem(index) = strVal;
//#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
//}
//---	end IMPLEMENT_WXGRID
string		GridControl::GetComboItem(long index)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetComboItem(index);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.ComboItem(index);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

bool		GridControl::GetIsSelected(long Row)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetIsSelected(Row);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.IsSelected(Row);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetIsSelected(long Row, bool bSel)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetIsSelected(Row, bSel);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.IsSelected(Row) = bSel;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

int			GridControl::GetColDataType(long Col)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetColDataType(Col);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.ColDataType(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetColDataType(long Col, int nType)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetColDataType(Col, nType);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.ColDataType(Col) = nType;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

bool		GridControl::GetIsSubtotal(long Row)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetIsSubtotal(Row);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.IsSubtotal(Row);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetIsSubtotal(long Row, bool bVal)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetIsSubtotal(Row, bVal);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.IsSubtotal(Row) = bVal;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
long		GridControl::GetRowOutlineLevel(long Row)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetRowOutlineLevel(Row);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.RowOutlineLevel(Row);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetRowOutlineLevel(long Row, long nLevel)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetRowOutlineLevel(Row, nLevel);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.RowOutlineLevel(Row) = nLevel;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

long		GridControl::GetSelectedRow(long index)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetSelectedRow(index);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.SelectedRow(index);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

void		GridControl::SetColWidth(long Col, int nWidth)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetColWidth(Col, nWidth);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.ColWidth(Col) = nWidth;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
int			GridControl::GetColWidth(long Col = 0)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetColWidth(Col);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.ColWidth(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
int			GridControl::GetRowHeight(long Row)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetRowHeight(Row);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.RowHeight(Row);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetRowHeight(long Row, int nHeight)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetRowHeight(Row, nHeight);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.RowHeight(Row) = nHeight;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

bool		GridControl::GetIsRowHidden(long Row)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetIsRowHidden(Row);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.RowHidden(Row);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetIsRowHidden(long Row, bool bVal)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetIsRowHidden(Row, bVal);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.RowHidden(Row) = bVal;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
bool		GridControl::GetIsColHidden(long Col)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetIsColHidden(Col);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.ColHidden(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
void		GridControl::SetIsColHidden(long Col, bool bVal)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetIsColHidden(Col, bVal);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.ColHidden(Col) = bVal;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

int			GridControl::GetColAlignment(long Col)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetColAlignment(Col);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.ColAlignment(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

int			GridControl::GetFixedAlignment(long Col)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetFixedAlignment(Col);
#else		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.FixedAlignment(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

/// Kenny 04/27/2010 QA80-15357 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID
void		GridControl::SetFixedAlignment(long Col, int nMode)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetFixedAlignment(Col, nMode);
#else
	m_flx.FixedAlignment(Col) = nMode;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

int			GridControl::GetColFormat(long Col)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	return m_flx.GetColFormat(Col);
#else
	return m_flx.ColFormat(Col);
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}

void		GridControl::SetColFormat(long Col, string strFormat)
{
#ifdef		__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
	m_flx.SetColFormat(Col, strFormat);
#else
	m_flx.ColFormat(Col) = strFormat;
#endif		//__REPLACE_VSFLEX_WITH_64_MP_WXGRID__
}
/// End QA80-15357 REPLACE_VSFLEX_WITH_64_MP_COMPATIABLE_WXGRID

/// Hong 05/27/10 ORG-131 MATRIX_ADD_GENERAL_LABEL_SUPPORT_AS_WKSHEET
void		GridControl::SetResizeMode(int nMode)
{
	m_flx.AllowUserResizing = nMode;
}

int			GridControl::GetResizeMode()
{
	return m_flx.AllowUserResizing;
}
/// end MATRIX_ADD_GENERAL_LABEL_SUPPORT_AS_WKSHEET


#endif //_GRID_CONTROL_H_

