This commit is contained in:
HuangHai
2026-01-29 08:22:08 +08:00
parent 8aa397cea7
commit 8101a3eafc
38 changed files with 1167 additions and 261 deletions

Binary file not shown.

View File

@@ -3,8 +3,20 @@
"WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\", "WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\",
"Documents": [ "Documents": [
{ {
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|d:\\dswork\\aidata\\wordaddin\\wordaddin\\modeldefinitions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|d:\\dswork\\aidata\\wordaddin\\wordaddin\\outlineresultform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\modeldefinitions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\outlineresultform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\loginform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\loginform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\imageoptionsform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\imageoptionsform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\createoutlineform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\createoutlineform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
} }
], ],
"DocumentGroupContainers": [ "DocumentGroupContainers": [
@@ -23,15 +35,47 @@
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 0, "DocumentIndex": 0,
"Title": "ModelDefinitions.cs", "Title": "OutlineResultForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs", "DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\ModelDefinitions.cs", "RelativeDocumentMoniker": "WordAddIn\\OutlineResultForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs", "ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\ModelDefinitions.cs", "RelativeToolTip": "WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
"ViewState": "AgIAAAkAAAAAAAAAAAAuwBIAAAAoAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T13:21:19.787Z", "WhenOpened": "2026-01-28T23:14:29.889Z",
"EditorCaption": "" "EditorCaption": " [\u8BBE\u8BA1]"
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "LoginForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\LoginForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\LoginForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\LoginForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\LoginForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:26.027Z"
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "ImageOptionsForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ImageOptionsForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\ImageOptionsForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ImageOptionsForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\ImageOptionsForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:18.293Z"
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "CreateOutlineForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\CreateOutlineForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\CreateOutlineForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\CreateOutlineForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\CreateOutlineForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:17.315Z"
} }
] ]
} }

View File

@@ -3,8 +3,20 @@
"WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\", "WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\",
"Documents": [ "Documents": [
{ {
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|d:\\dswork\\aidata\\wordaddin\\wordaddin\\modeldefinitions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|d:\\dswork\\aidata\\wordaddin\\wordaddin\\outlineresultform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\modeldefinitions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\outlineresultform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\loginform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\loginform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\imageoptionsform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\imageoptionsform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
},
{
"AbsoluteMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|D:\\dsWork\\aiData\\WordAddIn\\wordaddin\\createoutlineform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative:wordaddin\\createoutlineform.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
} }
], ],
"DocumentGroupContainers": [ "DocumentGroupContainers": [
@@ -23,15 +35,47 @@
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 0, "DocumentIndex": 0,
"Title": "ModelDefinitions.cs", "Title": "OutlineResultForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs", "DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\ModelDefinitions.cs", "RelativeDocumentMoniker": "WordAddIn\\OutlineResultForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs", "ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\ModelDefinitions.cs", "RelativeToolTip": "WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
"ViewState": "AgIAAAkAAAAAAAAAAAAuwBIAAAAoAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T13:21:19.787Z", "WhenOpened": "2026-01-28T23:14:29.889Z",
"EditorCaption": "" "EditorCaption": " [\u8BBE\u8BA1]"
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "LoginForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\LoginForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\LoginForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\LoginForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\LoginForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:26.027Z"
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "ImageOptionsForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ImageOptionsForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\ImageOptionsForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ImageOptionsForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\ImageOptionsForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:18.293Z"
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "CreateOutlineForm.cs [\u8BBE\u8BA1]",
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\CreateOutlineForm.cs",
"RelativeDocumentMoniker": "WordAddIn\\CreateOutlineForm.cs",
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\CreateOutlineForm.cs [\u8BBE\u8BA1]",
"RelativeToolTip": "WordAddIn\\CreateOutlineForm.cs [\u8BBE\u8BA1]",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-28T23:14:17.315Z"
} }
] ]
} }

View File

@@ -32,14 +32,69 @@ namespace WordAddIn
private AiService _aiService = new AiService(); private AiService _aiService = new AiService();
// 登录状态标识 (静态变量,确保在插件生命周期内保持状态) // 登录状态标识 (静态变量,确保在插件生命周期内保持状态)
private static bool _isLoggedIn = false; private static bool _isLoggedIn = false;
// 登录凭证存储路径
private string _tokenFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WordAddIn", "login.cookie");
/// <summary>
/// 保存登录状态到本地文件
/// </summary>
private void SaveLoginState()
{
try
{
string dir = Path.GetDirectoryName(_tokenFilePath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
File.WriteAllText(_tokenFilePath, "logged_in|" + DateTime.Now.Ticks);
}
catch (Exception ex)
{
try { File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} SaveLoginState Error: {ex.Message}\n"); } catch { }
}
}
/// <summary>
/// 加载本地登录状态
/// </summary>
private void LoadLoginState()
{
try
{
if (File.Exists(_tokenFilePath))
{
// 简单验证:文件存在即视为已登录。实际可校验内容有效期。
_isLoggedIn = true;
}
}
catch (Exception ex)
{
try { File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} LoadLoginState Error: {ex.Message}\n"); } catch { }
}
}
// 存储文档的全文分析上下文 (通过"通读全文"功能生成),用于辅助 AI 理解文档背景 // 存储文档的全文分析上下文 (通过"通读全文"功能生成),用于辅助 AI 理解文档背景
private string _documentContext = null; private string _documentContext = null;
// 存储外部参考文档内容 (通过"补充背景"功能导入),用于辅助 AI 进行写作 // 存储外部参考文档内容 (通过"补充背景"功能导入),用于辅助 AI 进行写作
private string _referenceContext = null; private string _referenceContext = null;
// 样式刷状态常量
private const int BRUSH_NONE = -1;
private const int BRUSH_MAIN_TITLE = 0;
private const int BRUSH_HEADING1 = 1;
private const int BRUSH_HEADING2 = 2;
private const int BRUSH_HEADING3 = 3;
private const int BRUSH_BODY = 10;
// 当前激活的样式刷等级
private int _currentBrushLevel = BRUSH_NONE;
// 样式刷配置缓存与状态控制
private OutlineStyleConfig _cachedStyleConfig = null;
private long _lastBrushClickTicks = 0;
private bool _isBrushSticky = false;
/// <summary> /// <summary>
/// 默认构造函数 /// 默认构造函数
/// </summary> /// </summary>
@@ -98,6 +153,596 @@ namespace WordAddIn
} }
catch {} catch {}
this.ribbon = ribbonUI; this.ribbon = ribbonUI;
// 加载登录状态
LoadLoginState();
try
{
if (AddInContext.CurrentApplication != null)
{
AddInContext.CurrentApplication.WindowSelectionChange += CurrentApplication_WindowSelectionChange;
}
}
catch { }
}
/// <summary>
/// 控制 Ribbon 按钮的可用状态 (Enabled)。
/// 未登录时返回 false (灰色不可用),登录后返回 true。
/// </summary>
/// <param name="control">控件</param>
/// <returns>是否可用</returns>
public bool GetControlEnabled(Office.IRibbonControl control)
{
return _isLoggedIn;
}
/// <summary>
/// 【登录】按钮点击事件处理。
/// </summary>
/// <param name="control">控件</param>
public void OnLoginClick(Office.IRibbonControl control)
{
using (LoginForm login = new LoginForm())
{
if (login.ShowDialog() == DialogResult.OK)
{
_isLoggedIn = true;
SaveLoginState();
// 刷新 Ribbon 状态,使按钮变亮
if (ribbon != null)
{
ribbon.Invalidate();
}
}
}
}
public void OnStyleBrushToggle(Office.IRibbonControl control, bool pressed)
{
int targetLevel = BRUSH_NONE;
switch (control.Id)
{
case "tbtnStyleMainTitle": targetLevel = BRUSH_MAIN_TITLE; break;
case "tbtnStyleLevel1": targetLevel = BRUSH_HEADING1; break;
case "tbtnStyleLevel2": targetLevel = BRUSH_HEADING2; break;
case "tbtnStyleLevel3": targetLevel = BRUSH_HEADING3; break;
case "tbtnStyleBody": targetLevel = BRUSH_BODY; break;
}
if (pressed)
{
// 激活样式刷
_currentBrushLevel = targetLevel;
_lastBrushClickTicks = DateTime.Now.Ticks;
_isBrushSticky = false; // 默认为单次使用模式
// 缓存配置,避免每次选区变化都反序列化,提高性能
try
{
string styleJson = Settings.Default.OutlineStyles;
_cachedStyleConfig = string.IsNullOrEmpty(styleJson) ? new OutlineStyleConfig() : JsonConvert.DeserializeObject<OutlineStyleConfig>(styleJson);
}
catch { _cachedStyleConfig = new OutlineStyleConfig(); }
// 反向模式:如果已经选中了文字,直接应用样式并退出刷子模式
bool appliedImmediate = false;
try
{
if (AddInContext.CurrentApplication != null)
{
var sel = AddInContext.CurrentApplication.Selection;
// wdSelectionNormal = 2 (普通文本选区)
if (sel != null && sel.Type == Word.WdSelectionType.wdSelectionNormal && sel.Range.End > sel.Range.Start)
{
foreach (Word.Paragraph p in sel.Range.Paragraphs)
{
ApplyStyleToParagraph(p, targetLevel, _cachedStyleConfig);
}
appliedImmediate = true;
}
}
}
catch (Exception ex)
{
try { File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} ReverseApply Error: {ex.Message}\n"); } catch { }
}
if (appliedImmediate)
{
// 如果已立即应用,则重置刷子状态
_currentBrushLevel = BRUSH_NONE;
_cachedStyleConfig = null;
// 刷新控件状态,使按钮弹起
if (ribbon != null)
{
ribbon.InvalidateControl(control.Id);
// 确保其他按钮状态也正确
ribbon.InvalidateControl("tbtnStyleMainTitle");
ribbon.InvalidateControl("tbtnStyleLevel1");
ribbon.InvalidateControl("tbtnStyleLevel2");
ribbon.InvalidateControl("tbtnStyleLevel3");
ribbon.InvalidateControl("tbtnStyleBody");
}
return;
}
}
else
{
// 尝试关闭样式刷
long elapsedTicks = DateTime.Now.Ticks - _lastBrushClickTicks;
TimeSpan elapsed = new TimeSpan(elapsedTicks);
// 如果点击间隔很短 (例如 500ms 内),视为双击,进入"连续使用"模式
// 此时保持激活状态,并设为粘滞模式
if (elapsed.TotalMilliseconds < 500 && _currentBrushLevel == targetLevel)
{
_isBrushSticky = true;
// 强制刷新控件状态,使其保持按下
ribbon.InvalidateControl(control.Id);
return;
}
// 正常关闭
_currentBrushLevel = BRUSH_NONE;
_cachedStyleConfig = null;
_isBrushSticky = false;
}
// 刷新所有相关按钮状态
if (ribbon != null)
{
ribbon.InvalidateControl("tbtnStyleMainTitle");
ribbon.InvalidateControl("tbtnStyleLevel1");
ribbon.InvalidateControl("tbtnStyleLevel2");
ribbon.InvalidateControl("tbtnStyleLevel3");
ribbon.InvalidateControl("tbtnStyleBody");
}
}
public bool GetStyleBrushPressed(Office.IRibbonControl control)
{
switch (control.Id)
{
case "tbtnStyleMainTitle": return _currentBrushLevel == BRUSH_MAIN_TITLE;
case "tbtnStyleLevel1": return _currentBrushLevel == BRUSH_HEADING1;
case "tbtnStyleLevel2": return _currentBrushLevel == BRUSH_HEADING2;
case "tbtnStyleLevel3": return _currentBrushLevel == BRUSH_HEADING3;
case "tbtnStyleBody": return _currentBrushLevel == BRUSH_BODY;
default: return false;
}
}
private void CurrentApplication_WindowSelectionChange(Word.Selection Sel)
{
if (_currentBrushLevel == BRUSH_NONE) return;
if (_cachedStyleConfig == null) return;
try
{
foreach (Word.Paragraph p in Sel.Paragraphs)
{
ApplyStyleToParagraph(p, _currentBrushLevel, _cachedStyleConfig);
}
// 如果不是粘滞模式 (单次使用),应用一次后立即关闭
if (!_isBrushSticky)
{
_currentBrushLevel = BRUSH_NONE;
_cachedStyleConfig = null;
if (ribbon != null)
{
ribbon.InvalidateControl("tbtnStyleMainTitle");
ribbon.InvalidateControl("tbtnStyleLevel1");
ribbon.InvalidateControl("tbtnStyleLevel2");
ribbon.InvalidateControl("tbtnStyleLevel3");
ribbon.InvalidateControl("tbtnStyleBody");
}
}
}
catch (Exception ex)
{
try { File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Brush Error: {ex.Message}\n"); } catch { }
}
}
private void ApplyStyleToParagraph(Word.Paragraph p, int level, OutlineStyleConfig styleConfig)
{
TextStyle ts = null;
try
{
switch (level)
{
case 0: // 主标题
ts = styleConfig.MainTitle;
p.set_Style(Word.WdBuiltinStyle.wdStyleTitle);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
break;
case 1: // 一级标题
ts = styleConfig.Heading1;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading1);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
break;
case 2: // 二级标题
ts = styleConfig.Heading2;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
break;
case 3: // 三级标题
ts = styleConfig.Heading3;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading3);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
break;
case 10: // 正文
p.set_Style(Word.WdBuiltinStyle.wdStyleNormal);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
p.Format.CharacterUnitFirstLineIndent = 2; // 首行缩进2字符
return;
default:
if (level >= 1 && level <= 5) {
ts = styleConfig.Heading3;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading3);
}
break;
}
}
catch
{
try
{
if (level == 0) p.set_Style("标题");
else if (level == 10) p.set_Style("正文");
else p.set_Style("标题 " + level);
}
catch { }
}
if (ts != null)
{
try { p.Range.Font.Name = ts.FontName; } catch { }
try { p.Range.Font.NameFarEast = ts.FontName; } catch { }
try { p.Range.Font.Size = ts.FontSize; } catch { }
try { p.Range.Font.Bold = ts.IsBold ? 1 : 0; } catch { }
try { p.Range.Font.Color = (Word.WdColor)ts.Color; } catch { }
if (level == 0)
{
p.Format.Alignment = (Word.WdParagraphAlignment)ts.Alignment;
}
p.Format.CharacterUnitFirstLineIndent = 0;
p.Format.FirstLineIndent = 0;
}
// 智能序号填充 (Smart Numbering)
// 仅对 Level 1-3 生效,尝试探测上一级或同级序号并自动填充
if (level >= 1 && level <= 3)
{
SmartNumbering.Apply(p, level);
}
}
/// <summary>
/// 智能序号处理辅助类
/// </summary>
private static class SmartNumbering
{
// 常见序号正则
// 1. 中文序号: 一、 (支持 一、到 九十九、)
private static readonly Regex RegexChinese = new Regex(@"^([一二三四五六七八九十]+)、");
// 2. 章节序号: 第一章 (支持 第一章 到 第九十九章)
private static readonly Regex RegexChapter = new Regex(@"^第([0-9一二三四五六七八九十]+)章");
// 3. 数字点序号: 1. (支持 1. 到 99.)
private static readonly Regex RegexNumericDot = new Regex(@"^(\d+)\.");
// 4. 层级数字序号: 1.1 或 1.1.1
private static readonly Regex RegexHierarchical = new Regex(@"^(\d+(\.\d+)+)");
// 5. 括号数字: (1) 或 (一) - 暂不作为主要探测目标,避免误判
public static void Apply(Word.Paragraph p, int level)
{
try
{
// 1. 寻找前一个同级标题 (Sibling)
var siblingInfo = FindPreviousSibling(p, level);
if (siblingInfo.Found)
{
// 发现同级,延续序号
string newPrefix = IncrementNumbering(siblingInfo.Text, siblingInfo.Type);
if (!string.IsNullOrEmpty(newPrefix))
{
ReplacePrefix(p, newPrefix);
}
}
else
{
// 未发现同级,寻找父级 (Parent) 以决定起始序号
// 例如: Level 2 未找到同级,但找到 Level 1 "第一章",则可能开始 "1.1" 或 "一、"
// 策略:如果找不到同级,尝试根据父级重置为 "1" 或 "1.1"
var parentInfo = FindParent(p, level);
if (parentInfo.Found)
{
string startPrefix = GenerateStartNumbering(parentInfo.Text, level);
if (!string.IsNullOrEmpty(startPrefix))
{
ReplacePrefix(p, startPrefix);
}
}
else
{
// 既无同级也无父级 (可能是文档开头),尝试默认初始化
// 如果是 Level 1 且无前文,默认 "一、"
if (level == 1)
{
ReplacePrefix(p, "一、");
}
}
}
}
catch (Exception ex)
{
try { File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} SmartNumbering Error: {ex.Message}\n"); } catch { }
}
}
private struct NumberingInfo
{
public bool Found;
public string Text;
public NumberingType Type;
}
private enum NumberingType
{
None,
Chinese, // 一、
Chapter, // 第一章
NumericDot, // 1.
Hierarchical // 1.1
}
private static NumberingInfo FindPreviousSibling(Word.Paragraph p, int level)
{
// 向前搜索最多 100 段,避免性能问题
int maxLookBack = 100;
Word.Paragraph curr = p;
for (int i = 0; i < maxLookBack; i++)
{
curr = curr.Previous();
if (curr == null) break;
int currLevel = (int)curr.Format.OutlineLevel; // wdOutlineLevel1 = 1
if (currLevel == level)
{
// 找到同级
string text = curr.Range.Text.Trim();
var type = DetectType(text);
if (type != NumberingType.None)
{
return new NumberingInfo { Found = true, Text = text, Type = type };
}
}
else if (currLevel < level && currLevel >= 1) // wdOutlineLevel1=1 < wdOutlineLevel2=2
{
// 遇到父级 (OutlineLevel 值越小级别越高)
// 停止搜索,说明是该章节的第一项
return new NumberingInfo { Found = false };
}
}
return new NumberingInfo { Found = false };
}
private static NumberingInfo FindParent(Word.Paragraph p, int level)
{
int maxLookBack = 200;
Word.Paragraph curr = p;
for (int i = 0; i < maxLookBack; i++)
{
curr = curr.Previous();
if (curr == null) break;
int currLevel = (int)curr.Format.OutlineLevel;
if (currLevel < level && currLevel >= 1) // 找到父级
{
string text = curr.Range.Text.Trim();
return new NumberingInfo { Found = true, Text = text, Type = DetectType(text) };
}
}
return new NumberingInfo { Found = false };
}
private static NumberingType DetectType(string text)
{
if (RegexHierarchical.IsMatch(text)) return NumberingType.Hierarchical;
if (RegexChapter.IsMatch(text)) return NumberingType.Chapter;
if (RegexChinese.IsMatch(text)) return NumberingType.Chinese;
if (RegexNumericDot.IsMatch(text)) return NumberingType.NumericDot;
return NumberingType.None;
}
private static string IncrementNumbering(string text, NumberingType type)
{
try
{
if (type == NumberingType.Chinese)
{
var match = RegexChinese.Match(text);
string numStr = match.Groups[1].Value;
int num = ChineseToInt(numStr);
return IntToChinese(num + 1) + "、";
}
else if (type == NumberingType.Chapter)
{
var match = RegexChapter.Match(text);
string numStr = match.Groups[1].Value;
// 可能是中文也可能是数字
int num = 0;
if (int.TryParse(numStr, out int n)) num = n;
else num = ChineseToInt(numStr);
// 保持原格式 (中文或数字)
string newNumStr = int.TryParse(numStr, out _) ? (num + 1).ToString() : IntToChinese(num + 1);
return "第" + newNumStr + "章 "; // 增加一个空格
}
else if (type == NumberingType.NumericDot)
{
var match = RegexNumericDot.Match(text);
int num = int.Parse(match.Groups[1].Value);
return (num + 1) + ". ";
}
else if (type == NumberingType.Hierarchical)
{
var match = RegexHierarchical.Match(text);
string fullNum = match.Groups[1].Value; // "1.1"
string[] parts = fullNum.Split('.');
if (parts.Length > 0)
{
int last = int.Parse(parts[parts.Length - 1]);
parts[parts.Length - 1] = (last + 1).ToString();
return string.Join(".", parts) + " ";
}
}
}
catch { }
return null;
}
private static string GenerateStartNumbering(string parentText, int currentLevel)
{
// 根据父级生成子级其实序号
// 父: 第1章 -> 子: 1.1
// 父: 1. -> 子: 1.1
// 父: 1.1 -> 子: 1.1.1
// 父: 一、 -> 子: 1. (或其他)
try
{
var parentType = DetectType(parentText);
string parentNum = "1";
if (parentType == NumberingType.Chapter)
{
var m = RegexChapter.Match(parentText);
string s = m.Groups[1].Value;
if (int.TryParse(s, out int n)) parentNum = n.ToString();
else parentNum = ChineseToInt(s).ToString();
}
else if (parentType == NumberingType.NumericDot)
{
var m = RegexNumericDot.Match(parentText);
parentNum = m.Groups[1].Value;
}
else if (parentType == NumberingType.Hierarchical)
{
var m = RegexHierarchical.Match(parentText);
parentNum = m.Groups[1].Value;
}
// Chinese "一、" usually maps to child "1" not "1.1" depending on style
// 构造
// 如果父级是 "1",当前是 Level 2,则 "1.1"
// 如果父级是 "1.1",当前是 Level 3,则 "1.1.1"
return parentNum + ".1 ";
}
catch { }
return "1. "; // Fallback
}
private static void ReplacePrefix(Word.Paragraph p, string newPrefix)
{
string text = p.Range.Text;
// 移除旧的前缀
string cleanText = text;
if (RegexHierarchical.IsMatch(text)) cleanText = RegexHierarchical.Replace(text, "", 1);
else if (RegexChapter.IsMatch(text)) cleanText = RegexChapter.Replace(text, "", 1);
else if (RegexChinese.IsMatch(text)) cleanText = RegexChinese.Replace(text, "", 1);
else if (RegexNumericDot.IsMatch(text)) cleanText = RegexNumericDot.Replace(text, "", 1);
cleanText = cleanText.TrimStart(); // 去除可能的空格
// 写入新文本 (注意保留段落标记)
// 直接设置 Range.Text 会覆盖格式,需小心
// 策略:Range.InsertBefore? 不,这会保留旧文本
// 策略:定位到 Start,删除旧前缀长度,插入新前缀
// 简单实现:覆盖 Text,重置 Style (因为 Text 赋值会清除部分格式,但我们是在 ApplyStyle 中,Style 刚被设置)
// 更好:只操作 Range 的 Start 到 Match End
// 正则匹配旧前缀的长度
int oldLength = 0;
if (RegexHierarchical.IsMatch(text)) oldLength = RegexHierarchical.Match(text).Length;
else if (RegexChapter.IsMatch(text)) oldLength = RegexChapter.Match(text).Length;
else if (RegexChinese.IsMatch(text)) oldLength = RegexChinese.Match(text).Length;
else if (RegexNumericDot.IsMatch(text)) oldLength = RegexNumericDot.Match(text).Length;
// 删除旧前缀
if (oldLength > 0)
{
var range = p.Range;
range.End = range.Start + oldLength;
range.Delete();
}
// 插入新前缀
p.Range.InsertBefore(newPrefix);
}
// 简易中文数字转换 (支持 1-99)
private static readonly string[] CN_Nums = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
private static readonly string[] CN_Units = { "", "十", "百" };
private static int ChineseToInt(string s)
{
if (string.IsNullOrEmpty(s)) return 0;
// 简单映射
int result = 0;
int temp = 0; // 当前位数值
// 仅处理 一到九十九
// 十 -> 10, 十一 -> 11, 二十 -> 20
if (s.StartsWith("十")) result += 10;
foreach (char c in s)
{
string cs = c.ToString();
int idx = Array.IndexOf(CN_Nums, cs);
if (idx > 0)
{
temp = idx;
if (s.EndsWith(cs)) result += temp; // 个位
}
else if (cs == "十")
{
if (temp == 0) temp = 1; // "十" 前没数视为1
result += temp * 10;
temp = 0;
}
}
if (s == "十") return 10;
return result > 0 ? result : 0;
}
private static string IntToChinese(int n)
{
if (n <= 0) return n.ToString();
if (n <= 10) return CN_Nums[n];
if (n < 20) return "十" + CN_Nums[n % 10];
if (n < 100) return CN_Nums[n / 10] + "十" + (n % 10 == 0 ? "" : CN_Nums[n % 10]);
return n.ToString(); // 超过99暂返数字
}
} }
/// <summary> /// <summary>
@@ -722,6 +1367,25 @@ namespace WordAddIn
headings = new List<WordAddIn.AiService.HeadingInfo>(); headings = new List<WordAddIn.AiService.HeadingInfo>();
} }
// 加载大纲样式配置
string styleJson = Settings.Default.OutlineStyles;
OutlineStyleConfig styleConfig = null;
try
{
styleConfig = string.IsNullOrEmpty(styleJson)
? new OutlineStyleConfig()
: JsonConvert.DeserializeObject<OutlineStyleConfig>(styleJson);
}
catch
{
styleConfig = new OutlineStyleConfig();
}
if (styleConfig == null) styleConfig = new OutlineStyleConfig();
var defaultStyleConfig = new OutlineStyleConfig();
if (styleConfig.Heading1 == null) styleConfig.Heading1 = defaultStyleConfig.Heading1;
if (styleConfig.Heading2 == null) styleConfig.Heading2 = defaultStyleConfig.Heading2;
if (styleConfig.Heading3 == null) styleConfig.Heading3 = defaultStyleConfig.Heading3;
// 4. 应用样式 (在 UI 线程操作 Word 对象) // 4. 应用样式 (在 UI 线程操作 Word 对象)
// 遍历所有段落,性能可能受文档长度影响,但对于一般文档可接受 // 遍历所有段落,性能可能受文档长度影响,但对于一般文档可接受
int changeCount = 0; int changeCount = 0;
@@ -737,31 +1401,14 @@ namespace WordAddIn
if (match != null) if (match != null)
{ {
// 是标题:设置对应的 Word 内置标题样式 // 使用统一的样式应用方法
Word.WdBuiltinStyle styleEnum = Word.WdBuiltinStyle.wdStyleNormal; ApplyStyleToParagraph(p, match.level, styleConfig);
switch (match.level)
{
case 1: styleEnum = Word.WdBuiltinStyle.wdStyleHeading1; break;
case 2: styleEnum = Word.WdBuiltinStyle.wdStyleHeading2; break;
case 3: styleEnum = Word.WdBuiltinStyle.wdStyleHeading3; break;
case 4: styleEnum = Word.WdBuiltinStyle.wdStyleHeading4; break;
case 5: styleEnum = Word.WdBuiltinStyle.wdStyleHeading5; break;
default: styleEnum = Word.WdBuiltinStyle.wdStyleHeading1; break;
}
p.set_Style(styleEnum);
// 标题通常不需要首行缩进,强制清除
p.Format.CharacterUnitFirstLineIndent = 0;
p.Format.FirstLineIndent = 0;
changeCount++; changeCount++;
} }
else else
{ {
// 6. 非标题(正文):统一设置首行缩进 2 字符 // 6. 非标题(正文):应用正文样式(包含首行缩进)
// 让文档看起来更规范 ApplyStyleToParagraph(p, 10, styleConfig);
p.Format.CharacterUnitFirstLineIndent = 2;
indentCount++; indentCount++;
} }
} }
@@ -769,7 +1416,7 @@ namespace WordAddIn
string msg = $"格式美化完成!\n- 已调整 {changeCount} 处标题格式。"; string msg = $"格式美化完成!\n- 已调整 {changeCount} 处标题格式。";
if (indentCount > 0) if (indentCount > 0)
{ {
msg += $"\n- 已对 {indentCount} 个段落应用首行缩进。"; msg += $"\n- 已对 {indentCount} 个段落应用正文样式(首行缩进)。";
} }
MessageBox.Show(msg); MessageBox.Show(msg);
} }
@@ -812,41 +1459,29 @@ namespace WordAddIn
prompt = prompt.Trim(); prompt = prompt.Trim();
} }
// 2. 如果选区为空(或只包含空白字符),尝试获取剪贴板文本
if (string.IsNullOrWhiteSpace(prompt))
{
try
{
if (Clipboard.ContainsText())
{
prompt = Clipboard.GetText().Trim();
}
}
catch (Exception ex)
{
// 忽略剪贴板访问错误(如被其他进程占用)
Console.WriteLine("Clipboard access failed: " + ex.Message);
}
}
// 3. 如果依然为空,提示用户
if (string.IsNullOrWhiteSpace(prompt))
{
MessageBox.Show("未能获取生图描述。\n请选择文档中的文字,或确保剪贴板中有文本内容。");
return;
}
// 获取全文背景和参考资料上下文,合并到 Prompt 中供用户预览和编辑 // 获取全文背景和参考资料上下文,合并到 Prompt 中供用户预览和编辑
string context = GetCombinedContext(); string context = GetCombinedContext();
if (!string.IsNullOrWhiteSpace(context)) if (!string.IsNullOrWhiteSpace(context))
{ {
// 注意:这里我们只把 Selection 作为 SourceText 传给 Form
// Context 可以作为补充,但目前的 Form 逻辑主要是处理 SourceText
// 如果需要 Context,可能需要 Form 支持额外参数,或者直接 append 到 prompt
// 为了保持简单,我们暂时只传递选区文本,Context 在这里 append 到 prompt 会导致
// SourceText 包含 Context,这可能不是用户想要的(如果他们只选了一个词)
// 但之前的逻辑是 append,所以我们保持一致,或者让 Form 决定
// 之前的逻辑: prompt += context
// 现在的逻辑: prompt 传给 Form.SourceText
// 如果 prompt 包含 context,那么 Form 的 Input Box 也会包含 context
// 这对于“选区”来说可能有点多,但对于“生成”来说是必要的
// 让我们暂时保持原样,把 context 加进去,用户可以在 Input Box 里删掉
prompt += $"\n\n{context}"; prompt += $"\n\n{context}";
} }
// 弹出选项窗体 // 弹出选项窗体
using (var form = new ImageOptionsForm()) using (var form = new ImageOptionsForm())
{ {
// 传入源文本 // 传入源文本 (可能是选区,也可能是空)
form.SourceText = prompt; form.SourceText = prompt;
if (form.ShowDialog() != DialogResult.OK) if (form.ShowDialog() != DialogResult.OK)
@@ -893,12 +1528,15 @@ namespace WordAddIn
/// <summary> /// <summary>
/// 【关于】按钮点击事件处理。 /// 【关于】按钮点击事件处理。
/// 显示插件版本和作者信息。 /// 显示插件版本和作者信息,以及功能使用说明。
/// </summary> /// </summary>
/// <param name="control">触发事件的 Ribbon 控件</param> /// <param name="control">触发事件的 Ribbon 控件</param>
public void OnAboutClick(Office.IRibbonControl control) public void OnAboutClick(Office.IRibbonControl control)
{ {
MessageBox.Show("Version 0.2\n作者:黄海", "关于 AI 助手"); using (var form = new AboutForm())
{
form.ShowDialog();
}
} }
/// <summary> /// <summary>
@@ -986,71 +1624,14 @@ namespace WordAddIn
p.Range.Text = item.Title.Trim() + "\r"; p.Range.Text = item.Title.Trim() + "\r";
// 7. 根据层级应用对应的样式 (字体、大小、加粗、对齐) // 7. 根据层级应用对应的样式 (字体、大小、加粗、对齐)
TextStyle ts = null;
try try
{ {
File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Processing Item: {item.Title}, Level: {item.Level}\n"); File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Processing Item: {item.Title}, Level: {item.Level}\n");
ApplyStyleToParagraph(p, item.Level, styleConfig);
switch (item.Level)
{
case 0: // 主标题
ts = styleConfig.MainTitle;
p.set_Style(Word.WdBuiltinStyle.wdStyleTitle);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
break;
case 1: // 一级标题
ts = styleConfig.Heading1;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading1);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
break;
case 2: // 二级标题
ts = styleConfig.Heading2;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
break;
case 3: // 三级标题
ts = styleConfig.Heading3;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading3);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
break;
default:
ts = styleConfig.Heading3;
// 默认也应用三级标题样式,确保出现在大纲中
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading3);
p.Format.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
p.Range.ParagraphFormat.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
break;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Error setting style: {ex.Message}\n"); File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Error setting style: {ex.Message}\n");
// Fallback: try setting style by name if object fails
try
{
if (item.Level == 0) p.set_Style("标题");
else p.set_Style("标题 " + item.Level);
}
catch { }
}
// 应用自定义样式属性
if (ts != null)
{
p.Range.Font.Name = ts.FontName;
try { p.Range.Font.NameFarEast = ts.FontName; } catch { }
p.Range.Font.Size = ts.FontSize;
p.Range.Font.Bold = ts.IsBold ? 1 : 0;
p.Range.Font.Color = Word.WdColor.wdColorBlack; // 强制设为黑色,避免出现默认蓝色的情况
if (item.Level == 0) // 仅主标题应用自定义对齐方式
{
p.Format.Alignment = (Word.WdParagraphAlignment)ts.Alignment;
}
} }
// 更新插入位置到当前段落之后,准备插入下一行 // 更新插入位置到当前段落之后,准备插入下一行
@@ -1128,7 +1709,26 @@ namespace WordAddIn
return false; return false;
} }
private static void ApplyHeadingStylesToInsertedRange(Word.Document doc, int start, int end, OutlineStyleConfig styleConfig) private static int GuessHeadingLevel(string text)
{
if (string.IsNullOrWhiteSpace(text)) return 10;
string t = text.Trim();
// Level 3: 1.1.1
if (Regex.IsMatch(t, @"^\d+\.\d+\.\d+")) return 3;
// Level 2: 1.1
if (Regex.IsMatch(t, @"^\d+\.\d+")) return 2;
// Level 1: 1. or 1、 or 第x章 or 一、
if (Regex.IsMatch(t, @"^第[一二三四五六七八九十0-9]+章")) return 1;
if (Regex.IsMatch(t, @"^[一二三四五六七八九十]+、")) return 1;
if (Regex.IsMatch(t, @"^\d+(\.|、)")) return 1;
return 10; // Body
}
private void ApplyHeadingStylesToInsertedRange(Word.Document doc, int start, int end, OutlineStyleConfig styleConfig)
{ {
if (doc == null) return; if (doc == null) return;
if (end <= start) return; if (end <= start) return;
@@ -1155,74 +1755,7 @@ namespace WordAddIn
level = GuessHeadingLevel(text); level = GuessHeadingLevel(text);
} }
ApplyParagraphStyle(p, level, styleConfig); ApplyStyleToParagraph(p, level, styleConfig);
}
}
private static int GuessHeadingLevel(string text)
{
var t = (text ?? "").Trim();
if (string.IsNullOrWhiteSpace(t)) return 1;
if (Regex.IsMatch(t, @"^第[一二三四五六七八九十0-9]+章")) return 1;
if (Regex.IsMatch(t, @"^(附录|结语|结论|参考文献|致谢)\b")) return 1;
if (Regex.IsMatch(t, @"^\d+\.\d+\.\d+")) return 3;
if (Regex.IsMatch(t, @"^\d+\.\d+")) return 2;
if (Regex.IsMatch(t, @"^\d+\s")) return 1;
if (Regex.IsMatch(t, @"^[一二三四五六七八九十]+、")) return 2;
return 1;
}
private static void ApplyParagraphStyle(Word.Paragraph p, int level, OutlineStyleConfig styleConfig)
{
if (p == null) return;
if (styleConfig == null) styleConfig = new OutlineStyleConfig();
if (level < 0) level = 0;
if (level > 3) level = 3;
TextStyle ts;
Word.WdOutlineLevel outlineLevel;
switch (level)
{
case 0:
ts = styleConfig.MainTitle;
p.set_Style(Word.WdBuiltinStyle.wdStyleTitle);
outlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
break;
case 1:
ts = styleConfig.Heading1;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading1);
outlineLevel = Word.WdOutlineLevel.wdOutlineLevel1;
break;
case 2:
ts = styleConfig.Heading2;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
outlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
break;
default:
ts = styleConfig.Heading3;
p.set_Style(Word.WdBuiltinStyle.wdStyleHeading3);
outlineLevel = Word.WdOutlineLevel.wdOutlineLevel3;
break;
}
try { p.Format.OutlineLevel = outlineLevel; } catch { }
try { p.Range.ParagraphFormat.OutlineLevel = outlineLevel; } catch { }
if (ts != null)
{
try { p.Range.Font.Name = ts.FontName; } catch { }
try { p.Range.Font.NameFarEast = ts.FontName; } catch { }
try { p.Range.Font.Size = ts.FontSize; } catch { }
try { p.Range.Font.Bold = ts.IsBold ? 1 : 0; } catch { }
try { p.Range.Font.Color = Word.WdColor.wdColorBlack; } catch { }
if (level == 0)
{
try { p.Format.Alignment = (Word.WdParagraphAlignment)ts.Alignment; } catch { }
}
} }
} }

View File

@@ -2,21 +2,33 @@
<ribbon> <ribbon>
<tabs> <tabs>
<tab id="tabAiAssistant" label="AI助手"> <tab id="tabAiAssistant" label="AI助手">
<group id="groupUser" label="用户">
<button id="btnLogin" label="登录" size="large" onAction="OnLoginClick" imageMso="Lock" />
</group>
<group id="groupContent" label="内容创作"> <group id="groupContent" label="内容创作">
<button id="btnCreateOutline" label="创建大纲" size="large" onAction="OnCreateOutlineClick" imageMso="ViewOutlineView" /> <button id="btnCreateOutline" label="创建大纲" size="large" onAction="OnCreateOutlineClick" getEnabled="GetControlEnabled" imageMso="ViewOutlineView" />
<button id="btnOutlineSetting" label="大纲配置" size="large" onAction="OnOutlineSettingClick" imageMso="ParagraphDialog" /> <button id="btnReadFull" label="通读全文" size="large" onAction="OnReadFullClick" getEnabled="GetControlEnabled" imageMso="FindDialog" />
<button id="btnReadFull" label="通读全文" size="large" onAction="OnReadFullClick" imageMso="FindDialog" /> <button id="btnSummarizeOutline" label="总结大纲" size="large" onAction="OnSummarizeOutlineClick" getEnabled="GetControlEnabled" imageMso="GroupSmartArtQuickStyles" />
<button id="btnSummarizeOutline" label="总结大纲" size="large" onAction="OnSummarizeOutlineClick" imageMso="GroupSmartArtQuickStyles" /> <button id="btnImportReference" label="补充背景" size="large" onAction="OnImportReferenceClick" getEnabled="GetControlEnabled" imageMso="ImportTextFile" />
<button id="btnImportReference" label="补充背景" size="large" onAction="OnImportReferenceClick" imageMso="ImportTextFile" /> <button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" getEnabled="GetControlEnabled" imageMso="ReviewCompareTwoVersions" />
<button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" imageMso="ReviewCompareTwoVersions" /> <button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" getEnabled="GetControlEnabled" imageMso="Spelling" />
<button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" imageMso="Spelling" /> <button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" getEnabled="GetControlEnabled" imageMso="SmartArtInsert" />
<button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" imageMso="SmartArtInsert" /> <button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" getEnabled="GetControlEnabled" />
<button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" /> <button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" getEnabled="GetControlEnabled" imageMso="PictureInsertFromFile" />
<button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" imageMso="PictureInsertFromFile" /> </group>
<group id="grpStyleWorkspace" label="样式工作区">
<toggleButton id="tbtnStyleMainTitle" label="主标题" size="large" onAction="OnStyleBrushToggle" getPressed="GetStyleBrushPressed" getEnabled="GetControlEnabled" imageMso="ShapeStar" />
<toggleButton id="tbtnStyleLevel1" label="一级样式" size="large" onAction="OnStyleBrushToggle" getPressed="GetStyleBrushPressed" getEnabled="GetControlEnabled" imageMso="ShapeIsoscelesTriangle" />
<toggleButton id="tbtnStyleLevel2" label="二级样式" size="large" onAction="OnStyleBrushToggle" getPressed="GetStyleBrushPressed" getEnabled="GetControlEnabled" imageMso="ShapeOval" />
<toggleButton id="tbtnStyleLevel3" label="三级样式" size="large" onAction="OnStyleBrushToggle" getPressed="GetStyleBrushPressed" getEnabled="GetControlEnabled" imageMso="ShapeRightArrow" />
<toggleButton id="tbtnStyleBody" label="正文样式" size="large" onAction="OnStyleBrushToggle" getPressed="GetStyleBrushPressed" getEnabled="GetControlEnabled" imageMso="AlignLeft" />
</group> </group>
<group id="groupConfig" label="设置"> <group id="groupConfig" label="设置">
<labelControl id="lblCurrentModel" getLabel="GetCurrentModelLabel" /> <labelControl id="lblCurrentModel" getLabel="GetCurrentModelLabel" getEnabled="GetControlEnabled" />
<dropDown id="ddlModelSelect" label="模型选择" sizeString="WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" onAction="OnModelSelection" getItemCount="GetModelCount" getItemLabel="GetModelLabel" getSelectedItemIndex="GetSelectedModelIndex" imageMso="ServerConnection" /> <dropDown id="ddlModelSelect" label="模型选择" sizeString="WWWWWWWWWWWWWWW" onAction="OnModelSelection" getItemCount="GetModelCount" getItemLabel="GetModelLabel" getSelectedItemIndex="GetSelectedModelIndex" getEnabled="GetControlEnabled" imageMso="ServerConnection" />
<button id="btnOutlineSettings" label="大纲配置" size="large" onAction="OnOutlineSettingClick" getEnabled="GetControlEnabled" imageMso="TextStylesGallery" />
</group>
<group id="groupHelp" label="帮助">
<button id="btnAbout" label="关于" size="large" onAction="OnAboutClick" imageMso="Info" /> <button id="btnAbout" label="关于" size="large" onAction="OnAboutClick" imageMso="Info" />
</group> </group>
</tab> </tab>

View File

@@ -56,14 +56,14 @@ namespace WordAddIn
this.txtTopic.Multiline = true; this.txtTopic.Multiline = true;
this.txtTopic.Name = "txtTopic"; this.txtTopic.Name = "txtTopic";
this.txtTopic.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtTopic.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtTopic.Size = new System.Drawing.Size(440, 240); this.txtTopic.Size = new System.Drawing.Size(460, 240);
this.txtTopic.TabIndex = 1; this.txtTopic.TabIndex = 1;
// //
// btnGenerate // btnGenerate
// //
this.btnGenerate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnGenerate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnGenerate.DialogResult = System.Windows.Forms.DialogResult.OK; this.btnGenerate.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnGenerate.Location = new System.Drawing.Point(240, 310); this.btnGenerate.Location = new System.Drawing.Point(260, 310);
this.btnGenerate.Name = "btnGenerate"; this.btnGenerate.Name = "btnGenerate";
this.btnGenerate.Size = new System.Drawing.Size(100, 35); this.btnGenerate.Size = new System.Drawing.Size(100, 35);
this.btnGenerate.TabIndex = 2; this.btnGenerate.TabIndex = 2;
@@ -75,7 +75,7 @@ namespace WordAddIn
// //
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(360, 310); this.btnCancel.Location = new System.Drawing.Point(380, 310);
this.btnCancel.Name = "btnCancel"; this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(100, 35); this.btnCancel.Size = new System.Drawing.Size(100, 35);
this.btnCancel.TabIndex = 3; this.btnCancel.TabIndex = 3;
@@ -86,6 +86,7 @@ namespace WordAddIn
// //
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.CancelButton = this.btnCancel; this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(500, 370); this.ClientSize = new System.Drawing.Size(500, 370);
this.MinimumSize = new System.Drawing.Size(400, 300); this.MinimumSize = new System.Drawing.Size(400, 300);

View File

@@ -37,11 +37,15 @@ namespace WordAddIn
public string SelectedStyle { get; private set; } public string SelectedStyle { get; private set; }
private ComboBox cmbStyles; private ComboBox cmbStyles;
private RadioButton rbClipboard;
private RadioButton rbInput;
private TextBox txtInput;
private TextBox txtFinalPrompt; private TextBox txtFinalPrompt;
private CheckBox chkOptimize; private CheckBox chkOptimize;
private Button btnOk; private Button btnOk;
private Button btnCancel; private Button btnCancel;
private Label lblStyle; private Label lblStyle;
private Label lblSource;
private Label lblPrompt; private Label lblPrompt;
private readonly Dictionary<string, string> _styleTemplates = new Dictionary<string, string>(); private readonly Dictionary<string, string> _styleTemplates = new Dictionary<string, string>();
@@ -93,17 +97,22 @@ namespace WordAddIn
private void InitializeComponent() private void InitializeComponent()
{ {
this.Text = "生成配图选项 - 支持编辑提示词"; this.Text = "生成配图设置";
this.Size = new Size(500, 520); this.Size = new Size(500, 650);
this.MinimumSize = new Size(400, 400); // 设置最小尺寸 this.MinimumSize = new Size(400, 500);
this.StartPosition = FormStartPosition.CenterParent; this.StartPosition = FormStartPosition.CenterParent;
this.AutoScaleMode = AutoScaleMode.Dpi; // 支持 DPI 缩放 this.AutoScaleMode = AutoScaleMode.Dpi;
this.FormBorderStyle = FormBorderStyle.Sizable; // 允许调整大小 this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.MaximizeBox = true; // 允许最大化 this.FormBorderStyle = FormBorderStyle.Sizable;
this.MaximizeBox = true;
this.MinimizeBox = true; this.MinimizeBox = true;
this.lblStyle = new Label(); this.lblStyle = new Label();
this.cmbStyles = new ComboBox(); this.cmbStyles = new ComboBox();
this.lblSource = new Label();
this.rbClipboard = new RadioButton();
this.rbInput = new RadioButton();
this.txtInput = new TextBox();
this.lblPrompt = new Label(); this.lblPrompt = new Label();
this.txtFinalPrompt = new TextBox(); this.txtFinalPrompt = new TextBox();
this.chkOptimize = new CheckBox(); this.chkOptimize = new CheckBox();
@@ -115,52 +124,81 @@ namespace WordAddIn
// lblStyle // lblStyle
this.lblStyle.AutoSize = true; this.lblStyle.AutoSize = true;
this.lblStyle.Location = new Point(20, 20); this.lblStyle.Location = new Point(20, 20);
this.lblStyle.Text = "图片风格:"; this.lblStyle.Text = "1. 图片风格:";
// cmbStyles // cmbStyles
this.cmbStyles.DropDownStyle = ComboBoxStyle.DropDownList; this.cmbStyles.DropDownStyle = ComboBoxStyle.DropDownList;
this.cmbStyles.Location = new Point(20, 45); this.cmbStyles.Location = new Point(20, 45);
this.cmbStyles.Size = new Size(440, 25); this.cmbStyles.Size = new Size(440, 25);
this.cmbStyles.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; // 宽度自适应 this.cmbStyles.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
this.cmbStyles.SelectedIndexChanged += CmbStyles_SelectedIndexChanged; this.cmbStyles.SelectedIndexChanged += CmbStyles_SelectedIndexChanged;
// lblSource
this.lblSource.AutoSize = true;
this.lblSource.Location = new Point(20, 85);
this.lblSource.Text = "2. 内容来源:";
// rbClipboard
this.rbClipboard.AutoSize = true;
this.rbClipboard.Location = new Point(40, 110);
this.rbClipboard.Text = "使用剪贴板内容";
this.rbClipboard.CheckedChanged += RbSource_CheckedChanged;
// rbInput
this.rbInput.AutoSize = true;
this.rbInput.Location = new Point(200, 110);
this.rbInput.Text = "手动录入/编辑";
this.rbInput.CheckedChanged += RbSource_CheckedChanged;
// txtInput
this.txtInput.Location = new Point(40, 140);
this.txtInput.Multiline = true;
this.txtInput.ScrollBars = ScrollBars.Vertical;
this.txtInput.Size = new Size(420, 100);
this.txtInput.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
this.txtInput.TextChanged += TxtInput_TextChanged;
// lblPrompt // lblPrompt
this.lblPrompt.AutoSize = true; this.lblPrompt.AutoSize = true;
this.lblPrompt.Location = new Point(20, 85); this.lblPrompt.Location = new Point(20, 255);
this.lblPrompt.Text = "提示词预览 (您可以直接修改下面的生成指令):"; this.lblPrompt.Text = "3. 最终提示词预览 (可直接修改):";
// txtFinalPrompt // txtFinalPrompt
this.txtFinalPrompt.Location = new Point(20, 110); this.txtFinalPrompt.Location = new Point(20, 280);
this.txtFinalPrompt.Multiline = true; this.txtFinalPrompt.Multiline = true;
this.txtFinalPrompt.ScrollBars = ScrollBars.Vertical; this.txtFinalPrompt.ScrollBars = ScrollBars.Vertical;
this.txtFinalPrompt.Size = new Size(440, 280); this.txtFinalPrompt.Size = new Size(440, 220);
this.txtFinalPrompt.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; // 全向自适应 this.txtFinalPrompt.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
// chkOptimize // chkOptimize
this.chkOptimize.AutoSize = true; this.chkOptimize.AutoSize = true;
this.chkOptimize.Location = new Point(20, 400); this.chkOptimize.Location = new Point(20, 520);
this.chkOptimize.Size = new Size(400, 20); this.chkOptimize.Size = new Size(400, 24);
this.chkOptimize.Text = "使用 AI 优化提示词 (自动翻译成英文并丰富细节)"; this.chkOptimize.Text = "使用 AI 优化提示词 (自动翻译成英文并丰富细节)";
this.chkOptimize.Checked = true; this.chkOptimize.Checked = true;
this.chkOptimize.Anchor = AnchorStyles.Bottom | AnchorStyles.Left; // 底部固定 this.chkOptimize.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
// btnOk // btnOk
this.btnOk.Text = "开始生成"; this.btnOk.Text = "开始生成";
this.btnOk.DialogResult = DialogResult.OK; this.btnOk.DialogResult = DialogResult.OK;
this.btnOk.Location = new Point(280, 430); this.btnOk.Location = new Point(260, 560);
this.btnOk.Size = new Size(90, 30); this.btnOk.Size = new Size(100, 35);
this.btnOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; // 右下固定 this.btnOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
this.btnOk.Click += BtnOk_Click; this.btnOk.Click += BtnOk_Click;
// btnCancel // btnCancel
this.btnCancel.Text = "取消"; this.btnCancel.Text = "取消";
this.btnCancel.DialogResult = DialogResult.Cancel; this.btnCancel.DialogResult = DialogResult.Cancel;
this.btnCancel.Location = new Point(380, 430); this.btnCancel.Location = new Point(380, 560);
this.btnCancel.Size = new Size(80, 30); this.btnCancel.Size = new Size(80, 35);
this.btnCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; // 右下固定 this.btnCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
this.Controls.Add(this.lblStyle); this.Controls.Add(this.lblStyle);
this.Controls.Add(this.cmbStyles); this.Controls.Add(this.cmbStyles);
this.Controls.Add(this.lblSource);
this.Controls.Add(this.rbClipboard);
this.Controls.Add(this.rbInput);
this.Controls.Add(this.txtInput);
this.Controls.Add(this.lblPrompt); this.Controls.Add(this.lblPrompt);
this.Controls.Add(this.txtFinalPrompt); this.Controls.Add(this.txtFinalPrompt);
this.Controls.Add(this.chkOptimize); this.Controls.Add(this.chkOptimize);
@@ -174,16 +212,68 @@ namespace WordAddIn
protected override void OnLoad(EventArgs e) protected override void OnLoad(EventArgs e)
{ {
base.OnLoad(e); base.OnLoad(e);
// 默认选中第一个风格(通常是逻辑架构图,如果 keys 顺序不对可能需要指定)
// Initialize Source Logic
// If SourceText is provided (from Selection), populate txtInput and select rbInput
if (!string.IsNullOrWhiteSpace(this.SourceText))
{
this.txtInput.Text = this.SourceText;
this.rbInput.Checked = true;
}
else
{
// No selection, check clipboard
this.rbClipboard.Checked = true;
// Trigger logic to load clipboard if possible
RbSource_CheckedChanged(this.rbClipboard, EventArgs.Empty);
}
// Default Style Selection
if (this.cmbStyles.Items.Count > 0) if (this.cmbStyles.Items.Count > 0)
{ {
// 尝试找到上次选中的或默认逻辑架构图
int index = this.cmbStyles.FindString("逻辑架构图"); int index = this.cmbStyles.FindString("逻辑架构图");
this.cmbStyles.SelectedIndex = index >= 0 ? index : 0; this.cmbStyles.SelectedIndex = index >= 0 ? index : 0;
} }
else else
{ {
// Fallback update if no items or default UpdatePrompt();
}
}
private void RbSource_CheckedChanged(object sender, EventArgs e)
{
if (rbClipboard.Checked)
{
this.txtInput.Enabled = false;
try
{
if (Clipboard.ContainsText())
{
this.SourceText = Clipboard.GetText().Trim();
}
else
{
this.SourceText = "";
}
}
catch
{
this.SourceText = "";
}
}
else if (rbInput.Checked)
{
this.txtInput.Enabled = true;
this.SourceText = this.txtInput.Text;
}
UpdatePrompt();
}
private void TxtInput_TextChanged(object sender, EventArgs e)
{
if (rbInput.Checked)
{
this.SourceText = this.txtInput.Text;
UpdatePrompt(); UpdatePrompt();
} }
} }

View File

@@ -55,7 +55,7 @@ namespace WordAddIn
// //
this.lblMessage.BackColor = System.Drawing.Color.Transparent; this.lblMessage.BackColor = System.Drawing.Color.Transparent;
this.lblMessage.Dock = System.Windows.Forms.DockStyle.None; this.lblMessage.Dock = System.Windows.Forms.DockStyle.None;
this.lblMessage.Font = new System.Drawing.Font("Microsoft YaHei UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblMessage.Font = new System.Drawing.Font("Microsoft YaHei UI", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblMessage.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); this.lblMessage.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblMessage.Location = new System.Drawing.Point(0, 150); this.lblMessage.Location = new System.Drawing.Point(0, 150);
this.lblMessage.Name = "lblMessage"; this.lblMessage.Name = "lblMessage";
@@ -68,7 +68,7 @@ namespace WordAddIn
// //
this.txtProgress.BackColor = System.Drawing.Color.White; this.txtProgress.BackColor = System.Drawing.Color.White;
this.txtProgress.BorderStyle = System.Windows.Forms.BorderStyle.None; this.txtProgress.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txtProgress.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtProgress.Font = new System.Drawing.Font("Microsoft YaHei UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtProgress.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); this.txtProgress.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.txtProgress.Location = new System.Drawing.Point(40, 190); this.txtProgress.Location = new System.Drawing.Point(40, 190);
this.txtProgress.Name = "txtProgress"; this.txtProgress.Name = "txtProgress";

View File

@@ -43,7 +43,7 @@ namespace WordAddIn
// lblTitle // lblTitle
// //
this.lblTitle.AutoSize = false; this.lblTitle.AutoSize = false;
this.lblTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold); this.lblTitle.Font = new System.Drawing.Font("微软雅黑", 18F, System.Drawing.FontStyle.Bold);
this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(43)))), ((int)(((byte)(87)))), ((int)(((byte)(154))))); this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(43)))), ((int)(((byte)(87)))), ((int)(((byte)(154)))));
this.lblTitle.Location = new System.Drawing.Point(0, 25); this.lblTitle.Location = new System.Drawing.Point(0, 25);
this.lblTitle.Name = "lblTitle"; this.lblTitle.Name = "lblTitle";
@@ -55,7 +55,7 @@ namespace WordAddIn
// lblUser // lblUser
// //
this.lblUser.AutoSize = true; this.lblUser.AutoSize = true;
this.lblUser.Font = new System.Drawing.Font("微软雅黑", 11F); this.lblUser.Font = new System.Drawing.Font("微软雅黑", 13F);
this.lblUser.Location = new System.Drawing.Point(80, 85); this.lblUser.Location = new System.Drawing.Point(80, 85);
this.lblUser.Name = "lblUser"; this.lblUser.Name = "lblUser";
this.lblUser.Size = new System.Drawing.Size(63, 20); this.lblUser.Size = new System.Drawing.Size(63, 20);
@@ -64,7 +64,7 @@ namespace WordAddIn
// //
// txtUsername // txtUsername
// //
this.txtUsername.Font = new System.Drawing.Font("微软雅黑", 11F); this.txtUsername.Font = new System.Drawing.Font("微软雅黑", 13F);
this.txtUsername.Location = new System.Drawing.Point(160, 80); this.txtUsername.Location = new System.Drawing.Point(160, 80);
this.txtUsername.Name = "txtUsername"; this.txtUsername.Name = "txtUsername";
this.txtUsername.Size = new System.Drawing.Size(220, 27); this.txtUsername.Size = new System.Drawing.Size(220, 27);
@@ -74,7 +74,7 @@ namespace WordAddIn
// lblPass // lblPass
// //
this.lblPass.AutoSize = true; this.lblPass.AutoSize = true;
this.lblPass.Font = new System.Drawing.Font("微软雅黑", 11F); this.lblPass.Font = new System.Drawing.Font("微软雅黑", 13F);
this.lblPass.Location = new System.Drawing.Point(80, 145); this.lblPass.Location = new System.Drawing.Point(80, 145);
this.lblPass.Name = "lblPass"; this.lblPass.Name = "lblPass";
this.lblPass.Size = new System.Drawing.Size(58, 20); this.lblPass.Size = new System.Drawing.Size(58, 20);
@@ -83,7 +83,7 @@ namespace WordAddIn
// //
// txtPassword // txtPassword
// //
this.txtPassword.Font = new System.Drawing.Font("微软雅黑", 11F); this.txtPassword.Font = new System.Drawing.Font("微软雅黑", 13F);
this.txtPassword.Location = new System.Drawing.Point(160, 140); this.txtPassword.Location = new System.Drawing.Point(160, 140);
this.txtPassword.Name = "txtPassword"; this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '●'; this.txtPassword.PasswordChar = '●';
@@ -97,7 +97,7 @@ namespace WordAddIn
this.btnLogin.Cursor = System.Windows.Forms.Cursors.Hand; this.btnLogin.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnLogin.FlatAppearance.BorderSize = 0; this.btnLogin.FlatAppearance.BorderSize = 0;
this.btnLogin.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btnLogin.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnLogin.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold); this.btnLogin.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold);
this.btnLogin.ForeColor = System.Drawing.Color.White; this.btnLogin.ForeColor = System.Drawing.Color.White;
this.btnLogin.Location = new System.Drawing.Point(110, 220); this.btnLogin.Location = new System.Drawing.Point(110, 220);
this.btnLogin.Name = "btnLogin"; this.btnLogin.Name = "btnLogin";
@@ -111,7 +111,7 @@ namespace WordAddIn
// //
this.btnCancel.Cursor = System.Windows.Forms.Cursors.Hand; this.btnCancel.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Font = new System.Drawing.Font("微软雅黑", 10F); this.btnCancel.Font = new System.Drawing.Font("微软雅黑", 12F);
this.btnCancel.Location = new System.Drawing.Point(250, 220); this.btnCancel.Location = new System.Drawing.Point(250, 220);
this.btnCancel.Name = "btnCancel"; this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(120, 40); this.btnCancel.Size = new System.Drawing.Size(120, 40);
@@ -124,6 +124,7 @@ namespace WordAddIn
this.AcceptButton = this.btnLogin; this.AcceptButton = this.btnLogin;
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.BackColor = System.Drawing.Color.White; this.BackColor = System.Drawing.Color.White;
this.CancelButton = this.btnCancel; this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(500, 320); this.ClientSize = new System.Drawing.Size(500, 320);

View File

@@ -206,5 +206,14 @@ namespace WordAddIn.Models
/// 2: 右对齐 /// 2: 右对齐
/// </summary> /// </summary>
public int Alignment { get; set; } = 0; public int Alignment { get; set; } = 0;
/// <summary>
/// 字体颜色 (Word WdColor 枚举值)
/// 默认值为黑色 (wdColorBlack = -16777216, but usually 0 or auto)
/// 在 Word Interop 中,wdColorBlack = 0 (0x000000)
/// wdColorAutomatic = -16777216 (0xFF000000)
/// 我们存储 int 值。
/// </summary>
public int Color { get; set; } = 0; // 0 = Black
} }
} }

View File

@@ -79,6 +79,7 @@ namespace WordAddIn
// OutlineResultForm // OutlineResultForm
// //
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.ClientSize = new System.Drawing.Size(584, 461); this.ClientSize = new System.Drawing.Size(584, 461);
this.Controls.Add(this.btnClose); this.Controls.Add(this.btnClose);
this.Controls.Add(this.btnCopy); this.Controls.Add(this.btnCopy);

View File

@@ -81,6 +81,7 @@ namespace WordAddIn
this.AcceptButton = this.btnSave; this.AcceptButton = this.btnSave;
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.CancelButton = this.btnCancel; this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(450, 360); this.ClientSize = new System.Drawing.Size(450, 360);
this.MinimumSize = new System.Drawing.Size(350, 300); this.MinimumSize = new System.Drawing.Size(350, 300);

View File

@@ -82,7 +82,7 @@ namespace WordAddIn
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.tabControl.Controls.Add(this.tabFile); this.tabControl.Controls.Add(this.tabFile);
this.tabControl.Controls.Add(this.tabText); this.tabControl.Controls.Add(this.tabText);
this.tabControl.Font = new System.Drawing.Font("微软雅黑", 11F); this.tabControl.Font = new System.Drawing.Font("微软雅黑", 13F);
this.tabControl.Location = new System.Drawing.Point(25, 25); this.tabControl.Location = new System.Drawing.Point(25, 25);
this.tabControl.Name = "tabControl"; this.tabControl.Name = "tabControl";
this.tabControl.SelectedIndex = 0; this.tabControl.SelectedIndex = 0;
@@ -105,7 +105,7 @@ namespace WordAddIn
// lblFileTip // lblFileTip
// //
this.lblFileTip.AutoSize = true; this.lblFileTip.AutoSize = true;
this.lblFileTip.Font = new System.Drawing.Font("微软雅黑", 12F); this.lblFileTip.Font = new System.Drawing.Font("微软雅黑", 14F);
this.lblFileTip.Location = new System.Drawing.Point(30, 60); this.lblFileTip.Location = new System.Drawing.Point(30, 60);
this.lblFileTip.Name = "lblFileTip"; this.lblFileTip.Name = "lblFileTip";
this.lblFileTip.Size = new System.Drawing.Size(255, 21); this.lblFileTip.Size = new System.Drawing.Size(255, 21);
@@ -116,7 +116,7 @@ namespace WordAddIn
// //
this.txtFilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) this.txtFilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.txtFilePath.Font = new System.Drawing.Font("微软雅黑", 11F); this.txtFilePath.Font = new System.Drawing.Font("微软雅黑", 13F);
this.txtFilePath.Location = new System.Drawing.Point(30, 100); this.txtFilePath.Location = new System.Drawing.Point(30, 100);
this.txtFilePath.Name = "txtFilePath"; this.txtFilePath.Name = "txtFilePath";
this.txtFilePath.ReadOnly = true; this.txtFilePath.ReadOnly = true;
@@ -127,7 +127,7 @@ namespace WordAddIn
// //
this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnBrowse.Cursor = System.Windows.Forms.Cursors.Hand; this.btnBrowse.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnBrowse.Font = new System.Drawing.Font("微软雅黑", 10F); this.btnBrowse.Font = new System.Drawing.Font("微软雅黑", 12F);
this.btnBrowse.Location = new System.Drawing.Point(440, 98); this.btnBrowse.Location = new System.Drawing.Point(440, 98);
this.btnBrowse.Name = "btnBrowse"; this.btnBrowse.Name = "btnBrowse";
this.btnBrowse.Size = new System.Drawing.Size(100, 35); this.btnBrowse.Size = new System.Drawing.Size(100, 35);
@@ -152,7 +152,7 @@ namespace WordAddIn
this.txtReferenceInput.BackColor = System.Drawing.Color.WhiteSmoke; this.txtReferenceInput.BackColor = System.Drawing.Color.WhiteSmoke;
this.txtReferenceInput.BorderStyle = System.Windows.Forms.BorderStyle.None; this.txtReferenceInput.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txtReferenceInput.Dock = System.Windows.Forms.DockStyle.Fill; this.txtReferenceInput.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtReferenceInput.Font = new System.Drawing.Font("微软雅黑", 11F); this.txtReferenceInput.Font = new System.Drawing.Font("微软雅黑", 13F);
this.txtReferenceInput.Location = new System.Drawing.Point(10, 10); this.txtReferenceInput.Location = new System.Drawing.Point(10, 10);
this.txtReferenceInput.Name = "txtReferenceInput"; this.txtReferenceInput.Name = "txtReferenceInput";
this.txtReferenceInput.Size = new System.Drawing.Size(557, 247); this.txtReferenceInput.Size = new System.Drawing.Size(557, 247);
@@ -163,7 +163,7 @@ namespace WordAddIn
// //
this.lblWordCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblWordCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lblWordCount.AutoSize = true; this.lblWordCount.AutoSize = true;
this.lblWordCount.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold); this.lblWordCount.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Bold);
this.lblWordCount.Location = new System.Drawing.Point(30, 355); this.lblWordCount.Location = new System.Drawing.Point(30, 355);
this.lblWordCount.Name = "lblWordCount"; this.lblWordCount.Name = "lblWordCount";
this.lblWordCount.Size = new System.Drawing.Size(117, 22); this.lblWordCount.Size = new System.Drawing.Size(117, 22);
@@ -173,7 +173,7 @@ namespace WordAddIn
// numWordCount // numWordCount
// //
this.numWordCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.numWordCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.numWordCount.Font = new System.Drawing.Font("微软雅黑", 14F); this.numWordCount.Font = new System.Drawing.Font("微软雅黑", 16F);
this.numWordCount.Increment = new decimal(new int[] { this.numWordCount.Increment = new decimal(new int[] {
100, 100,
0, 0,
@@ -246,6 +246,7 @@ namespace WordAddIn
this.AcceptButton = this.btnGenerate; this.AcceptButton = this.btnGenerate;
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.BackColor = System.Drawing.Color.White; this.BackColor = System.Drawing.Color.White;
this.CancelButton = this.btnCancel; this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(650, 520); this.ClientSize = new System.Drawing.Size(650, 520);

View File

@@ -18,6 +18,10 @@ namespace WordAddIn
private NumericUpDown numSize; private NumericUpDown numSize;
private CheckBox chkBold; private CheckBox chkBold;
private ComboBox cmbAlign; private ComboBox cmbAlign;
private Button btnColor; // 颜色选择按钮
private Panel pnlColorPreview; // 颜色预览面板
private int _selectedColor = 0; // 存储选中的颜色值 (Word WdColor)
private bool _showAlign; private bool _showAlign;
/// <summary> /// <summary>
@@ -70,6 +74,17 @@ namespace WordAddIn
this.Controls.Add(numSize); this.Controls.Add(numSize);
this.Controls.Add(chkBold); this.Controls.Add(chkBold);
// 颜色选择
Label lblColor = new Label { Text = "颜色:", Location = new Point(180, 67), AutoSize = true };
btnColor = new Button { Text = "选择...", Location = new Point(220, 63), Width = 60, Height = 25 };
pnlColorPreview = new Panel { Location = new Point(290, 65), Width = 20, Height = 20, BorderStyle = BorderStyle.FixedSingle, BackColor = Color.Black };
btnColor.Click += BtnColor_Click;
this.Controls.Add(lblColor);
this.Controls.Add(btnColor);
this.Controls.Add(pnlColorPreview);
// 对齐方式 (可选) // 对齐方式 (可选)
if (_showAlign) if (_showAlign)
{ {
@@ -83,6 +98,35 @@ namespace WordAddIn
} }
} }
private void BtnColor_Click(object sender, EventArgs e)
{
using (ColorDialog colorDialog = new ColorDialog())
{
// Set initial color based on current selection
colorDialog.Color = pnlColorPreview.BackColor;
if (colorDialog.ShowDialog() == DialogResult.OK)
{
pnlColorPreview.BackColor = colorDialog.Color;
// Convert .NET Color to Word WdColor (int)
// Word stores colors as BGR (0xBBGGRR) in lower 24 bits
// But .NET Color.ToArgb() returns ARGB (0xAARRGGBB)
// WdColor is weird.
// wdColorBlack = 0
// wdColorRed = 255 (0x0000FF)
// It seems to be standard RGB or BGR integer value.
// Let's use ColorTranslator or manual conversion.
// Word Interop usually expects BGR int for some properties, or standard OLE color.
// Actually, WdColor enum has values like wdColorRed = 0xFF.
// The safest way is to cast the RGB value.
// However, ColorTranslator.ToOle(c) returns BGR, which is what Office usually expects.
_selectedColor = ColorTranslator.ToOle(colorDialog.Color);
}
}
}
/// <summary> /// <summary>
/// 将 TextStyle 对象应用到界面控件。 /// 将 TextStyle 对象应用到界面控件。
/// </summary> /// </summary>
@@ -98,6 +142,17 @@ namespace WordAddIn
numSize.Value = (decimal)style.FontSize; numSize.Value = (decimal)style.FontSize;
chkBold.Checked = style.IsBold; chkBold.Checked = style.IsBold;
_selectedColor = style.Color;
// Convert OLE Color back to .NET Color for preview
try
{
pnlColorPreview.BackColor = ColorTranslator.FromOle(_selectedColor);
}
catch
{
pnlColorPreview.BackColor = Color.Black;
}
if (_showAlign && cmbAlign != null) if (_showAlign && cmbAlign != null)
{ {
@@ -116,6 +171,8 @@ namespace WordAddIn
style.FontName = cmbFont.Text; style.FontName = cmbFont.Text;
style.FontSize = (float)numSize.Value; style.FontSize = (float)numSize.Value;
style.IsBold = chkBold.Checked; style.IsBold = chkBold.Checked;
style.Color = _selectedColor;
if (_showAlign && cmbAlign != null) if (_showAlign && cmbAlign != null)
{ {
style.Alignment = cmbAlign.SelectedIndex; style.Alignment = cmbAlign.SelectedIndex;

View File

@@ -288,6 +288,9 @@
<Compile Include="StyleEditorControl.cs"> <Compile Include="StyleEditorControl.cs">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
<Compile Include="AboutForm.cs">
<SubType>Form</SubType>
</Compile>
<EmbeddedResource Include="AiRibbon.xml" /> <EmbeddedResource Include="AiRibbon.xml" />
<None Include="ThisAddIn.Designer.xml"> <None Include="ThisAddIn.Designer.xml">
<DependentUpon>ThisAddIn.cs</DependentUpon> <DependentUpon>ThisAddIn.cs</DependentUpon>

View File

@@ -166,14 +166,14 @@
</dependentAssembly> </dependentAssembly>
</dependency> </dependency>
<dependency> <dependency>
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="WordAddIn.dll" size="109568"> <dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="WordAddIn.dll" size="122368">
<assemblyIdentity name="WordAddIn" version="1.0.0.0" language="neutral" processorArchitecture="msil" /> <assemblyIdentity name="WordAddIn" version="1.0.0.0" language="neutral" processorArchitecture="msil" />
<hash> <hash>
<dsig:Transforms> <dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" /> <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms> </dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /> <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
<dsig:DigestValue>b7Cc32gOO4NDdlCmmAwOKVKIxiGSuuKv6qdRFKUoZo8=</dsig:DigestValue> <dsig:DigestValue>Sv+qgHZFDhjy9IFwv7kNOHU+fY7HZYjsKfxAAPn7OKk=</dsig:DigestValue>
</hash> </hash>
</dependentAssembly> </dependentAssembly>
</dependency> </dependency>
@@ -200,4 +200,4 @@
</vstov4:customizations> </vstov4:customizations>
</vstav3:application> </vstav3:application>
</vstav3:addIn> </vstav3:addIn>
<publisherIdentity name="CN=DESKTOP-Q6H7B6L\Administrator" issuerKeyHash="42606c52715d5764c2f9dab5bee6dcd76cc7a67d" /><Signature Id="StrongNameSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>UhpvvvhZ0JKx4s3N602bgk5DyV5yFn1sFdOJrcd9Vjg=</DigestValue></Reference></SignedInfo><SignatureValue>GZa7zL6wJ+jKnaAHu66eweHxTbmrpypWRicD0zClj3D28NdnnNe1IO51tYdaVglSZ9frQUYeS0mDj2FrUXr26NET0eFZTrfjXBwXtTsiiVnD53Zfd/MGpLF1LlXran/i7/Q8CknNtNDechzMVjs7uDS2Gx+PsycmEu03QrNpC1Y=</SignatureValue><KeyInfo Id="StrongNameKeyInfo"><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><msrel:RelData xmlns:msrel="http://schemas.microsoft.com/windows/rel/2005/reldata"><r:license xmlns:r="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:as="http://schemas.microsoft.com/windows/pki/2005/Authenticode"><r:grant><as:ManifestInformation Hash="38567dc7ad89d3156c7d16725ec9434e829b4debcdcde2b192d059f8be6f1a52" Description="" Url=""><as:assemblyIdentity name="WordAddIn.dll" version="1.0.0.5" publicKeyToken="06a92c46db516926" language="neutral" processorArchitecture="msil" type="win32" /></as:ManifestInformation><as:SignedBy /><as:AuthenticodePublisher><as:X509SubjectName>CN=DESKTOP-Q6H7B6L\Administrator</as:X509SubjectName></as:AuthenticodePublisher></r:grant><r:issuer><Signature Id="AuthenticodeSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>vkwRm4lIKJ57QGSD+RJm0qwloH1cmITo8KKjBN5VXXY=</DigestValue></Reference></SignedInfo><SignatureValue>Sk6rRKpxCaPMi39cj35dPg3SXlS0etffN9z9NtdtGDm2TdptcSY9ljLa1p8fhfNBSTQn2T8wpTC+BYYgLfBI0ymRfH38uKAFdfXvTkOTfM0LPWguRxvu/GLrXsh9K3SrxJnuLk3Dc1Rdh5/BG91NPAtojdkcVvXhnB4fdPZlboM=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIICDTCCAXagAwIBAgIQJpSlsxfGbpRNgyjD5Q/yDjANBgkqhkiG9w0BAQsFADBFMUMwQQYDVQQDHjoARABFAFMASwBUAE8AUAAtAFEANgBIADcAQgA2AEwAXABBAGQAbQBpAG4AaQBzAHQAcgBhAHQAbwByMB4XDTI2MDEyNDAwMzYxNVoXDTI3MDEyNDA2MzYxNVowRTFDMEEGA1UEAx46AEQARQBTAEsAVABPAFAALQBRADYASAA3AEIANgBMAFwAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaECAwEAATANBgkqhkiG9w0BAQsFAAOBgQC3GjWMhEFFrn9PGYrQVGNAaibG1sR/eRX3ZWNRjYLhiqbsdeHvm4CX/W0EWd9yZlbaej87XyeUbX+mC3q3yMFVPCRn/W65WYyBPbWTWmSfU9VLKKULAH6WqjS7CqEU3cQSuKcU6nYG4AJu2/FkQJaA82tr3pvcQD28HmOlDeNh0Q==</X509Certificate></X509Data></KeyInfo></Signature></r:issuer></r:license></msrel:RelData></KeyInfo></Signature></asmv1:assembly> <publisherIdentity name="CN=DESKTOP-Q6H7B6L\Administrator" issuerKeyHash="42606c52715d5764c2f9dab5bee6dcd76cc7a67d" /><Signature Id="StrongNameSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>ZOkNjAKYNyMSBNhvZ8gVr+wBPStzS85tNEApEJeuU10=</DigestValue></Reference></SignedInfo><SignatureValue>m54F1LbgqoSzKzsz7VyEaU5L5VPSErBFaVB+4TDGDHYawHVbgmm+xC3AcJZeVCYlrEobHTKRQrug9hgt0u3q6pK+tYcye6oXQEkxZPWvSR+HCMd642w1HnEXe0OYgQrgr3BCfGgCbbqjGgSCyI3JsakstMSgAudffFmbmK9rbLI=</SignatureValue><KeyInfo Id="StrongNameKeyInfo"><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><msrel:RelData xmlns:msrel="http://schemas.microsoft.com/windows/rel/2005/reldata"><r:license xmlns:r="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:as="http://schemas.microsoft.com/windows/pki/2005/Authenticode"><r:grant><as:ManifestInformation Hash="5d53ae97102940346dce4b732b3d01ecaf15c8676fd80412233798028c0de964" Description="" Url=""><as:assemblyIdentity name="WordAddIn.dll" version="1.0.0.5" publicKeyToken="06a92c46db516926" language="neutral" processorArchitecture="msil" type="win32" /></as:ManifestInformation><as:SignedBy /><as:AuthenticodePublisher><as:X509SubjectName>CN=DESKTOP-Q6H7B6L\Administrator</as:X509SubjectName></as:AuthenticodePublisher></r:grant><r:issuer><Signature Id="AuthenticodeSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>t0BRfVoNqhoaPOc2UKbHbTHoevSy5xe2FpaMu7/cbao=</DigestValue></Reference></SignedInfo><SignatureValue>yhN59Dtne4w1PdCUP45PNv5AM8RCDXSK1L/BP2VtKtHrZuR58L+mJcST1vBX4HkDilbegq8WX2Ox7Hf+kqLSuS6LMP4teKrzuzF9ROH0TFnLKUOPuWrJjtBoZAmInun8Vfqxq2fCpOCDd/wRrDqRjm2YQHn/qHwHQkXNzlzfjuA=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIICDTCCAXagAwIBAgIQJpSlsxfGbpRNgyjD5Q/yDjANBgkqhkiG9w0BAQsFADBFMUMwQQYDVQQDHjoARABFAFMASwBUAE8AUAAtAFEANgBIADcAQgA2AEwAXABBAGQAbQBpAG4AaQBzAHQAcgBhAHQAbwByMB4XDTI2MDEyNDAwMzYxNVoXDTI3MDEyNDA2MzYxNVowRTFDMEEGA1UEAx46AEQARQBTAEsAVABPAFAALQBRADYASAA3AEIANgBMAFwAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaECAwEAATANBgkqhkiG9w0BAQsFAAOBgQC3GjWMhEFFrn9PGYrQVGNAaibG1sR/eRX3ZWNRjYLhiqbsdeHvm4CX/W0EWd9yZlbaej87XyeUbX+mC3q3yMFVPCRn/W65WYyBPbWTWmSfU9VLKKULAH6WqjS7CqEU3cQSuKcU6nYG4AJu2/FkQJaA82tr3pvcQD28HmOlDeNh0Q==</X509Certificate></X509Data></KeyInfo></Signature></r:issuer></r:license></msrel:RelData></KeyInfo></Signature></asmv1:assembly>

View File

@@ -14,8 +14,8 @@
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" /> <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms> </dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /> <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
<dsig:DigestValue>obQbc7h6zkA0TnoIduOuBc41vNKQMHpPh/AfJA2YISk=</dsig:DigestValue> <dsig:DigestValue>9reCGw0n5BNGpv4nRAlMEl+9KA74gqf2Bi31YDIuVSE=</dsig:DigestValue>
</hash> </hash>
</dependentAssembly> </dependentAssembly>
</dependency> </dependency>
<publisherIdentity name="CN=DESKTOP-Q6H7B6L\Administrator" issuerKeyHash="42606c52715d5764c2f9dab5bee6dcd76cc7a67d" /><Signature Id="StrongNameSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>ZwzyY1yEsVCU4BhxJzLlO8ZQHNeXqVPqlmSJisLn3tY=</DigestValue></Reference></SignedInfo><SignatureValue>crILPNEfy0A7RZ296BpImLzFIcUZ0g/jODUjoCsDq5DmdI/7irDKROQteazqexi045TvacD9fYe6amgHBgdxM4ET4/rIoivBaRBjMdzsUKvowukrNf9VhMJC3RpRd8HWkugN8+7/JfKjXTsCdZyVXNNOzKr0eYJeuYe3ghBj33E=</SignatureValue><KeyInfo Id="StrongNameKeyInfo"><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><msrel:RelData xmlns:msrel="http://schemas.microsoft.com/windows/rel/2005/reldata"><r:license xmlns:r="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:as="http://schemas.microsoft.com/windows/pki/2005/Authenticode"><r:grant><as:ManifestInformation Hash="d6dee7c28a896496ea53a997d71c50c63be532277118e09450b1845c63f20c67" Description="" Url=""><as:assemblyIdentity name="WordAddIn.vsto" version="1.0.0.5" publicKeyToken="06a92c46db516926" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" /></as:ManifestInformation><as:SignedBy /><as:AuthenticodePublisher><as:X509SubjectName>CN=DESKTOP-Q6H7B6L\Administrator</as:X509SubjectName></as:AuthenticodePublisher></r:grant><r:issuer><Signature Id="AuthenticodeSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>2aT8MYvx/mBGrPRVOvz9piTveMU6NJjxI8LltLyjLWw=</DigestValue></Reference></SignedInfo><SignatureValue>hqq7e3z1TzCr+rHGXu1pVw078sk9+Ur7YDZf2YI3Pw1Y5+78F0ize4FhdGdcVjmBmq7f0/5qrA3jqbCcf0hUwd+4AiQSlEeAV50B9SlrvcoRwVjXl6CjkSnKyUEOChNJgA7rgr931hNUXsdIUQ6vtEqdHMLf4WT1bSDiqqvfxYI=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIICDTCCAXagAwIBAgIQJpSlsxfGbpRNgyjD5Q/yDjANBgkqhkiG9w0BAQsFADBFMUMwQQYDVQQDHjoARABFAFMASwBUAE8AUAAtAFEANgBIADcAQgA2AEwAXABBAGQAbQBpAG4AaQBzAHQAcgBhAHQAbwByMB4XDTI2MDEyNDAwMzYxNVoXDTI3MDEyNDA2MzYxNVowRTFDMEEGA1UEAx46AEQARQBTAEsAVABPAFAALQBRADYASAA3AEIANgBMAFwAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaECAwEAATANBgkqhkiG9w0BAQsFAAOBgQC3GjWMhEFFrn9PGYrQVGNAaibG1sR/eRX3ZWNRjYLhiqbsdeHvm4CX/W0EWd9yZlbaej87XyeUbX+mC3q3yMFVPCRn/W65WYyBPbWTWmSfU9VLKKULAH6WqjS7CqEU3cQSuKcU6nYG4AJu2/FkQJaA82tr3pvcQD28HmOlDeNh0Q==</X509Certificate></X509Data></KeyInfo></Signature></r:issuer></r:license></msrel:RelData></KeyInfo></Signature></asmv1:assembly> <publisherIdentity name="CN=DESKTOP-Q6H7B6L\Administrator" issuerKeyHash="42606c52715d5764c2f9dab5bee6dcd76cc7a67d" /><Signature Id="StrongNameSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>SUC6Yjv6NvxmVHgsXQGLba0wVDBY01J0NUXy81ARtjM=</DigestValue></Reference></SignedInfo><SignatureValue>rJF3Cswyo7dSJZ0ZBkoYjEc/BDekJOQ+kDoxvMOf7UWBYec+2EOUBXb+XZwVF7uVLXOJsDTJncnHBf9hcrcwnq8fF7HWuDw9lOMkzvDs5kPvkp9aTIFvPuu8BotBAYV3sn1jHnrtOAf2mkmD/1LU2hyhiH5ymyyI0w17Rwi+f0k=</SignatureValue><KeyInfo Id="StrongNameKeyInfo"><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><msrel:RelData xmlns:msrel="http://schemas.microsoft.com/windows/rel/2005/reldata"><r:license xmlns:r="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:as="http://schemas.microsoft.com/windows/pki/2005/Authenticode"><r:grant><as:ManifestInformation Hash="33b61150f3f245357452d358305430ad6d8b015d2c785466fc36fa3b62ba4049" Description="" Url=""><as:assemblyIdentity name="WordAddIn.vsto" version="1.0.0.5" publicKeyToken="06a92c46db516926" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" /></as:ManifestInformation><as:SignedBy /><as:AuthenticodePublisher><as:X509SubjectName>CN=DESKTOP-Q6H7B6L\Administrator</as:X509SubjectName></as:AuthenticodePublisher></r:grant><r:issuer><Signature Id="AuthenticodeSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>BmlXdT7EP/tEd4mBeMHh2OJ8nURtQ9BfdX3rIi01DPA=</DigestValue></Reference></SignedInfo><SignatureValue>eRIoPFOTfeko5ygKR1m63sb+yJ8qFp9CZniS9T8sMW1WmMAZozZJXiMH+bYIHO1P6Z+47rJHoSfmvUSESLpHIzk0s+WYSd/w4NK/aGE+vIwFA/SeHCWeqfhqC65ZjS0hVbQJ7ScoJfiBTLjNBEPmD/tQhQM/m8/jLv6cRZ8ToQA=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIICDTCCAXagAwIBAgIQJpSlsxfGbpRNgyjD5Q/yDjANBgkqhkiG9w0BAQsFADBFMUMwQQYDVQQDHjoARABFAFMASwBUAE8AUAAtAFEANgBIADcAQgA2AEwAXABBAGQAbQBpAG4AaQBzAHQAcgBhAHQAbwByMB4XDTI2MDEyNDAwMzYxNVoXDTI3MDEyNDA2MzYxNVowRTFDMEEGA1UEAx46AEQARQBTAEsAVABPAFAALQBRADYASAA3AEIANgBMAFwAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA23ghUI75yy8GcLhPT5yA+v2ssRfSW+chNqMI+pq5OAr7RXQJOt/+bHdoT9NoS9GQkvblc7ekoUNShIcN601ZZOPgAxkXaQS+La14Wp8GOwnM1qHNJwgla4VAIYjmCj3CUMXLsxspOFVZKRnB6/idYku4Gzhc7NjRBAwe8qWBXaECAwEAATANBgkqhkiG9w0BAQsFAAOBgQC3GjWMhEFFrn9PGYrQVGNAaibG1sR/eRX3ZWNRjYLhiqbsdeHvm4CX/W0EWd9yZlbaej87XyeUbX+mC3q3yMFVPCRn/W65WYyBPbWTWmSfU9VLKKULAH6WqjS7CqEU3cQSuKcU6nYG4AJu2/FkQJaA82tr3pvcQD28HmOlDeNh0Q==</X509Certificate></X509Data></KeyInfo></Signature></r:issuer></r:license></msrel:RelData></KeyInfo></Signature></asmv1:assembly>

View File

@@ -12,3 +12,17 @@ D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.CoreCompi
D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.Up2Date D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.Up2Date
D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.dll D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.dll
D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.pdb D:\dsWork\aiData\addOne\WordAddIn\WordAddIn\obj\Debug\WordAddIn.pdb
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\WordAddIn.dll
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\WordAddIn.pdb
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\WordAddIn.dll.manifest
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\WordAddIn.vsto
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\Microsoft.Office.Tools.Common.v4.0.Utilities.dll
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\Newtonsoft.Json.dll
d:\dsWork\aiData\WordAddIn\WordAddIn\bin\Debug\Newtonsoft.Json.xml
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.AssemblyReference.cache
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.Properties.Resources.resources
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.GenerateResource.cache
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.CoreCompileInputs.cache
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.csproj.Up2Date
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.dll
d:\dsWork\aiData\WordAddIn\WordAddIn\obj\Debug\WordAddIn.pdb

View File

@@ -1 +1 @@
e154ea9669b13c0b299747f4b6bfc75e5ab40e13fd7d98491977bb58e397c4dc a8dbfbd53c9d2d6a82eb262741605b35dd6e229dda7031b84eeac3678ff78031

View File

@@ -121,6 +121,102 @@ namespace WpsInstaller
Pause(); Pause();
} }
static void UninstallOldVersions()
{
Console.WriteLine("Checking for existing versions to uninstall...");
// 1. Cleanup VSTO Keys
CleanupVstoKeys();
// 2. Cleanup WPS Keys
CleanupWpsKeys();
// 3. Cleanup COM Registration (WPS)
UnregisterCom("{D8E52004-9D68-4509-8A11-66774D4F0523}", "WordAddIn.WpsAddIn");
}
static void UnregisterCom(string guid, string progId)
{
try
{
// Try to find CodeBase from HKCR\CLSID\{GUID}\InprocServer32
string clsidKeyPath = @"CLSID\" + guid;
string inprocKeyPath = clsidKeyPath + @"\InprocServer32";
string oldDllPath = null;
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(inprocKeyPath))
{
if (key != null)
{
oldDllPath = key.GetValue("CodeBase") as string;
if (string.IsNullOrEmpty(oldDllPath))
{
oldDllPath = key.GetValue("") as string; // Default value
}
}
}
if (!string.IsNullOrEmpty(oldDllPath))
{
// Fix file:/// prefix if present
if (oldDllPath.StartsWith("file:///", StringComparison.OrdinalIgnoreCase))
{
oldDllPath = oldDllPath.Substring(8).Replace('/', '\\');
}
if (File.Exists(oldDllPath))
{
Console.WriteLine(" Found old COM registration pointing to: " + oldDllPath);
Console.WriteLine(" Unregistering assembly...");
string regAsmPath = GetRegAsmPath();
if (!string.IsNullOrEmpty(regAsmPath))
{
string args = string.Format("\"{0}\" /u /tlb", oldDllPath);
ProcessStartInfo psi = new ProcessStartInfo(regAsmPath, args);
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
using (Process p = Process.Start(psi))
{
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
// Console.WriteLine(output); // Optional: show output
}
Console.WriteLine(" [OK] RegAsm /u completed.");
}
}
else
{
Console.WriteLine(" Old COM DLL not found at: " + oldDllPath + ". Skipping RegAsm /u.");
}
}
// Force delete registry keys to be sure
try
{
Registry.ClassesRoot.DeleteSubKeyTree(clsidKeyPath, false);
Console.WriteLine(" [OK] Deleted HKCR\\" + clsidKeyPath);
}
catch {}
try
{
if (!string.IsNullOrEmpty(progId))
{
Registry.ClassesRoot.DeleteSubKeyTree(progId, false);
Console.WriteLine(" [OK] Deleted HKCR\\" + progId);
}
}
catch {}
}
catch (Exception ex)
{
Console.WriteLine(" Warning during COM unregistration: " + ex.Message);
}
}
static void Pause() static void Pause()
{ {
Console.WriteLine("\nPress any key to exit..."); Console.WriteLine("\nPress any key to exit...");

View File

@@ -1,6 +1,5 @@
D:\dsWork\aiData\WordAddIn\WpsInstaller\bin\Debug\WpsInstaller.exe D:\dsWork\aiData\WordAddIn\WpsInstaller\bin\Debug\WpsInstaller.exe
D:\dsWork\aiData\WordAddIn\WpsInstaller\bin\Debug\WpsInstaller.pdb D:\dsWork\aiData\WordAddIn\WpsInstaller\bin\Debug\WpsInstaller.pdb
D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.csproj.AssemblyReference.cache
D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.csproj.CoreCompileInputs.cache
D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.exe D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.exe
D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.pdb D:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.pdb
d:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.csprojResolveAssemblyReference.cache