析锦基于Monaco技术实现的Winform语法高亮编辑器

winform中,我们有时需要高亮显示基于某种语言的语法编辑器。

目前比较强大且UI现代化的,无疑是宇宙最强IDE的兄弟:VS Code。

类似 VS Code 的体验,可以考虑使用 Monaco Editor(VS Code 使用的编辑器)。虽然它主要用于 Web,但你可以在 WPF 或者 Winform 中嵌入一个浏览器控件(如 WebView2)并加载 Monaco Editor。

当然,适用于Winform的这种语法高亮的编辑器,除了Monaco外,还有AvalonEdit、ScintillaNET等,都可以用于复杂需求的高亮显示。



今天,我们只讲 Monaco 如何引入到 Winform 中。

本文是基于 XejeN 的 C/S 框架编写的,若您想了解 XejeN 的 C/S 框架,可以阅读此文章:
https://blog.csdn.net/mazhiyuan1981/article/details/138852326

若您想直接下载XejeN的 C/S 框架,可以访问:https://gitee.com/mazhiyuan1981/xejen-open.git

好的,下面我们开始介绍如何将 Monaco 编辑器引入到 Winform 中。


一、新建一个 Winform 项目

二、创建一个 Winform 窗体

窗体留出一个Panel控件,用于承载 Monaco 编辑器

三、安装必要的 Winform 浏览网页的 WebView2 控件

四、创建一个承载编辑器的网页界面

此为重点,这个html页面,将会显示和编辑数据内容,并能获取编辑器内容。

主要是通过setEditorContent和getEditorContent这两个方法完成的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Monaco Editor</title>
    <link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/vs/editor/editor.main.css">
    <style>
        html, body, #container {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        #container {
            display: flex;
        }
    </style>
</head>
<body>
    <div id="container"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/vs/loader.js"></script>
    <script>
        require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/vs' } });
        window.MonacoEnvironment = { getWorkerUrl: function (workerId, label) { return `data:text/javascript;base64,${btoa("self.MonacoEnvironment = { baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/' }; importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/vs/base/worker/workerMain.js');")}` } };

        require(['vs/editor/editor.main'], function () {
            window.editor = monaco.editor.create(document.getElementById('container'), {
                value: "",
                language: 'plaintext',
                automaticLayout: true  // This line ensures the editor adjusts to its container's size
            });

            window.addEventListener('resize', () => {
                window.editor.layout();  // Adjust editor layout on window resize
            });

            window.chrome.webview.postMessage('initialized');
        });

        window.setEditorContent = function (content, language) {
            window.editor.setValue(content);
            monaco.editor.setModelLanguage(window.editor.getModel(), language);
        };

        window.getEditorContent = function () {
            return window.editor.getValue();
        };
    </script>
</body>
</html>

五、在 Winform 窗体界面中,加载编辑器并执行

        private void LoadEditorAsync()
        {
            if (string.IsNullOrEmpty(Data)) return;

            string content;
            string language;

            if (Data.IsJson())
            {
                content = Data.FormatJson();
                language = "json";
            }
            else if (Data.IsXml())
            {
                content = Data.FormatXml();
                language = "xml";
            }
            else
            {
                content = Data;
                language = "plaintext";
            }

            string htmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "monaco-editor.html");

            DataTextBox.CoreWebView2InitializationCompleted += (sender, args) =>
            {
                if (!args.IsSuccess)
                {
                    MessageBox.Show("WebView2 initialization failed.");
                    return;
                }

                DataTextBox.CoreWebView2.WebMessageReceived += (sender2, args2) =>
                {
                    if (args2.TryGetWebMessageAsString() == "initialized")
                    {
                        DataTextBox.CoreWebView2.ExecuteScriptAsync($"setEditorContent({JsonConvert.SerializeObject(content)}, '{_language ?? language}');");
                        SaveButton.Enabled = true;
                    }
                };

                DataTextBox.CoreWebView2.NavigateToString(File.ReadAllText(htmlPath));
            };

            DataTextBox.Source = new Uri(htmlPath);
        }

六、获取编辑器修改后的内容
 

        /// <summary>
        /// 获取文本数据内容
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetDataAsync()
        {
            return JsonConvert.DeserializeObject(await DataTextBox.CoreWebView2.ExecuteScriptAsync("getEditorContent();")).ToString();
        }

使用GetDataAsync方法,去调用html页面的js方法getEditorContent,便可以取到编辑器的内容

七、将monaco-editor.html设置为:如果较新则复制


 

完整源码位置在:

完整Demo演示位置在:

源码位置:https://gitee.com/mazhiyuan1981/xejen-open.git

祝您用餐愉快。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部