#include "StdAfx.h" #include "RecipeMgr.h" #include "LogMgr.h" #include "FileMgr.h" #include "CStringFuc.h" #include "WaferRecipeDataMgr.h" #include "MsgBox.h" #include "DlgChildRecipe.h" #include "CommonParaMgr.h" #include "GlobalFunction.h" #include "Laser.h" #include "ProgramLaserTuiHuo.h" #include "RecipeMgr.h" #include "DlgRecipeCtrl.h" #include "MyXmlMgr.h" #include "ExceptionMsg.h" #include "AuthorityMgr.h" #include "CommonParaMgr.h" #include "Propertie.h" #include "PropertieMgr.h" #define RECIPE_FILE_PATH _T("\\RecipePar\\") #define RECIPE_GROUP_NAME_FILE _T("\\font\\GroupNameList")//组名列表文件 #define SECS_RECIPE_FILE_PATH _T("\\SecsRecipe") #define RECIPE_GROUP_CNT 10 //recipe 分组的数量 #define ONE_GROUP_PAR_CNT 50 //一个recipe 分组参数的数量 #define NEW_RECIPE_FILE_PATH _T("\\Recipe\\") #define RECIPE_FILE_SUFFIX "rcp" //recipe 文件使用的后缀 #define XML_ITEM_PAR_TYPE "ParType" #define XML_ITEM_PAR_VAL "ParVal" #define RCP_PAR_TYPE_DOUBLE "Double" #define RCP_PAR_TYPE_STRING "String" #define RCP_PAR_TYPE_BOOL "Bool" #define RCP_PAR_TYPE_INT "Int" #define NULL_RECIPE_NAME "" //无效的recipe 名称 #define PARA_MODIFY_DATA_PATH _T("\\ParaModifyRecord\\") #define OFFSET_TAB_FILE_PATH "\\OffsetTable\\TableFile\\" #define MFC_CTRLSCAL _T("\\CommPar\\MFC_CtrlScal.bin") // MFC流量控制系数表 #if 1 CSubRecipe::CSubRecipe(void) { m_bUseSubRecipe = true;//生产中是否使用 ReadMFCCtrlScalFile(); //初始化recipe 参数容器 IntiRecipeParVec(); } //从指定文件中读取Mfc系数 void CSubRecipe::ReadMFCCtrlScalFile() { CFileMgr FileMgr; CString FilePath; vector> StrVec; FileMgr.GetFullFilePath(FilePath, MFC_CTRLSCAL); FileMgr.ReadFileToStrVec(FilePath, StrVec); int StrSize = StrVec.size(); for (int i = 0; i < StrSize; i++) { if (2 == StrVec[i].size()) { MFCScalStrVec.push_back(StrVec[i]); } } return; } //初始化recipe 参数容器(中间可以添加新的参数) void CSubRecipe::IntiRecipeParVec() { //可以被编辑的参数要在前面定义 { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_FRE; RecipePar.m_ParShowName = "Laser1 Frequency"; RecipePar.m_ParUnit = "Hz";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 1000;//默认值 RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_FRE); RecipePar.m_DetailInfo = "激光1频率:一秒内激光脉冲个数"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER2_FRE; RecipePar.m_ParShowName = "Laser2 Frequency"; RecipePar.m_ParUnit = "Hz";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 1000;//默认值 RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_FRE); RecipePar.m_DetailInfo = "激光2频率:一秒内激光脉冲个数"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_PRF2_DELAY; RecipePar.m_ParShowName = "Two Pulse Delay"; RecipePar.m_ParUnit = "ns";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_PULSE_DELAY); RecipePar.m_DetailInfo = "双脉冲延时:激光器脉冲延时时间"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_CURR_1; RecipePar.m_ParShowName = "Laser1 Current"; RecipePar.m_ParUnit = "A";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_CURR_1); RecipePar.m_DetailInfo = "Laser1电流值:工艺设置电流值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_CURR_2; RecipePar.m_ParShowName = "Laser2 Current"; RecipePar.m_ParUnit = "A";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_CURR_2); RecipePar.m_DetailInfo = "Laser2电流值:工艺设置电流值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_EDI_1; RecipePar.m_ParShowName = "Laser1 Edi"; RecipePar.m_ParUnit = "J/cm2";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_EDI_1); RecipePar.m_DetailInfo = "Laser1目标功率密度 :最终的edi还要加上Laser Edi Offset和补偿表中的Laser Edi Offset值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_EDI_2; RecipePar.m_ParShowName = "Laser2 Edi"; RecipePar.m_ParUnit = "J/cm2";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_EDI_2); RecipePar.m_DetailInfo = "Laser2目标功率密度 :最终的edi还要加上Laser Edi Offset和补偿表中的Laser Edi Offset值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_EDI_OFFSET_1; RecipePar.m_ParShowName = "Laser1 Edi Offset"; RecipePar.m_ParUnit = "J/cm2";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = -2; RecipePar.m_DoubleMaxVal = 2; RecipePar.m_DetailInfo = "Laser1目标功率密度补偿"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER_EDI_OFFSET_2; RecipePar.m_ParShowName = "Laser2 Edi Offset"; RecipePar.m_ParUnit = "J/cm2";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = -2; RecipePar.m_DoubleMaxVal = 2; RecipePar.m_DetailInfo = "Laser2目标功率密度补偿"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_EDI_CHECK_SCOPE; RecipePar.m_ParShowName = "Edi Check Scope"; RecipePar.m_ParUnit = "J/cm2";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = 5; RecipePar.m_DetailInfo = "功率密度复检卡控范围:等于0表示不进行复检,大于表示要进行复检且复检调整后的功率密度在这个误差范围之内"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_OVERLAP_RATIO_X; RecipePar.m_ParShowName = "Overlap Rate X"; RecipePar.m_ParUnit = "%";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = 99; RecipePar.m_DetailInfo = "X方向光斑重叠率:会影响X方向扫描速度的计算值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_OVERLAP_RATIO_Y; RecipePar.m_ParShowName = "Overlap Rate Y"; RecipePar.m_ParUnit = "%";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = 99; RecipePar.m_DetailInfo = "Y方向光斑重叠率:会影响Y方向移动间隔"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_FOCUS_ADJUST_VAL; RecipePar.m_ParShowName = "Foucs Adjust Val"; RecipePar.m_ParUnit = "mm";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MIN_FOCUS_ADJUST); RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_FOCUS_ADJUST); RecipePar.m_DetailInfo = "Z轴焦距微调值:用于工艺前Z轴在目前设置的激光焦距点上下进行微调"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_FIX_SCAN_SPEED; RecipePar.m_ParShowName = "Fix Scan Speed"; RecipePar.m_ParUnit = "mm/s";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MIN_SCAN_SPEED); RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_SCAN_SPEED); RecipePar.m_DetailInfo = "固定扫描速度:等于0时无效,大于0时X方向光斑重叠率无效,工艺过程中将使用这个速度值作为X方向的扫描速度"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_FIX_SCAN_LINE_GAP; RecipePar.m_ParShowName = "Fix Scan Line Gap"; RecipePar.m_ParUnit = "mm";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_FIX_SCAN_LINE_GAP); RecipePar.m_DetailInfo = "固定扫描间隔:等于0时无效,大于0时Y方向光斑重叠率无效,工艺过程中将使用这个值作为Y方向的扫描移动间隔"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_SCAN_LINE_START_IDX; RecipePar.m_ParShowName = "Start Scan Line Idx"; //RecipePar.m_ParUnit = "mm";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = 100000; RecipePar.m_DetailInfo = "扫描线的起始索引值:表示从第几根线开始扫描,用于补打wafer"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_ALIGNER_ANG; RecipePar.m_ParShowName = "Wafer Aligner Angle"; RecipePar.m_ParUnit = "degree";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 270; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = 360; RecipePar.m_DetailInfo = "wafer准直角度:用于控制wafer放到stage上的notch方向,多subrcp的情况第一个sub的值为有效值"; m_RecipeParVec.push_back(RecipePar); } { int StrSize = MFCScalStrVec.size(); double m_MinVal = 0.0; double m_MaxVal = 0.0; if (StrSize > 0) { m_MinVal = CStringToDouble(MFCScalStrVec[0][1]); m_MaxVal = CStringToDouble(MFCScalStrVec[StrSize - 1][1]); } CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_N2_VAL; RecipePar.m_ParShowName = "N2 Val"; RecipePar.m_ParUnit = "L";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = m_MinVal; RecipePar.m_DoubleMinVal = m_MinVal; RecipePar.m_DoubleMaxVal = m_MaxVal; RecipePar.m_DetailInfo = "MFC流量控制值:MFC控制N2流量值"; m_RecipeParVec.push_back(RecipePar); } //下拉框参数------------------------------------------------ { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_SCAN_AREA; RecipePar.m_ParShowName = "Scan Area"; RecipePar.m_ParType = _RecipeParType_CString;//参数的类型 RecipePar.m_DetailInfo = "扫描区域文件名称:用于指定扫描区域的图形文件,确定扫描的范围"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_AREA_IDX; RecipePar.m_ParShowName = "Area Idx"; RecipePar.m_ParType = _RecipeParType_Int;//参数的类型 RecipePar.m_ParIntVal = 1; RecipePar.m_DetailInfo = "扫描区域编号:扫描区域文件中包含多个扫描区域时,每个sub rcp只能选择一个区域编号进行工艺"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_N2_STATE; RecipePar.m_ParShowName = "N2"; RecipePar.m_ParType = _RecipeParType_Bool;//参数的类型 RecipePar.m_ParBoolVal = true; RecipePar.m_DetailInfo = "N2开关控制,退火过程中是否自动打开N2"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_USE_CUR_N2VAL; RecipePar.m_ParShowName = "Use CurN2Val"; RecipePar.m_ParType = _RecipeParType_Bool;//参数的类型 RecipePar.m_ParBoolVal = false; RecipePar.m_DetailInfo = "MFC控制开关:是否使用recipe的MFC流量控制值"; m_RecipeParVec.push_back(RecipePar); } #ifdef __OFFSET_TABLE__ { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_OFFSET_TAB; RecipePar.m_ParShowName = "Offset Table"; RecipePar.m_ParType = _RecipeParType_CString;//参数的类型 RecipePar.m_ParStrVal = RECIPE_OFFSET_TBL_NULL; RecipePar.m_DetailInfo = "补偿表的名称:用于link指定的补偿表,可以补偿edi和激光电流值"; m_RecipeParVec.push_back(RecipePar); } #endif { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_RUNTIMES; RecipePar.m_ParShowName = "Run Times"; RecipePar.m_ParType = _RecipeParType_Int;//参数的类型 RecipePar.m_ParIntVal = 1;//默认值 RecipePar.m_DetailInfo = "工艺运行次数:正常设置为1,大于1时表示跑cycle,多subrcp的情况第一个sub的值为有效值"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_CASSETTE_TIER_COUNT; RecipePar.m_ParShowName = "Cassette Tier Cout"; RecipePar.m_ParUnit = ""; RecipePar.m_ParType = _RecipeParType_Int;//参数的类型 RecipePar.m_ParDoubleVal = 13;//默认值 RecipePar.m_DoubleMinVal = 13; RecipePar.m_DoubleMaxVal = 25; RecipePar.m_DetailInfo = "料盒层数设置:设置料盒层数,机械手根据料盒层数mapping"; m_RecipeParVec.push_back(RecipePar); } //不能被编辑的参数--------------------------------------------------------------- #if 1 { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER1_POW; RecipePar.m_ParShowName = "Laser1 Power"; RecipePar.m_ParUnit = "w";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_POW_1); RecipePar.m_bRcpInfoPar = true;//是否为计算参数(不能被编辑) //RecipePar.m_DetailInfo = "Laser1功率值:1.Laser固定电流为0时,根据edi自动计算 2.Laser固定电流大于0时,在功率点检表中查找对应的功率值,用于计算衰减角度"; RecipePar.m_DetailInfo = "Laser1功率值:在功率点检表中查找对应的功率值,用于计算衰减角度"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_LASER2_POW; RecipePar.m_ParShowName = "Laser2 Power"; RecipePar.m_ParUnit = "w";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_LASER_POW_2); RecipePar.m_bRcpInfoPar = true;//是否为计算参数(不能被编辑) //RecipePar.m_DetailInfo = "Laser2功率值:1.Laser固定电流为0时,根据edi自动计算 2.Laser固定电流大于0时,在功率点检表中查找对应的功率值,用于计算衰减角度"; RecipePar.m_DetailInfo = "Laser2功率值:在功率点检表中查找对应的功率值,用于计算衰减角度"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_SCAN_SPEED; RecipePar.m_ParShowName = "Scan Speed"; RecipePar.m_ParUnit = "mm/s";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MIN_SCAN_SPEED); RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_SCAN_SPEED); RecipePar.m_bRcpInfoPar = true;//是否为计算参数(不能被编辑) RecipePar.m_DetailInfo = "X方向扫描速度:固定扫描速度等于0时,由X方向重叠率计算得出,固定扫描速度大于0时,等于固定扫描速度"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_ROTATO_DIMMER_ANG; RecipePar.m_ParShowName = "Dimmer1 Angle"; RecipePar.m_ParUnit = "degree";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_DIMMER_ANG_1); RecipePar.m_bRcpInfoPar = true;//是否为计算参数(不能被编辑) RecipePar.m_DetailInfo = "Laser1衰减角度:由edi,频率,功率计算得出的衰减器角度,固定电流值大于0才会生效"; m_RecipeParVec.push_back(RecipePar); } { CRecipeParameter RecipePar; RecipePar.m_ParName = RECIPE_PAR_NAME_ROTATO_DIMMER_ANG2; RecipePar.m_ParShowName = "Dimmer2 Angle"; RecipePar.m_ParUnit = "degree";//参数的单位,用于显示 RecipePar.m_ParType = _RecipeParType_Double;//参数的类型 RecipePar.m_ParDoubleVal = 0; RecipePar.m_DoubleMinVal = 0; RecipePar.m_DoubleMaxVal = gCommonParaMgr->GetCommonParaVal(RECIPE_PAR_MAX_DIMMER_ANG_2); RecipePar.m_bRcpInfoPar = true;//是否为计算参数(不能被编辑) RecipePar.m_DetailInfo = "Laser2衰减角度:由edi,频率,功率计算得出的衰减器角度,固定电流值大于0才会生效"; m_RecipeParVec.push_back(RecipePar); } #endif } #endif #if 1 //根据参数的类型返回CString 类型值 CString CRecipeParameter::GetParStr() { CString ParStr; switch(m_ParType) { case _RecipeParType_Double: ParStr = Db2CString(m_ParDoubleVal); break; case _RecipeParType_Bool: ParStr = (m_ParBoolVal)?(BOOL_STR_ON):(BOOL_STR_OFF); break; case _RecipeParType_CString: ParStr = m_ParStrVal; break; case _RecipeParType_Int: ParStr = Int2CString(m_ParIntVal); break; default: break; } return ParStr; } CString CRecipeParameter::GetParTypeStr() { CString Str; switch(m_ParType) { case _RecipeParType_Double: Str = RCP_PAR_TYPE_DOUBLE; break; case _RecipeParType_Bool: Str = RCP_PAR_TYPE_BOOL; break; case _RecipeParType_CString: Str = RCP_PAR_TYPE_STRING; break; case _RecipeParType_Int: Str = RCP_PAR_TYPE_INT; break; default: break; } return Str; } void CRecipeParameter::SetValByStr(CString s) { switch(m_ParType) { case _RecipeParType_Double: m_ParDoubleVal = CStringToDouble(s); break; case _RecipeParType_Bool: m_ParBoolVal = ((s==BOOL_STR_ON))?(true):(false); break; case _RecipeParType_CString: m_ParStrVal = s; break; case _RecipeParType_Int: m_ParIntVal = CStringToInt(s); break; default: break; } } void CRecipeParameter::SetTypeByStr(CString TypeStr) { if(TypeStr==RCP_PAR_TYPE_DOUBLE) { m_ParType = _RecipeParType_Double; } if(TypeStr==RCP_PAR_TYPE_STRING) { m_ParType = _RecipeParType_CString; } if(TypeStr==RCP_PAR_TYPE_BOOL) { m_ParType = _RecipeParType_Bool; } if(TypeStr==RCP_PAR_TYPE_INT) { m_ParType = _RecipeParType_Int; } } void CRecipeParameter::GetRangeStr(CString &Min,CString &Max) { if(m_ParType==_RecipeParType_Double) { Min = Db2CString(m_DoubleMinVal); Max = Db2CString(m_DoubleMaxVal); } else { Min = Max = "---"; } } #endif #if 1 CRecipe::CRecipe(void) { m_DoubleValCnt = 0;//double 类型参数的数量 m_GroupIdx = -1;//组的编号 m_RecipeIdx = -1;//在组中的编号 m_CurSubRecipeIdx = 0;//当前使用的SubRecipe 索引号 m_bEnableEdit = true;//当前时候可以编辑 RecipeReset(); CSubRecipe SubRecipe; SubRecipe.m_SubRecipeName = "SubRecipe1"; m_SubRecipeVec.push_back(SubRecipe);//默认有一个SubRecipe } void CRecipe::RecipeReset() { m_RecipeName = NULL_RECIPE_NAME;//Recipe 名 } bool CRecipe::IsValid() { return (m_RecipeName != NULL_RECIPE_NAME); } vector &CRecipe::GetRecipeParVec() { return m_SubRecipeVec[m_CurSubRecipeIdx].m_RecipeParVec; }; //保存RecipePar 到文件 void CRecipe::SaveRecipeParToFile(CString FilePath) { } //从文件读取recipe 参数 void CRecipe::ReadRecipeParFromFile(CString FilePath) { } //通过参数名获取参数 CRecipeParameter CRecipe::GetRecipePar(CString ParName) { CRecipeParameter Par; vector &RecipeParVec = GetRecipeParVec(); int size = RecipeParVec.size(); for(int i=0;i &RecipeParVec = GetRecipeParVec(); int size = RecipeParVec.size(); for(int i=0;iWriteDebugLog("Func---->Check Recipe Par Range"); vector &RecipeParVec = GetRecipeParVec(); int size = RecipeParVec.size(); for(int i=0;iGetCommonParaVal(RecipePar.m_ParName); if(IsDbEqualZero(DoubleMaxVal)) DoubleMaxVal = RecipePar.m_DoubleMaxVal; if(ParValDoubleMaxVal) { CString s,s1; s += "["; s += RecipePar.m_ParShowName; s += "]"; s1.Format(" : %.2f",ParVal); s += s1; s1.Format("\n超出范围[%.2f~%.2f]",RecipePar.m_DoubleMinVal,DoubleMaxVal); s += s1; if(bShowMsg) { CMsgBox MsgBox; MsgBox.Show(s); } return false; } return true; } //检查ParName 参数的范围 bool CRecipe::CheckParRangeByName(CString ParName,double val) { CRecipeParameter RecipePar = GetRecipePar(ParName); return CheckParRangeExt(RecipePar,val,true); } //获取显示用的名字 CString CRecipe::GetShowName() { CString s("无"); if(m_GroupIdx>=0 && m_RecipeIdx>=0) { s.Format("[%d][%d]",m_GroupIdx+1,m_RecipeIdx+1); s += m_RecipeName; } else//恢复用recipe { s = "Recover : "+m_RecipeName; } return s; } void CRecipe::AddSubRecipe(CString SubRecipeName) { int size = m_SubRecipeVec.size(); if(size>0) { CSubRecipe SubRecipe = m_SubRecipeVec[m_CurSubRecipeIdx];//用当前选择的sub recipe 进行复制 SubRecipe.m_SubRecipeName = SubRecipeName; m_SubRecipeVec.push_back(SubRecipe); } } void CRecipe::DelSubRecipe(CString SubRecipeName) { int size = m_SubRecipeVec.size(); if(m_SubRecipeVec.size()>1)//两个以上才能删除 { vector::iterator iter = m_SubRecipeVec.begin(); vector::iterator iter_end = m_SubRecipeVec.end(); for(;iter!=iter_end;iter++) { if((*iter).m_SubRecipeName == SubRecipeName) { m_SubRecipeVec.erase(iter); m_CurSubRecipeIdx = 0; break; } } } } CString CRecipe::GetCurSubRecipeName() { CString RecipeName; if(m_CurSubRecipeIdx>=0 && m_CurSubRecipeIdx=0 && m_CurSubRecipeIdxGetOffsetTablePath(TableName); CSubRecipe &SubRecipe = m_SubRecipeVec[m_CurSubRecipeIdx]; bool Ret = SubRecipe.m_OffsetTable.ReadOffsetTableFile(TableFilePath); if(TableName==RECIPE_OFFSET_TBL_NULL) Ret = true; return Ret; } //获取OffsetTable指定参数的值 double CRecipe::GetOffsetParVal(CString ParName) { CSubRecipe &SubRecipe = m_SubRecipeVec[m_CurSubRecipeIdx]; return SubRecipe.m_OffsetTable.GetOffsetParVal(ParName); } #endif CRecipeMgr *gRecipeMgr = new CRecipeMgr; CRecipeMgr::CRecipeMgr(void) { m_CurSelGroupIdx = 0;//当前选择的gourp 索引值 m_CurSelRecipeIdx = 0;//当前选择的recipe 索引值 m_CurSelRecipeParIdx = -1;//当前选择的par 索引值 m_pRecipeGroupComb = NULL; m_FocusAdjustMin = 0;//焦距调整范围最小值 m_FocusAdjustMax = 0;//焦距调整范围最大值 } CRecipeMgr::~CRecipeMgr(void) { } void CRecipeMgr::OnAppInitialize() { //创建recipe 目录 CreatRecipeFilePath(); //初始化recipe dlg CDlgChildRecipe *pDlg = dynamic_cast(gChildRecipe); pDlg->InitDialogItem(); } //获取参数名list 文件路径 CString CRecipeMgr::GetRecipeNameListPath() { CFileMgr FileMgr; CString FilePath; FileMgr.GetFullFilePath(FilePath,RECIPE_GROUP_NAME_FILE);//获取完整路径 return FilePath; } //获取参数组的路径GroupIdx(0~RECIPE_GROUP_CNT) CString CRecipeMgr::GetGroupDirPath(int GroupIdx) { CFileMgr FileMgr; CString FilePath; CString GroupDirName; GroupDirName.Format("ParGroup%d\\",GroupIdx); GroupDirName = RECIPE_FILE_PATH + GroupDirName; FileMgr.GetFullFilePath(FilePath,GroupDirName);//获取完整路径 return FilePath; } //设置当前选中的Recipe 索引值 void CRecipeMgr::SetCurSelRecipeIdx(int Idx) { int size = m_CurGroupRecipeVec.size(); if(Idx>=0 && IdxWriteDebugLog(s); } } #if 1 //保存当前选择的Recipe void CRecipeMgr::SaveCurSelRecipe(CRecipe Recipe) { int size = m_CurGroupRecipeVec.size(); if(m_CurSelRecipeIdx>=0 && m_CurSelRecipeIdx",m_CurSelGroupIdx+1); Num2.Format("<%d>",m_CurSelRecipeIdx+1); CString GroupRecipeStr; GroupRecipeStr += Num1; GroupRecipeStr += m_RecipeGroupNameVec[m_CurSelGroupIdx]; GroupRecipeStr += Num2; GroupRecipeStr += m_CurGroupRecipeVec[m_CurSelRecipeIdx].m_RecipeName; return GroupRecipeStr; } //创建当前recipe 的扫描路径 void CRecipeMgr::CreatRecipeScanPath(CRecipe *pRecipe,int SubRecipeIdx) { pRecipe->SetCurSubRecipeIdx(SubRecipeIdx);//设置为当前的SubRecipeIdx CRecipeParameter RecipePar; //打开扫描区域 CString AreaName; RecipePar = pRecipe->GetRecipePar(RECIPE_PAR_NAME_SCAN_AREA); AreaName = RecipePar.m_ParStrVal; if(!gWaferRecipeDataMgr->SelScanAreaByName(AreaName)) { CString Msg("扫描区域不存在: "); Msg += AreaName; CExceptionMsg ExceptionMsg; ExceptionMsg.SetMsg(Msg); throw ExceptionMsg; } //创建扫描路径 int AreaIdx; RecipePar = pRecipe->GetRecipePar(RECIPE_PAR_NAME_AREA_IDX); AreaIdx = RecipePar.m_ParIntVal-1; gWaferRecipeDataMgr->CreatScanPath(AreaIdx); m_pView->RefreshView(); } void CRecipeMgr::CreatScanPath(CString AreaName,int AreaIdx) { //打开路径 if(!gWaferRecipeDataMgr->SelScanAreaByName(AreaName)) { return; } //创建扫描路径 gWaferRecipeDataMgr->CreatScanPath(AreaIdx); //默认选择area //CObjContainer &ObjContainer = gLayer.GetObjContainer(); //ObjContainer.SelObjByIdx(AreaIdx); m_pView->RefreshView(); } #endif #if 1 #if 1 CString CRecipeMgr::GetRecipePath() { CString DirPath = gProgramLaserTuiHuo->GetLaipuLaserDataDir(NEW_RECIPE_FILE_PATH); return DirPath; } void CRecipeMgr::CreatRecipeFilePath() { CString DirPath = GetRecipePath(); CFileMgr FileMgr; if(!FileMgr.IsDirectoryExists(DirPath)) FileMgr.CreatDir(DirPath); DirPath += "\\"; } //获取组Recipe文件的完整路径(参数RecipeName 无后缀) CString CRecipeMgr::GetCtrlRecipeFilePath(CString GroupName,CString RecipeName) { CString Path = GetRecipePath(); Path += GroupName; Path += "\\"; Path += RecipeName; Path += "."; Path += RECIPE_FILE_SUFFIX; return Path; } #endif #if 1 //设置当前选中的group 索引值 void CRecipeMgr::SetCurSelGourpIdx(int Idx) { int size = m_NewRecipeGroupNameVec.size(); if(Idx>=0 && Idx &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); CString Name; Name.Format("SubRecipe%ld",SubRecipeVec.size()+1); EditName1 = m_CurSelRecipeName; EditName2 = Name; } break; case _RecipeCtrl_DelSubRecipe: { CtrlItem.m_DlgTitle = "Delete Sub Recipe"; vector &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); EditName1 = m_CurSelRecipeName; EditName2 = SubRecipeVec[m_CurEditRecipe.m_CurSubRecipeIdx].m_SubRecipeName; } break; case _RecipeCtrl_SubRecipeName: { CtrlItem.m_DlgTitle = "Sub Recipe ReName"; vector &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); EditName1 = SubRecipeVec[m_CurEditRecipe.m_CurSubRecipeIdx].m_SubRecipeName; EditName2 = EditName1; } break; default: break; } } //绑定组下拉列表 void CRecipeMgr::BindingRecipeGroupComb(CComboBox *p) { m_pRecipeGroupComb = p; UpdateRecipeGroupVec(); UpdateRecipeGroupComb(m_pRecipeGroupComb); }; //刷新RecipeGroup 信息 void CRecipeMgr::UpdateRecipeGroupInfo() { UpdateRecipeGroupVec(); UpdateRecipeGroupComb(m_pRecipeGroupComb); } //更新组列表容器 void CRecipeMgr::UpdateRecipeGroupVec() { m_NewRecipeGroupNameVec.clear(); CString DirPath = GetRecipePath(); CFileMgr FileMgr; vector FilePathVec; FileMgr.GetChildFileOrDirName(true,GetRecipePath(),FilePathVec,""); int size = FilePathVec.size(); for(int k=0;k=0) ComboBox.SetCurSel(idx); } void CRecipeMgr::UpdateSelRecipeComb(CComboBox &ComboBox,vector &SelGroupRecipeNameVec) { ComboBox.ResetContent();//清空 //从当前选中的recipe 目录读取recipe 文件列表 ReadCurGroupRecipeName(SelGroupRecipeNameVec); int size = SelGroupRecipeNameVec.size(); for(int k=0;k &SubRecipeVec = Recipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); for(int k=0;k &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); for(int k=0;k &RecipeParVec = m_CurEditRecipe.GetRecipeParVec(); int size = RecipeParVec.size(); if(size<=0) return; int RecipeListIdx = 0; int RecipeInfoListIdx = 0; for(int k=0;k &RecipeParVec = Recipe.GetRecipeParVec(); int size = RecipeParVec.size(); if(size<=0) return; int RecipeListIdx = 0; int RecipeInfoListIdx = 0; for(int k=0;k &RecipeParVec = Recipe.GetRecipeParVec(); int size = RecipeParVec.size(); int RecipeListIdx = 0; int RecipeInfoListIdx = 0; for(int k=0;kGetCurUserName(),true); CsvData.AddData("操作时间",false); CsvData.AddData(WorkTime.GetDateTime("/",":"),true); CsvData.AddData("Group 路径",false); CsvData.AddData(Path,true); CsvData.AddData("操作类型",false); CsvData.AddData("删除recipe group",true); vector RcpPathVec; FileMgr.GetChildFileOrDirName(false,Path,RcpPathVec,RECIPE_FILE_SUFFIX); int size1 = RcpPathVec.size(); for(int i=0;iWriteDebugLog(RecipeFilePath); CRecipe Recipe; SaveRecipeToXml(RecipeFilePath,Recipe); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_AddRecipe; RecipeCtrlPar.m_FilePath = RecipeFilePath; RecipeCtrlPar.m_RcpName = RecipeName; SaveRecipeHistoy(RecipeCtrlPar); } //删除Recipe void CRecipeMgr::DeletRecipe(CString RecipeName) { CString Path = GetCtrlRecipeFilePath(m_CurSelGroupName,RecipeName); CFileMgr FileMgr; FileMgr.DeleteFolder(Path); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_DelRecipe; RecipeCtrlPar.m_FilePath = Path; RecipeCtrlPar.m_RcpName = RecipeName; SaveRecipeHistoy(RecipeCtrlPar); } //移动recipe 到GroupName void CRecipeMgr::MoveRecipe(CString GroupName,CString RecipeName) { CString OldPath = GetCtrlRecipeFilePath(m_CurSelGroupName,RecipeName); CString NewPath = GetCtrlRecipeFilePath(GroupName,RecipeName); CFileMgr FileMgr; FileMgr.MoveFolder(OldPath,NewPath); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_MoveRecipe; RecipeCtrlPar.m_FilePath = OldPath; RecipeCtrlPar.m_NewFilePath = NewPath; RecipeCtrlPar.m_RcpName = RecipeName; SaveRecipeHistoy(RecipeCtrlPar); } //复制选择的recipe 到当前的group void CRecipeMgr::CopyRecipe(CString NewRecipeName) { if(!CheckRecipeNameExist(NewRecipeName)) return; CString OldPath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurSelRecipeName); CString NewPath = GetCtrlRecipeFilePath(m_CurSelGroupName,NewRecipeName); CFileMgr FileMgr; FileMgr.CopyFolder(OldPath,NewPath); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_CopyRecipe; RecipeCtrlPar.m_FilePath = OldPath; RecipeCtrlPar.m_RcpName = m_CurSelRecipeName; RecipeCtrlPar.m_RcpNameNew = NewRecipeName; SaveRecipeHistoy(RecipeCtrlPar); } bool CRecipeMgr::ReadEditRecipeFromFile() { CString RecipeFilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurSelRecipeName); if(ReadRecipeFromXml(RecipeFilePath,m_CurEditRecipe)) { m_CurEditRecipe.m_RecipeName = m_CurSelRecipeName; return true; } return false; } bool CRecipeMgr::ReadEditRecipeFromFile(CRecipe &Recipe,int SelGroupIdx,CString SelRecipeName) { int size = m_NewRecipeGroupNameVec.size(); if(SelGroupIdx<0||SelGroupIdx>=size) return false; CString SelGroupName = m_NewRecipeGroupNameVec[SelGroupIdx]; CString RecipeFilePath = GetCtrlRecipeFilePath(SelGroupName,SelRecipeName); Recipe.m_RecipeName = SelRecipeName; return ReadRecipeFromXml(RecipeFilePath,Recipe); } //改变组名称 void CRecipeMgr::ChangeGroupName(CString NewGroupName) { CString OldGroupPath = GetRecipePath(); CString NewGroupPath = OldGroupPath + NewGroupName; OldGroupPath += m_CurSelGroupName; CFileMgr FileMgr; FileMgr.ReNameFolder(OldGroupPath,NewGroupPath); m_CurSelGroupName = NewGroupName; m_CurEditRecipe.m_FilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurSelRecipeName); } //改变recipe 名称 void CRecipeMgr::ChangeRecipeName(CString NewRcpName) { if(!CheckRecipeNameExist(NewRcpName)) return; CString OldPath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurSelRecipeName); CString NewPath = GetCtrlRecipeFilePath(m_CurSelGroupName,NewRcpName); CFileMgr FileMgr; FileMgr.ReNameFolder(OldPath,NewPath); SetCurSelRecipeName(NewRcpName); m_CurEditRecipe.m_FilePath = NewPath; } //改变SubRecipe 名称 void CRecipeMgr::ChangeSubRecipeName(CString NewRcpName) { m_CurEditRecipe.SetCurSubRecipeName(NewRcpName); //保存 CString RecipeFilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurEditRecipe.m_RecipeName); SaveRecipeToXml(m_CurEditRecipe.m_FilePath,m_CurEditRecipe); } CString CRecipeMgr::GetRecipeCtrlName(ERecipeCtrlType RecipeCtrlType) { CString CtrlName; switch(RecipeCtrlType) { case _RecipeCtrl_AddGroup: CtrlName = "Add Group"; break; case _RecipeCtrl_DelGroup: CtrlName = "Delete Group"; break; case _RecipeCtrl_GroupName: CtrlName = "Group ReName"; break; case _RecipeCtrl_AddRecipe: CtrlName = "Add Recipe"; break; case _RecipeCtrl_DelRecipe: CtrlName = "Delete Recipe"; break; case _RecipeCtrl_CopyRecipe: CtrlName = "Copy Recipe"; break; case _RecipeCtrl_MoveRecipe: CtrlName = "Move Recipe"; break; case _RecipeCtrl_RecipeName: CtrlName = "Recipe ReName"; break; case _RecipeCtrl_AddSubRecipe: CtrlName = "Add SubRecipe"; break; case _RecipeCtrl_DelSubRecipe: CtrlName = "Delete SubRecipe"; break; case _RecipeCtrl_SubRecipeName: CtrlName = "SubRecipe ReName"; break; default: break; } return CtrlName; } //从当前选中的recipe 目录读取recipe 文件列表 void CRecipeMgr::ReadCurGroupRecipeName(vector &SelGroupRecipeNameVec) { SelGroupRecipeNameVec.clear(); CString RecipePath = GetRecipePath(); RecipePath += m_CurSelGroupName; CFileMgr FileMgr; vector FilePathVec; FileMgr.GetChildFileOrDirName(false,RecipePath,FilePathVec,RECIPE_FILE_SUFFIX); int size = FilePathVec.size(); for(int k=0;k" + EditName2; bUpdateRecipeGroup = true; break; case _RecipeCtrl_RecipeName: ChangeRecipeName(EditName2); CtrlStr = EditName1 + "->" + EditName2; bUpdateRecipeGroup = false; break; case _RecipeCtrl_AddRecipe: AddRecipe(SelGroupName,EditName2); CtrlStr = EditName2 + " To Group : " + SelGroupName; break; case _RecipeCtrl_DelRecipe: DeletRecipe(EditName2); CtrlStr = EditName2 + "Delete From Group: " + EditName1; break; case _RecipeCtrl_MoveRecipe: MoveRecipe(SelGroupName,EditName2); CtrlStr = EditName2 + " To Group : " + SelGroupName; break; case _RecipeCtrl_CopyRecipe: CopyRecipe(EditName2); CtrlStr = EditName1 + "Copy To: " + EditName2; break; case _RecipeCtrl_AddSubRecipe: AddSubRecipe(EditName2); CtrlStr = EditName2 + " To Recipe : " + EditName1; break; case _RecipeCtrl_DelSubRecipe: DelSubRecipe(EditName2); CtrlStr = EditName2 + " From Recipe : " + EditName1; break; case _RecipeCtrl_SubRecipeName: ChangeSubRecipeName(EditName2); CtrlStr = EditName1 + "->" + EditName2; break; default: break; } if(bUpdateRecipeGroup) { UpdateRecipeGroupVec(); UpdateRecipeGroupComb(m_pRecipeGroupComb); } CString CtrlName = "RecipeCtrl-->"; CtrlName += GetRecipeCtrlName(RecipeCtrlType); CtrlName += " : "; CString Log = CtrlName + CtrlStr; gLogMgr->WriteDebugLog(Log); return ErrMsg; } bool CRecipeMgr::EditRecipeByCtrlType(ERecipeCtrlType CtrlType) { CString ErrMsg; //检查执行条件 switch(CtrlType) { case _RecipeCtrl_AddGroup: break; case _RecipeCtrl_AddRecipe: break; case _RecipeCtrl_GroupName: if(m_CurSelGroupName=="") { ErrMsg = "没有选择要操作的group"; } break; case _RecipeCtrl_RecipeName: case _RecipeCtrl_MoveRecipe: case _RecipeCtrl_CopyRecipe: case _RecipeCtrl_DelRecipe: case _RecipeCtrl_AddSubRecipe: case _RecipeCtrl_DelSubRecipe: if(!IsbSelEditRecipe()) ErrMsg = "没有选择要操作的Recipe"; break; default: break; } if(ErrMsg=="" && CtrlType==_RecipeCtrl_DelSubRecipe) { if(m_CurEditRecipe.GetSubRecipeVec().size()<=1) ErrMsg = "只有一个sub Recipe 不能删除"; } if(ErrMsg!="") { CMsgBox MsgBox; MsgBox.Show(ErrMsg); return false; } m_CurRecipeCtrlType = CtrlType; CDlgRecipeCtrl dlg; return (dlg.DoModal()==IDOK); } //添加一个sub recipe 到当前编辑的recipe 中 void CRecipeMgr::AddSubRecipe(CString SubRecipeName) { m_CurEditRecipe.AddSubRecipe(SubRecipeName); //保存 CString RecipeFilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurEditRecipe.m_RecipeName); SaveRecipeToXml(m_CurEditRecipe.m_FilePath,m_CurEditRecipe); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_AddSubRecipe; RecipeCtrlPar.m_FilePath = RecipeFilePath; RecipeCtrlPar.m_RcpName = m_CurEditRecipe.m_RecipeName; RecipeCtrlPar.m_SubRcpName = SubRecipeName; SaveRecipeHistoy(RecipeCtrlPar); } void CRecipeMgr::DelSubRecipe(CString SubRecipeName) { m_CurEditRecipe.DelSubRecipe(SubRecipeName); //保存 CString RecipeFilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurEditRecipe.m_RecipeName); SaveRecipeToXml(m_CurEditRecipe.m_FilePath,m_CurEditRecipe); CRecipeCtrlPar RecipeCtrlPar; RecipeCtrlPar.m_CtrlType = _RecipeCtrl_DelSubRecipe; RecipeCtrlPar.m_FilePath = RecipeFilePath; RecipeCtrlPar.m_RcpName = m_CurEditRecipe.m_RecipeName; RecipeCtrlPar.m_SubRcpName = SubRecipeName; SaveRecipeHistoy(RecipeCtrlPar); } //移动SubRecipe 的顺序 bool CRecipeMgr::MoveSubRecipe(bool bMoveUp) { if(!IsbSelEditRecipe()) { CMsgBox MsgBox; MsgBox.Show("没有选择要操作的Recipe"); return false; } int CurSubRecipeIdx = m_CurEditRecipe.m_CurSubRecipeIdx; int SwapSubRecipeIdx = (bMoveUp)?(CurSubRecipeIdx-1):(CurSubRecipeIdx+1);//交换的索引值 vector &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); if(SwapSubRecipeIdx >=0 && SwapSubRecipeIdx &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); if(idx>=0&&idx=0&&idxWriteDebugLog(Log); CMyXmlMgr XmlMgr; XmlMgr.SaveXmlItemToFile(FilePath,XmlItemRoot); Log += " Complete" ; gLogMgr->WriteDebugLog(Log); } //从xml 文件中读取Recipe 参数 bool CRecipeMgr::ReadRecipeFromXml(CString FilePath,CRecipe &Recipe) { CMyXmlMgr XmlMgr; CMyXmlItem XmlItemRoot; XmlMgr.ReadXmlItemFromFile(FilePath,XmlItemRoot); vector &SubRecipeVec = XmlItemRoot.m_XmlItemVec; int SubRecipeCnt = SubRecipeVec.size(); if(SubRecipeCnt<=0) { return false; } Recipe.m_FilePath = FilePath; Recipe.m_SubRecipeVec.clear(); Recipe.m_CurSubRecipeIdx = 0; for(int i=0;i &RecipeParVec = XmlItemSubRecipe.m_XmlItemVec; int ParCnt = RecipeParVec.size(); for(int j=0;j &RecipeParInfoVec = XmlItemRecipePar.m_XmlItemVec; int ParInfoCnt = RecipeParInfoVec.size(); for(int k=0;k &RecipeParInfoValVec = XmlItemParInfo.m_XmlItemVec; if(!RecipeParInfoValVec.empty()) { ParInfoVal = RecipeParInfoValVec[0].m_XmlItemName; } if(ParInfoName==XML_ITEM_PAR_TYPE) { XmlRecipePar.SetTypeByStr(ParInfoVal); } if(ParInfoName==XML_ITEM_PAR_VAL) { XmlRecipePar.SetValByStr(ParInfoVal); } } vector &SubRecipeParVec = SubRecipe.m_RecipeParVec; int SubRecipeParCnt = SubRecipeParVec.size(); for(int m=0;mWriteDebugLog(Log); return true; } //创建当前检测数据目录 CString CRecipeMgr::CreatCurParDataPath() { CString MonitoringDataPath = gProgramLaserTuiHuo->GetLaipuLaserDataDir(PARA_MODIFY_DATA_PATH); CString Path = MonitoringDataPath; CFileMgr FileMgr; CWorkTime WorkTime; Path += WorkTime.GetCurYear(); Path += "\\"+WorkTime.GetCurMonth(); Path += "\\"+WorkTime.GetCurDay(); Path += "\\"; if(!FileMgr.IsDirectoryExists(Path)) { FileMgr.CreatDir(Path); } return Path; } void CRecipeMgr::ResetParIdxSet() { m_ErrRangeParIdxSet.clear(); m_ChangeParIdxSet.clear(); } //保存当前编辑的recipe bool CRecipeMgr::SaveEditRecipePar(CListCtrl &ListCtrl,CListCtrl &RecipeInfoList) { CMsgBox MsgBox; ResetParIdxSet(); if(!IsbSelEditRecipe()) { MsgBox.Show("没有选择要操作的Recipe"); return false; } CWorkTime WorkTime; bool bHasParChange = false;//是否有参数变化 CCsvData CsvData; CsvData.AddData("用户",false); CsvData.AddData(gAuthorityMgr->GetCurUserName(),true); CsvData.AddData("操作时间",false); CsvData.AddData(WorkTime.GetDateTime("/",":"),true); CsvData.AddData("Recipe Name",false); CsvData.AddData(m_CurEditRecipe.m_RecipeName,true); CsvData.AddData("SubRecipe Name",false); CsvData.AddData(m_CurEditRecipe.GetCurSubRecipeName(),true); CsvData.AddData("SubRecipe Idx",false); CsvData.AddData(Int2CString(m_CurEditRecipe.GetCurSubRecipeIdx()),true); CsvData.AddData("rcp路径",false); CsvData.AddData(m_CurEditRecipe.m_FilePath,true); CsvData.AddData(" ",false); CsvData.AddData(" ",true); CsvData.AddData("参数名",false); CsvData.AddData("参数值",false); CsvData.AddData("修改值",true); CRecipe RecipeTmp = m_CurEditRecipe;//临时recipe 用来记录range 出错的时候的临时值 bool bLaser1EdiZero = false;//Edi 是否为0 bool bLaser2EdiZero = false; bool bRangeCheckOk = true;//参数范围检查 vector &RecipeParVec = m_CurEditRecipe.GetRecipeParVec(); vector &RecipeParVecTmp = RecipeTmp.GetRecipeParVec(); int size = RecipeParVec.size(); for(int k=0;k=RecipePar.m_DoubleMinVal && Val<=RecipePar.m_DoubleMaxVal)) { bRangeCheckOk = false; RecipeParTmp.m_ParDoubleVal = CStringToDouble(ParValStr); m_ErrRangeParIdxSet.insert(k); } else { RecipePar.m_ParDoubleVal = CStringToDouble(ParValStr); RecipeParTmp.m_ParDoubleVal = RecipePar.m_ParDoubleVal; if(RecipePar.m_ParName==RECIPE_PAR_NAME_LASER_EDI_1 && IsDbEqualZero(RecipePar.m_ParDoubleVal)) { bLaser1EdiZero = true; } if(RecipePar.m_ParName==RECIPE_PAR_NAME_LASER_EDI_2 && IsDbEqualZero(RecipePar.m_ParDoubleVal)) { bLaser2EdiZero = true; } } } else if(RecipePar.m_ParType==_RecipeParType_Bool) { RecipePar.m_ParBoolVal = (ParValStr==BOOL_STR_ON)?true:false; RecipeParTmp.m_ParBoolVal = RecipePar.m_ParBoolVal; } else if(RecipePar.m_ParType==_RecipeParType_Int) { RecipePar.m_ParIntVal = CStringToDouble(ParValStr); RecipeParTmp.m_ParIntVal = RecipePar.m_ParIntVal; } else if(RecipePar.m_ParType==_RecipeParType_CString) { RecipePar.m_ParStrVal = ParValStr; RecipeParTmp.m_ParStrVal = RecipePar.m_ParStrVal; } ParValNew = RecipePar.GetParStr(); Log += ParValNew; Log += "]"; gLogMgr->WriteDebugLog(Log); //只记录非计算参数 if(!RecipePar.m_bRcpInfoPar) { if(ParValOld!=ParValNew) { bHasParChange = true; m_ChangeParIdxSet.insert(k); } else//无变化 { ParValNew = ""; } CsvData.AddData(RecipePar.m_ParShowName,false); CsvData.AddData(ParValOld,false); CsvData.AddData(ParValNew,true); } } //更新recipe 的非设置参数 UpdateEditRecipeList(ListCtrl,RecipeInfoList,false); //检查计算参数的范围 { vector &RecipeParVec = m_CurEditRecipe.GetRecipeParVec(); int size = RecipeParVec.size(); for(int k=0;k=RecipePar.m_DoubleMinVal && RecipePar.m_ParDoubleVal<=RecipePar.m_DoubleMaxVal)) { //edi为0的时候dimmer ang == nan不要提示错误 if(RecipePar.m_ParName==RECIPE_PAR_NAME_ROTATO_DIMMER_ANG && bLaser1EdiZero) continue; if(RecipePar.m_ParName==RECIPE_PAR_NAME_ROTATO_DIMMER_ANG2 && bLaser2EdiZero) continue; bRangeCheckOk = false; m_ErrRangeParIdxSet.insert(k); } } } } //刷新list 显示 UpdateEditRecipeListExt(ListCtrl,RecipeTmp); if(!bRangeCheckOk) { MsgBox.Show("参数范围检查失败"); return false; } //保存修改记录 if(bHasParChange)//有变化时才保存 { CString FileName = WorkTime.GetCurTime("_"); FileName += "_"; FileName += m_CurEditRecipe.m_RecipeName; CString DataPath = CreatCurParDataPath(); CFileMgr FileMgr; FileMgr.WriteDataToExcel(DataPath,FileName,CsvData,false); } CString RecipeFilePath = GetCtrlRecipeFilePath(m_CurSelGroupName,m_CurEditRecipe.m_RecipeName); SaveRecipeToXml(m_CurEditRecipe.m_FilePath,m_CurEditRecipe); CString s = m_CurEditRecipe.m_RecipeName; if(bHasParChange) s += " 修改成功"; else s += " 参数无变化"; MsgBox.Show(s); return true; } //保存recipe的操作记录 void CRecipeMgr::SaveRecipeHistoy(CRecipeCtrlPar RecipeCtrlPar) { CWorkTime WorkTime; CCsvData CsvData; CsvData.AddData("用户",false); CsvData.AddData(gAuthorityMgr->GetCurUserName(),true); CsvData.AddData("操作时间",false); CsvData.AddData(WorkTime.GetDateTime("/",":"),true); CsvData.AddData("rcp路径",false); CsvData.AddData(RecipeCtrlPar.m_FilePath,true); CsvData.AddData("操作类型",false); CsvData.AddData(GetRecipeCtrlName(RecipeCtrlPar.m_CtrlType),true); CsvData.AddData("Recipe Name",false); CsvData.AddData(RecipeCtrlPar.m_RcpName,true); switch(RecipeCtrlPar.m_CtrlType) { case _RecipeCtrl_CopyRecipe: { CsvData.AddData("Copy Recipe Name",false); CsvData.AddData(RecipeCtrlPar.m_RcpNameNew,true); } break; case _RecipeCtrl_RecipeName: { CsvData.AddData("New Recipe Name",false); CsvData.AddData(RecipeCtrlPar.m_RcpNameNew,true); } break; case _RecipeCtrl_MoveRecipe: { CsvData.AddData("rcp移动路径",false); CsvData.AddData(RecipeCtrlPar.m_NewFilePath,true); } break; case _RecipeCtrl_AddSubRecipe: case _RecipeCtrl_DelSubRecipe: { CsvData.AddData("Sub Recipe Name",false); CsvData.AddData(RecipeCtrlPar.m_SubRcpName,true); } break; default: break; } CString FileName = WorkTime.GetCurTime("_"); FileName += "_"; FileName += RecipeCtrlPar.m_RcpName; CString DataPath = CreatCurParDataPath(); CFileMgr FileMgr; FileMgr.WriteDataToExcel(DataPath,FileName,CsvData,false); } //更新当前的无效参数索引值 void CRecipeMgr::UpdateInvalidParIdxSet(CRecipe &Recipe) { m_InvalidParIdxSet.clear(); CRecipeParameter RecipePar; //edi check scope 为0 时参数无效,使用config 参数 RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_EDI_CHECK_SCOPE); if(IsDbEqualZero(RecipePar.m_ParDoubleVal)) m_InvalidParIdxSet.insert(Rcp_EdiScope_Idx); //如果设置了固定扫描速度,重叠率X 无效 RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_FIX_SCAN_SPEED); if(!IsDbEqualZero(RecipePar.m_ParDoubleVal)) m_InvalidParIdxSet.insert(Rcp_OverlapX_Idx); else m_InvalidParIdxSet.insert(Rcp_FixSpeed_Idx); //如果设置了固定扫描间隔,重叠率Y 无效 RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_FIX_SCAN_LINE_GAP); if(!IsDbEqualZero(RecipePar.m_ParDoubleVal)) m_InvalidParIdxSet.insert(Rcp_OverlapY_Idx); else m_InvalidParIdxSet.insert(Rcp_FixGap_Idx); RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_OFFSET_TAB); if(RecipePar.m_ParStrVal ==RECIPE_OFFSET_TBL_NULL) m_InvalidParIdxSet.insert(Rcp_OffsetTab_Idx); } #endif #if 1 //更新recipe 的非设置参数 bool CRecipeMgr::UpdateRecipeInfoPar(CRecipe &Recipe) { CString log; log = "Flow---->UpdateRecipeInfoPar : "; log += Recipe.m_RecipeName; gLogMgr->WriteDebugLog(log); //更新系统参数 gLaser->UpdateLaserProp(); int BakSubRecipeIdx = Recipe.GetCurSubRecipeIdx();//用于恢复 vector &SubRecipeVec = Recipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); for(int k=0;kGetSpotSize(_LaserDeviceType_MainLaser1);//光斑尺寸 if(gLaser->IsbScanByDirX()) RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_OVERLAP_RATIO_X); else RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_OVERLAP_RATIO_Y); OverlapRatio = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_FRE); Laser1Fre = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER2_FRE); Laser2Fre = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_EDI_1); Laser1Edi = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_EDI_2); Laser2Edi = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_EDI_OFFSET_1); Laser1EdiOffset = RecipePar.m_ParDoubleVal; RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_EDI_OFFSET_2); Laser2EdiOffset = RecipePar.m_ParDoubleVal; //重叠率/频率/光斑尺寸---->扫描速度 double ScanSpeed = gWaferRecipeDataMgr->CalScanSpeedByOverlapRatio(OverlapRatio,Laser1Fre); if(ScanSpeed>0) { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_SCAN_SPEED); RecipePar.m_ParDoubleVal = ScanSpeed; Recipe.SetRecipePar(RECIPE_PAR_NAME_SCAN_SPEED,RecipePar); } //电流是Recipe 中的设定值 //功率是固定电流点检对应的功率值(还和频率有关) double Laser1FixCurr = 0; double Laser2FixCurr = 0; { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_CURR_1); Laser1FixCurr = RecipePar.m_ParDoubleVal; Recipe.SetRecipePar(RECIPE_PAR_NAME_LASER_CURR_1,RecipePar); } { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER_CURR_2); Laser2FixCurr = RecipePar.m_ParDoubleVal; Recipe.SetRecipePar(RECIPE_PAR_NAME_LASER_CURR_2,RecipePar); } double Laser1FixPow = 0; double Laser2FixPow = 0; gLaser->GetLaserFixedCurrentPow(_LaserDeviceType_MainLaser1,Laser1Fre,Laser1FixCurr,Laser1FixPow); gLaser->GetLaserFixedCurrentPow(_LaserDeviceType_MainLaser2,Laser2Fre,Laser2FixCurr,Laser2FixPow); { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER1_POW); RecipePar.m_ParDoubleVal = Laser1FixPow; Recipe.SetRecipePar(RECIPE_PAR_NAME_LASER1_POW,RecipePar); } { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_LASER2_POW); RecipePar.m_ParDoubleVal = Laser2FixPow; Recipe.SetRecipePar(RECIPE_PAR_NAME_LASER2_POW,RecipePar); } //读取功率补偿表 { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_OFFSET_TAB); CString OffsetTableName = RecipePar.m_ParStrVal; if(!Recipe.ReadOffsetTableFile(OffsetTableName)) { //标记为异常 m_ErrRangeParIdxSet.insert(Rcp_OffsetTab_Idx); } } //[功率密度/频率/光斑尺寸]--->[衰减器的旋转角度] { double OffsetTabEdi = Recipe.GetOffsetParVal(RECIPE_OFFSET_PAR_LASER1_EDI); double Edi = Laser1Edi + Laser1EdiOffset + OffsetTabEdi; double RotatoDimmerAng = gWaferRecipeDataMgr->CalRotatoDimmerAng(SpotSize.w,SpotSize.h,Edi,Laser1Fre,Laser1FixPow); if(!(RotatoDimmerAng>-180 && RotatoDimmerAng<180))//无效计算范围 { log.Format("Err Ang = %lf",RotatoDimmerAng); gLogMgr->WriteDebugLog(log); } { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_ROTATO_DIMMER_ANG); RecipePar.m_ParDoubleVal = RotatoDimmerAng; Recipe.SetRecipePar(RECIPE_PAR_NAME_ROTATO_DIMMER_ANG,RecipePar); } } { double OffsetTabEdi = Recipe.GetOffsetParVal(RECIPE_OFFSET_PAR_LASER2_EDI); double Edi = Laser2Edi + Laser2EdiOffset + OffsetTabEdi; double RotatoDimmerAng = gWaferRecipeDataMgr->CalRotatoDimmerAng(SpotSize.w,SpotSize.h,Edi,Laser2Fre,Laser2FixPow); if(!(RotatoDimmerAng>-180 && RotatoDimmerAng<180))//无效计算范围 { log.Format("Err Ang = %lf",RotatoDimmerAng); gLogMgr->WriteDebugLog(log); } { RecipePar = Recipe.GetRecipePar(RECIPE_PAR_NAME_ROTATO_DIMMER_ANG2); RecipePar.m_ParDoubleVal = RotatoDimmerAng; Recipe.SetRecipePar(RECIPE_PAR_NAME_ROTATO_DIMMER_ANG2,RecipePar); } } } Recipe.SetCurSubRecipeIdx(BakSubRecipeIdx);//恢复 return true; } //通过参数名获取当前的recipe 参数 CRecipeParameter CRecipeMgr::GetCurRecipePar(CString ParName) { return m_CurWorkRecipe.GetRecipePar(ParName); } void CRecipeMgr::CreatCurEditRecipeScanPath() { //打开扫描区域 CRecipe &CurEditRecipe = m_CurEditRecipe; CRecipeParameter RecipePar = CurEditRecipe.GetRecipePar(RECIPE_PAR_NAME_SCAN_AREA); CString AreaName = RecipePar.m_ParStrVal; RecipePar = CurEditRecipe.GetRecipePar(RECIPE_PAR_NAME_AREA_IDX); int AreaIdx = RecipePar.m_ParIntVal-1; CreatScanPath(AreaName,AreaIdx); } #endif #if 1 void CRecipeMgr::UpdateEditRecipeListExt(CRecipe &Recipe,CListCtrl &RecipeList,CListCtrl &RecipeInfoList) { if(!Recipe.IsValid()) return; RecipeList.DeleteAllItems(); RecipeInfoList.DeleteAllItems(); //更新recipe 的非设置参数 UpdateRecipeInfoPar(Recipe); vector &RecipeParVec = Recipe.GetRecipeParVec(); int size = RecipeParVec.size(); if(size<=0) return; int RecipeListIdx = 0; int RecipeInfoListIdx = 0; for(int k=0;k &SubRecipeVec = Recipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); if(size<=0) return; for(int k=0;k RcpGroupPathVec; CString DirPath = GetRecipePath(); CFileMgr FileMgr; //先找到所有组文件夹的路径 FileMgr.GetChildFileOrDirName(true,DirPath,RcpGroupPathVec,""); //获取所有组文件 int size = RcpGroupPathVec.size(); for(int k=0;k RcpPathVec; FileMgr.GetChildFileOrDirName(false,RcpGroupPathVec[k],RcpPathVec,RECIPE_FILE_SUFFIX); int size1 = RcpPathVec.size(); for(int i=0;iWriteDebugLog("Func---->UpdateLaserFocusProp"); //激光焦距值 double FocusZMoveUpVal = 0; { //添加属性变量映射 CString Path = "Laser"; CString Name = _T("m_FocusZMoveUpVal");//变量名字 CPropertie Propertie; Propertie.SetpVal((void*)&FocusZMoveUpVal); Propertie.SetType(_PROP_TYPE_DOUBLE); Propertie.SetPath(Path); Propertie.SetName(Name); Propertie.WriteRead(true);//读取属性 } //测距仪Z轴坐标 double DistanceMeterPosZ = 0; { //添加属性变量映射 CString Path = "PlatSpecialPosMgr"; CString Name = _T("m_SpecialPosTypeDistance_MeterPos_z");//变量名字 CPropertie Propertie; Propertie.SetpVal((void*)&DistanceMeterPosZ); Propertie.SetType(_PROP_TYPE_DOUBLE); Propertie.SetPath(Path); Propertie.SetName(Name); Propertie.WriteRead(true);//读取属性 } //Z轴安全坐标 double MotorZSafeCoord = 0; { //添加属性变量映射 CString Path = "PlatSpecialPosMgr"; CString Name = _T("m_MotorZSafeCoord");//变量名字 CPropertie Propertie; Propertie.SetpVal((void*)&MotorZSafeCoord); Propertie.SetType(_PROP_TYPE_DOUBLE); Propertie.SetPath(Path); Propertie.SetName(Name); Propertie.WriteRead(true);//读取属性 } CString log; log.Format("FocusZMoveUpVal=%f,DistanceMeterPosZ=%f,MotorZSafeCoord=%f",FocusZMoveUpVal,DistanceMeterPosZ,MotorZSafeCoord); gLogMgr->WriteDebugLog(log); //计算焦距微调范围 double LaserFocusZ = DistanceMeterPosZ + FocusZMoveUpVal; m_FocusAdjustMin = (MotorZSafeCoord - LaserFocusZ)+0.5;//向上调0.5mm m_FocusAdjustMax = (LaserFocusZ*-1)-1;////向下调1 mm log.Format("LaserFocusZ=%f,FocusAdjustMin=%f,FocusAdjustMax=%f",LaserFocusZ,m_FocusAdjustMin,m_FocusAdjustMax); gLogMgr->WriteDebugLog(log); } //获取TabName 的完整路径 CString CRecipeMgr::GetOffsetTablePath(CString TabName) { CString TabPath = gProgramLaserTuiHuo->GetLaipuLaserDataDir(OFFSET_TAB_FILE_PATH); TabPath += TabName; TabPath += ".tbl"; return TabPath; } #endif CString CRecipeMgr::GetShowParText(int Row) { CString str = ""; vector &SubRecipeVec = m_CurEditRecipe.GetSubRecipeVec(); int size = SubRecipeVec.size(); if (size <= 0) { str = "无有效Recipe"; } str = SubRecipeVec[0].m_RecipeParVec[Row].m_DetailInfo; return str; } #endif