#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	dir_p,
	dir_n,
	dir_b,
};
enum{
	method_max,
	method_win,
	method_first,
	method_second,
	method_residue,
};
enum{
	option_r,
	option_p,
};
enum{
	filter_none,
	filter_h,
	filter_num,
};
//put additional include files here
#include <..\Originlab\curve_utils.h>
//#include <..\Originlab\blpwiz.h>
#include <..\originlab\graph_utils.h>
#include <..\originlab\grobj_utils.h>
//#include <..\originlab\pawizcore.h>
#ifdef _FOR_SMART_LOADING_ONLY
	#include <xfGraph_utils.h>
	#include <..\OriginLab\nlsf_utils.h>
	#include <..\originlab\Peaks_Utils.h>
#endif // _FOR_SMART_LOADING_ONLY

/*
* Iris 8/21/2009 QA80-14165 SHOW_PRO_CONTROL_WITH_DISABLE_AND_PRO_TAG							*
* Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO											*
* Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD			*
* Folger 09/27/2010 CODE_CLEANUP_ABOUT_FINDING_PEAKS											*
*/

//put your own support static functions here
static int _get_find_peaks_xf_error_code(int nOCMathErr)
{
	switch (nOCMathErr)
	{
	case OE_BAD_PARAM:
		return XFERR_BAD_PARAM_FOR_FIND_PEAKS;
	case OE_NO_PEAK_FOUND:
		return XFERR_NO_PEAK_FOUND;
	}
	return XFERR_FINDPEAKS_FUNCTION_UNKNOWN_ERR;
}

static bool _get_check_input_data(const TreeNode& trInput, vector& vx, vector&vy, string* pstrErrMsg = NULL)
{	
	XYRange iy;	
	if ( okxf_resolve_tree_construct_range(&trInput, &iy) && iy.GetData(vy, vx) )
	{ // support nonmonotonic data
		///------ Folger 09/27/2010 CODE_CLEANUP_ABOUT_FINDING_PEAKS
		//vector<uint> vnIndices;
		//vx.Sort(SORT_ASCENDING, true, vnIndices);
		//vy.Reorder(vnIndices);
		check_sort_data_for_find_peaks(vy, vx);
		///------ End CODE_CLEANUP_ABOUT_FINDING_PEAKS
		return true;
	}
	
	if ( pstrErrMsg )
		*pstrErrMsg = CER_INVALID_RANGE;	
	return false;
}

static bool _auto_method_parameters(TreeNode& trGetN, const vector& vx, const vector& vy, string* pstrErrMsg = NULL)
{	
	if ( method_win == trGetN.method.nVal )
	{
		double dHeight = 20, dWidth = 50;
		if (trGetN.option.nVal == option_r) //raw size
		{
			double dMin, dMax, dTotalHeight, dTotalWidth;	
			vy.GetMinMax(dMin, dMax);
			dTotalHeight = max(abs(dMax), abs(dMin));
			dTotalWidth = abs(vx[vx.GetSize()-1] - vx[0]); 	
			
			dHeight *= dTotalHeight/100;
			dWidth *= dTotalWidth/100;
		}		
		TreeNode trNode = trGetN.height;
		if ( 1 == octree_get_auto_support(&trNode) )
		{
			trGetN.height.dVal = dHeight;
		}
		trNode = trGetN.height;
		if ( 1 == octree_get_auto_support(&trNode) )
		{
			trGetN.width.dVal = dWidth;
		}
	}
	return true;
}

static bool _auto_filter_parameter(TreeNode& trGetN, const vector& vy, string* pstrErrMsg = NULL)
{
	TreeNode trNode = trGetN.value;	
	if ( 1 == octree_get_auto_support(&trNode) )
	{
		switch ( trGetN.filter.nVal )
		{
		case filter_h:
			double dMin, dMax, dTotalHeight, dDefaultHeightPer = 0.20;	
			vy.GetMinMax(dMin, dMax);
			dTotalHeight = max(abs(dMax), abs(dMin));			
			trNode.dVal = dTotalHeight * dDefaultHeightPer;
			break;
		case filter_num:
			trNode.dVal = 1; // we default peak number to 1 if auto, basically we do NOT encourage user use auto for this case
			break;
		}
	}
	return true;
}

static bool _auto_marker_parameters(TreeNode& trGetN, const vector& vx, const vector& vy, string* pstrErrMsg = NULL)
{
	TreeNode trNode = trGetN.hwidth;	
	if ( 1 == octree_get_auto_support(&trNode) )
	{
		//double dTotalWidth, dDefaultWidthPer = 0.25;	
		double dTotalWidth, dDefaultWidthPer = 1;	//Sandy 2008-6-11 should find in full range for each special data
		dTotalWidth = abs(vx[vx.GetSize()-1] - vx[0]); 			
		trNode.dVal = dTotalWidth * dDefaultWidthPer;
	}
	trNode = trGetN.fheight;	
	if ( 1 == octree_get_auto_support(&trNode) )
	{
		vector vySmoothed;
		vySmoothed = vy;		
		if ( trGetN.smooth.nVal > 1 )
		{
			///------ Folger 09/27/2010 CODE_CLEANUP_ABOUT_FINDING_PEAKS
			//vector vytemp;
			//vytemp = vySmoothed;
			//ocmath_savitsky_golay(vytemp, vySmoothed, vySmoothed.GetSize(), trGetN.smooth.nVal/2);
			ocmath_savitsky_golay(vy, vySmoothed, vySmoothed.GetSize(), trGetN.smooth.nVal/2);
			///------ End CODE_CLEANUP_ABOUT_FINDING_PEAKS
		}
		trNode.dVal = get_feet_height_by_percent_of_total_height(vySmoothed, 0.001);
	}
	return true;
}

/// Hong 06/06/08 v8.0879 SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX
static void _auto_smooth_point(TreeNode& trGetN, bool& bOKEnable, string* pstrErrMsg = NULL)
{
	TreeNode trInput = trGetN.iy;	
	vector vx, vy;
	if ( bOKEnable = _get_check_input_data(trInput, vx, vy, pstrErrMsg) )
		bOKEnable = update_smooth_point(trGetN, vy, pstrErrMsg);
}
/// end SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX

static bool _update_auto_value_by_input_change(TreeNode& trGetN, string* pstrErrMsg = NULL)
{
	// do auto
	TreeNode trInput = trGetN.iy;
	vector vx, vy;
	if ( _get_check_input_data(trInput, vx, vy, pstrErrMsg) )
	{
		// update smooth point
		update_smooth_point(trGetN, vy);
		// auto method parameters
		_auto_method_parameters(trGetN, vx, vy);
		// auto filter parameter
		_auto_filter_parameter(trGetN, vy);			
		// auto marker parameters
		_auto_marker_parameters(trGetN, vx, vy);
		
		//trGetN.npts.nVal = (int)(0.03* vy.GetSize());///Sandy 2008-12-15 local points should not use auto setting , the best local number is 2.
		return true;
	}
	
	return false;
}

static void update_method_params_status(TreeNode& trGetN)
{
	bool bShowPts = (method_max == trGetN.method.nVal) ? true : false;
	trGetN.npts.Show = bShowPts;
	
	bool bShowWinParams = (method_win == trGetN.method.nVal) ? true : false;		
	trGetN.option.Show = bShowWinParams;
	trGetN.height.Show = bShowWinParams;
	trGetN.width.Show = bShowWinParams;
}

static void update_filter_params_status(TreeNode& trGetN)
{
	bool bEnable = (filter_none == trGetN.filter.nVal) ? false : true;
	string strLabel;
	switch ( trGetN.filter.nVal )
	{
	case filter_h:
		strLabel = _L("Threshold Height");
		break;
	case filter_num:
		strLabel = _L("Number of Peaks");
		break;
	case filter_none:
	default:
		strLabel = _L("Filter Value");
	}
	trGetN.value.Enable = bEnable;
	trGetN.value.SetAttribute(STR_LABEL_ATTRIB, strLabel);
}

/* variable marker removed
static void update_marker_params_status(TreeNode& trGetN)
{
	bool bEnable = trGetN.marker.nVal;
	trGetN.hwidth.Enable = bEnable;
	trGetN.fheight.Enable = bEnable;
}
*/
static void _update_variables_status(TreeNode& trGetN)
{
	update_method_params_status(trGetN);
	update_filter_params_status(trGetN);
	//update_marker_params_status(trGetN);
}

void pkFind(const XYRange& iy, const int& smooth, const int& dir, const int& method, const int& npts, const int& option, const double& height, const double& width, const int& filter, const double& value, const double& hwidth, const double& fheight, vector& ocenter, vector& oleft, vector& oright, vector& ocenter_x, vector& ocenter_y, vector& oleft_x, vector& oleft_y, vector& oright_x, vector& oright_y)
{
	vector vx, vy, vxOrigin, vyOrigin;		
	if(!iy.GetData(vy, vx) || vx.GetSize() < 3)
		XF_THROW(XFERR_GET_DATA_FAILED);
	
	///------ Folger 09/27/2010 CODE_CLEANUP_ABOUT_FINDING_PEAKS
	//vxOrigin = vx;
	//vyOrigin = vy;
	///------ End CODE_CLEANUP_ABOUT_FINDING_PEAKS
	
	int nSize = vy.GetSize();
	double maxWidth = width, minHeight = height;
	vector<int> vPeaksInd(nSize);			
	vector vxPeaks(nSize), vyPeaks(nSize);	
	int nRet = find_peaks(vx, vy, vxPeaks, vyPeaks, vPeaksInd, method, maxWidth, minHeight, smooth, dir+1, npts, option, filter-1, &value);
	if ( nRet != OE_NOERROR )
	{
		int nXFErr = _get_find_peaks_xf_error_code(nRet);
		if (nXFErr == XFERR_FINDPEAKS_FUNCTION_UNKNOWN_ERR)
		{
			XF_THROW_EX(XFERR_FINDPEAKS_FUNCTION_UNKNOWN_ERR, nRet);
		}
		else
		{
			XF_THROW(nXFErr);
		}
	}
	
	vector<uint> vn;
	//vPeaksInd.Sort(SORT_ASCENDING, true, vn);
	vxPeaks.Sort(SORT_ASCENDING, true, vn);
	vyPeaks.Reorder(vn);
	vPeaksInd.Reorder(vn);
	
	
	
	// output
	if (ocenter)
		ocenter = vPeaksInd + 1; // convert to LT index
	
	///----Sandy 2008-9-11 QA80-12184 NEED_OUTPUT_MORE_DETAIL_PEAK_INFOMATION_VECTORS 
	if (ocenter_x)
		ocenter_x = vxPeaks; 
	
	if (ocenter_y)
		ocenter_y = vyPeaks; 
	//end
	
	/// find marker	
	
	//if ( oleft || oright )
	if ( oleft || oright || oleft_x || oright_x || oleft_y || oright_y )///----Sandy 2008-9-11 QA80-12184 NEED_OUTPUT_MORE_DETAIL_PEAK_INFOMATION_VECTORS 
	{
		///------ Folger 09/27/2010 CODE_CLEANUP_ABOUT_FINDING_PEAKS
		vxOrigin = vx;
		vyOrigin = vy;
		///------ End CODE_CLEANUP_ABOUT_FINDING_PEAKS
		
		int nPeakNum = vxPeaks.GetSize();
		vector<int> vFeetInd(nPeakNum*2);
		//vxPeaks.Reorder(vn);
		//vyPeaks.Reorder(vn);
		
	
		///Sandy 2008-6-11 should find marker with original data
		//nRet = ocmath_find_markers_of_peaks_by_height_and_width(vy.GetSize(), vx, vy, nPeakNum, vPeaksInd, nPeakNum*2, vFeetInd,  
		nRet = ocmath_find_markers_of_peaks_by_height_and_width(vxOrigin.GetSize(), vxOrigin, vyOrigin, nPeakNum, vPeaksInd, nPeakNum*2, vFeetInd,  
															 fheight, hwidth, 0);
		if (nRet != OE_NOERROR)
		{
			int nXFErr = _get_find_peaks_xf_error_code(nRet);
			if (nXFErr == XFERR_FINDPEAKS_FUNCTION_UNKNOWN_ERR)
			{
				XF_THROW_EX(XFERR_FINDPEAKS_FUNCTION_UNKNOWN_ERR, nRet);
			}
			else
			{
				XF_THROW(nXFErr);
			}
		}
		
		vector vxLFeet, vxRFeet; 
		vector vyLFeet, vyRFeet;	
		get_peaks_info_from_index_within_maxwidth(vyOrigin, vxOrigin, nPeakNum, vPeaksInd, vxPeaks, vyPeaks, vFeetInd, vxLFeet, vyLFeet, vxRFeet, vyRFeet, &hwidth, &hwidth);
		
		// output
		matrix mat;
		mat.SetSize(nPeakNum, 2);
		mat.SetByVector(vFeetInd);		
		if (oleft)
		{
			mat.GetColumn(oleft, 0);
			oleft += 1; // convert to LT index
		}
		
		///----Sandy 2008-9-11 QA80-12184 NEED_OUTPUT_MORE_DETAIL_PEAK_INFOMATION_VECTORS 
		if (oleft_x)
		{
			oleft_x = vxLFeet; 
		}
		
		if (oleft_y)
		{
			oleft_y = vyLFeet; 
		}
		//end
	
	
		if (oright)
		{
			mat.GetColumn(oright, 1);
			oright += 1;// convert to LT index
		}
		
		///----Sandy 2008-9-11 QA80-12184 NEED_OUTPUT_MORE_DETAIL_PEAK_INFOMATION_VECTORS 
		if (oright_x)
		{
			oright_x = vxRFeet; 
		}
		
		if (oright_y)
		{
			oright_y = vyRFeet; 
		}
		//end
	}
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int pkFind_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return pkFind_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	/// Iris 8/21/2009 QA80-14165 SHOW_PRO_CONTROL_WITH_DISABLE_AND_PRO_TAG
	// check and corrent method option for regular version. 
	// and on init also need check input range if valid.
	/*
	// deal init event here
	if ( nEventID == GETNE_ON_INIT )
	{
		_update_variables_status(trGetN);
		return true;
	}
	
	// deal theme swith event here
	if ( nEventID == GETNE_ON_THEME )
	{
		_update_variables_status(trGetN);
		bOKEnable = _update_auto_value_by_input_change(trGetN, &strErrMsg);
		return true;
	}
	*/
	///Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO
	string strTempMethodErrMsg;
	if ( !lstrcmpi(lpcszNodeName, "method") || nEventID == GETNE_ON_INIT || nEventID == GETNE_ON_THEME )
	{
		if( !is_find_peak_method_available(trGetN.method.nVal) )
		{
			string strProOption = get_selected_string_from_combolist(trGetN.method);
			trGetN.method.nVal = method_max;
			if( !lstrcmpi(lpcszNodeName, "method") )
			{
				strTempMethodErrMsg = XFERR_PRO_OPTION_WARNNING_MSG;
				strTempMethodErrMsg += ":" + strProOption;
			}
		}
	}
	///End CENTRALIZE_FIND_PEAK_METHOD_COMBO
	
	if ( nEventID == GETNE_ON_INIT || nEventID == GETNE_ON_THEME )
	{
		_update_variables_status(trGetN);
		
		string strMsgTemp;
		bOKEnable = _update_auto_value_by_input_change(trGetN, &strMsgTemp);
		if( !strMsgTemp.IsEmpty() )
			strErrMsg = strMsgTemp;
		return true;
	}
	///end SHOW_PRO_CONTROL_WITH_DISABLE_AND_PRO_TAG	
	
	if ( !lstrcmpi(lpcszNodeName, "iy") )
	{
		//bOKEnable = _update_auto_value_by_input_change(trGetN, &strErrMsg);	
		string strMsgTemp;
		bOKEnable = _update_auto_value_by_input_change(trGetN, &strMsgTemp);
		if( !strMsgTemp.IsEmpty() )
			strErrMsg = strMsgTemp;
		return true;
	}
	
	if ( !lstrcmpi(lpcszNodeName, "smooth") )
	{
		/// Hong 06/06/08 v8.0879 SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX
		/*
		TreeNode trInput = trGetN.iy;	
		vector vx, vy;
		if ( bOKEnable = _get_check_input_data(trInput, vx, vy, &strErrMsg) )
			bOKEnable = update_smooth_point(trGetN, vy, &strErrMsg);
		*/
		_auto_smooth_point(trGetN, bOKEnable, &strErrMsg);
		/// end SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX
		return true;
	}
	
	if ( !lstrcmpi(lpcszNodeName, "method") )
	{
		update_method_params_status(trGetN);
		/// Hong 06/06/08 v8.0879 SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX
		_auto_smooth_point(trGetN, bOKEnable, &strErrMsg);
		/// end SANDY_ASK_SMOOTH_AUTO_TO_ZERO_FOR_LOCAL_MAX
	
		///Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO
		if( (strErrMsg.IsEmpty() || !lstrcmpi(strErrMsg, "method") )&& !strTempMethodErrMsg.IsEmpty() )
			strErrMsg = strTempMethodErrMsg;
		///End CENTRALIZE_FIND_PEAK_METHOD_COMBO
		return true;
	}
	
	if ( !lstrcmpi(lpcszNodeName, "option") || !lstrcmpi(lpcszNodeName, "width") || !lstrcmpi(lpcszNodeName, "height") )
	{
		TreeNode trInput = trGetN.iy;	
		vector vx, vy;
		if ( bOKEnable = _get_check_input_data(trInput, vx, vy, &strErrMsg) )
			_auto_method_parameters(trGetN, vx, vy);
			
		return true;
	}
	
	if ( !lstrcmpi(lpcszNodeName, "filter") || !lstrcmpi(lpcszNodeName, "value") )
	{
		update_filter_params_status(trGetN);
		TreeNode trInput = trGetN.iy;	
		vector vx, vy;
		if ( bOKEnable = _get_check_input_data(trInput, vx, vy, &strErrMsg) )
			_auto_filter_parameter(trGetN, vy);
		
		return true;
	}
	
	if ( !lstrcmpi(lpcszNodeName, "marker") || !lstrcmpi(lpcszNodeName, "hwidth") || !lstrcmpi(lpcszNodeName, "fheight") )
	{
		//update_marker_params_status(trGetN);				
		TreeNode trInput = trGetN.iy;	
		vector vx, vy;
		if ( bOKEnable = _get_check_input_data(trInput, vx, vy, &strErrMsg) )
			_auto_marker_parameters(trGetN, vx, vy);
		
		return true;
	}
	return false;

}

int pkFind_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void pkFind_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	///Jasmine 08/28/09 CENTRALIZE_FIND_PEAK_METHOD_COMBO
	/*
	/// Hong 06/06/08 v8.0879 REMOVE_PRO_ONLY_METHOD_FROM_REGULAR_PRODUCT
	string		strCombo = REGULAR_FIND_PEAK_METHOD;
	TreeNode	trMethod = trGetN.method;
	if ( is_pro_version() )
	{
		strCombo += "|" + PRO_ONLY_FIND_PEAK_METHOD;	
	}
	else
	{
		/// Iris 8/21/2009 QA80-14165 SHOW_PRO_CONTROL_WITH_DISABLE_AND_PRO_TAG
		string str = PRO_ONLY_FIND_PEAK_METHOD;
		vector<string> vs;
		str.GetTokens(vs, '|');
		for(int nn=0; nn < vs.GetSize(); nn++)
		{
			vs[nn] += " " + STR_PRO_POSTFIX;
		}
		str.SetTokens(vs, '|');
		strCombo += "|" + str;
		///end SHOW_PRO_CONTROL_WITH_DISABLE_AND_PRO_TAG
		
		if ( trMethod.nVal >= strCombo.GetNumTokens() )
			XF_THROW(CER_NOT_AVAILABLE_IN_REGULAR_VERSION);
	}			
	trMethod.SetAttribute(STR_COMBO_ATTRIB, strCombo);
	/// end REMOVE_PRO_ONLY_METHOD_FROM_REGULAR_PRODUCT
	*/
	if(nGetNDialog >= 0)
	{
		string strMethods = get_find_peak_methods();
		trGetN.method.SetAttribute(STR_COMBO_ATTRIB, strMethods);
	}
	/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
	//if( nGetNDialog > 0 && !is_find_peak_method_available(trGetN.method.nVal) )
	//	trGetN.method.nVal = method_max;
	if( !is_find_peak_method_available(trGetN.method.nVal) )
	{
		if(nGetNDialog <= 0)
		{
			string strProOption = get_selected_string_from_combolist(trGetN.method);
			warning_msg_box(XFERR_PRO_OPTION_WARNNING_MSG, strProOption, false, 'E');
			nRet = XFEVT_ABORT;
			return;
		}
		else if( nGetNDialog > 0 )
		{		
			trGetN.method.nVal = method_max;
		}
	}		
	///end SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
	///End CENTRALIZE_FIND_PEAK_METHOD_COMBO
	
	if(nGetNDialog >= 0)
		_update_auto_value_by_input_change(trGetN);
	
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int pkFind_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
