zxd
2023-09-14 d34256830982fb9ea822c1e9b874c3b7fa0a614d
Modify(包含部分测试代码)
1.添加注释
2.ins按钮功能
8个文件已修改
1635 ■■■■■ 已修改文件
MTerm1/MTerm1.vcxproj 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MTerm1Doc.cpp 251 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MTerm1Doc.h 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MTerm1View.cpp 1138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MTerm1View.h 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MyFormInputShow.cpp 115 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MyFormInputShow.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MyFormLog.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MTerm1/MTerm1.vcxproj
@@ -30,14 +30,14 @@
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v142</PlatformToolset>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v142</PlatformToolset>
    <PlatformToolset>v143</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
@@ -45,14 +45,14 @@
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v142</PlatformToolset>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v142</PlatformToolset>
    <PlatformToolset>v143</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
MTerm1/MTerm1Doc.cpp
@@ -204,43 +204,65 @@
}
*/
/// <summary>
/// 处理新文档的创建事件
/// </summary>
/// <returns></returns>
BOOL CMTerm1Doc::OnNewDocument()
{
    if (!CDocument::OnNewDocument())
    {
        return FALSE;
    }
    // TODO: 在此添加重新初始化代码
    // (SDI 文档将重用该文档)
//    LoadFromFile(_T("0prog1.txt"));
    //LoadFromFile(_T("0prog1.txt"));
    return TRUE;
}
/// <summary>
/// 处理打开的文档
/// </summary>
/// <param name="lpszPathName">指向要打开的文件路径的指针</param>
/// <returns></returns>
BOOL CMTerm1Doc::OnOpenDocument(LPCTSTR lpszPathName)
{
//    if (!CDocument::OnOpenDocument(lpszPathName))
//        return FALSE;
    // TODO:  在此添加您专用的创建代码
    CString s1;
    CString s1;//日志信息
    s1.Format(_T("OnOpenDocument %s"), lpszPathName);
    SysLog(s1);
    //加载文件内容
    LoadFromFile(lpszPathName);
    return TRUE;
}
/// <summary>
/// 处理保存文档的事件
/// </summary>
/// <param name="lpszPathName">指向要打开的文件路径的指针</param>
/// <returns></returns>
BOOL CMTerm1Doc::OnSaveDocument(LPCTSTR lpszPathName)
{
    // TODO: 在此添加专用代码和/或调用基类
    CString s1;
    s1.Format(_T("OnSaveDocument %s"), lpszPathName);
    SysLog(s1);
    SaveToFile(lpszPathName);
    return TRUE;
    //0912-zxd-Modify
     int result = SaveToFile(lpszPathName);
    return result == 1 ? TRUE : FALSE;
//    return CDocument::OnSaveDocument(lpszPathName);
}
/// <summary>
/// 处理关闭文档的事件
/// </summary>
void CMTerm1Doc::OnCloseDocument()
{
    // TODO: 在此添加专用代码和/或调用基类
@@ -250,8 +272,10 @@
    CDocument::OnCloseDocument();
}
// CMTerm1Doc 序列化
/// <summary>
///  CMTerm1Doc 序列化
/// </summary>
/// <param name="ar"></param>
void CMTerm1Doc::Serialize(CArchive& ar)
{
    CString s1;
@@ -304,6 +328,10 @@
    SetSearchContent(strSearchContent);
}
/// <summary>
/// 设置文档的搜索内容
/// </summary>
/// <param name="value">要搜索内容的字符串值</param>
void CMTerm1Doc::SetSearchContent(const CString& value)
{
    if (value.IsEmpty())
@@ -327,11 +355,17 @@
// CMTerm1Doc 诊断
#ifdef _DEBUG
/// <summary>
/// 验证对象的有效性
/// </summary>
void CMTerm1Doc::AssertValid() const
{
    CDocument::AssertValid();
}
/// <summary>
/// 诊断信息的输出
/// </summary>
/// <param name="dc"></param>
void CMTerm1Doc::Dump(CDumpContext& dc) const
{
    CDocument::Dump(dc);
@@ -339,11 +373,14 @@
#endif //_DEBUG
// CMTerm1Doc 命令
/// <summary>
/// 加载指定的文件
/// </summary>
/// <param name="sFilePathName">需要加载的文件的路径名</param>
/// <returns></returns>
int CMTerm1Doc::LoadFromFile(CString sFilePathName)
{
    // TODO: 在此处添加实现代码.
    CFile file1;
    CFile file1;//打开指定的文件
    CFileException e;
    bool r = file1.Open(sFilePathName, CFile::modeRead, &e);
    if (r)
@@ -353,64 +390,80 @@
        file1.Read(s1A.GetBuffer(l + 2048), l);
        file1.Close();
        s1A.ReleaseBuffer(l);
        TransFileToProg(s1A);
        UpdateAllViews(NULL);
        TransFileToProg(s1A);//文件内容转换为Prog格式
        UpdateAllViews(NULL);//更新所有的视图,以反映新加载的内容
    }
    return 0;
}
/// <summary>
/// 保存文件
/// </summary>
/// <param name="sFilePathName">需要保存的文件的路径名</param>
/// <returns></returns>
int CMTerm1Doc::SaveToFile(CString sFilePathName)
{
    // TODO: 在此处添加实现代码.
    CString s1;
    CFile file1;
    CFileException e;
    bool r = file1.Open(sFilePathName, CFile::modeReadWrite, &e);
    bool r = file1.Open(sFilePathName, CFile::modeReadWrite, &e);//读写模式打开文件
    if (r)
    {
        CStringA s1A;
        CStringA sSectionNameA;
        //写入系统配置
        GetSectionTxt(SectionSysCfg, sSectionNameA); //
        GetSectionTxt(SectionSysCfg, sSectionNameA); //获取系统配置的文本表示
        s1A = "[" + sSectionNameA + "]\r\n";
        file1.Write(s1A, s1A.GetLength());
        file1.Write(s1A, s1A.GetLength());//将获取到的文本内容写入文件
        //写入程序
        GetSectionTxt(SectionProg, sSectionNameA); //
        GetSectionTxt(SectionProg, sSectionNameA); //获取程序的文本表示
        s1A = "[" + sSectionNameA + "]\r\n";
        file1.Write(s1A, s1A.GetLength());
        file1.Write(s1A, s1A.GetLength());//获取到的文本内容写入文件
        TransToTxt(s1A);
        file1.Write(s1A, s1A.GetLength());
        TransToTxt(s1A);//将程序内容转换为文本格式
        file1.Write(s1A, s1A.GetLength());//将转换后的文本内容写入文件
        //写入注释
        GetSectionTxt(SectionAnno, sSectionNameA); //
        GetSectionTxt(SectionAnno, sSectionNameA); //获取注释的文本表示
        s1A = "[" + sSectionNameA + "]\r\n";
        file1.Write(s1A, s1A.GetLength());
        //循环遍历所有注释,并将其写入文件
        for (int i = 0; i < nCoilAnnoCount; i++)
        {
            if (mCoilAnnos[i].sAnno.IsEmpty()) { continue; }
            s1 = mCoilAnnos[i].sCoilName + _T("\t") + mCoilAnnos[i].sAnno+ _T("\r\n");
            s1 = mCoilAnnos[i].sCoilName + _T("\t") + mCoilAnnos[i].sAnno + _T("\r\n");
            s1A = s1;
            file1.Write(s1A, s1A.GetLength());
        }
        //写入触点监控列表
        GetSectionTxt(SectionCoilList, sSectionNameA); //
        GetSectionTxt(SectionCoilList, sSectionNameA); //获取触点监控列表的文本表示
        s1A = "[" + sSectionNameA + "]\r\n";
        file1.Write(s1A, s1A.GetLength());
        //写入数据监控列表
        GetSectionTxt(SectionDataList, sSectionNameA); //
        GetSectionTxt(SectionDataList, sSectionNameA); //获取数据监控列表的文本表示
        s1A = "[" + sSectionNameA + "]\r\n";
        file1.Write(s1A, s1A.GetLength());
        file1.Close();
        return 1;
    }
    return 0;
    else//文件打开失败
    {
        return 0;
    }
}
/// <summary>
/// 根据文本匹配类型的Key并返回
/// </summary>
/// <param name="txt"></param>
/// <returns></returns>
int CMTerm1Doc::TxtToSection(CStringA txt)
{
    for (int i = 0; i < nSectionDefCount; i++) {
@@ -421,6 +474,12 @@
    return SectionNone;
}
/// <summary>
/// 根据Key匹配类型的文本,通过txt传递,返回查询执行结果
/// </summary>
/// <param name="nSectionType"></param>
/// <param name="txt"></param>
/// <returns></returns>
int CMTerm1Doc::GetSectionTxt(int nSectionType, CStringA & txt)
{
    for (int i = 0; i < nSectionDefCount; i++) {
@@ -432,6 +491,13 @@
    return false;
}
/// <summary>
///
/// </summary>
/// <param name="nSectionType">Section类型</param>
/// <param name="nSectionLine">行号</param>
/// <param name="nSectionLines">行数</param>
/// <returns></returns>
int CMTerm1Doc::GetSectionPos(int nSectionType, int * nSectionLine, int * nSectionLines)
{
    for (int i = 0; i < nSectionCount; i++) {
@@ -444,6 +510,13 @@
    return false;
}
/// <summary>
/// 文本表示的操作转换为其相应的操作类型、参数数量和参数类型
/// </summary>
/// <param name="optxt">表示操作的字符串</param>
/// <param name="ParamCount">返回与给定操作相对应的参数数量</param>
/// <param name="ParamType">返回与给定操作相对应的参数类型</param>
/// <returns>-1:匹配失败</returns>
int CMTerm1Doc::TxtToOp(CStringA optxt, int* ParamCount, int* ParamType)
{
    for (int i = 0; i < nOpDefCount; i++){
@@ -455,6 +528,13 @@
    }
    return -1;
}
/// <summary>
/// 操作类型转换为其相应的文本表示
/// </summary>
/// <param name="nOp">操作类型</param>
/// <param name="OpTxt">操作文本</param>
/// <returns></returns>
int CMTerm1Doc::OpToTxt(int nOp, CStringA & OpTxt)
{
    for (int i = 0; i < nOpDefCount; i++){
@@ -466,6 +546,12 @@
    return false;
}
/// <summary>
/// 操作类型转换为其相应的前台展示文本
/// </summary>
/// <param name="nOp">操作类型</param>
/// <param name="OpShowTxt">前台展示文本</param>
/// <returns></returns>
int CMTerm1Doc::OpToShowTxt(int nOp, CStringA & OpShowTxt)
{
    for (int i = 0; i < nOpDefCount; i++) {
@@ -477,6 +563,13 @@
    return false;
}
/// <summary>
/// 文本转线圈类型
/// </summary>
/// <param name="Typetxt">线圈类型</param>
/// <param name="nCoilType">线圈类型</param>
/// <param name="nCoilAddr">线圈地址</param>
/// <returns></returns>
int CMTerm1Doc::TxtToCoilType(CStringA Typetxt, int* nCoilType, int* nCoilAddr)
{
    Typetxt.MakeUpper();
@@ -492,6 +585,12 @@
    return false;;
}
/// <summary>
/// 线圈类型转文本
/// </summary>
/// <param name="nType">线圈类型</param>
/// <param name="typeTxt">线圈文本</param>
/// <returns></returns>
int CMTerm1Doc::CoilTypeToTxt(int nType, CStringA & typeTxt)
{
    for (int i = 0; i < nCoilTypeDefCount; i++)
@@ -504,6 +603,13 @@
    return false;
}
/// <summary>
///
/// </summary>
/// <param name="Typetxt"></param>
/// <param name="nDataType"></param>
/// <param name="nDataAddr"></param>
/// <returns></returns>
int CMTerm1Doc::TxtToDataType(CStringA Typetxt, int * nDataType, int* nDataAddr)
{
    Typetxt.MakeUpper();
@@ -521,6 +627,12 @@
}
/// <summary>
///
/// </summary>
/// <param name="nType"></param>
/// <param name="typeTxt"></param>
/// <returns></returns>
int CMTerm1Doc::DataTypeToTxt(int nType, CStringA & typeTxt)
{
    for (int i = 0; i < nDataTypeDefCount; i++)
@@ -533,6 +645,13 @@
    return false;
}
/// <summary>
/// 获取与特定类型和地址相对应的线圈注释
/// </summary>
/// <param name="nType"></param>
/// <param name="nAddr"></param>
/// <param name="sAnno"></param>
/// <returns></returns>
int CMTerm1Doc::GetAnno(unsigned short nType, unsigned short nAddr, CString & sAnno)
{
    // TODO: 在此处添加实现代码.
@@ -547,6 +666,12 @@
    return 0;
}
/// <summary>
/// 设置或更新特定线圈的注释
/// </summary>
/// <param name="sCoilName"></param>
/// <param name="sAnno"></param>
/// <returns></returns>
int CMTerm1Doc::SetAnno(CString sCoilName, CString sAnno)
{
    // TODO: 在此处添加实现代码.
@@ -575,6 +700,14 @@
    return 2;
}
/// <summary>
/// 直接使用类型和地址参数来设置或更新特定线圈的注释
/// </summary>
/// <param name="nType">类型</param>
/// <param name="nAddr">地址</param>
/// <param name="sCoilName">线圈名称</param>
/// <param name="sAnno">线圈注释</param>
/// <returns></returns>
int CMTerm1Doc::SetAnno(unsigned short nType, unsigned short nAddr, CString sCoilName, CString sAnno)
{
    // TODO: 在此处添加实现代码.
@@ -593,6 +726,14 @@
    nCoilAnnoCount++;
    return 0;
}
/// <summary>
/// 转换文本行为Prog格式
/// </summary>
/// <param name="txtLines">文本行集合</param>
/// <param name="StartLine">开始行</param>
/// <param name="ProgLines">程序行</param>
/// <returns></returns>
int CMTerm1Doc::TransLinesToProg(const CStringArray & txtLines, int StartLine , int ProgLines)
{
    CString s1;
@@ -607,27 +748,41 @@
    else nProgLines = ProgLines;
    int nProgPos = 0;
    //逐行读取并转化
    for (int i = nProgStartLine; i < nProgStartLine + nProgLines; i++)
    {
        CString sLine;
        sLine = txtLines.GetAt(i);
        //清除空格和制表符
        sLine.Trim();
        sLine.Replace(_T("\t"), _T(" "));
        sLine.Replace(_T("   "), _T(" "));
        sLine.Replace(_T("  "), _T(" "));
        //使用空格分隔字符串,并将其存储在 strarr2 数组中
        CStringArray strarr2;
        DivideStringToArray(sLine, _T(" "), strarr2);
        if (strarr2.GetSize() == 0) continue;
        if (strarr2.GetSize() == 0)
        {
            continue;
        }
        //从数组中提取指令,并将其转换为大写形式
        CString sCmd;
        sCmd = strarr2.GetAt(0);
        sCmd.MakeUpper();
        //使用 TxtToOp 函数将指令文本转换为操作类型。
        CStringA s1A;
        s1A = sCmd;
        int nParamCount, nParamType;
        int nType, nAddr;
        int k = TxtToOp(s1A, &nParamCount, &nParamType);
        if (k >= 0)
        {
            //根据参数类型,使用 TxtToCoilType 或 TxtToDataType 函数将参数文本转换为参数类型和地址
            Progs[nProgPos].nOpType1 = k;
            for (int j = 0; j < 3 && j < nParamCount && j < strarr2.GetSize() - 1; j++)
            {
@@ -644,7 +799,7 @@
                    Progs[nProgPos].Params[j].nParamType = nType;
                    Progs[nProgPos].Params[j].nParamAddr = nAddr;
                }
                else {
                else {
                }
            }
@@ -653,6 +808,8 @@
            nProgPos++;
        }
    }
    m_nProgSteps = nProgPos;
    // 先扫描分开的程序段
    int stpos[100] = { 0 };
@@ -662,7 +819,10 @@
    // 查找匹配指令和地址
    s1.Format(_T("DOC::Trans to Prog "));
    SysLog(s1);
    for (int i = 0; i < m_nProgSteps; i++) {
    //匹配指令(错误,此处匹配指令使用数字
    for (int i = 0; i < m_nProgSteps; i++)
    {
        int nOpType = Progs[i].nOpType1;
        int nParamCount = Progs[i].nParamCount;
        switch (Progs[i].nOpType1)
@@ -700,8 +860,10 @@
        }
        StackDeeps[i] = nCurStackDeep;
    }
    s1.Format(_T("Remaining STs %d"), nSts);
    SysLog(s1);
    for (int i = 0; i < nSts; i++) {
        s1.Format(_T("[%d] %d "), i, stpos[i]);
        SysLog(s1);
@@ -789,6 +951,11 @@
    return 0;
}
/// <summary>
/// 解析文件为梯形图
/// </summary>
/// <param name="ProgTxtA">文本</param>
/// <returns></returns>
int CMTerm1Doc::TransFileToProg(CStringA ProgTxtA)
{
    CString s1;
@@ -798,6 +965,7 @@
    sProg.Replace(_T("\r\n"), _T("\n"));
    sProg.Replace(_T("\r"), _T("\n"));
    //分割文本字符串
    DivideStringToArray(sProg, _T("\n"), txtLines);
    nSectionCount = 0;
@@ -811,7 +979,8 @@
        int nRightBracket;
        if (sLine.Find(_T("[")) == 0 && (nRightBracket = sLine.Find(_T("]"))) > 1)
        {        //找到 [ ] 标志
            if (nSectionCount > 0) {
            if (nSectionCount > 0)
            {
                Sections[nSectionCount - 1].nLines = i - Sections[nSectionCount - 1].nSectionLineNo - 1;
                s1.Format(_T("- Line %d  Section %d Ends, %d Lines"), i, nSectionCount -1 ,Sections[nSectionCount - 1].nLines);
                SysLog(s1);
@@ -821,6 +990,7 @@
            sSectionName = sLine.Mid(1, nRightBracket - 1);
            sSectionNameA = sSectionName;
            int theSection = TxtToSection(sSectionNameA);
            s1.Format(_T("+ Line %d  Section %d : [%s] type:%d  "), i + 1, nSectionCount, sSectionName, theSection);
            SysLog(s1);
            Sections[nSectionCount].nSectionType = theSection;
@@ -852,7 +1022,10 @@
    int nAnnoLines = 0;
    int bAnnoSection = GetSectionPos(SectionAnno, &nAnnoSectionLine, &nAnnoLines);
    if (bAnnoSection) { nAnnoStartLine = nAnnoSectionLine + 1; }
    if (bAnnoSection)
    {
        nAnnoStartLine = nAnnoSectionLine + 1;
    }
    for (int i = nAnnoStartLine; i < nAnnoStartLine + nAnnoLines; i++)
    {
@@ -886,6 +1059,8 @@
    return 0;
}
//文本段在此处组装
int CMTerm1Doc::TransToTxt(CStringA &ProgTxt)
{
    CStringA s1, s2;
@@ -1828,7 +2003,7 @@
    }
}
//*/
void CMTerm1Doc::OnMenuShowConsole()
{
    // TODO: 在此添加命令处理程序代码
@@ -1845,7 +2020,7 @@
        ASSERT_VALID(theApp.m_pCtrlViewTemplate);
        CFrameWnd * pFrame = theApp.m_pCtrlViewTemplate->CreateNewFrame(this, NULL);
        ASSERT_KINDOF(CFrameWnd, pFrame);
        theApp.m_pCtrlViewTemplate->InitialUpdateFrame(pFrame, this);
         theApp.m_pCtrlViewTemplate->InitialUpdateFrame(pFrame, this);
    }
}
MTerm1/MTerm1Doc.h
@@ -78,49 +78,48 @@
    stKMem KMem;
    enum enParamTypes
    enum enParamTypes            //参数类型
    {
        KLParamCoil,
        KLParamWord,
        KLParamNum,
        KLParamCoil,            //参数为线圈,1bit
        KLParamWord,            //参数为字类型, 16bit
        KLParamNum,                //参数为立即数
    };
    struct stOpDef
    struct stOpDef                //指令定义
    {
        int nOpType1;
        CStringA OpTxt;
        int nParamCount;
        int nParamType;
        CStringA ShowTxt;
        int nOpType1;            //指令类型
        CStringA OpTxt;            //指令文本显示
        int nParamCount;        //指令的参数个数
        int nParamType;            //指令的参数类型
        CStringA ShowTxt;        //指令的显示文本
    };
    static stOpDef OpDef[];
    static int nOpDefCount;
    struct stParam
    struct stParam                //参数定义
    {
        CStringA sParamStr;
        int nParamType;
        int nParamAddr;
        CStringA sParamStr;        //参数显示文本
        int nParamType;            //参数类型
        int nParamAddr;            //参数地址.
    };
    struct stProg
    struct stProg                //程序定义
    {
        int nOpType1;
        int nBinStep;
        int nParamCount;
        stParam Params[3];
        int PairTo;
        int nOpType1;            //指令类型
        int nBinStep;            //指令步
        int nParamCount;        //参数数量
        stParam Params[3];        //参数们
        int PairTo;                //对应指令
    };
    struct stCoilAnno
    struct stCoilAnno            //线圈注释定义
    {
        unsigned short nType;
        unsigned short nAddr;
        CString sCoilName;
        CString sAnno;
        unsigned short nType;    //类型
        unsigned short nAddr;    //地址
        CString sCoilName;        //线圈名称
        CString sAnno;            //注释文本
    };
    stCoilAnno mCoilAnnos[10000]=
    stCoilAnno mCoilAnnos[10000] =
    {
    };
@@ -128,21 +127,21 @@
    enum enSection {
        SectionNone = 0,
        SectionSysCfg = 1,
        SectionProg = 2,
        SectionAnno = 3,
        SectionCoilList = 4,
        SectionDataList = 5,
    enum enSection {                //数据节类型定义
        SectionNone = 0,            //
        SectionSysCfg = 1,            //系统配置节
        SectionProg = 2,            //程序节
        SectionAnno = 3,            //注释节
        SectionCoilList = 4,        //线圈列表节
        SectionDataList = 5,        //数据列表节
    };
    struct stSectionDef
    struct stSectionDef
    {
        int nSectionType;
        CStringA SectionName;
    };
     stSectionDef SectionDef[5]=
    stSectionDef SectionDef[5] =
    {
        {SectionSysCfg,"SYSCFG"},
        {SectionProg,"PROG"},
@@ -150,22 +149,23 @@
        {SectionCoilList,"MONCOILLIST"},
        {SectionDataList,"MONDATALIST"},
    };
     int nSectionDefCount = sizeof(SectionDef) / sizeof(stSectionDef);
     int TxtToSection(CStringA txt);
     int GetSectionTxt(int nSectionType, CStringA & txt);
     int ScanSections();
     struct stSection{
         int nSectionType;
         int nSectionLineNo;
         int nLines;
     };
     stSection Sections[100] = { 0 };
     int nSectionCount;
     int GetSectionPos(int nSectionType, int * nSectionLine, int * nSectionLines);
    int nSectionDefCount = sizeof(SectionDef) / sizeof(stSectionDef);
    int TxtToSection(CStringA txt);
    int GetSectionTxt(int nSectionType, CStringA& txt);
    int ScanSections();
// 操作
    struct stSection {
        int nSectionType;
        int nSectionLineNo;
        int nLines;
    };
    stSection Sections[100] = { 0 };
    int nSectionCount;
    int GetSectionPos(int nSectionType, int* nSectionLine, int* nSectionLines);
    // 操作
public:
    int TxtToOp(CStringA optxt, int* ParamCount, int* ParamType);
    int OpToTxt(int nOp, CStringA & OpTxt);
MTerm1/MTerm1View.cpp
@@ -28,6 +28,10 @@
IMPLEMENT_DYNCREATE(CMTerm1View, CScrollView)
/// <summary>
/// 消息映射
/// 是 MFC 中用于将 Windows 消息(如鼠标点击、按键等)映射到成员函数的机制。
/// </summary>
BEGIN_MESSAGE_MAP(CMTerm1View, CScrollView)
    // 标准打印命令
    ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)
@@ -102,19 +106,31 @@
    return CScrollView::PreCreateWindow(cs);
}
/// <summary>
///  MFC 中的一个函数,它在视图首次显示之前被调用
/// </summary>
void CMTerm1View::OnInitialUpdate()
{
    CScrollView::OnInitialUpdate();
    //创建了三种不同的字体
    TextFont.CreateFont(13, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
    MonTextFont.CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
    AnnoFont.CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
    //获取了状态栏的引用并存储在 m_pStatusBar 成员变量中
    m_pStatusBar = ((CChildFrame *)GetParentFrame())->GetStatusBar();
    CSize sizeTotal;
    // TODO: 计算此视图的合计大小
    sizeTotal.cx = m_LeftMargin + m_CellWidth* m_CellPerLine + m_CellWidth *2;
    sizeTotal.cy = 2000;
    //设置了滚动大小
    SetScrollSizes(MM_TEXT, sizeTotal);
    CString s1;
    CString s1;//没啥用
    //设置了两个定时器,一个间隔为50毫秒,另一个为10毫秒。
    SetTimer(1, 50,NULL);
    SetTimer(2, 10, NULL);
@@ -130,25 +146,27 @@
        return;
    // TODO: 在此处为本机数据添加绘制代码
    CString s1;
    CString s1;//没啥用
    needReDraw = 1;
    DrawLDSGraph(pDC);
    needReDraw = 0;
}
// CMTerm1View 打印
// CMTerm1View 打印,MFC 函数,用于准备打印。
BOOL CMTerm1View::OnPreparePrinting(CPrintInfo* pInfo)
{
    // 默认准备
    return DoPreparePrinting(pInfo);
}
// MFC 函数,用于在打印开始之前进行初始化。
void CMTerm1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: 添加额外的打印前进行的初始化过程
}
//MFC 函数,用于在打印结束后进行清理。
void CMTerm1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: 添加打印后进行的清理过程
@@ -158,16 +176,19 @@
// CMTerm1View 诊断
#ifdef _DEBUG
//函数用于验证对象的有效性。
void CMTerm1View::AssertValid() const
{
    CScrollView::AssertValid();
}
 }
// 函数用于将对象的内容转储到指定的上下文。
void CMTerm1View::Dump(CDumpContext& dc) const
{
    CScrollView::Dump(dc);
}
//函数返回与此视图关联的文档对象。
CMTerm1Doc* CMTerm1View::GetDocument() const // 非调试版本是内联的
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMTerm1Doc)));
@@ -175,6 +196,7 @@
}
#endif //_DEBUG
//MFC 函数,用于处理视图的创建事件。
int CMTerm1View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CScrollView::OnCreate(lpCreateStruct) == -1)
@@ -185,9 +207,13 @@
    return 0;
}
/// <summary>
/// 用于重新绘制视图。
/// </summary>
/// <returns></returns>
int CMTerm1View::DoReDraw()
{
    // TODO: 在此处添加实现代码.
    CPoint scroll1;
    scroll1 = this->GetScrollPosition();
@@ -210,6 +236,13 @@
    return 0;
}
/// <summary>
/// 滚动到特定单元格
/// 函数内部计算了单元格的总高度,考虑了是否显示注释
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::ScrollToCell(int nRow, int nCol)
{
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
@@ -227,36 +260,57 @@
    return 0;
}
/// <summary>
/// 滚动单元格进入视图(未完成的功能)
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::ScrollCellIntoView(int nRow, int nCol)
{
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
    return 0;
}
/// <summary>
/// 检查单元格是否在视图中(未完成的功能)
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::isCellInView(int nRow, int nCol)
{
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
    return 0;
}
/// <summary>
/// 用于在视图中绘制图形的主要函数
/// </summary>
/// <param name="pDC">文档</param>
/// <returns></returns>
int CMTerm1View::DrawLDSGraph(CDC* pDC)
{
    // TODO: 在此处添加实现代码.
    CString s1;
    CString s1;//没啥用
    //验证文档引用
    CMTerm1Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)    return false;
    if (m_bMonitoring) {
        pDoc->DoPLCMonitor();
    }
    int x1, y1, x2, y2;
    //    RECT rect1;
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
    int nDataType, nDataAddr;
    int nStat;
    CBrush br0(BkColor);
    CBrush br01(BkEditColor);
    CBrush br0(BkColor);//背景颜色
    CBrush br01(BkEditColor);//编辑(选中)状态下的背景颜色
    int nRow, nCol;
    CRect rect0;
    this->GetClientRect(&rect0);
@@ -264,19 +318,26 @@
    CPoint scroll1;
    scroll1 = this->GetScrollPosition();
    int nFirstVisibleLine;
    int nLastVisibleLine;
    int nFirstVisibleLine;//用于确定可见行范围-起始位置
    int nLastVisibleLine;//用于确定可见行范围-终止位置
    //通过滚动位置和视图的高度计算上述两个值
    nFirstVisibleLine = (scroll1.y - m_TopMargin) / CellTotalHeight;
    nLastVisibleLine = (rect0.Height() + scroll1.y - m_TopMargin) / CellTotalHeight + 1;
    if (nFirstVisibleLine < 0) { nFirstVisibleLine = 0; }
    if (nLastVisibleLine < 0) { nLastVisibleLine = 0; }
    if (nFirstVisibleLine < 0)
    {
        nFirstVisibleLine = 0;
    }
    if (nLastVisibleLine < 0)
    {
        nLastVisibleLine = 0;
    }
    //选择字体
    CFont *pOldFont;
    pOldFont = (CFont *)pDC->SelectObject(&TextFont);
    for (int i = nFirstVisibleLine; i < nLastVisibleLine && i < 1000; i++) {
    for (int i = nFirstVisibleLine; i < nLastVisibleLine && i < 1000; i++)
    {
        // 画一行 单元
        nRow = i;
        int x0, y0;
@@ -401,7 +462,6 @@
    return 0;
}
void  CMTerm1View::DrawFocusRect(CDC* pDC)
{
//    DrawCell(pDC, m_oldFocusRow, m_oldFocusCol);
@@ -430,7 +490,6 @@
//    pDC->SelectObject(poldBrush);
}
int CMTerm1View::DrawLeftRightLine(CDC* pDC, int x0, int y0, int size1, int size2)
{
    // TODO: 在此处添加实现代码.
@@ -452,7 +511,6 @@
    pDC->LineTo(x2, y2);
    return 0;
}
void CMTerm1View::DrawOT(CDC* pDC, int x0, int y0)
{
@@ -535,6 +593,7 @@
    pDC->LineTo(x2, y2);
    return 0;
}
int CMTerm1View::DrawAngleBracket(CDC* pDC, int x0, int y0, int size1, int size2)
{
    // TODO: 在此处添加实现代码.
@@ -542,7 +601,7 @@
    DrawLeftRightLine(pDC, x0, y0, size1, size2);
    // 左尖括号
    x1 = x0 + size1 + 6;
    y1 = y0 + m_LinePosY -6;
    y1 = y0 + m_LinePosY -6;
    x2 = x1 -6;
    y2 = y1 +6 ;
    pDC->MoveTo(x1, y1);
@@ -664,7 +723,7 @@
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
    rect1.left = m_LeftMargin + 1 + m_CellWidth * nCol;
    rect1.right = rect1.left + m_CellWidth;
    rect1.right = rect1.left + m_CellWidth;
    rect1.top = m_TopMargin + CellTotalHeight * nRow;
    rect1.bottom = rect1.top + CellTotalHeight;
@@ -1138,6 +1197,13 @@
    CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
/// <summary>
/// 单元格焦点变化*选中点变化
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::CellFocusChg(int nRow, int nCol)
{
    CString s1;
@@ -1150,8 +1216,6 @@
    auto p1 = (CMainFrame*)AfxGetMainWnd();
    auto p2 = p1->GetInputWnd();
    p2->SetCurCellPos(nRow,nCol,thecell);
    return 0;
}
@@ -1169,10 +1233,21 @@
    int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
    nRow = (ty - m_TopMargin) / CellTotalHeight;
    nCol = (tx - m_LeftMargin) / m_CellWidth;
    if (nRow < 0) { nRow = 0; }
    if (nCol < 0) { nCol = 0; }
    if (nCol >= m_CellPerLine) { nCol = m_CellPerLine - 1; }
    s1.Format(_T("LD %d %d  %02X  Scroll %d %d  Total %d %d Row %d Col %d"), point.x, point.y, nFlags, scroll1.x, scroll1.y, tx, ty, nRow, nCol);
    if (nRow < 0)
    {
        nRow = 0;
    }
    if (nCol < 0)
    {
        nCol = 0;
    }
    if (nCol >= m_CellPerLine)
    {
        nCol = m_CellPerLine - 1;
    }
    s1.Format(_T("OnLButtonDown::zxd:: LD %d %d  %02X  Scroll %d %d  Total %d %d Row %d Col %d"), point.x, point.y, nFlags, scroll1.x, scroll1.y, tx, ty, nRow, nCol);
    DbgLog(s1);//zxd add to test
    m_pStatusBar->SetPaneText(6, s1);
    m_FocusRow = nRow;
    m_FocusCol = nCol;
@@ -1800,7 +1875,10 @@
    }
}
/// <summary>
/// 程序数据转为梯形图
/// </summary>
/// <returns></returns>
int CMTerm1View::TransProgToLDS()
{
    CString s1;
@@ -1826,518 +1904,526 @@
    int cx = 0, cy = 0;
    int maxy = 0;
    for (int i = 0; i < pDoc->m_nProgSteps; i++)
    try
    {
        int nOp = pDoc->Progs[i].nOpType1;
        int nParamCount = pDoc->Progs[i].nParamCount;
        CStringA OpName;
        CStringA ShowTxt;
        pDoc->OpToTxt(nOp, OpName);
        pDoc->OpToShowTxt(nOp, ShowTxt);
        int nPairTo = pDoc->Progs[i].PairTo;
        int nPairOp = 0;
        if (nPairTo) nPairOp = pDoc->Progs[nPairTo].nOpType1;
        int nCellType;
        switch (nOp)
        for (int i = 0; i < pDoc->m_nProgSteps; i++)
        {
            int nOp = pDoc->Progs[i].nOpType1;
            int nParamCount = pDoc->Progs[i].nParamCount;
            CStringA OpName;
            CStringA ShowTxt;
            pDoc->OpToTxt(nOp, OpName);
            pDoc->OpToShowTxt(nOp, ShowTxt);
            int nPairTo = pDoc->Progs[i].PairTo;
            int nPairOp = 0;
            if (nPairTo) nPairOp = pDoc->Progs[nPairTo].nOpType1;
            int nCellType;
            switch (nOp)
            {
        case OP_NOP:
            break;
        case OP_ST:
        case OP_ST_:
            if (i == 0) {
            case OP_NOP:
                break;
            case OP_ST:
            case OP_ST_:
                if (i == 0) {
            }
            else {
                //记录当前位置
                EndPt[nEndPts] = POINT{ cx,cy };
                nEndPts++;
                if (nPairOp == OP_ANS) {
                    //继续前进
                    //cx = 0, cy = nCurLine;
                    //cx = StPts[nSts - 1].x;
                    //nCurLine = cy + 1; //另起一行
///*
                    nCurLine=cy;
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx +1; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                }
                else {
                    //记录当前位置
                    EndPt[nEndPts] = POINT{ cx,cy };
                    nEndPts++;
                    if (nPairOp == OP_ANS) {
                        //继续前进
                        //cx = 0, cy = nCurLine;
                        //cx = StPts[nSts - 1].x;
                        //nCurLine = cy + 1; //另起一行
    ///*
                        nCurLine = cy;
                        int hasData = 1;
                        while (hasData) {
                            hasData = 0;
                            for (int j = cx + 1; j < m_CellPerLine; j++) {
                                if (Cells[nCurLine][j].nType != 0) {
                                    nCurLine++; hasData = 1; break;
                                }
                            }
                        }
                        //                    nCurLine = maxy + 1; //另起一行
                        if (nCurLine > maxy) maxy = nCurLine;
                        for (int j = cy; j < nCurLine; j++) {
                            Cells[j][cx].bLeftLineDn = 1;
                            Cells[j + 1][cx].bLeftLineUp = 1;
                        }
                        cy = nCurLine;
                        //*/
                    }
                    //                    nCurLine = maxy + 1; //另起一行
                    if (nCurLine > maxy) maxy = nCurLine;
                    for (int j = cy; j < nCurLine; j++) {
                        Cells[j][cx].bLeftLineDn = 1;
                        Cells[j + 1][cx].bLeftLineUp = 1;
                    }
                    cy = nCurLine;
//*/
                }
                else if (nPairOp == OP_ORS) {
                    cx = StPts[nSts - 1].x;
                    nCurLine = cy + 1; //另起一行
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                    else if (nPairOp == OP_ORS) {
                        cx = StPts[nSts - 1].x;
                        nCurLine = cy + 1; //另起一行
                        int hasData = 1;
                        while (hasData) {
                            hasData = 0;
                            for (int j = cx; j < m_CellPerLine; j++) {
                                if (Cells[nCurLine][j].nType != 0) {
                                    nCurLine++; hasData = 1; break;
                                }
                            }
                        }
                        //                    nCurLine = maxy + 1; //另起一行
                        if (nCurLine > maxy) maxy = nCurLine;
                        for (int j = cy; j < nCurLine; j++) {
                            Cells[j][cx].bLeftLineDn = 1;
                            Cells[j + 1][cx].bLeftLineUp = 1;
                        }
                        cy = nCurLine;
                    }
                    //                    nCurLine = maxy + 1; //另起一行
                    if (nCurLine > maxy) maxy = nCurLine;
                    for (int j = cy; j < nCurLine; j++) {
                        Cells[j][cx].bLeftLineDn = 1;
                        Cells[j + 1][cx].bLeftLineUp = 1;
                    else if (nPairOp == 0) {
                        nCurLine = maxy + 1; //另起一行
                        maxy = nCurLine;
                        cx = 0; cy = nCurLine;
                    }
                    cy = nCurLine;
                }
                else if (nPairOp == 0) {
                    nCurLine = maxy + 1; //另起一行
                    maxy = nCurLine;
                    cx = 0; cy = nCurLine;
                }
            }
            stpos[nSts] = i;
            StPts[nSts] = POINT{ cx,cy };
            nSts++;
            Cells[cy][cx].nType = pDoc->Progs[i].nOpType1 == OP_ST ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;    //移到下一格
            break;
        case OP_ST_EQ:
        case OP_ST_NE:
        case OP_ST_LT:
        case OP_ST_GT:
        case OP_ST_LE:
        case OP_ST_GE:
            if (i == 0) {
                stpos[nSts] = i;
                StPts[nSts] = POINT{ cx,cy };
                nSts++;
                Cells[cy][cx].nType = pDoc->Progs[i].nOpType1 == OP_ST ? typeNO : typeNC; //typeNC
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                cx++;    //移到下一格
                break;
            case OP_ST_EQ:
            case OP_ST_NE:
            case OP_ST_LT:
            case OP_ST_GT:
            case OP_ST_LE:
            case OP_ST_GE:
                if (i == 0) {
            }
            else {
                //记录当前位置
                EndPt[nEndPts] = POINT{ cx,cy };
                nEndPts++;
                if (nPairOp == OP_ANS) {
                    //继续前进
                    //cx = 0, cy = nCurLine;
                }
                else if (nPairOp == OP_ORS) {
                    cx = StPts[nSts - 1].x;
                    nCurLine = cy + 1; //另起一行
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                else {
                    //记录当前位置
                    EndPt[nEndPts] = POINT{ cx,cy };
                    nEndPts++;
                    if (nPairOp == OP_ANS) {
                        //继续前进
                        //cx = 0, cy = nCurLine;
                    }
                    else if (nPairOp == OP_ORS) {
                        cx = StPts[nSts - 1].x;
                        nCurLine = cy + 1; //另起一行
                        int hasData = 1;
                        while (hasData) {
                            hasData = 0;
                            for (int j = cx; j < m_CellPerLine; j++) {
                                if (Cells[nCurLine][j].nType != 0) {
                                    nCurLine++; hasData = 1; break;
                                }
                            }
                        }
                    }
                    //                    nCurLine = maxy + 1; //另起一行
                    if (nCurLine > maxy) maxy = nCurLine;
                    for (int j = cy; j < nCurLine; j++) {
                        Cells[j][cx].bLeftLineDn = 1;
                        Cells[j + 1][cx].bLeftLineUp = 1;
                    }
                    cy = nCurLine;
                }
                else if (nPairOp == 0) {
                    nCurLine = maxy + 1; //另起一行
                    maxy = nCurLine;
                    cx = 0; cy = nCurLine;
                }
            }
            stpos[nSts] = i;
            StPts[nSts] = POINT{ cx,cy };
            nSts++;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sParam = OpName;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;    //移到下3格
            break;
        case OP_AN:
        case OP_AN_:
            Cells[cy][cx].nType = nOp == OP_AN ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;
            break;
        case OP_AN_EQ:
        case OP_AN_NE:
        case OP_AN_LT:
        case OP_AN_GT:
        case OP_AN_LE:
        case OP_AN_GE:
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
        case OP_OR:
        case OP_OR_:
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            cx = StPts[nSts - 1].x;
            nCurLine = cy + 1; //另起一行
            {
                int hasData = 1;
                while (hasData) {
                    hasData = 0;
                    for (int j = cx; j < m_CellPerLine; j++) {
                        if (Cells[nCurLine][j].nType != 0) {
                            nCurLine++; hasData = 1; break;
                        //                    nCurLine = maxy + 1; //另起一行
                        if (nCurLine > maxy) maxy = nCurLine;
                        for (int j = cy; j < nCurLine; j++) {
                            Cells[j][cx].bLeftLineDn = 1;
                            Cells[j + 1][cx].bLeftLineUp = 1;
                        }
                        cy = nCurLine;
                    }
                    else if (nPairOp == 0) {
                        nCurLine = maxy + 1; //另起一行
                        maxy = nCurLine;
                        cx = 0; cy = nCurLine;
                    }
                }
            }
            if (nCurLine > maxy)    maxy = nCurLine;
            for (int j = cy; j < nCurLine; j++) {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            cy = nCurLine;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].nType = nOp == OP_OR ? typeNO : typeNC; //typeNC
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;
            if (cx < EndPt[nEndPts - 1].x)
            {    //本行补齐
                for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                {
                    Cells[cy][j].nType = typeLine1;
                }
                cx = EndPt[nEndPts - 1].x;
            }
            else {
                //前一行补齐
                for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                {
                    Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                }
                stpos[nSts] = i;
                StPts[nSts] = POINT{ cx,cy };
                nSts++;
                Cells[cy][cx].nType = typeCMP;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sParam = OpName;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                cx += 3;    //移到下3格
                break;
            }
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //光标位置, 前一结束点位置
            cy = EndPt[nEndPts - 1].y;
            nEndPts--;
            case OP_AN:
            case OP_AN_:
            break;
        case OP_OR_EQ:
        case OP_OR_NE:
        case OP_OR_LT:
        case OP_OR_GT:
        case OP_OR_LE:
        case OP_OR_GE:
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            cx = StPts[nSts - 1].x;
            nCurLine = cy + 1; //另起一行
            {
                int hasData = 1;
                while (hasData) {
                    hasData = 0;
                    for (int j = cx; j < m_CellPerLine; j++) {
                        if (Cells[nCurLine][j].nType != 0) {
                            nCurLine++; hasData = 1; break;
                        }
                    }
                }
            }
            if (nCurLine > maxy)    maxy = nCurLine;
            for (int j = cy; j < nCurLine; j++) {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            cy = nCurLine;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            if (cx < EndPt[nEndPts - 1].x)
            {    //本行补齐
                for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                {
                    Cells[cy][j].nType = typeLine1;
                }
                cx = EndPt[nEndPts - 1].x;
            }
            else {
                //前一行补齐
                for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                {
                    Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                }
            }
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //光标位置, 前一结束点位置
            cy = EndPt[nEndPts - 1].y;
            nEndPts--;
            break;
        case OP_NOT:
            Cells[cy][cx].nType = typeNOT;
            Cells[cy][cx].sCoilName = _T("NOT");
            Cells[cy][cx].nProgStep = i;
            cx++;
            break;
        case OP_DF:
        case OP_DF_:
            Cells[cy][cx].nType = nOp == OP_DF ? typeDF : typeDF_;
            Cells[cy][cx].sCoilName = nOp == OP_DF ? _T("DF") : _T("DF/");
            Cells[cy][cx].nProgStep = i;
            cx++;
            break;
        case OP_ANS:
            nSts--;
            nEndPts--;
            break;
        case OP_ORS:
            // 当前序列与前面的序列合并。
            //当前序列的开始结束位置
            //EndPt[nEndPts] = POINT{ cx,cy };
            //nEndPts++;
            //StPts[nSts - 1]; EndPt[nEndPts - 1];
            //前一序列的开始结束位置
            StPts[nSts - 1]; EndPt[nEndPts - 1];
            //判断二者长度
            if (cx < EndPt[nEndPts - 1].x)
            {    //本行补齐
                for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                {
                    Cells[cy][j].nType = typeLine1;
                }
                cx = EndPt[nEndPts - 1].x;
            }
            else {
                //前一行补齐
                for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                {
                    Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                }
            }
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //光标位置, 前一结束点位置
            cy = EndPt[nEndPts - 1].y;
            nSts--;
            nEndPts--;
            break;
        case OP_PSHS:
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            break;
        case OP_RDS:
            cx = EndPt[nEndPts - 1].x;
            for (int j = cx; j < m_CellPerLine; j++) {
                if (Cells[cy][j].nType != 0)
                {
                    cy++; j = cx - 1; //break;
                }
            }
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            break;
        case OP_POPS:
            cx = EndPt[nEndPts - 1].x;
            for (int j = cx; j < m_CellPerLine; j++) {
                if (Cells[cy][j].nType != 0)
                {
                    cy++; j = cx - 1; break;
                }
            }
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
                Cells[j][cx].bLeftLineDn = 1;
                Cells[j + 1][cx].bLeftLineUp = 1;
            }
            nEndPts--;
            break;
        case OP_OUT:
        case OP_SET:
        case OP_RESET:
            nCellType = nOp == OP_OUT ? typeOUT : nOp == OP_SET ? typeSET : typeRESET;
            nCurLine = cy;
            if (cx <= m_CellPerLine) {
                int hasData = 1;
                while (hasData) {
                    hasData = 0;
                    for (int j = cx; j < m_CellPerLine; j++) {
                        if (Cells[nCurLine][j].nType != 0) {
                            nCurLine++; hasData = 1; break;
                        }
                    }
                }
                //if (nCurLine > maxy)    maxy = nCurLine;
                for (int j = cy; j < nCurLine; j++) {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                cy = nCurLine;
                for (int j = cx; j < m_CellPerLine; j++)
                {
                    Cells[cy][j].nType = typeLine1;
                }
                Cells[cy][m_CellPerLine - 1].nType = nCellType;
                Cells[cy][m_CellPerLine - 1].nProgStep = i;
                Cells[cy][m_CellPerLine - 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][m_CellPerLine - 1].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][m_CellPerLine - 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][m_CellPerLine - 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            }
            else {
                Cells[cy][cx].nType = nCellType;
                Cells[cy][cx].nType = nOp == OP_AN ? typeNO : typeNC; //typeNC
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                cx++;
                break;
            case OP_AN_EQ:
            case OP_AN_NE:
            case OP_AN_LT:
            case OP_AN_GT:
            case OP_AN_LE:
            case OP_AN_GE:
                Cells[cy][cx].nType = typeCMP;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                cx += 3;
                break;
            case OP_OR:
            case OP_OR_:
                EndPt[nEndPts] = POINT{ cx,cy };
                nEndPts++;
                cx = StPts[nSts - 1].x;
                nCurLine = cy + 1; //另起一行
                {
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                            }
                        }
                    }
                }
                if (nCurLine > maxy)    maxy = nCurLine;
                for (int j = cy; j < nCurLine; j++) {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                cy = nCurLine;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].nType = nOp == OP_OR ? typeNO : typeNC; //typeNC
                Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                cx++;
                if (cx < EndPt[nEndPts - 1].x)
                {    //本行补齐
                    for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                    {
                        Cells[cy][j].nType = typeLine1;
                    }
                    cx = EndPt[nEndPts - 1].x;
                }
                else {
                    //前一行补齐
                    for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                    {
                        Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                    }
                }
                //连接上下线
                for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
                {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                //光标位置, 前一结束点位置
                cy = EndPt[nEndPts - 1].y;
                nEndPts--;
                break;
            case OP_OR_EQ:
            case OP_OR_NE:
            case OP_OR_LT:
            case OP_OR_GT:
            case OP_OR_LE:
            case OP_OR_GE:
                EndPt[nEndPts] = POINT{ cx,cy };
                nEndPts++;
                cx = StPts[nSts - 1].x;
                nCurLine = cy + 1; //另起一行
                {
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                            }
                        }
                    }
                }
                if (nCurLine > maxy)    maxy = nCurLine;
                for (int j = cy; j < nCurLine; j++) {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                cy = nCurLine;
                Cells[cy][cx].nType = typeCMP;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                cx += 3;
                if (cx < EndPt[nEndPts - 1].x)
                {    //本行补齐
                    for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                    {
                        Cells[cy][j].nType = typeLine1;
                    }
                    cx = EndPt[nEndPts - 1].x;
                }
                else {
                    //前一行补齐
                    for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                    {
                        Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                    }
                }
                //连接上下线
                for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
                {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                //光标位置, 前一结束点位置
                cy = EndPt[nEndPts - 1].y;
                nEndPts--;
                break;
            case OP_NOT:
                Cells[cy][cx].nType = typeNOT;
                Cells[cy][cx].sCoilName = _T("NOT");
                Cells[cy][cx].nProgStep = i;
                cx++;
                break;
            case OP_DF:
            case OP_DF_:
                Cells[cy][cx].nType = nOp == OP_DF ? typeDF : typeDF_;
                Cells[cy][cx].sCoilName = nOp == OP_DF ? _T("DF") : _T("DF/");
                Cells[cy][cx].nProgStep = i;
                cx++;
                break;
            case OP_ANS:
                nSts--;
                nEndPts--;
                break;
            case OP_ORS:
                // 当前序列与前面的序列合并。
                //当前序列的开始结束位置
                //EndPt[nEndPts] = POINT{ cx,cy };
                //nEndPts++;
                //StPts[nSts - 1]; EndPt[nEndPts - 1];
                //前一序列的开始结束位置
                StPts[nSts - 1]; EndPt[nEndPts - 1];
                //判断二者长度
                if (cx < EndPt[nEndPts - 1].x)
                {    //本行补齐
                    for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
                    {
                        Cells[cy][j].nType = typeLine1;
                    }
                    cx = EndPt[nEndPts - 1].x;
                }
                else {
                    //前一行补齐
                    for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
                    {
                        Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                    }
                }
                //连接上下线
                for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
                {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                //光标位置, 前一结束点位置
                cy = EndPt[nEndPts - 1].y;
                nSts--;
                nEndPts--;
                break;
            case OP_PSHS:
                EndPt[nEndPts] = POINT{ cx,cy };
                nEndPts++;
                break;
            case OP_RDS:
                cx = EndPt[nEndPts - 1].x;
                for (int j = cx; j < m_CellPerLine; j++) {
                    if (Cells[cy][j].nType != 0)
                    {
                        cy++; j = cx - 1; //break;
                    }
                }
                for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
                {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                break;
            case OP_POPS:
                cx = EndPt[nEndPts - 1].x;
                for (int j = cx; j < m_CellPerLine; j++) {
                    if (Cells[cy][j].nType != 0)
                    {
                        cy++; j = cx - 1; break;
                    }
                }
                for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
                {
                    Cells[j][cx].bLeftLineDn = 1;
                    Cells[j + 1][cx].bLeftLineUp = 1;
                }
                nEndPts--;
                break;
            case OP_OUT:
            case OP_SET:
            case OP_RESET:
                nCellType = nOp == OP_OUT ? typeOUT : nOp == OP_SET ? typeSET : typeRESET;
                nCurLine = cy;
                if (cx <= m_CellPerLine) {
                    int hasData = 1;
                    while (hasData) {
                        hasData = 0;
                        for (int j = cx; j < m_CellPerLine; j++) {
                            if (Cells[nCurLine][j].nType != 0) {
                                nCurLine++; hasData = 1; break;
                            }
                        }
                    }
                    //if (nCurLine > maxy)    maxy = nCurLine;
                    for (int j = cy; j < nCurLine; j++) {
                        Cells[j][cx].bLeftLineDn = 1;
                        Cells[j + 1][cx].bLeftLineUp = 1;
                    }
                    cy = nCurLine;
                    for (int j = cx; j < m_CellPerLine; j++)
                    {
                        Cells[cy][j].nType = typeLine1;
                    }
                    Cells[cy][m_CellPerLine - 1].nType = nCellType;
                    Cells[cy][m_CellPerLine - 1].nProgStep = i;
                    Cells[cy][m_CellPerLine - 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                    Cells[cy][m_CellPerLine - 1].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                    Cells[cy][m_CellPerLine - 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                    Cells[cy][m_CellPerLine - 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                }
                else {
                    Cells[cy][cx].nType = nCellType;
                    Cells[cy][cx].nProgStep = i;
                    Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
                    Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
                    Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
                    Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                }
                if (cy > maxy) { maxy = cy; }
                //cy++;
                break;
            case OP_TML:
            case OP_TMR:
            case OP_TMX:
            case OP_TMY:
                Cells[cy][cx].nType = typeTM;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = KLDataTypeEV;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                cx += 3;
                break;
            case OP_INC:
            case OP_DEC:
                Cells[cy][cx].nType = typeFN1;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                cx += 2;
                break;
            case OP_MV:
            case OP_ADD2:
            case OP_SUB2:
                Cells[cy][cx].nType = typeFN2;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                cx += 3;
                break;
            case OP_ADD3:
            case OP_SUB3:
            case OP_MUL:
            case OP_DIV:
                Cells[cy][cx].nType = typeFN3;
                Cells[cy][cx].nProgStep = i;
                Cells[cy][cx].sCoilName = ShowTxt;
                Cells[cy][cx + 1].nType = typeExt1;
                Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
                Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
                Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
                Cells[cy][cx + 2].nType = typeExt1;
                Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
                Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
                Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
                Cells[cy][cx + 3].nType = typeExt1;
                Cells[cy][cx + 3].sParam = pDoc->Progs[i].Params[2].sParamStr;
                Cells[cy][cx + 3].nDataType = pDoc->Progs[i].Params[2].nParamType;
                Cells[cy][cx + 3].nDataAddr = pDoc->Progs[i].Params[2].nParamAddr;
                cx += 4;
                break;
            default:
                break;
            }
            if (cy > maxy) { maxy = cy; }
            //cy++;
            break;
        case OP_TML:
        case OP_TMR:
        case OP_TMX:
        case OP_TMY:
            Cells[cy][cx].nType = typeTM;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = KLDataTypeEV;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
        case OP_INC:
        case OP_DEC:
            Cells[cy][cx].nType = typeFN1;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx += 2;
            break;
        case OP_MV:
        case OP_ADD2:
        case OP_SUB2:
            Cells[cy][cx].nType = typeFN2;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
        case OP_ADD3:
        case OP_SUB3:
        case OP_MUL:
        case OP_DIV:
            Cells[cy][cx].nType = typeFN3;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            Cells[cy][cx + 3].nType = typeExt1;
            Cells[cy][cx + 3].sParam = pDoc->Progs[i].Params[2].sParamStr;
            Cells[cy][cx + 3].nDataType = pDoc->Progs[i].Params[2].nParamType;
            Cells[cy][cx + 3].nDataAddr = pDoc->Progs[i].Params[2].nParamAddr;
            cx += 4;
            break;
        default:
            break;
        }
    }
    catch (const std::exception&)
    {
        DbgLog(_T("无法绘制图形(程序不合理)"));
    }
    m_nTotalRow = maxy + 1;
    /*
        for (int i = 0; i < 25; i++)
@@ -2354,7 +2440,10 @@
    return 0;
}
/// <summary>
/// 梯形图转Prog
/// </summary>
/// <returns></returns>
int CMTerm1View::TransLDSToProg()
{
    // TODO: 在此处添加实现代码.
@@ -2444,11 +2533,15 @@
            nCurPosY = i;
            stProgSection thisprogsec;
            if (Cells[i][0].nType)
            ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec,nSteps);
            {
                //循环遍历单元格
                ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
            }
            sProg += sProgSec;
            nAllSteps += nSteps;
            Progsec += thisprogsec;
        }
        DbgLog(_T("\r\n")+ sProg);
        int n = int(Progsec.Progs.size());
        s1.Format(_T("progSec steps %d "), n);
@@ -2488,6 +2581,19 @@
    return 0;
}
/// <summary>
/// :绘制每个单元格的内容
/// </summary>
/// <param name="nStartLine"></param>
/// <param name="nEndLine"></param>
/// <param name="nPosY"></param>
/// <param name="nPosX"></param>
/// <param name="nLevel"></param>
/// <param name="progsec"></param>
/// <param name="sProgSec"></param>
/// <param name="nSteps"></param>
/// <returns></returns>
int CMTerm1View::ScanLDSCells(int nStartLine, int nEndLine, int nPosY, int nPosX, int nLevel, stProgSection & progsec, CString & sProgSec, int &nSteps)
{
    // TODO: 在此处添加实现代码.
@@ -2506,7 +2612,8 @@
        CMTerm1Doc::stProg theprog;
        CStringA sCellNameA;
        sCellNameA = sCellName;
        if (nType == typeNO) {
        if (nType == typeNO)
        {
            if (j==0) {
                s1.Format(_T("%d %d ST %s"), nCurPosY, nCurPosX,sCellName);
                sProgSec.AppendFormat(_T("ST %s\r\n"),sCellName);
@@ -2764,7 +2871,10 @@
                    CString ProgSec;
                    int theSteps = 0;
                    stProgSection thisprogsec;
                    //
                    int r = ScanLDSCells(nStartLine, nEndLine, nLineTop, j + nNextX, nLevel,thisprogsec, ProgSec,theSteps);
                    sProgSec += ProgSec;
                    nSteps += theSteps;
                    progsec += thisprogsec;
MTerm1/MTerm1View.h
@@ -123,14 +123,15 @@
    int m_TopMargin = 0;        
    int m_LeftMargin = 54;        //左侧边距
    int m_CellPerLine = 16;        //每行单元数
    int m_CellWidth = 64;        //单元宽度
     int m_CellWidth = 64;        //单元宽度
    int m_CellHeight = 28;        //单元高度
    int m_CommentHeight = 32;    //注释高度
    int m_LinePosY = 20;        //元件显示位置
    int m_FocusRow = 0;             //焦点行列位置
     int m_FocusRow = 0;             //焦点行列位置
    int m_FocusCol = 0;
    int m_oldFocusRow = 0;
    int m_oldFocusCol = 0;
    int m_nCurProgStep = 0;
@@ -197,6 +198,10 @@
    void DrawCell(CDC* pDC, int nRow, int nCol);
    int TransProgToLDS();
    /// <summary>
    /// Flag::是否需要重绘视图,默认为1=>true
    /// </summary>
    int needReDraw = 1;
    int DoReDraw();
@@ -283,7 +288,7 @@
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    int ScanLDSCells(int nStartLine, int nEndLine, int nPosY, int nPosX, int nLevel, stProgSection & progsec, CString & sProgSec, int &nSteps);
    void SetCellToView(stCell cell1);
};
#ifndef _DEBUG  // MultiTerminal2View.cpp 中的调试版本
MTerm1/MyFormInputShow.cpp
@@ -5,8 +5,8 @@
#include "MTerm1.h"
#include "MyFormInputShow.h"
#include "MainFrm.h"
// CMyFormLog
structButton myButtons[6][3][11] =
@@ -437,9 +437,6 @@
    SysLog(s1);
}
void CMyFormInputShow::SetBtnDisplayESC(int n)
{
    for (int n = 1; n < 5; n++)
@@ -462,9 +459,9 @@
{
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 11; j++) {
          for (int j = 0; j < 11; j++) {
            m_buttons[current_btn_window][i][j].ShowWindow(SW_HIDE);
        }
         }
    }
    for (int i = 0; i < 3; i++) {
@@ -474,7 +471,6 @@
    }
    current_btn_window = n;
}
void CMyFormInputShow::stInit()
{
@@ -494,7 +490,9 @@
         false,
         false,
         0x10,
        _T("")
        _T(""),
        0,
        0
    };
}
@@ -866,6 +864,7 @@
    }
    strNum = stDisplayCell.num;
    str = strOp + _T(" ") + strParam + " " + strNum;
    //设置输入框中的文本
    SetDlgItemText(IDC_EDIT_INPUT, str);
    return 0;
}
@@ -873,7 +872,8 @@
int CMyFormInputShow::SetCurCellPos(int nRow, int nCol, CMTerm1View::stCell theCell)
{
    m_InputCell.clear();
    m_InputCell.row = nRow;
    m_InputCell.col = nCol;
    int nType = theCell.nType;
    switch (nType)
    {
@@ -1041,18 +1041,109 @@
    //    m_wndDlgBar_Func_Key.SetBtnDisplayESC();
}
/// <summary>
/// 插入按钮点击事件
/// </summary>
void CMyFormInputShow::OnBtnInsert()
{
    // TODO: 在此添加命令处理程序代码
    SetDisplay(0x00240000);
    //    m_wndDlgBar_Func_Key.SetBtnDisplayESC();
    if (m_InputCell.OP == NULL)
    {
        DbgLog(_T("Error:插入失败,未选择要插入的操作"));
        return;
    }
    if (m_InputCell.num == (_T("")))
    {
        DbgLog(_T("Error:插入失败,未设置编号"));
        return;
    }
    CString s1;
    CString strName;
    CMTerm1View::stCell cell1;
    CMainFrame* p1 = (CMainFrame*)AfxGetMainWnd();
    CMDIChildWnd* pChild = (CMDIChildWnd*)p1->GetActiveFrame();
    CView* p2 = (CView*)pChild->GetActiveView();
    if (p2 == NULL) return;
    CMTerm1View* p3 = (CMTerm1View*)p2;
    switch (m_InputCell.OP)
    {
    case CMTerm1View::typeNO:
    case CMTerm1View::typeNC:
    case CMTerm1View::typeOUT:
    case CMTerm1View::typeSET:
    case CMTerm1View::typeRESET:
    case CMTerm1View::typeTM:
        switch (m_InputCell.param)
        {
        case KLCoilTypeX:
            strName = "X";
            break;
        case KLCoilTypeY:
            strName = "Y";
            break;
        case KLCoilTypeR:
            strName = "R";
            break;
        case KLCoilTypeLR:
            strName = "L";
            break;
        case KLCoilTypeT:
            strName = "T";
            break;
        case KLCoilTypeC:
            strName = "C";
            break;
        case OP_TMX:
            strName = "TMX   ";
        case OP_TMY:
            strName = "TMY   ";
        case OP_TMR:
            strName = "TMR   ";
        case OP_TML:
            strName = "TML   ";
        default:
            break;
        }
    default:
        break;
    }
    cell1.sCoilName = strName + m_InputCell.num;
    cell1.nType = m_InputCell.OP;
    cell1.nProgStep = 0;
    cell1.bEditing = 1;
    cell1.sParam = strName + m_InputCell.num;;
    cell1.bLeftLineUp = 0;
    cell1.nDataType = CMTerm1View::typeCoil;
    cell1.nDataAddr = _tstoi(m_InputCell.num);
    cell1.bModified = 1;
    //
    p3->SetCellToView(cell1);
    //插入完成后,设置按钮返回第一页
    SetBtnDisplay(0);
    DbgLog(cell1.sCoilName);
}
/// <summary>
/// 删除按钮点击事件
/// </summary>
void CMyFormInputShow::OnBtnDelete()
{
    // TODO: 在此添加命令处理程序代码
    SetDisplay(0x00340000);
    //    m_wndDlgBar_Func_Key.SetBtnDisplayESC();
}
void CMyFormInputShow::OnBtnEsc()
{
    // TODO: 在此添加命令处理程序代码
MTerm1/MyFormInputShow.h
@@ -3,7 +3,7 @@
#include "afxcmn.h"
#include "MTerm1View.h"
#pragma region DDFINES CMyFormLog 窗体视图
// CMyFormLog 窗体视图
#define IDC_BUTTON_AND                     33101
#define IDC_BUTTON_OR                      33102
@@ -65,6 +65,9 @@
#define IDC_BUTTON_TML                  34704
#define IDC_BUTTON_CT                   34706
#pragma endregion
typedef struct tagStructButton {
    int nID;
    CString sCaption;
@@ -90,6 +93,9 @@
    CString sCellName;
    CString sParamName;
    CString num = _T("");
    int row = 0;
    int col = 0;
    void clear() { OP = 0; bnot = 0; bpp = 0; bpn = 0; bcmpEq = 0; bcmpLt = 0;
    bcmpGt = 0; bDouble = 0; bDouble1 = 0; bFloat = 0; bFloat1 = 0; bLeftLineUp = 0; brightLineUp = 0;
    param = 0; sCellName.Empty(); num.Empty();
@@ -107,6 +113,9 @@
public:
    enum { IDD = IDD_FORM_INPUTSHOW};
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
MTerm1/MyFormLog.h
@@ -37,6 +37,7 @@
    CEdit m_edit_log;
    CRichEditCtrl m_richedit_log;
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnEnChangeRichedit2Log();
};