语法高亮编辑控件Scintilla在MFC中的简单使用之完整示例

 

该示例是一个简单的NC程序编辑器,附件代码在Visual Studio .NET 2003(VC++7.1)下编译通过。

第一部分、修改Scintilla,使其支持NC程序

1.修改SciLexer.h,加上自己的token类型定义

C++代码
  1. #define SCLEX_NCPROG 87 //淡月清风 2008年11月7日17:19:23   
  2.   
  3. #define typeDefault     0x00   
  4. #define typeLineStart   0x01   
  5. #define typeG           0x02   
  6. #define typeGValue      0x03   
  7. #define typeM           0x04   
  8. #define typeMValue      0x05   
  9. #define typeX           0x06   
  10. #define typeXValue      0x07   
  11. #define typeY           0x08   
  12. #define typeYValue      0x09   
  13. #define typeI           0x0A   
  14. #define typeIValue      0x0B   
  15. #define typeJ           0x0C   
  16. #define typeJValue      0x0D   
  17. #define typeComment             0x0E    //()   
  18. #define typeNCProgramStart      0x0F    //%   
  19. #define typeNCDescription       0x10    //;   
  20. #define typeNCProgramEnd        0x11    //“\ESC”    ASCII码是27   
  21. #define typeNCLineNumber        0x12    //行号 N   
  22. #define typeNCLineNumberValue   0x13    //行号 01201   
  23. #define typeProgramNumber       0x14       
  24. #define typeF                   0x15   
  25. #define typeFValue              0x16  

2.编写NC程序词法分析的Lex程序LexNCProg.cxx 

这个Lex程序扫描全部字符,并标记当前字符的状态,它使用的是状态机技术(类似于状态模式)。

C++代码
  1. //Scintilla source code edit control   
  2. /** @file LexNCProg.cxx  
  3. **  Lexer for NC Program.  
  4. **/  
  5. // Copyright 2008-2010 by 淡月清风 <dgx_lsyd3@163.com>   
  6. //修改记录:   
  7. //  2008年12月15日12:08:39:   
  8. //      1.使大小写不区分   
  9. //      2.G01,02等的省略写法,X,Y直接在行首无法识别的BUG   
  10.   
  11. #include <stdlib.h>   
  12. #include <string.h>   
  13. #include <ctype.h>   
  14. #include <stdio.h>   
  15. #include <stdarg.h>   
  16. #include <windows.h>   
  17.   
  18. #include "Platform.h"   
  19.   
  20. #include "PropSet.h"   
  21. #include "Accessor.h"   
  22. #include "StyleContext.h"   
  23. #include "KeyWords.h"   
  24. #include "Scintilla.h"   
  25. #include "SciLexer.h"   
  26.   
  27. #ifdef SCI_NAMESPACE   
  28. using namespace Scintilla;   
  29. #endif   
  30.   
  31. static const char * const NCProgWordListDesc[] =   
  32. {   
  33.     0   
  34. };   
  35.   
  36. static void ColouriseNCProgDoc(   
  37.     unsigned int startPos, int length, int initStyle,   
  38.     WordList *keywordlists[],   
  39.     Accessor &styler)   
  40. {   
  41.     static int LastTokenTypeForComment = typeLineStart;   
  42.     static int LastTokenType=typeLineStart;   
  43.   
  44.     static int nLastGCode = -1;                     //记录本行之前的G代码。   
  45.     char szLastGCode[100];   
  46.     memset(szLastGCode, 0, 100);   
  47.        
  48.     StyleContext sc(startPos, length, initStyle, styler);   
  49.     sc.SetState(typeLineStart);   
  50.     for (; sc.More(); sc.Forward())   
  51.     {   
  52.         //char szText[4];   
  53.         //sprintf(szText,"%c",sc.ch);   
  54.         //OutputDebugString(szText);   
  55.            
  56.         int ch = sc.ch;   
  57.         int chNext = sc.chNext;   
  58.         int chPrev = sc.chPrev;   
  59.            
  60.         if (isalpha(ch))   
  61.         {   
  62.             ch = toupper(ch);   
  63.         }   
  64.         if (isalpha(chNext))   
  65.         {   
  66.             chNext = toupper(chNext);   
  67.         }   
  68.         if (isalpha(chPrev))   
  69.         {   
  70.             chPrev = toupper(chPrev);   
  71.         }   
  72.            
  73.         // 重点关注:从这里开始执行词法分析代码   
  74.         // 若注释可以出现在任何位置   
  75.         // 当前字符是注释开始   
  76.         if (ch == '(')   
  77.         {   
  78.             LastTokenTypeForComment = sc.state;   
  79.             sc.SetState(typeComment);   
  80.         }   
  81.         //当前状态是注释   
  82.         else if (sc.state == typeComment || LastTokenType==typeComment)   
  83.         {   
  84.             sc.SetState(typeComment);   
  85.             if (ch == ')')   
  86.             {   
  87.                 sc.ForwardSetState(LastTokenTypeForComment);   
  88.             }   
  89.         }   
  90.         else    
  91.         {   
  92.             if (ch == '\n' || ch == '\r')   
  93.             {   
  94.                 sc.SetState(typeLineStart);   
  95.             }   
  96.             //当前状态是行首   
  97.             else if (sc.state == typeLineStart)   
  98.             {   
  99.                 if (ch == 'O' || ch == 'P')//EIA的行号以大写的'O'开始,PA的是P。字母o和数字0混在一起,认不出来了,呵呵   
  100.                 {   
  101.                     if (isdigit(chNext))   
  102.                     {   
  103.                         sc.SetState(typeProgramNumber);   
  104.                     }   
  105.                 }   
  106.                 else if (ch == 'M')   
  107.                 {   
  108.                     if (isdigit(chNext))   
  109.                     {   
  110.                         sc.SetState(typeM);   
  111.                     }   
  112.                 }   
  113.                 else if (ch == 'G')   
  114.                 {   
  115.                     if (isdigit(chNext))   
  116.                     {   
  117.                         memset(szLastGCode, 0, 100);   
  118.                         sc.SetState(typeG);   
  119.                     }   
  120.                 }   
  121.                 else if (ch == '%')   
  122.                 {   
  123.                     sc.SetState(typeNCProgramStart);   
  124.                 }   
  125.                 else if (ch == ';')   
  126.                 {   
  127.                     sc.SetState(typeNCDescription);   
  128.                 }   
  129.                 else if (ch == '\x1B')//\ESC   
  130.                 {   
  131.                     sc.SetState(typeNCProgramEnd);   
  132.                 }   
  133.                 else if (ch == 'N')   
  134.                 {   
  135.                     if (isdigit(chNext))   
  136.                     {   
  137.                         sc.SetState(typeNCLineNumber);   
  138.                     }   
  139.                 }   
  140.                 //行首就是XY等坐标数据,那么看上几行的G代码是否包含G00,G01,G02,G03等   
  141.                 else if (nLastGCode == 0 || nLastGCode == 1 || nLastGCode == 2 || nLastGCode == 3)   
  142.                 {   
  143.                     //注意这里:省略了G指令的写法,我们要将他补上   
  144.                     if (ch == 'X')   
  145.                     {   
  146.                         if (isdigit(chNext))   
  147.                             sc.SetState(typeX);   
  148.                     }   
  149.                     else if (ch == 'Y')   
  150.                     {   
  151.                         if (isdigit(chNext))   
  152.                             sc.SetState(typeY);   
  153.                     }   
  154.                     else if (ch == 'I')   
  155.                     {   
  156.                         if (isdigit(chNext))   
  157.                             sc.SetState(typeI);   
  158.                     }   
  159.                     else if (ch == 'J')   
  160.                     {   
  161.                         if (isdigit(chNext))   
  162.                             sc.SetState(typeJ);   
  163.                     }   
  164.                 }   
  165.             }   
  166.             //当前状态是程序号   
  167.             else if (sc.state == typeProgramNumber)   
  168.             {   
  169.                 if (isdigit(ch))   
  170.                 {   
  171.                     sc.SetState(typeProgramNumber);   
  172.                 }   
  173.             }   
  174.             //当前状态是行号   
  175.             else if (sc.state == typeNCLineNumber)   
  176.             {   
  177.                 if (isdigit(ch))   
  178.                 {   
  179.                     sc.SetState(typeNCLineNumberValue);   
  180.                 }   
  181.             }   
  182.             //当前状态是行号的值   
  183.             else if (sc.state == typeNCLineNumberValue)   
  184.             {   
  185.                 if (isdigit(ch))   
  186.                 {   
  187.                     sc.SetState(typeNCLineNumberValue);   
  188.                 }   
  189.                 else if (ch == 'M')   
  190.                 {   
  191.                     if (isdigit(chNext))   
  192.                         sc.SetState(typeM);   
  193.                 }   
  194.                 else if (ch == 'G')   
  195.                 {   
  196.                     if (isdigit(chNext))   
  197.                     {   
  198.                         memset(szLastGCode, 0, 100);   
  199.                         sc.SetState(typeG);   
  200.                     }   
  201.                 }   
  202.                 //行号后紧接着就是XY等坐标数据,那么就要看上几行的G代码是否包含G00,G01,G02,G03等   
  203.                 else if (nLastGCode == 0 || nLastGCode == 1 || nLastGCode == 2 || nLastGCode == 3)   
  204.                 {   
  205.                     //注意这里:省略了G指令的写法,我们要将他补上   
  206.                     if (ch == 'X')   
  207.                     {   
  208.                         if (isdigit(chNext))   
  209.                             sc.SetState(typeX);   
  210.                     }   
  211.                     else if (ch == 'Y')   
  212.                     {   
  213.                         if (isdigit(chNext))   
  214.                             sc.SetState(typeY);   
  215.                     }   
  216.                     else if (ch == 'I')   
  217.                     {   
  218.                         if (isdigit(chNext))   
  219.                             sc.SetState(typeI);   
  220.                     }   
  221.                     else if (ch == 'J')   
  222.                     {   
  223.                         if (isdigit(chNext))   
  224.                             sc.SetState(typeJ);   
  225.                     }   
  226.                     else if (ch == 'F')   
  227.                     {   
  228.                         if (isdigit(chNext))   
  229.                             sc.SetState(typeF);   
  230.                     }   
  231.                 }   
  232.             }   
  233.             //当前状态是M   
  234.             else if (sc.state == typeM)   
  235.             {   
  236.                 if (isdigit(ch))   
  237.                 {   
  238.                     sc.SetState(typeMValue);   
  239.                 }   
  240.             }   
  241.             //当前状态是M的值   
  242.             else if (sc.state == typeMValue)   
  243.             {   
  244.                 if (isdigit(ch))   
  245.                 {   
  246.                     sc.SetState(typeMValue);   
  247.                 }   
  248.             }   
  249.             //当前状态是G   
  250.             else if (sc.state == typeG)   
  251.             {   
  252.                 if (isdigit(ch))   
  253.                 {   
  254.                     sc.SetState(typeGValue);   
  255.                     char szChar[10];   
  256.                     memset(szChar, 0, 10);   
  257.                     sprintf(szChar, "%c", (char)ch);   
  258.                     //itoa(UpperLowerChar,szChar,10);   
  259.                     strcat(szLastGCode, szChar);   
  260.                 }   
  261.             }   
  262.             else if (sc.state == typeF)   
  263.             {   
  264.                 if (isdigit(ch))   
  265.                 {   
  266.                     sc.SetState(typeFValue);   
  267.                 }   
  268.             }   
  269.             //当前状态是G的值   
  270.             else if (sc.state == typeGValue)   
  271.             {   
  272.                 if (isdigit(ch))   
  273.                 {   
  274.                     sc.SetState(typeGValue);   
  275.                     char szChar[10];   
  276.                     memset(szChar, 0, 10);   
  277.                     sprintf(szChar, "%c", (char)ch);   
  278.                     //itoa(UpperLowerChar,szChar,10);   
  279.                     strcat(szLastGCode, szChar);   
  280.                 }   
  281.                 else if (ch == 'X')   
  282.                 {   
  283.                     if (isdigit(chNext))   
  284.                         sc.SetState(typeX);   
  285.                 }   
  286.                 else if (ch == 'Y')   
  287.                 {   
  288.                     if (isdigit(chNext))   
  289.                         sc.SetState(typeY);   
  290.                 }   
  291.                 else if (ch == 'I')   
  292.                 {   
  293.                     if (isdigit(chNext))   
  294.                         sc.SetState(typeI);   
  295.                 }   
  296.                 else if (ch == 'J')   
  297.                 {   
  298.                     if (isdigit(chNext))   
  299.                         sc.SetState(typeI);   
  300.                 }   
  301.             }   
  302.             //当前状态是X   
  303.             else if (sc.state == typeX)   
  304.             {   
  305.                 if (isdigit(ch))   
  306.                 {   
  307.                     sc.SetState(typeXValue);   
  308.                 }   
  309.   
  310.             }   
  311.             //当前状态是X的值   
  312.             else if (sc.state == typeXValue)   
  313.             {   
  314.                 if (isdigit(ch))   
  315.                 {   
  316.                     sc.SetState(typeXValue);   
  317.                 }   
  318.                 else if (ch == 'Y')   
  319.                 {   
  320.                     if (isdigit(chNext))   
  321.                         sc.SetState(typeY);   
  322.                 }   
  323.                 else if (ch == 'I')   
  324.                 {   
  325.                     if (isdigit(chNext))   
  326.                         sc.SetState(typeI);   
  327.                 }   
  328.                 else if (ch == 'J')   
  329.                 {   
  330.                     if (isdigit(chNext))   
  331.                         sc.SetState(typeJ);   
  332.                 }   
  333.                 else if (ch == 'F')   
  334.                 {   
  335.                     if (isdigit(chNext))   
  336.                         sc.SetState(typeF);   
  337.                 }   
  338.             }   
  339.             //当前状态是Y   
  340.             else if (sc.state == typeY)   
  341.             {   
  342.                 if (isdigit(ch))   
  343.                 {   
  344.                     sc.SetState(typeYValue);   
  345.                 }   
  346.             }   
  347.             //当前状态是Y的值   
  348.             else if (sc.state == typeYValue)   
  349.             {   
  350.                 if (isdigit(ch))   
  351.                 {   
  352.                     sc.SetState(typeYValue);   
  353.                 }   
  354.                 else if (ch == 'I')   
  355.                 {   
  356.                     if (isdigit(chNext))   
  357.                         sc.SetState(typeI);   
  358.                 }   
  359.                 else if (ch == 'J')   
  360.                 {   
  361.                     if (isdigit(chNext))   
  362.                         sc.SetState(typeJ);   
  363.                 }   
  364.                 else if (ch == 'F')   
  365.                 {   
  366.                     if (isdigit(chNext))   
  367.                         sc.SetState(typeF);   
  368.                 }   
  369.             }   
  370.             //当前状态是I   
  371.             else if (sc.state == typeI)   
  372.             {   
  373.                 if (isdigit(ch))   
  374.                 {   
  375.                     sc.SetState(typeIValue);   
  376.                 }   
  377.             }   
  378.             //当前状态是I的值   
  379.             else if (sc.state == typeIValue)   
  380.             {   
  381.                 if (isdigit(ch))   
  382.                 {   
  383.                     sc.SetState(typeIValue);   
  384.                 }   
  385.                 else if (ch == 'J')   
  386.                 {   
  387.                     if (isdigit(chNext))   
  388.                         sc.SetState(typeJ);   
  389.                 }   
  390.                 else if (ch == 'F')   
  391.                 {   
  392.                     if (isdigit(chNext))   
  393.                         sc.SetState(typeF);   
  394.                 }   
  395.             }   
  396.             //当前状态是J   
  397.             else if (sc.state == typeJ)   
  398.             {   
  399.                 if (isdigit(ch))   
  400.                 {   
  401.                     sc.SetState(typeJValue);   
  402.                 }   
  403.             }   
  404.             //当前状态是J的值   
  405.             else if (sc.state == typeJValue)   
  406.             {   
  407.                 if (isdigit(ch))   
  408.                 {   
  409.                     sc.SetState(typeJValue);   
  410.                 }   
  411.                 else if (ch == 'F')   
  412.                 {   
  413.                     if (isdigit(chNext))   
  414.                         sc.SetState(typeF);   
  415.                 }   
  416.             }   
  417.             else  
  418.             {   
  419.                 sc.SetState(typeDefault);   
  420.             }          
  421.         }   
  422.         nLastGCode = atoi(szLastGCode);   
  423.         LastTokenType=sc.state;   
  424.     }   
  425.     sc.Complete();   
  426. }   
  427.   
  428. LexerModule lmNCProg(SCLEX_NCPROG, ColouriseNCProgDoc, "NCProg", 0, NCProgWordListDesc);  

3.修改KeyWords.cxx,加上:

C++代码
  1. LINK_LEXER(lmNCProg);   

编译即可。
源代码如下:Scintilla(NCProg).rar

第二部分、在项目中使用

具体参看如下源代码和说明。

NcEditDemo.rar

封装Scintilla的简单NC编辑器控件应用文档.pdf

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在一个TextBox实现C++语法,可以通过以下步骤实现: 1. 在TextBox的TextChanged事件获取文本框的文本。 2. 使用正则表达式匹配C++语法的关键字、注释、字符串等。 3. 为匹配到的文本设置不同的颜色。 以下是一个简单示例代码,可以实现关键字和注释的: ```csharp private void textBox1_TextChanged(object sender, EventArgs e) { string syntax = @"(\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while)\b)|(\/\/.*)"; MatchCollection matches = Regex.Matches(textBox1.Text, syntax, RegexOptions.Multiline); int startIndex = textBox1.SelectionStart; int length = textBox1.SelectionLength; foreach (Match match in matches) { textBox1.Select(match.Index, match.Length); textBox1.SelectionColor = Color.Blue; } textBox1.Select(startIndex, length); } ``` 需要注意的是,这个示例代码只是一个简单的实现,还有很多C++语法的特性没有考虑到。如果需要完整的C++语法支持,可以考虑使用专业的文本编辑件,比如Scintilla

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值