using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using AIProofread.Controls; using AIProofread.core; using AIProofread.Util; using DocumentFormat.OpenXml.Office2013.WebExtentionPane; using log4net; using Microsoft.Office.Interop.Word; using Newtonsoft.Json; using UtilLib; using CustomTaskPane = Microsoft.Office.Tools.CustomTaskPane; namespace AIProofread.Model { /// /// 文档信息 包含文档相关数据、面板及对文档的相关操作 /// public class DocumentInfo { public ILog Logger = LogHelper.GetLogger(typeof(DocumentInfo)); public static readonly int MIN_WIDTH = 420; private static char[] ArticleSpecialChars = new char[4] { '\a', '\r', '\v', '\f' }; private static object missing = System.Reflection.Missing.Value; /// /// 是否已经校对 /// public bool hasProofreaded = false; /// /// 是否已经处理了校对结果 /// public bool hasProcessMark = false; /// /// /// public Dictionary marks = new Dictionary(); /// /// 最小宽度 /// public static int MinWidth = 0; /// /// 校对选区集合 /// private List ranges = new List(); /// /// 当前选中对现象编号 /// private int selectProofreadId; //private Document currentDocument; /// /// 当前对应文档 /// public Document CurrentDocument { get; set; } /// /// 文件名称 /// public string fileName; private string uniqueId; public string UniqueId { get { return uniqueId; } } public string ProofreadCachePath { get { return CurrentDocument.FullName + "-proofread.json"; } } public bool IsActive { get; internal set; } = false; public bool PaneVisible { get; set; } = false; public int Id { get; set; } public CustomTaskPane TaskPane { get; set; } public WdProtectionType ProtectionType { get { return CurrentDocument.ProtectionType; } } /// /// 是否已校对 /// public bool Proofread { get; set; } /// /// 是否校对中 /// public bool Proofreading { get; set; } // 初始化 public DocumentInfo(Document doc) { Logger.Debug("new DocumentInfo for " + doc.Name); this.CurrentDocument = doc; Initialize(); } /// /// 显示面板 /// public void ShowPane() { if (null == TaskPane) { CreateTaskPane(); } Logger.Debug("TaskPane.Visible {" + TaskPane == null ? "null" : (TaskPane.Visible ? "true" : "false") + " => true " + fileName); TaskPane.Visible = PaneVisible = true; } /// /// 隐藏面板 /// public void HidePane() { //if (!PaneVisible) return; ShowDocumentStatus("HidePane"); Logger.Debug($"TaskPane.Visible {TaskPane.Visible} => false"); TaskPane.Visible = PaneVisible = false; } public void RunInMainThread(Action action,bool isClose = false) { Logger.Debug("RunInMainThread for " + fileName); if (null == TaskPane && !isClose) { CreateTaskPane(); } TaskPane.Control.BeginInvoke(action); } public void ShowDialog(string message, string confirmText, string confirmAction) { TaskPane.Control.BeginInvoke(new Action(() => { //MessageBox.Show(message, "提示"); FormMessage.ShowMessage(message, confirmText, confirmAction); })); } public FormMessage ShowMessage(string message, int closeDelay, bool showCloseBtn = true) { var msgForm = FormMessage.ShowMessage(message, closeDelay); if (closeDelay > 0) { if (!showCloseBtn) { msgForm.HideCloseBtn(); } // n毫秒后自动关闭 System.Threading.Tasks.Task.Delay(closeDelay).ContinueWith(t => { if (msgForm.IsDisposed) return; TaskPane.Control.BeginInvoke(new Action(() => { msgForm.Close(); })); }); } return msgForm; } public void ShowLogin(string action) { TaskPane.Control.BeginInvoke(new Action(() => { FormLogin frm = new FormLogin(action); Globals.ThisAddIn.LoginFormList.Add(frm); frm.ShowDialog(); })); } private void ShowDocumentStatus(string tag) { // Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}"); } /// /// 激活 /// public void Active() { try { Logger.Debug("激活 for " + CurrentDocument.Name + " 没有 visible is " + PaneVisible); ShowDocumentStatus("Active"); IsActive = true; if (Config.IS_WPS && null != TaskPane) { TaskPane.Visible = PaneVisible; } } catch (Exception e) { Logger.Error("Active Error", e); } } public void Deactive() { try { ShowDocumentStatus("Deactive"); IsActive = false; if (Config.IS_WPS && null != TaskPane) { PaneVisible = TaskPane.Visible; TaskPane.Visible = false; Logger.Debug("取消 for " + CurrentDocument.Name + " current visible " + PaneVisible); } } catch (Exception e) { Logger.Error("Deactive Error", e); } } public void Dispose() { try { // 判断TaskPane是否已经释放 if (null == TaskPane) return; if (TaskPane.Control.IsDisposed) return; ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control; control.ResetWeb(); HidePane(); TaskPane?.Dispose(); // 释放com try { Marshal.ReleaseComObject(CurrentDocument); } catch (Exception) { } } catch (Exception e) { LogHelper.Log("Error", e); } } // 计算uniqueId private void ComputeUniqueId() { string filename = CurrentDocument.FullName; if (!string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(filename)) { return; } // 通过文档路径生成唯一id uniqueId = filename.GetHashCode().ToString(); } /// /// 添加变量控制重复调用 /// private bool isResizing = false; private void Control_SizeChanged(object sender, EventArgs e) { if (isResizing) return; if (TaskPane != null && TaskPane.Visible && TaskPane.Width < MinWidth) { isResizing = true; SendKeys.Send("{ESC}"); TaskPane.Width = MinWidth; isResizing = false; } } // 创建pane 并初始化 public void CreateTaskPane() { Logger.Debug("CreateTaskPane"); var control = new ProofreadMainControl(); if (MinWidth < 10) { MinWidth = MIN_WIDTH * control.LabelWidth() / 42; } // 创建pane TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(control, Config.RUN_IN_DEBUG ? CurrentDocument.Name : " "); // 默认隐藏 TaskPane.Visible = false; // 设置宽度 control.Width = MinWidth; TaskPane.Width = MinWidth; // 监听尺寸变化 防止最小尺寸小于设置值 control.SizeChanged += Control_SizeChanged; TaskPane.VisibleChanged += TaskPane_VisibleChanged; } /// /// 检查按钮状态 /// public void CheckBtnStatus() { // if (Globals.ThisAddIn.ribbon != null) { var visible = TaskPane.Visible; Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !visible && Proofread; Globals.ThisAddIn.ribbon.SetCommonBtnStatus(!Proofreading); } } private void TaskPane_VisibleChanged(object sender, EventArgs e) { // 异步等待500ms System.Threading.Tasks.Task.Delay(1000).ContinueWith(t => { Logger.Debug($"2==> VisibleChanged {CurrentDocument.Name} is {TaskPane.Visible}"); if (Config.IS_WPS) { if (CurrentDocument == Globals.ThisAddIn.ActiveDocument.CurrentDocument) { // 如果已经隐藏 则记录隐藏用于(WPS)多面板的切换的处理 PaneVisible = TaskPane.Visible; } } Globals.ThisAddIn.ActiveDocument?.CheckBtnStatus(); }); CheckBtnStatus(); //Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !TaskPane.Visible && Proofread; } public void Initialize() { this.fileName = CurrentDocument.FullName; ranges.Clear(); ComputeUniqueId(); if (TaskPane == null) { Logger.Debug("Initialize(334) and CreateTaskPane for " + CurrentDocument.Name); CreateTaskPane(); } } //处理文档选区时 判断当前选区是否有校对项 有则选择该范围 public void ProcessSelectionChange(Selection s) { // 判断选区内是否有书签 if (s.Bookmarks != null && s.Bookmarks.Count > 0) { // 判断是否时点击 点击的起始和结束位置相同 if (s.Range.Start == s.Range.End) { // var count = s.Bookmarks.Count; // 原则只有一个书签 //foreach (Microsoft.Office.Interop.Word.Bookmark item in s.Bookmarks) //{ // int proofreadId = Config.GetBookmarkIdByName(item.Name); // if (proofreadId > 0) // { // //Bridge.bridge.SelectMarkById(proofreadId, 0); // return; // } //} } } } // 获取当前文档文本 public string GetAllText() { return CurrentDocument.Range().Text; } /// /// 获取当前选中文本 /// /// public string GetSelectedText() { // 获取当前文档的选区 var selection = Globals.ThisAddIn.Application.Selection; return selection.Text; } /// /// 获取指定选区的文本 /// /// /// public string GetRangeText(Range range) { string text = range?.Text; return string.IsNullOrEmpty(text) ? "" : text; } /// /// 获取指定选区的文本 /// /// /// /// public string GetRangeText(int start, int end) { if (start >= end) return null; return GetRangeText(CurrentDocument.Range(start, end)); } public Range Range(int start, int end) { if (start >= end) return null; return CurrentDocument.Range(start, end); } /// /// 保存校对缓存结果 /// private void SaveProofreadCache(string cacheData) { // 判断文档是否已经保存 if (!CurrentDocument.Saved) { // 保存文档 if (!CurrentDocument.Saved) { // 提示保存文档 var result = MessageBox.Show("当前文档尚未保存,是否保存?", "提示", MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { CurrentDocument.Save(); } else { return; } } } } // 定位所有的校对项 public void LocateAllProofreadItems(List list) { // 获取所有的校对项 //List proofreadItems = GetProofreadItems(); var prevOffset = 0; foreach (var item in list) { if (item.CorrectItems != null && item.CorrectItems.Count > 0) { foreach (var correct in item.CorrectItems) { var range = LocateProofreadItem(correct, item, ref prevOffset); if (range == null) continue; } } } } /// /// 查找偏移量 /// private static readonly int INSERT_FIND_OFFSET = 5; /// /// 定位校对项 /// /// 校对项 /// 校对上下文 /// 上一步的 /// private Range LocateProofreadItem(CorrectItem correct, CorrectContext ctx, ref int prevOffset) { var document = CurrentDocument; // 校对项的段落号超过文档的段落数,直接返回 if (ctx.ParagraphNumber > document.Paragraphs.Count) return null; // 获取当前段落 var paragraph = document.Paragraphs[ctx.ParagraphNumber]; if (paragraph == null) return null; var paraRange = paragraph.Range; var paraText = paraRange.Text; var paraStart = paraRange.Start; //var offset = paraStart + ctx.SentenceOffset; //var cutLength = Math.Min(c.InsertLen, paraText.Length - offset); var sentence = paraRange.Sentences[ctx.SentenceNumber]; //paraText.Substring(ctx.SentenceOffset, ctx.InsertLength); ctx.SentenceOffset = sentence.Start; var offset = paraStart + ctx.SentenceOffset; if (sentence.Text == ctx.Insert) { // 比对原始内容与校对原文是否一致 var range = document.Range(offset + correct.Start, offset + correct.End); // if (range.Text == correct.Origin) return range; } var originText = ctx.Insert; // 如果是新增 则查找定位 if (correct.Tag == "i") { // 找前缀 var prefix1 = correct.Start > 2 ? ( correct.Start > INSERT_FIND_OFFSET ? originText.Substring(correct.Start - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET) : originText.Substring(0, correct.Start) ) : null; // 找后缀 var suffix1 = prefix1 == null ? ( correct.End + INSERT_FIND_OFFSET < originText.Length ? originText.Substring(correct.Start, INSERT_FIND_OFFSET) : originText.Substring(correct.Start, originText.Length - correct.Start) ) : null; // 偏移量 var start1 = prefix1 != null || suffix1 != null ? paraText.IndexOf(prefix1 ?? suffix1, prevOffset) : -1; if (start1 != -1) { var findOffset = paraStart + start1 + (prefix1 != null ? prefix1.Length : 0); return document.Range(findOffset, findOffset); } } // 执行查找 int wordStart = correct.Start; int wordEnd = correct.End; // 找前缀 var prefix = wordStart > 2 ? ( wordStart > INSERT_FIND_OFFSET ? originText.Substring(wordStart - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET) : originText.Substring(0, wordStart) ) : null; // 找后缀 var suffix = prefix == null ? ( wordEnd + INSERT_FIND_OFFSET < originText.Length ? originText.Substring(wordStart, INSERT_FIND_OFFSET) : originText.Substring(wordStart, originText.Length - wordStart) ) : null; var start = prefix != null || suffix != null ? paraText.IndexOf(prefix ?? suffix, prevOffset) // item.start + : -1; if (start != -1) { var findOffset = paraRange.Start + start + (prefix != null ? prefix.Length : 0); var range = document.Range(findOffset, findOffset + wordEnd - wordStart); if (range.Text == correct.Origin) { return range; } } // 直接定位查找 start = paraText.IndexOf(correct.Origin, prevOffset); if (start == -1) return null; // 定位整体开始位置 start = paraStart + start; return document.Range(start, start + correct.Origin.Length); } public void GlobalCallback(string callbackId, string result) { ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control; try { if (control.web.CoreWebView2 == null) { Thread.Sleep(1000); } control.web.CoreWebView2.ExecuteScriptAsync($"window.__global_callback_function('{callbackId}','{result}');"); } catch (Exception ex) { LogHelper.Log("GlobalCallback", "call web global function error \n" + ex.Message + "\n" + callbackId + result); } } public void SendMessageToWeb(string msg, object data) { var json = JsonConvert.SerializeObject(new WebMessage(msg, data)); ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control; try { if (control.web.CoreWebView2 == null) { Thread.Sleep(1000); } control.web.CoreWebView2.PostWebMessageAsJson(json); } catch (Exception ex) { LogHelper.Log("SendMessage", "send message to web error \n" + ex.Message + "\n" + msg + data.ToString()); } } public void ClearAllProofreadMark() { try { selectProofreadId = -1; foreach (var item in marks.Values) { if (item.mark != null) { if (item.content.Tag == "i" && item.content.IsAccept == AcceptStatus.Default) { item.mark.Text = ""; } item.ResetMarkStyle(); } } DocumentUtil.ClearProofreadMarks(); } catch (Exception ex) { LogHelper.Log("ClearAllProofreadMark", ex); } // 清空marks marks.Clear(); } public void SelectMarkById(int proofreadId) { SelectMarkById(proofreadId, true); } /// /// 选中标签 /// /// public void SelectMarkById(int proofreadId, bool noticeToWeb) { if (proofreadId == selectProofreadId) return; // 取消上一个标签移除 if (selectProofreadId != -1 && marks.ContainsKey(selectProofreadId)) { var m = marks[selectProofreadId]; if (m != null && CurrentDocument.Bookmarks.Exists(m.Name)) { marks[selectProofreadId].UnSelect(); } else { marks.Remove(selectProofreadId); } } selectProofreadId = proofreadId; if (proofreadId != -1 && marks.ContainsKey(proofreadId)) { var mark = marks[proofreadId].mark; if (mark == null) return; // 已经不存在该标签了 if (mark != null && !CurrentDocument.Bookmarks.Exists(mark.Name)) { marks.Remove(proofreadId); return; } //object lineNum = (int)mark.Range.Information[WdInformation.wdFirstCharacterLineNumber] - 1; //object goToLine = WdGoToItem.wdGoToLine; //object goNext = WdGoToDirection.wdGoToNext; //Globals.ThisAddIn.Application.ActiveWindow.Selection.GoTo(ref goToLine, ref goNext, ref lineNum); // //object bookmark = WdGoToItem.wdGoToBookmark; //object bookmarkName = mark.Name; var targetRange = mark.Range; // 选中 targetRange.Select(); Globals.ThisAddIn.Application.ActiveWindow.ScrollIntoView(targetRange);//.Selection.GoTo(ref bookmark, ref missing, ref missing, ref bookmarkName); // //mark.DisableCharacterSpaceGrid = false; // 先滚动到可视区域 //doc.ActiveWindow.ScrollIntoView(mark.Range); marks[proofreadId].Select(); //Globals.ThisAddIn.SendMessageToWeb("select", proofreadId); } if (noticeToWeb) { Globals.ThisAddIn.SendMessageToWeb("select-proofread", proofreadId); } } public void InitProofread(List list) { hasProofreaded = true; int prevOffset = 0; List disabledList = new List(); List insertMarks = new List(); foreach (var correct in list) { if (LogHelper.LoggerForm != null) { LogHelper.Log(string.Format("correct content:{0}", correct.Insert)); } int currentOffset = correct.SentenceOffset; if (correct.CorrectItems != null && correct.CorrectItems.Count > 0) { prevOffset = 0; int index = 0; foreach (var item in correct.CorrectItems) { if (marks.ContainsKey(item.Id)) continue; // Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text)); int _prev = prevOffset; bool isDisabled = false; // 判断查找内容是否在原始数据中,否则直跳过 if (item.Tag != "i" && item.Origin.Trim().Length > 0) { isDisabled = correct.Insert.IndexOf(item.Origin) == -1; } // 查找对应区域并再该区域添加书签 var mark = isDisabled ? null : DocumentUtil.FindRangeAndCreateBookmark(item, correct, CurrentDocument, ref prevOffset); // 防止调用方法中没有更新 if (_prev >= prevOffset) { prevOffset = currentOffset + item.Start; } if (item.Tag != "i") index++; if (mark != null) { marks.Add(item.Id, new ProofreadItem(item, correct.Insert, mark, Id)); try { if (item.Tag == "i") { insertMarks.Add(new InsertMarkData() { Mark = mark, InsertLength = item.Text.Length }); } else { SetMarkStyle(mark); } } catch (Exception e) { LogHelper.Log(string.Format("mark color error {0}", e.Message)); } } else { disabledList.Add(item.Id); var msg = new Dictionary{ {"message","没有找到标记对象" }, { "origin",item }, { "origin_correct",correct }, { "new_text",correct.NewText }, { "paragraph_num",correct.ParagraphNumber }, }; LogHelper.Log(JsonConvert.SerializeObject(msg)); } } } } // 为了避免影响其他文本定位,操作完成后才使用空格填充 try { foreach (var item in insertMarks) { item.Mark.Text = ToolUtil.GetBlankText(item.InsertLength); SetMarkStyle(item.Mark); } } catch (Exception) { } insertMarks.Clear(); //foreach (var item in marks) //{ // if (item.Value.mark != null) // { // if (item.Value.content.Tag == "i") // { // item.Value.mark.Text = ToolUtil.GetBlankText(item.Value.content.Text.Length); // } // if (item.Value.content.Color != null) // { // try // { // var color = (WdColor)ColorTranslator.ToOle(Colors.FromHex(item.Value.content.Color)); // // 给选区添加背景颜色 // item.Value.mark.Shading.BackgroundPatternColor = color; // } // catch (Exception) // { // //item.Value.mark.Shading.BackgroundPatternColor = WdColor.wdColorLightOrange; // } // } // } //} // 隐藏面板对应校对项 MainPanelWebMessage.DisabledProofreadItem(disabledList); } private void SetMarkStyle(Microsoft.Office.Tools.Word.Bookmark mark) { // 颜色转码 var color = (WdColor)ColorTranslator.ToOle(Colors.FromHex(Config.TextBackgroundColor)); // 给选区添加背景颜色 mark.Shading.BackgroundPatternColor = color; } public void InitProofreadCache(List list, Dictionary itemInfoDic) { marks.Clear(); foreach (var correct in list) { correct.CorrectItems.ForEach(item => { var mark = DocumentUtil.FindBookMarkByCorrect(item); if (mark != null) { var pi = new ProofreadItem(item, correct.Insert, mark, Id); // 是否存在样式信息 if (itemInfoDic != null && itemInfoDic.ContainsKey(item.Id)) { // 获取样式信息并还原 var info = itemInfoDic[item.Id]; try { pi.originColor = info.Color; pi.originBackgroundColor = info.Background; pi.originSize = info.Size; } catch (Exception ex) { LogHelper.Log(ex); } } marks.Add(item.Id, pi); } }); //marks.Add(item.Id, new ProofreadItem(item.CorrectItems[0], null, Id)); } } private void FindMarkByCorrectItem() { } public DocumentContent GetAllParagraphs() { string rangeText = CurrentDocument.Content.Text; string trimText = HostHelper.ReplaceSpecialChars(rangeText, isReplaceMultSpaceLine: true); string[] separator = new string[5] { "\r\a", "\a", "\r", "\v", "\f" }; string[] array4 = rangeText.Split(separator, StringSplitOptions.None); string[] array5 = trimText.Split('\n'); List list = new List(); var paragraphs = CurrentDocument.Paragraphs; int total = paragraphs.Count; for (int i = 1; i <= total; i++) { list.Add(GetParagraphText(paragraphs[i])); } return new DocumentContent() { OriginCut = array4, TrimCut = array5, Paragraphs = list.ToArray(), }; } private string GetParagraphText(Paragraph paragraph) { // 需要 return GetRangeText(paragraph.Range); } /// /// 获取文档段落总数 /// /// public int GetTotalParagraphNumber() { return CurrentDocument.Paragraphs.Count; } /// /// 读取文档原始文件并转换成base64 /// /// public string GetOriginFileData() { FileStream fs = new FileStream(CurrentDocument.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] bytes = new byte[fs.Length]; fs.Read(bytes, 0, bytes.Length); return Convert.ToBase64String(bytes); } /// /// 采纳校对项 /// /// /// internal void ProcessMark(int proofreadId, int status) { // 是否存在书签 if (proofreadId > 0 && marks.ContainsKey(proofreadId)) { hasProcessMark = true; // 采纳 marks[proofreadId].Process(status); } else { Logger.Debug("不存在此校对项"); } } internal bool Saved() { if (CurrentDocument.Saved) { return true; } if (!hasProofreaded && !CurrentDocument.Saved) // 没有校对前需要提示保存 { return false; } if (hasProofreaded && hasProcessMark && !CurrentDocument.Saved) { return false; } return true; } public void Save() { try { CurrentDocument.Save(); } catch (Exception ex) { LogHelper.Log(ex); } } public void FocusToPanel() { TaskPane.Visible = true; TaskPane.Control.Focus(); } public void Close() { try { // 清除标记内存数据 marks.Clear(); // 清除区域相关数据 ranges.Clear(); // TaskPane.Dispose(); this.Dispose(); } catch (Exception ex) { LogHelper.Log(ex); } } public void ExportResult(string modelType) { TaskPane.Control.BeginInvoke(new Action(() => { DocumentUtil.ExportProofreadResult(modelType); })); } public void ShowUpgrade(string data, bool force) { TaskPane.Control.BeginInvoke(new Action(() => { var upgradeData = JsonConvert.DeserializeObject(data); var needUpgrade = upgradeData.NeedUpgrade(Config.APP_VERSION); //force = force && !Config.UpgradeForcedNotice; if (force) { // 已经强制更新但被忽略过则不再提示 if (Config.UpgradeForcedNotice) return; var result = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question); if (result == DialogResult.No) { Config.UpgradeForcedNotice = true; Globals.ThisAddIn.ribbon.SetBtnStatus("disable-by-upgrade", false); return; } } if (upgradeData.Ext == 1) { if (!needUpgrade) { ShowDialog("当前版本为最新版本,无需升级", "", ""); } else { if (!force) { // 非强制则再问一次 var ret = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question); if (ret == DialogResult.No) { Globals.ThisAddIn.ribbon.SetBtnStatus("disable-by-upgrade", false); return; } } Bridge.bridge.OpenUrlWithOsBrowser(upgradeData.DownloadUrl); } } else { Bridge.StartUpgradeProcess(); } })); } public void ShowSetting() { TaskPane.Control.BeginInvoke(new Action(() => { FormSetting frm = new FormSetting(); frm.Show(); })); } public void ShowWebView(string url, int width, int height, bool dialog) { TaskPane.Control.BeginInvoke(new Action(() => { FormWebView view = new FormWebView(url, width, height); if (dialog) { view.StartPosition = FormStartPosition.CenterScreen; view.ShowDialog(); } else { view.StartPosition = FormStartPosition.CenterParent; view.Show(); } })); } public Dictionary GetProofreadOriginData() { Dictionary dic = new Dictionary(); // 变量文档所有marks 记录mark对应range的背景、大小、颜色 foreach (var item in marks) { if (item.Value.mark != null) { // 添加到数据 dic.Add(item.Key, new ProofreadRangeInfo() { Background = item.Value.originBackgroundColor, Color = item.Value.originColor, Size = item.Value.originSize }); } } return dic; } public void CheckPanel() { LogHelper.Log(CurrentDocument.FullName + $" TaskPane visible {PaneVisible} has " + (TaskPane == null ? "null" : "exists")); if (TaskPane == null) CreateTaskPane(); } } }