博客日历
2025年06月 | ||||||
一 | 二 | 三 | 四 | 五 | 六 | 七 |
26 | 27 | 28 | 29 | 30 | 31 | 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
存档
2025年03月 2024年
03月 04月 05月 2021年
01月 02月 11月 12月 2020年
02月 03月 04月 05月 06月 07月
09月 2018年
09月 2017年
01月 02月 07月 2016年
01月 04月 07月 08月 11月 12月
2015年
01月 02月 03月 05月 09月 10月
11月 2014年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2013年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2012年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2011年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2010年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2009年
03月 04月 05月 06月 07月 08月
09月 10月 11月 12月
语法高亮编辑控件Scintilla在MFC中的简单使用之完整示例
该示例是一个简单的NC程序编辑器,附件代码在Visual Studio .NET 2003(VC++7.1)下编译通过。
第一部分、修改Scintilla,使其支持NC程序
1.修改SciLexer.h,加上自己的token类型定义
C++代码
- #define SCLEX_NCPROG 87 //淡月清风 2008年11月7日17:19:23
- #define typeDefault 0x00
- #define typeLineStart 0x01
- #define typeG 0x02
- #define typeGValue 0x03
- #define typeM 0x04
- #define typeMValue 0x05
- #define typeX 0x06
- #define typeXValue 0x07
- #define typeY 0x08
- #define typeYValue 0x09
- #define typeI 0x0A
- #define typeIValue 0x0B
- #define typeJ 0x0C
- #define typeJValue 0x0D
- #define typeComment 0x0E //()
- #define typeNCProgramStart 0x0F //%
- #define typeNCDescription 0x10 //;
- #define typeNCProgramEnd 0x11 //“\ESC” ASCII码是27
- #define typeNCLineNumber 0x12 //行号 N
- #define typeNCLineNumberValue 0x13 //行号 01201
- #define typeProgramNumber 0x14
- #define typeF 0x15
- #define typeFValue 0x16
2.编写NC程序词法分析的Lex程序LexNCProg.cxx
这个Lex程序扫描全部字符,并标记当前字符的状态,它使用的是状态机技术(类似于状态模式)。
C++代码
- //Scintilla source code edit control
- /** @file LexNCProg.cxx
- ** Lexer for NC Program.
- **/
- // Copyright 2008-2010 by 淡月清风 <dgx_lsyd3@163.com>
- //修改记录:
- // 2008年12月15日12:08:39:
- // 1.使大小写不区分
- // 2.G01,02等的省略写法,X,Y直接在行首无法识别的BUG
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <windows.h>
- #include "Platform.h"
- #include "PropSet.h"
- #include "Accessor.h"
- #include "StyleContext.h"
- #include "KeyWords.h"
- #include "Scintilla.h"
- #include "SciLexer.h"
- #ifdef SCI_NAMESPACE
- using namespace Scintilla;
- #endif
- static const char * const NCProgWordListDesc[] =
- {
- 0
- };
- static void ColouriseNCProgDoc(
- unsigned int startPos, int length, int initStyle,
- WordList *keywordlists[],
- Accessor &styler)
- {
- static int LastTokenTypeForComment = typeLineStart;
- static int LastTokenType=typeLineStart;
- static int nLastGCode = -1; //记录本行之前的G代码。
- char szLastGCode[100];
- memset(szLastGCode, 0, 100);
- StyleContext sc(startPos, length, initStyle, styler);
- sc.SetState(typeLineStart);
- for (; sc.More(); sc.Forward())
- {
- //char szText[4];
- //sprintf(szText,"%c",sc.ch);
- //OutputDebugString(szText);
- int ch = sc.ch;
- int chNext = sc.chNext;
- int chPrev = sc.chPrev;
- if (isalpha(ch))
- {
- ch = toupper(ch);
- }
- if (isalpha(chNext))
- {
- chNext = toupper(chNext);
- }
- if (isalpha(chPrev))
- {
- chPrev = toupper(chPrev);
- }
- // 重点关注:从这里开始执行词法分析代码
- // 若注释可以出现在任何位置
- // 当前字符是注释开始
- if (ch == '(')
- {
- LastTokenTypeForComment = sc.state;
- sc.SetState(typeComment);
- }
- //当前状态是注释
- else if (sc.state == typeComment || LastTokenType==typeComment)
- {
- sc.SetState(typeComment);
- if (ch == ')')
- {
- sc.ForwardSetState(LastTokenTypeForComment);
- }
- }
- else
- {
- if (ch == '\n' || ch == '\r')
- {
- sc.SetState(typeLineStart);
- }
- //当前状态是行首
- else if (sc.state == typeLineStart)
- {
- if (ch == 'O' || ch == 'P')//EIA的行号以大写的'O'开始,PA的是P。字母o和数字0混在一起,认不出来了,呵呵
- {
- if (isdigit(chNext))
- {
- sc.SetState(typeProgramNumber);
- }
- }
- else if (ch == 'M')
- {
- if (isdigit(chNext))
- {
- sc.SetState(typeM);
- }
- }
- else if (ch == 'G')
- {
- if (isdigit(chNext))
- {
- memset(szLastGCode, 0, 100);
- sc.SetState(typeG);
- }
- }
- else if (ch == '%')
- {
- sc.SetState(typeNCProgramStart);
- }
- else if (ch == ';')
- {
- sc.SetState(typeNCDescription);
- }
- else if (ch == '\x1B')//\ESC
- {
- sc.SetState(typeNCProgramEnd);
- }
- else if (ch == 'N')
- {
- if (isdigit(chNext))
- {
- sc.SetState(typeNCLineNumber);
- }
- }
- //行首就是XY等坐标数据,那么看上几行的G代码是否包含G00,G01,G02,G03等
- else if (nLastGCode == 0 || nLastGCode == 1 || nLastGCode == 2 || nLastGCode == 3)
- {
- //注意这里:省略了G指令的写法,我们要将他补上
- if (ch == 'X')
- {
- if (isdigit(chNext))
- sc.SetState(typeX);
- }
- else if (ch == 'Y')
- {
- if (isdigit(chNext))
- sc.SetState(typeY);
- }
- else if (ch == 'I')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeJ);
- }
- }
- }
- //当前状态是程序号
- else if (sc.state == typeProgramNumber)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeProgramNumber);
- }
- }
- //当前状态是行号
- else if (sc.state == typeNCLineNumber)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeNCLineNumberValue);
- }
- }
- //当前状态是行号的值
- else if (sc.state == typeNCLineNumberValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeNCLineNumberValue);
- }
- else if (ch == 'M')
- {
- if (isdigit(chNext))
- sc.SetState(typeM);
- }
- else if (ch == 'G')
- {
- if (isdigit(chNext))
- {
- memset(szLastGCode, 0, 100);
- sc.SetState(typeG);
- }
- }
- //行号后紧接着就是XY等坐标数据,那么就要看上几行的G代码是否包含G00,G01,G02,G03等
- else if (nLastGCode == 0 || nLastGCode == 1 || nLastGCode == 2 || nLastGCode == 3)
- {
- //注意这里:省略了G指令的写法,我们要将他补上
- if (ch == 'X')
- {
- if (isdigit(chNext))
- sc.SetState(typeX);
- }
- else if (ch == 'Y')
- {
- if (isdigit(chNext))
- sc.SetState(typeY);
- }
- else if (ch == 'I')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeJ);
- }
- else if (ch == 'F')
- {
- if (isdigit(chNext))
- sc.SetState(typeF);
- }
- }
- }
- //当前状态是M
- else if (sc.state == typeM)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeMValue);
- }
- }
- //当前状态是M的值
- else if (sc.state == typeMValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeMValue);
- }
- }
- //当前状态是G
- else if (sc.state == typeG)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeGValue);
- char szChar[10];
- memset(szChar, 0, 10);
- sprintf(szChar, "%c", (char)ch);
- //itoa(UpperLowerChar,szChar,10);
- strcat(szLastGCode, szChar);
- }
- }
- else if (sc.state == typeF)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeFValue);
- }
- }
- //当前状态是G的值
- else if (sc.state == typeGValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeGValue);
- char szChar[10];
- memset(szChar, 0, 10);
- sprintf(szChar, "%c", (char)ch);
- //itoa(UpperLowerChar,szChar,10);
- strcat(szLastGCode, szChar);
- }
- else if (ch == 'X')
- {
- if (isdigit(chNext))
- sc.SetState(typeX);
- }
- else if (ch == 'Y')
- {
- if (isdigit(chNext))
- sc.SetState(typeY);
- }
- else if (ch == 'I')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- }
- //当前状态是X
- else if (sc.state == typeX)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeXValue);
- }
- }
- //当前状态是X的值
- else if (sc.state == typeXValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeXValue);
- }
- else if (ch == 'Y')
- {
- if (isdigit(chNext))
- sc.SetState(typeY);
- }
- else if (ch == 'I')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeJ);
- }
- else if (ch == 'F')
- {
- if (isdigit(chNext))
- sc.SetState(typeF);
- }
- }
- //当前状态是Y
- else if (sc.state == typeY)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeYValue);
- }
- }
- //当前状态是Y的值
- else if (sc.state == typeYValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeYValue);
- }
- else if (ch == 'I')
- {
- if (isdigit(chNext))
- sc.SetState(typeI);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeJ);
- }
- else if (ch == 'F')
- {
- if (isdigit(chNext))
- sc.SetState(typeF);
- }
- }
- //当前状态是I
- else if (sc.state == typeI)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeIValue);
- }
- }
- //当前状态是I的值
- else if (sc.state == typeIValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeIValue);
- }
- else if (ch == 'J')
- {
- if (isdigit(chNext))
- sc.SetState(typeJ);
- }
- else if (ch == 'F')
- {
- if (isdigit(chNext))
- sc.SetState(typeF);
- }
- }
- //当前状态是J
- else if (sc.state == typeJ)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeJValue);
- }
- }
- //当前状态是J的值
- else if (sc.state == typeJValue)
- {
- if (isdigit(ch))
- {
- sc.SetState(typeJValue);
- }
- else if (ch == 'F')
- {
- if (isdigit(chNext))
- sc.SetState(typeF);
- }
- }
- else
- {
- sc.SetState(typeDefault);
- }
- }
- nLastGCode = atoi(szLastGCode);
- LastTokenType=sc.state;
- }
- sc.Complete();
- }
- LexerModule lmNCProg(SCLEX_NCPROG, ColouriseNCProgDoc, "NCProg", 0, NCProgWordListDesc);
3.修改KeyWords.cxx,加上:
C++代码
- LINK_LEXER(lmNCProg);
编译即可。
源代码如下:Scintilla(NCProg).rar
第二部分、在项目中使用
具体参看如下源代码和说明。
NcEditDemo.rar
封装Scintilla的简单NC编辑器控件应用文档.pdf
上一篇: 语法高亮编辑控件Scintilla在MFC中的简单使用
下一篇: 将AStyle集成到VC++7.1
分类:Win32/C++ 查看次数:13353 发布时间:2009/5/12 18:53:08