繁体   English   中英

如何在 C# windows 表单 RichTextBox 中突出显示 HTML 语法?

[英]How to highlight HTML syntax in C# windows form RichTextBox?

我正在编写一个 c# Html 编辑器应用程序,您可以在其中的 RichTextBox 控件中键入代码。 我希望 RichTextBox 的行为像 notepad++ 和其他代码编辑器,其中 Html 语法在 colors 中突出显示,例如:

例子

如何在 RichTextBox 的 C# windows 中建立这个? 我几乎到处搜索,但没有找到任何对我有帮助的东西。 这是我到目前为止尝试过的,但我没有给出我想要的结果:

private void SyntaxHighlight()
        {
            string[] tags = { "html","head","body","a","b","img","strong","p","h1","h2","h3","h4","h5","h6","embed","iframe","span","form",
                            "button","input","textarea","br","div","style","script","table","tr","td","th","i","u","link","meta","title"};
            foreach (string s in tags)
            {
                richTextBox1.Find("<" + s); 
                richTextBox1.SelectionColor = Color.Blue;
                richTextBox1.Find(">");
                richTextBox1.SelectionColor = Color.Blue;
            }

            string[] attributes = { "href","src","height","width","rowspan","colspan","target","style","onclick","id","name","class"};
            foreach (string s in attributes)
            {
                richTextBox1.Find(s + "=");
                richTextBox1.SelectionColor = Color.Red;
            }
        }

有人能帮我吗? 我应该在 SyntaxHighlight() 方法中写什么? 有人可以给我适当的代码吗? 谢谢

在您的代码中,您只会发现HTML标记的第一个出现并将其突出显示。 但是,您应该遍历整个富文本内容,以查找同一文本的后续出现。 我只是根据您的确切代码进行了快速模拟,请检查一下。

    private void highlightHTMLText()
    {
        string[] tags = { "html","head","body","a","b","img","strong","p","h1","h2","h3","h4","h5","h6","embed","iframe","span","form",
                        "button","input","textarea","br","div","style","script","table","tr","td","th","i","u","link","meta","title"};
        foreach (string s in tags)
        {
            findAndHighlight("<" + s, Color.Blue);
            findAndHighlight("</" + s, Color.Blue);
            findAndHighlight(">", Color.Blue);
        }

        string[] attributes = { "href", "src", "height", "width", "rowspan", "colspan", "target", "style", "onclick", "id", "name", "class" };
        foreach (string s in attributes)
        {
            findAndHighlight(s + "=", Color.Red);
        }
    }

    private void findAndHighlight(string sSearchStr, Color oColor)
    {
        int index = richTextBox1.Text.IndexOf(sSearchStr);
        while (index != -1)
        {
            richTextBox1.Select(index, sSearchStr.Length);
            richTextBox1.SelectionColor = oColor;

            index = richTextBox1.Text.IndexOf(sSearchStr, index + sSearchStr.Length);
        }
    }

进一步根据答案,您应该能够使用Notepad ++本身使用的相同实用程序库Scintilla 如前所述,您不需要重新发明轮子,但是作为开发人员,我显然更喜欢自己的util(就是我;))。 希望这可以帮助。

查找不会移动光标,它会返回第一个匹配项的位置。 尝试以下方法:

如何从RichTextBox中选择文本,然后为其着色?

晚会有点晚了,但在想创建自己的离线版本的 CodePen 之后,我按照 CodePen 的主题实现了自己的 html 语法高亮版本。

这会进行语法突出显示和标记格式化,但格式化取决于您的 html 是否格式正确。

只需将其添加为您的 RichTextBox 的 class,相应地实例化它并在适合您的任何事件中调用它(我将它与 RTB 的 double_click 事件一起使用,但这确实消除了双击文本选择)。 我打算做的是添加一个计时器,一些 boolean 变量,并在 key_up 和 key_down 事件中进行操作,以将突出显示更新设置得更自动一些,对快捷方式的干扰更少。 (特此包含在类别下方)

    public void HighlightHTM(RichTextBox Htm_Input)
    {
        Htm_Input.Visible = false;
        #region store the original caret position + forecolor
        int originalIndex = Htm_Input.SelectionStart;
        int originalLength = Htm_Input.SelectionLength;
        Color originalColor = Color.FromArgb(200, 200, 200); // Grey
        #endregion
        #region try to format the markup
        try { Htm_Input.Text = XElement.Parse(Htm_Input.Text).ToString(); } catch { }
        #endregion
        #region match everything but puncutation and equals
        Regex e = new Regex(@"(.*?|=)[^\w\s]");
        MatchCollection eMatches = e.Matches(Htm_Input.Text);
        foreach (Match m in eMatches)
        {
            Htm_Input.SelectionStart = m.Groups[1].Index;
            Htm_Input.SelectionLength = m.Groups[1].Length;
            Htm_Input.SelectionColor = Color.FromArgb(221, 202, 126); // Yellow
        }
        #endregion
        #region match tags
        Regex t = new Regex(@"(<\w+|</\w+|/>|>)[^=]");
        MatchCollection tMatches = t.Matches(Htm_Input.Text, 0);
        foreach (Match m in tMatches)
        {
            Htm_Input.SelectionStart = m.Groups[1].Index;
            Htm_Input.SelectionLength = m.Groups[1].Length;
            Htm_Input.SelectionColor = Color.FromArgb(167, 146, 90); // Brown
        }
        #endregion
        #region match quotes
        Regex q = new Regex("\".*?\"");
        MatchCollection qMatches = q.Matches(Htm_Input.Text);
        foreach (Match m in qMatches)
        {
            Htm_Input.SelectionStart = m.Index;
            Htm_Input.SelectionLength = m.Length;
            Htm_Input.SelectionColor = Color.FromArgb(150, 179, 138); // Green
        }
        #endregion
        #region match inner html
        Regex h = new Regex(">(.+?)<");
        MatchCollection hMatches = h.Matches(Htm_Input.Text);
        foreach (Match m in hMatches)
        {
            Htm_Input.SelectionStart = m.Groups[1].Index;
            Htm_Input.SelectionLength = m.Groups[1].Length;
            Htm_Input.SelectionColor = Color.FromArgb(200, 200, 200); // Grey
        }
        #endregion
        #region restoring the original colors, for further writing
        Htm_Input.SelectionStart = originalIndex;
        Htm_Input.SelectionLength = originalLength;
        Htm_Input.SelectionColor = originalColor; // Light Grey
        #endregion
        Htm_Input.Focus();
        Htm_Input.Visible = true;
    }

编码愉快!

编辑:我还应该提到 that.doctype 破坏了格式,因为它在“格式良好”的上下文中并不完全是 xml 友好的,为了我的目的,所有标签包括正文和相关的关闭。 css 和 js 链接是在页面保存时以编程方式添加的,因此在 html RTB 中仅使用正文标签内的标记。 这消除了那个问题。

您会注意到这完全依赖于 Regex 而不是硬编码的标签和属性。 我这样做是因为标签和属性有一种经常在 w3 场景中出现和消失的趋势。 这将迫使开发人员不断地返回 go 并编辑这些字符串以删除不推荐使用的标签/属性或添加新的。 不是最优的。

我还认为提前 go 并包括实例化/使用示例以使其更即插即用是明智的。

在 public Main() 之上,像这样实例化:

    #region Class Instantiation
    SyntaxHighlight syntax = new SyntaxHighlight();
    #endregion

...并且,在您选择的事件处理程序中,这样称呼它:

    private void htm_input_DoubleClick(object sender, EventArgs e)
    {
        syntax.HighlightHTM(Htm_Input);
    }

自然地,添加一个 SaveFileDialog 和一个 OpenFileDialog 几乎可以提供您自己的功能,尽管非常基本,html 编辑器。 放入 WebBrowser 控件并将 RTB 的文本应用为 WebBrowser 的源,您就升级到了实时视图。

至少,这应该作为一般语法突出显示的可行参考。 它实际上归结为识别模式并操纵它们的 colors,因此,例如,这将有效地与 css、javascript 甚至 C# 一起工作,只需对模式识别参数进行一些轻微调整。

以下是我如何使用 key_up / key_down 设置自动刷新并将计时器设置为 1000 毫秒:

    #region Globals
    int r = 0;
    bool refresh = false;
    #endregion
    private void Htm_Input_KeyUp(object sender, KeyEventArgs e)
    {
        refresh = true; // enter refresh cycle
    }
    private void Htm_Input_KeyDown(object sender, KeyEventArgs e)
    {
        refresh = false; // abort refresh cycle
    }
    private void Timer_Refresh_Tick(object sender, EventArgs e)
    {
        // check if refresh cycle is entered, refresh at 3 seconds or reset the counter if aborted
        if (refresh) { if (r == 3) { syntax.HighlightHTM(Htm_Input); refresh = false; r = 0; } r++; } else { r = 0; }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM