析锦基于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
祝您用餐愉快。