用 C++Builder 用 TRichEdit 编写 SQL 编辑器

很想找一现成的 SQL 编辑器, 可是 NO!,只好自己努力一把了!

没有拼写检查,没有自动完成,只提供根据[关键字/函数/数据类型]进行着色.

[关键字/函数/数据类型]都是 MSSQL 的,其他数据库需要参考相关资料自己动手

 

.dfm

  object SQLEditor: TRichEdit
    Font.Color = clWindowText
    Font.Height = -15
    Font.Name = 'Consolas'
    OnChange = SQLEditorChange
  end

.h

class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TRichEdit *SQLEditor;
    TMemo *Memo1;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormDestroy(TObject *Sender);
    void __fastcall SQLEditorChange(TObject *Sender);
private:    // User declarations
    TStringList * FKeywords;     // 关键字
    TStringList * FFunctions;     // 函数
    TStringList * FDatatypes;    // 数据类型
public:        // User declarations
    __fastcall TForm1(TComponent* Owner);
};

.cpp

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{

    FKeywords = new TStringList;
    FFunctions = new TStringList;
    FDatatypes = new TStringList;

    FKeywords->Add("ADD");
    FKeywords->Add("ALL");
    FKeywords->Add("ALTER");
    FKeywords->Add("AND");
    FKeywords->Add("ANY");
    FKeywords->Add("AS");
    FKeywords->Add("ASC");
    FKeywords->Add("AUTHORIZATION");
    FKeywords->Add("BACKUP");
    FKeywords->Add("BEGIN");
    FKeywords->Add("BETWEEN");
    FKeywords->Add("BREAK");
    FKeywords->Add("BROWSE");
    FKeywords->Add("BULK");
    FKeywords->Add("BY");
    FKeywords->Add("CASCADE");
    FKeywords->Add("CASE");
    FKeywords->Add("CHECK");
    FKeywords->Add("CHECKPOINT");
    FKeywords->Add("CLOSE");
    FKeywords->Add("CLUSTERED");
    FKeywords->Add("COALESCE");
    FKeywords->Add("COLLATE");
    FKeywords->Add("COLUMN");
    FKeywords->Add("COMMIT");
    FKeywords->Add("COMPUTE");
    FKeywords->Add("CONSTRAINT");
    FKeywords->Add("CONTAINS");
    FKeywords->Add("CONTAINSTABLE");
    FKeywords->Add("CONTINUE");
    FKeywords->Add("CONVERT");
    FKeywords->Add("CREATE");
    FKeywords->Add("CROSS");
    FKeywords->Add("CURRENT");
    FKeywords->Add("CURRENT_DATE");
    FKeywords->Add("CURRENT_TIME");
    FKeywords->Add("CURRENT_TIMESTAMP");
    FKeywords->Add("CURRENT_USER");
    FKeywords->Add("CURSOR");
    FKeywords->Add("DATABASE");
    FKeywords->Add("DBCC");
    FKeywords->Add("DEALLOCATE");
    FKeywords->Add("DECLARE");
    FKeywords->Add("DEFAULT");
    FKeywords->Add("DELETE");
    FKeywords->Add("DENY");
    FKeywords->Add("DESC");
    FKeywords->Add("DISK");
    FKeywords->Add("DISTINCT");
    FKeywords->Add("DISTRIBUTED");
    FKeywords->Add("DOUBLE");
    FKeywords->Add("DROP");
    FKeywords->Add("DUMP");
    FKeywords->Add("ELSE");
    FKeywords->Add("END");
    FKeywords->Add("ERRLVL");
    FKeywords->Add("ESCAPE");
    FKeywords->Add("EXCEPT");
    FKeywords->Add("EXEC");
    FKeywords->Add("EXECUTE");
    FKeywords->Add("EXISTS");
    FKeywords->Add("EXIT");
    FKeywords->Add("EXTERNAL");
    FKeywords->Add("FETCH");
    FKeywords->Add("FILE");
    FKeywords->Add("FILLFACTOR");
    FKeywords->Add("FOR");
    FKeywords->Add("FOREIGN");
    FKeywords->Add("FREETEXT");
    FKeywords->Add("FREETEXTTABLE");
    FKeywords->Add("FROM");
    FKeywords->Add("FULL");
    FKeywords->Add("FUNCTION");
    FKeywords->Add("GOTO");
    FKeywords->Add("GRANT");
    FKeywords->Add("GROUP");
    FKeywords->Add("HAVING");
    FKeywords->Add("HOLDLOCK");
    FKeywords->Add("IDENTITY");
    FKeywords->Add("IDENTITY_INSERT");
    FKeywords->Add("IDENTITYCOL");
    FKeywords->Add("IF");
    FKeywords->Add("IN");
    FKeywords->Add("INDEX");
    FKeywords->Add("INNER");
    FKeywords->Add("INSERT");
    FKeywords->Add("INTERSECT");
    FKeywords->Add("INTO");
    FKeywords->Add("IS");
    FKeywords->Add("JOIN");
    FKeywords->Add("KEY");
    FKeywords->Add("KILL");
    FKeywords->Add("LEFT");
    FKeywords->Add("LIKE");
    FKeywords->Add("LINENO");
    FKeywords->Add("LOAD");
    FKeywords->Add("MERGE");
    FKeywords->Add("NATIONAL");
    FKeywords->Add("NOCHECK");
    FKeywords->Add("NONCLUSTERED");
    FKeywords->Add("NOT");
    FKeywords->Add("NULL");
    FKeywords->Add("NULLIF");
    FKeywords->Add("OF");
    FKeywords->Add("OFF");
    FKeywords->Add("OFFSETS");
    FKeywords->Add("ON");
    FKeywords->Add("OPEN");
    FKeywords->Add("OPENDATASOURCE");
    FKeywords->Add("OPENQUERY");
    FKeywords->Add("OPENROWSET");
    FKeywords->Add("OPENXML");
    FKeywords->Add("OPTION");
    FKeywords->Add("OR");
    FKeywords->Add("ORDER");
    FKeywords->Add("OUTER");
    FKeywords->Add("OVER");
    FKeywords->Add("PERCENT");
    FKeywords->Add("PIVOT");
    FKeywords->Add("PLAN");
    FKeywords->Add("PRECISION");
    FKeywords->Add("PRIMARY");
    FKeywords->Add("PRINT");
    FKeywords->Add("PROC");
    FKeywords->Add("PROCEDURE");
    FKeywords->Add("PUBLIC");
    FKeywords->Add("RAISERROR");
    FKeywords->Add("READ");
    FKeywords->Add("READTEXT");
    FKeywords->Add("RECONFIGURE");
    FKeywords->Add("REFERENCES");
    FKeywords->Add("REPLICATION");
    FKeywords->Add("RESTORE");
    FKeywords->Add("RESTRICT");
    FKeywords->Add("RETURN");
    FKeywords->Add("REVERT");
    FKeywords->Add("REVOKE");
    FKeywords->Add("RIGHT");
    FKeywords->Add("ROLLBACK");
    FKeywords->Add("ROWCOUNT");
    FKeywords->Add("ROWGUIDCOL");
    FKeywords->Add("RULE");
    FKeywords->Add("SAVE");
    FKeywords->Add("SCHEMA");
    FKeywords->Add("SECURITYAUDIT");
    FKeywords->Add("SELECT");
    FKeywords->Add("SESSION_USER");
    FKeywords->Add("SET");
    FKeywords->Add("SETUSER");
    FKeywords->Add("SHUTDOWN");
    FKeywords->Add("SOME");
    FKeywords->Add("STATISTICS");
    FKeywords->Add("SYSTEM_USER");
    FKeywords->Add("TABLE");
    FKeywords->Add("TABLESAMPLE");
    FKeywords->Add("TEXTSIZE");
    FKeywords->Add("THEN");
    FKeywords->Add("TO");
    FKeywords->Add("TOP");
    FKeywords->Add("TRAN");
    FKeywords->Add("TRANSACTION");
    FKeywords->Add("TRIGGER");
    FKeywords->Add("TRUNCATE");
    FKeywords->Add("TSEQUAL");
    FKeywords->Add("UNION");
    FKeywords->Add("UNIQUE");
    FKeywords->Add("UNPIVOT");
    FKeywords->Add("UPDATE");
    FKeywords->Add("UPDATETEXT");
    FKeywords->Add("USE");
    FKeywords->Add("USER");
    FKeywords->Add("VALUES");
    FKeywords->Add("VARYING");
    FKeywords->Add("VIEW");
    FKeywords->Add("WAITFOR");
    FKeywords->Add("WHEN");
    FKeywords->Add("WHERE");
    FKeywords->Add("WHILE");
    FKeywords->Add("WITH");
    FKeywords->Add("WRITETEXT");

    FKeywords->Sorted = true;

    FFunctions->Add("ABS");
    FFunctions->Add("ACOS");
    FFunctions->Add("ASCII");
    FFunctions->Add("ASIN");
    FFunctions->Add("ATAN");
    FFunctions->Add("ATN2");
    FFunctions->Add("AVG");
    FFunctions->Add("CEILING");
    FFunctions->Add("CHAR");
    FFunctions->Add("CHARINDEX");
    FFunctions->Add("CHECKSUM_AGG");
    FFunctions->Add("COS");
    FFunctions->Add("COT");
    FFunctions->Add("COUNT");
    FFunctions->Add("COUNT_BIG");
    FFunctions->Add("CURRENT_TIMESTAMP");
    FFunctions->Add("DATEADD");
    FFunctions->Add("DATEDIFF");
    FFunctions->Add("DATENAME");
    FFunctions->Add("DATEPART");
    FFunctions->Add("DAY");
    FFunctions->Add("DEGREES");
    FFunctions->Add("DIFFERENCE");
    FFunctions->Add("EXP");
    FFunctions->Add("FLOOR");
    FFunctions->Add("GETDATE");
    FFunctions->Add("GETUTCDATE");
    FFunctions->Add("GROUPING");
    FFunctions->Add("LEFT");
    FFunctions->Add("LEN");
    FFunctions->Add("LOG");
    FFunctions->Add("LOG10");
    FFunctions->Add("LOWER");
    FFunctions->Add("LTRIM");
    FFunctions->Add("MAX");
    FFunctions->Add("MIN");
    FFunctions->Add("MONTH");
    FFunctions->Add("NCHAR");
    FFunctions->Add("PATINDEX");
    FFunctions->Add("PATINDEX");
    FFunctions->Add("PI");
    FFunctions->Add("POWER");
    FFunctions->Add("QUOTENAME");
    FFunctions->Add("RADIANS");
    FFunctions->Add("RAND");
    FFunctions->Add("REPLACE");
    FFunctions->Add("REPLICATE");
    FFunctions->Add("REVERSE");
    FFunctions->Add("RIGHT");
    FFunctions->Add("ROUND");
    FFunctions->Add("RTRIM");
    FFunctions->Add("SIGN");
    FFunctions->Add("SIN");
    FFunctions->Add("SOUNDEX");
    FFunctions->Add("SPACE");
    FFunctions->Add("SQRT");
    FFunctions->Add("SQUARE");
    FFunctions->Add("STDEV");
    FFunctions->Add("STDEVP");
    FFunctions->Add("STR");
    FFunctions->Add("STUFF");
    FFunctions->Add("SUBSTRING");
    FFunctions->Add("SUM");
    FFunctions->Add("SYSDATETIME");
    FFunctions->Add("SYSDATETIMEOFFSET");
    FFunctions->Add("SYSUTCDATETIME");
    FFunctions->Add("TAN");
    FFunctions->Add("TEXTPTR");
    FFunctions->Add("TEXTVALID");
    FFunctions->Add("UNICODE");
    FFunctions->Add("UPPER");
    FFunctions->Add("VAR");
    FFunctions->Add("VARP");
    FFunctions->Add("YEAR");

    FFunctions->Sorted = true;

    FDatatypes->Add("BIGINT");
    FDatatypes->Add("BINARY");
    FDatatypes->Add("BIT");
    FDatatypes->Add("CHAR");
    FDatatypes->Add("DATE");
    FDatatypes->Add("DATETIME");
    FDatatypes->Add("DATETIME2");
    FDatatypes->Add("DATETIMEOFFSET");
    FDatatypes->Add("DECIMAL");
    FDatatypes->Add("FLOAT");
    FDatatypes->Add("IMAGE");
    FDatatypes->Add("INT");
    FDatatypes->Add("MONEY");
    FDatatypes->Add("NCHAR");
    FDatatypes->Add("NTEXT");
    FDatatypes->Add("NUMERIC");
    FDatatypes->Add("NVARCHAR");
    FDatatypes->Add("REAL");
    FDatatypes->Add("SMALLDATETIME");
    FDatatypes->Add("SMALLINT");
    FDatatypes->Add("SMALLMONEY");
    FDatatypes->Add("TEXT");
    FDatatypes->Add("TIME");
    FDatatypes->Add("TIMESTAMP");
    FDatatypes->Add("TINYINT");
    FDatatypes->Add("VARBINARY");
    FDatatypes->Add("VARCHAR");
    FDatatypes->Add("XML");

    FDatatypes->Sorted = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
    delete FDatatypes;
    delete FFunctions;
    delete FKeywords;
}

//---------------------------------------------------------------------------
void __fastcall TForm1::SQLEditorChange(TObject *Sender)
{
    int LStart = SQLEditor->SelStart;
    int LLength = SQLEditor->SelLength;
    try
    {
        SQLEditor->Perform(EM_HIDESELECTION, (NativeUInt)true, 0);

        int J = 0;
        int Z = 0;
        int L = SQLEditor->Lines->Text.Length();
        wchar_t * buf = SQLEditor->Lines->Text.c_str();

        SQLEditor->SelStart = 0;
        SQLEditor->SelLength = L;
        SQLEditor->SelAttributes->Color = SQLEditor->Font->Color;
        SQLEditor->SelAttributes->Style = SQLEditor->Font->Style;

        while (J < L)
        {
            int I, N = 0;
            String S = EmptyStr;
            SQLEditor->SelStart = J - Z;

            if (buf[J] == 0x0A)                             // "\n"
            {
                Z++;
            }
            else if (buf[J] == 0x27)                        // "'" 字符优先
            {
                I = J + 1;
                while (I < L)
                if (buf[I] == 0x27) break;
                else
                {
                    if (buf[I] == 0x0A) N++;
                    I++;
                }
                SQLEditor->SelLength = I - J - N + 1;
                SQLEditor->SelAttributes->Color = clRed;
                Z += N;
                J = I;
            }
            else if (buf[J] == '/' && buf[J+1] == '*')      // 块注解
            {
                I = J + 2;
                while (I < L)
                {
                    if (buf[I] == 0x0A) N++;
                    else if (buf[I] == '*' && buf[I+1] == '/')
                    {
                        I++;
                        break;
                    }
                    I++;
                }
                SQLEditor->SelLength = I - J - N + 1;
                SQLEditor->SelAttributes->Color = clGreen;
                Z += N;
                J = I;
            }
            else if ((buf[J] == '/' && buf[J+1] == '/')     // 行注解
                    || (buf[J] == '-' && buf[J+1] == '-'))
            {
                I = J + 2;
                while (I < L)
                {
                    if (buf[I] == 0x0A || buf[I] == 0x0D) break;
                    I++;
                }

                SQLEditor->SelLength = I - J + 1;
                SQLEditor->SelAttributes->Color = clGreen;
                J = I;
            }
            else
            {
                for (I = J; I < L; I++)
                if ((buf[I] >= 'A' && buf[I] <= 'Z')
                          || (buf[I] >= 'a' && buf[I] <= 'z')
                          || (buf[I] >= '0' && buf[I] <= '9')
                          || buf[I] == '.' || buf[I] == '_')
                    S += buf[I];
                else break;

                if (S.Length())
                {
                    Extended E;
                    S = S.UpperCase();
                    SQLEditor->SelLength = S.Length();

                    if (FKeywords->Find(S, I))              //关键字
                    {
                        SQLEditor->SelAttributes->Color = clBlue;
//                        SQLEditor->SelAttributes->Style = TFontStyles()<<fsBold;
                    }
                    else if (FFunctions->Find(S, I))        //函数
                    {
                        SQLEditor->SelAttributes->Color = clFuchsia;
//                        SQLEditor->SelAttributes->Style = TFontStyles()<<fsBold;
                    }
                    else if (FDatatypes->Find(S, I))        //数据类型
                    {
                        SQLEditor->SelAttributes->Color = TColor(0x4080FF);
//                        SQLEditor->SelAttributes->Style = TFontStyles()<<fsBold;
                    }
                    else if (TryStrToFloat(S, E))           //数字
                        SQLEditor->SelAttributes->Color = clRed;
                    J += SQLEditor->SelLength;
                    J--;
                }
            }
            J++;
        }
    }
    __finally
    {
        SQLEditor->SelStart = LStart;
        SQLEditor->SelLength = LLength;
        SQLEditor->Perform(EM_HIDESELECTION, (NativeUInt)false, 0);
    }
}
//---------------------------------------------------------------------------
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值