支持OneNote for Window10代码高亮工具

本文档介绍了一位开发者如何解决OneNote for Windows 10不支持代码高亮的问题。通过使用WPF+CefSharp加载静态HTML页面,结合SyntaxHighlighter库实现了代码高亮功能。作者详细分享了代码修改和实现过程,包括C#代码和WPF XAML布局。最后,展示了实现的最终效果,并提供了GitHub源码和安装包下载链接。
摘要由CSDN通过智能技术生成

支持OneNote for Window10代码高亮工具

如果有同学使用过OneNote,就会发现OneNote原本是不支持代码高亮的,OneNote目前有两个常见的版本,一个是Office自带的OneNote(下面简称为OneNoteOffice),这个OneNote是支持装高亮插件的,一个就是OneNote for Window10(下面简称为OneNote10),这个OneNote是不支持装插件的,两个版本的颜值对比:
oneNote for Window10
OneNote for Office
所以由于个人的习惯,我更习惯OneNote10的排布方式,OneNoteOffice虽然功能更强,但是排布上面看起来有点花里胡哨,而且我曾经由于代码高亮问题做过妥协,准备安装一个插件尝试一下能不能接受,结果就是插件也装不上去(可能是我菜吧):
在这里插入图片描述

后面寻求了一下OneNote10有没有现成的高亮代码软件,发现有一个叫做珍宝菜单的,然后发现有点小贵,勉强可以接受,但是付费机制有点坑爹,一台电脑要买一个激活码,这样买下去不得破产:
在这里插入图片描述
本着程序员刻(shi)苦(zai)钻(shi)研(qiong)的精神我开始了代码高亮的研究:

  1. 研究C#有没有现成的库可以实现代码高亮,期间还去研究珍宝插件的实现机制,结果核心算法是C++实在让人裂开;

  2. 网上在线代码高亮,研究了一下复制后存在于剪切板的html代码,灵机一动我可不可以自己拼一串Html代码出来,就这样勤勤恳恳的研究了好几天,发现我那学了一半的js还是太菜了,失败告终;在这里插入图片描述

  3. 第二次尝试虽然失败了,但是也让我关注到了js代码高亮库SyntaxHighlighter,所以我想我只要能模拟打开网页以及全部复制的操作不就行了,经过第二次的尝试,让我知道通过浏览器直接实现比较困难(菜是原罪),所以回到我自己熟悉的领域,WPF有没有办法内嵌一个网页呢?
    实际上有两种方案:
    第一种是使用自带WebBriwser;
    第二种是使用CefSharp包调用Chrom内核;
    本着面向谷歌编程的原则,我选择了第二种方案。

  4. 经过一波三折我最终敲定了以WPF+CefSharp+静态html的方式来实现代码高亮的方案:
    由于本人对js停留在一知半解的水平,所以采取的是js方法加C#修改html文本方式实现的:
    C#代码:

/// <summary>
        /// 粘贴到剪切板
        /// </summary>
        /// <param name="obj"></param>
        private void Paste(object obj)
        {
            string text = Clipboard.GetText();
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }
            else
            {
                CodeText = text;
                Render();
            }
        }

        private void Copy(object obj)
        {
            var mainFrame = _chromWebBrowser.GetBrowser().MainFrame;
            mainFrame.SelectAll();
            mainFrame.Copy();
        }
        /// <summary>
        /// 更改Html文件,重新加载渲染网页
        /// </summary>
        private void Render()
        {
            if (_chromWebBrowser == null) return;
            var htmlLineList = File.ReadAllLines(_htmlPath, Encoding.UTF8).ToList();
            string gutterStatus = GutterStatus ? "true" : "false";
            for (int i = 0; i < htmlLineList.Count; i++)
            {
                var current = htmlLineList[i];
                if (current.Contains("script") && current.Contains("codeTypeJs"))
                {
                    htmlLineList[i] = Regex.Replace(current, "scripts.+.js", $@"scripts/shBrush{CodeLanguage}.js");
                }
                else if (current.Contains("CShape代碼調用方法"))
                {
                    htmlLineList[i + 1] = $"HeightLight('{CodeStyle}','{FontFamily}',{(int)FontSize},{gutterStatus});";
                }
                else if (current.Contains("pre") && current.Contains("code_pre"))
                {
                    htmlLineList[i] = $"<pre id=\"code_pre\" class=\"brush:{CodeLanguage}\">";
                    if (!string.IsNullOrEmpty(CodeText))
                    {
                        i++;
                        while (true)
                        {
                            if (i > htmlLineList.Count - 1) throw new Exception("示例代码文件Code.html已损坏");
                            var htmlLineValue = htmlLineList[i];
                            if (htmlLineValue.Contains("</pre>"))
                            {
                                break;
                            }
                            else
                            {
                                htmlLineList.RemoveAt(i);
                            }
                        }
                        htmlLineList.Insert(i++, CodeText);
                        break;
                    }
                }
            }
            File.WriteAllLines(_htmlPath, htmlLineList, Encoding.UTF8);
            _chromWebBrowser.Load(_htmlPath);
            Thread.Sleep(100);
        }

WPF xaml代码:

<Window x:Class="HeightLightCode.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ui="clr-namespace:HeightLightCode.UI"
        xmlns:vm="clr-namespace:HeightLightCode.ViewModels"
        xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:vb="clr-namespace:HeightLightCode.VMBase"
        mc:Ignorable="d"
        Title="代码高亮软件" Height="450" MinHeight="450" MinWidth="800"  WindowStyle="None" AllowsTransparency="True" x:Name="mainWin"
        Width="800" Icon="..\Resources\YI32.png" ResizeMode="CanResizeWithGrip"  WindowStartupLocation="CenterScreen" Padding="0"
        ui:EllipseClipper.ClipReferObject="{Binding ElementName=toolbarImage}" Topmost="True"
        ui:EllipseClipper.IsWinClip="{Binding IsClip}" BorderThickness="1" BorderBrush="LightGray" ShowInTaskbar="False">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding WinInitCmd}" 
                                   CommandParameter="{Binding ElementName=mainWin}"></i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Window.Resources>
        <ResourceDictionary Source="..\UI\MainDict.xaml"></ResourceDictionary>
    </Window.Resources>
    <Window.DataContext>
        <vm:MainVm></vm:MainVm>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="55"/>
            <RowDefinition Height="40"></RowDefinition>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Height="25" Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Center" Margin="10 0 0 0">
            <TextBlock Text="字体:" VerticalAlignment="Center" Margin="0 0 3 0"></TextBlock>
            <ComboBox ItemsSource="{Binding FontFamilyCollection,UpdateSourceTrigger=PropertyChanged}"
                      SelectedItem="{Binding FontFamily,UpdateSourceTrigger=PropertyChanged}"
                      Width="180" Margin="0 0 10 0"></ComboBox>
            <TextBlock Text="字号:" VerticalAlignment="Center" Margin="0 0 3 0"></TextBlock>
            <ComboBox ItemsSource="{Binding FontSizeCollection,UpdateSourceTrigger=PropertyChanged}"
                      SelectedItem="{Binding FontSize,UpdateSourceTrigger=PropertyChanged}"
                      Width="100" Margin="0 0 10 0"></ComboBox>
            <TextBlock Text="代码样式:" VerticalAlignment="Center" Margin="0 0 3 0"></TextBlock>
            <ComboBox  ItemsSource="{Binding CodeStyleCollection,UpdateSourceTrigger=PropertyChanged}"
                       SelectedItem="{Binding CodeStyle,UpdateSourceTrigger=PropertyChanged}"
                       Width="100" Margin="0 0 10 0"></ComboBox>
            <TextBlock Text="编程语言:" VerticalAlignment="Center" Margin="0 0 3 0"></TextBlock>
            <ComboBox ItemsSource="{Binding CodeLanguageCollection,UpdateSourceTrigger=PropertyChanged}"
                      SelectedItem="{Binding CodeLanguage,UpdateSourceTrigger=PropertyChanged}"
                      Width="100" Margin="0 0 10 0"></ComboBox>
            <TextBlock Text="代码行号:" VerticalAlignment="Center" Margin="0 0 3 0"></TextBlock>
            <CheckBox IsChecked="{Binding GutterStatus,UpdateSourceTrigger=PropertyChanged}" Grid.Row="3"
                      HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="#8a8a8a" Padding="0">
                <CheckBox.LayoutTransform>
                    <ScaleTransform ScaleX="1.5" ScaleY="1.5" />
                </CheckBox.LayoutTransform>
            </CheckBox>
        </StackPanel>
        <GroupBox Grid.Row="2" Header="预览窗口" Margin="10 0 10 0">
            <cefSharp:ChromiumWebBrowser Grid.Row="2" MenuHandler="{StaticResource menuHandler}" x:Name="ChromBrower"
                                        />
        </GroupBox>

        <!--标题栏-->
        <Grid Background="#e7eaed">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseMove">
                    <vb:YIEventToCommand Command="{Binding WindowMoveCmd}" 
                                         PassToEventArgs="True"></vb:YIEventToCommand>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="55"></ColumnDefinition>
                <ColumnDefinition Width="auto"></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Image Margin="5" x:Name="toolbarImage" HorizontalAlignment="Center" VerticalAlignment="Center"
                   Source="..\Resources\YI64.png" Stretch="Fill" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseLeftButtonUp">
                        <i:InvokeCommandAction Command="{Binding TitleImageUpCmd}" CommandParameter="{Binding ElementName=toolbarImage}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeftButtonDown">
                        <i:InvokeCommandAction Command="{Binding TitleImageDownCmd}" CommandParameter="{Binding ElementName=toolbarImage}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding TitleImageEnterCmd}" CommandParameter="{Binding ElementName=toolbarImage}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding TitleImageLeaveCmd}" CommandParameter="{Binding ElementName=toolbarImage}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseRightButtonDown">
                        <i:InvokeCommandAction Command="{Binding TitleImageRightDownCmd}" CommandParameter="{Binding ElementName=toolbarImage}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Image>
            <TextBlock Grid.Column="1"   FontSize="20" Text="代码高亮软件" VerticalAlignment="Center" HorizontalAlignment="Left" Foreground="#4c4c4c"></TextBlock>
            <WrapPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="2">
                <Button Visibility="{Binding PinVisiblity, UpdateSourceTrigger=PropertyChanged,
                        Converter={StaticResource reverseVisiblityConverter}}"  
                        ToolTip="将窗体固定在最前"
                        Style="{StaticResource toolbarBtnStyle}" Command="{Binding PinCmd}">
                    <Image Source="..\Resources\窗口非置顶状态.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>

                <Button Visibility="{Binding PinVisiblity,UpdateSourceTrigger=PropertyChanged}"  
                        Style="{StaticResource toolbarBtnStyle}" Command="{Binding UnpinCmd}"
                        ToolTip="解除窗口置顶状态">
                    <Image Source="..\Resources\窗口置顶状态.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>

                <Button Command="{Binding MinimizedCmd}" Style="{StaticResource toolbarBtnStyle}">
                    <Image Source="..\Resources\最小化.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>

                <Button Visibility="{Binding NormalVisiblity,UpdateSourceTrigger=PropertyChanged,
                        Converter={StaticResource reverseVisiblityConverter}}"
                        Command="{Binding MaximizedCmd}" Style="{StaticResource toolbarBtnStyle}">
                    <Image Source="..\Resources\最大化.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>

                <Button Visibility="{Binding NormalVisiblity,UpdateSourceTrigger=PropertyChanged}"
                        Command="{Binding NormalCmd}" Style="{StaticResource toolbarBtnStyle}">
                    <Image Source="..\Resources\缩小.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>
                <Button Command="{Binding CloseCmd}" Style="{StaticResource toolbarBtnStyle}">
                    <Image Source="..\Resources\关闭.png" Stretch="Uniform" Height="20" Width="20"></Image>
                </Button>
            </WrapPanel>
        </Grid>
        <StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 0 10 0">
            <Button Template="{StaticResource ButtonTemplate}" Command="{Binding PasteCmd}" Content="粘贴" Width="70" Height="23"></Button>
            <Button Template="{StaticResource ButtonTemplate}" Command="{Binding CopyCmd}" Margin="10 0 0 0" Content="复制" Width="70" Height="23"></Button>
        </StackPanel>
        
    </Grid>
</Window>

静态网页内容:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <script type="text/javascript" src="scripts/shCore.js"></script>
  <script id="codeTypeJs" type="text/javascript" src="scripts/shBrushPhp.js"></script>
  <link id="css" type="text/css" rel="stylesheet" href="styles/shCoreDefault.css" />
  <script type="text/javascript">

    // 是否开启行号
    function SwitchGutter(isOpen) {
      //行号
      SyntaxHighlighter.defaults['gutter'] = isOpen;
    }
    //更改代码样式
    function ChangStyleType(type) {
      var css = document.getElementById("css");
      if ("Default" == type)
        css.setAttribute("href", "styles/shCoreDefault.css");
      if ("Emacs" == type)
        css.setAttribute("href", "styles/shCoreEmacs.css");
      if ("Django" == type)
        css.setAttribute("href", "styles/shCoreDjango.css");
      if ("Eclipse" == type)
        css.setAttribute("href", "styles/shCoreEclipse.css");
      if ("FadeToGrey" == type)
        css.setAttribute("href", "styles/shCoreFadeToGrey.css");
      if ("MDUltra" == type)
        css.setAttribute("href", "styles/shCoreMDUltra.css");
      if ("Midnight" == type)
        css.setAttribute("href", "styles/shCoreMidnight.css");
      if ("RDark" == type)
        css.setAttribute("href", "styles/shCoreRDark.css");
    }
    //更改字号、字体
    function ChangeFont(fontFamily, fontSize) {
      var styleContent = '.syntaxhighlighter a,';
      styleContent = styleContent + '.syntaxhighlighter div,';
      styleContent = styleContent + '.syntaxhighlighter code,';
      styleContent = styleContent + '.syntaxhighlighter table,';
      styleContent = styleContent + '.syntaxhighlighter table td,';
      styleContent = styleContent + '.syntaxhighlighter table tr,';
      styleContent = styleContent + '.syntaxhighlighter table tbody,';
      styleContent = styleContent + '.syntaxhighlighter table thead,';
      styleContent = styleContent + '.syntaxhighlighter table caption,';
      styleContent = styleContent + '.syntaxhighlighter textarea';
      styleContent = styleContent + '{';
      styleContent = styleContent + 'font-family:' + fontFamily + "!important;";
      styleContent = styleContent + 'font-size:' + fontSize + 'px !important;';
      styleContent = styleContent + 'line-height:1.2em !important;';
      styleContent = styleContent + "}";

      var fontStyle = document.createElement('style');
      fontStyle.type = 'text/css';
      document.getElementsByTagName('head')[0].appendChild(fontStyle);
      fontStyle.appendChild(document.createTextNode(styleContent))
    }
    function InitSetting() {
      
      //工具栏
      SyntaxHighlighter.defaults['toolbar'] = false;
      //滚动条
      var initstyle = document.createElement('style');
      initstyle.innerHTML = 'body::-webkit-scrollbar{width:0 !important;background:transparent}';
      document.head.appendChild(initstyle);
    }

    function HeightLight(codeStyleType,fontFamily,fontSize,gutterStatus) 
    {
      //更改样式
      ChangStyleType(codeStyleType);
      //更改字体、字号 
      ChangeFont(fontFamily, fontSize);
      SwitchGutter(gutterStatus);
      InitSetting();
    }
    
    window.onload = function () {
      //CShape代碼調用方法
      HeightLight('Default','微软雅黑',30,false);
    }
    SyntaxHighlighter.all();
    // SyntaxHighlighter.all();
  </script>
</head>

<body>
  <pre id="code_pre" class="brush:Php">
    /* ---示例代码----*/
    function echo (){
      var a="this is a example";
      alert("hello world "+a);
    }
    /* ---示例代码----*/
  </pre>
</body>
</html>

最终实现效果
在这里插入图片描述
右键在YI图标上点击可缩小为图标,在缩小的图标上左键点击则完成粘贴加复制的功能。

以上是部分实现的代码,具体代码见github:代码高亮软件
懒的编译的可下载安装包:代码高亮软件安装包
最后说一句,由于SyntaxHighlighter渲染的网页是以表格排布的,所以代码高亮结果复制到Word是不生效的。
才疏学浅,望大家多多指点!

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: OneNote for Windows 10是一款由微软开发的笔记软件,它可以帮助用户轻松地记录和组织笔记、想法、清单、图片、音频和视频等内容。它具有简单易用的界面和强大的功能,可以在不同设备之间同步笔记,支持手写、键盘输入和语音输入等多种方式记录内容。同时,它还可以与其他微软应用程序(如Outlook、Word、Excel等)进行集成,方便用户进行协作和分享。 ### 回答2: OneNote是微软推出的一款笔记软件,它在众多类似软件中脱颖而出,因为它具有云同步功能,让人们在任何地方使用不同设备都能访问到同一份笔记。OneNote的使用者分为两种:一种是使用Microsoft Office的人,可以在软件中直接调用OneNote;另一种是单独使用OneNote的人,他们会选择下载OneNote应用程序。 随着技术的发展,微软也在不断改进和升级OneNote应用程序。目前,OneNote for Windows 10已经成为主要版本之一,它使用了全新的用户界面和新的功能和工具,二者都经过了重新设计和改进,可让使用者更容易使用和操作。 OneNote for Windows 10有许多吸引人的特点,包括: 1.简洁易用的用户界面:它具有直观的布局和明亮的颜色,使使用者更容易浏览和管理笔记。 2.全面的笔记比较:现在,使用者可以比较笔记本、章节、页和段落之间的差异,从而更有效地将笔记组织成一致的格式。 3.数字墨水支持OneNote for Windows 10 对触屏笔记本电脑和平板电脑中的数字墨水使用提供了更好的支持,从而让人们使用笔记本或笔直触摸笔记本电脑时,感受到纸张上的自由。 4.更多的标签选项:现在,使用者可以在笔记中使用更多的标签,并将其与任务、会议和计划等联系起来。 5.与其他应用程序的兼容性:OneNote现在更好地支持Office和其他微软应用程序之间的协作工作。 随着时间的推移,OneNote for Windows 10 很可能还会有更多的新功能和工具,不断推动人们在笔记中进行更有创意的工作,帮助使用者更好地组织信息并增强生产力。 ### 回答3: OneNote for Windows 10是微软针对Windows 10系统推出的笔记应用程序。它具有简单易用的界面、强大的功能和高效的同步性能,已成为许多用户进行笔记管理和知识整理的不二选择。 OneNote for Windows 10具有很多的特点和优势。它可以在电脑、手机、iPad等多种设备上运行,并支持多平台之间的数据同步。用户可以随时随地对笔记进行编辑、添加或删除,实时同步到其他设备上。其次,这款应用具有丰富的编辑功能,支持插入图片、视频、表格、图表等多种数据类型,并可以进行手写识别、OCR转换等功能。用户可以根据自己的需求进行笔记的排版、分组、颜色标记和搜索等操作,帮助他们更好地整理和管理自己的笔记内容。 此外,OneNote for Windows 10支持与其他人合作。用户可以邀请他人共同编辑或查看自己的笔记,并可以进行评论和反馈。这为团队协作和知识共享提供了非常便捷的方式。最后,OneNote for Windows 10还可以与其他Microsoft Office软件进行集成,如Word、Excel、PowerPoint等,用户可以轻松地将笔记内容插入到其他文档中,提高了工作效率。 总的来说,OneNote for Windows 10是一款非常优秀的笔记应用程序,其丰富的功能和高效的同步性能为用户提供了非常便捷的笔记管理工具。无论是个人用户还是团队协作,OneNote都可以满足他们的需求。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值