'commit'
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,8 +3,20 @@
|
||||
"WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\",
|
||||
"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}",
|
||||
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative: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\\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": [
|
||||
@@ -23,15 +35,47 @@
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "ModelDefinitions.cs",
|
||||
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs",
|
||||
"RelativeDocumentMoniker": "WordAddIn\\ModelDefinitions.cs",
|
||||
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs",
|
||||
"RelativeToolTip": "WordAddIn\\ModelDefinitions.cs",
|
||||
"ViewState": "AgIAAAkAAAAAAAAAAAAuwBIAAAAoAAAAAAAAAA==",
|
||||
"Title": "OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs",
|
||||
"RelativeDocumentMoniker": "WordAddIn\\OutlineResultForm.cs",
|
||||
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"RelativeToolTip": "WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-01-28T13:21:19.787Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2026-01-28T23:14:29.889Z",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,8 +3,20 @@
|
||||
"WorkspaceRootPath": "D:\\dsWork\\aiData\\WordAddIn\\",
|
||||
"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}",
|
||||
"RelativeMoniker": "D:0:0:{EC0A80FA-FCBD-4239-945A-627B20CCCBAA}|WordAddIn\\WordAddIn.csproj|solutionrelative: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\\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": [
|
||||
@@ -23,15 +35,47 @@
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "ModelDefinitions.cs",
|
||||
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs",
|
||||
"RelativeDocumentMoniker": "WordAddIn\\ModelDefinitions.cs",
|
||||
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\ModelDefinitions.cs",
|
||||
"RelativeToolTip": "WordAddIn\\ModelDefinitions.cs",
|
||||
"ViewState": "AgIAAAkAAAAAAAAAAAAuwBIAAAAoAAAAAAAAAA==",
|
||||
"Title": "OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"DocumentMoniker": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs",
|
||||
"RelativeDocumentMoniker": "WordAddIn\\OutlineResultForm.cs",
|
||||
"ToolTip": "D:\\dsWork\\aiData\\WordAddIn\\WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"RelativeToolTip": "WordAddIn\\OutlineResultForm.cs [\u8BBE\u8BA1]",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-01-28T13:21:19.787Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2026-01-28T23:14:29.889Z",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -34,12 +34,67 @@ namespace WordAddIn
|
||||
// 登录状态标识 (静态变量,确保在插件生命周期内保持状态)
|
||||
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 理解文档背景
|
||||
private string _documentContext = null;
|
||||
|
||||
// 存储外部参考文档内容 (通过"补充背景"功能导入),用于辅助 AI 进行写作
|
||||
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>
|
||||
@@ -98,6 +153,596 @@ namespace WordAddIn
|
||||
}
|
||||
catch {}
|
||||
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>
|
||||
@@ -722,6 +1367,25 @@ namespace WordAddIn
|
||||
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 对象)
|
||||
// 遍历所有段落,性能可能受文档长度影响,但对于一般文档可接受
|
||||
int changeCount = 0;
|
||||
@@ -737,31 +1401,14 @@ namespace WordAddIn
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
// 是标题:设置对应的 Word 内置标题样式
|
||||
Word.WdBuiltinStyle styleEnum = Word.WdBuiltinStyle.wdStyleNormal;
|
||||
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;
|
||||
|
||||
// 使用统一的样式应用方法
|
||||
ApplyStyleToParagraph(p, match.level, styleConfig);
|
||||
changeCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 6. 非标题(正文):统一设置首行缩进 2 字符
|
||||
// 让文档看起来更规范
|
||||
p.Format.CharacterUnitFirstLineIndent = 2;
|
||||
// 6. 非标题(正文):应用正文样式(包含首行缩进)
|
||||
ApplyStyleToParagraph(p, 10, styleConfig);
|
||||
indentCount++;
|
||||
}
|
||||
}
|
||||
@@ -769,7 +1416,7 @@ namespace WordAddIn
|
||||
string msg = $"格式美化完成!\n- 已调整 {changeCount} 处标题格式。";
|
||||
if (indentCount > 0)
|
||||
{
|
||||
msg += $"\n- 已对 {indentCount} 个段落应用首行缩进。";
|
||||
msg += $"\n- 已对 {indentCount} 个段落应用正文样式(首行缩进)。";
|
||||
}
|
||||
MessageBox.Show(msg);
|
||||
}
|
||||
@@ -812,41 +1459,29 @@ namespace WordAddIn
|
||||
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 中供用户预览和编辑
|
||||
string context = GetCombinedContext();
|
||||
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}";
|
||||
}
|
||||
|
||||
// 弹出选项窗体
|
||||
using (var form = new ImageOptionsForm())
|
||||
{
|
||||
// 传入源文本
|
||||
// 传入源文本 (可能是选区,也可能是空)
|
||||
form.SourceText = prompt;
|
||||
|
||||
if (form.ShowDialog() != DialogResult.OK)
|
||||
@@ -893,12 +1528,15 @@ namespace WordAddIn
|
||||
|
||||
/// <summary>
|
||||
/// 【关于】按钮点击事件处理。
|
||||
/// 显示插件版本和作者信息。
|
||||
/// 显示插件版本和作者信息,以及功能使用说明。
|
||||
/// </summary>
|
||||
/// <param name="control">触发事件的 Ribbon 控件</param>
|
||||
public void OnAboutClick(Office.IRibbonControl control)
|
||||
{
|
||||
MessageBox.Show("Version 0.2\n作者:黄海", "关于 AI 助手");
|
||||
using (var form = new AboutForm())
|
||||
{
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -986,71 +1624,14 @@ namespace WordAddIn
|
||||
p.Range.Text = item.Title.Trim() + "\r";
|
||||
|
||||
// 7. 根据层级应用对应的样式 (字体、大小、加粗、对齐)
|
||||
TextStyle ts = null;
|
||||
try
|
||||
{
|
||||
File.AppendAllText(@"C:\Users\Public\WordAddInLog.txt", $"{DateTime.Now} Processing Item: {item.Title}, Level: {item.Level}\n");
|
||||
|
||||
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;
|
||||
}
|
||||
ApplyStyleToParagraph(p, item.Level, styleConfig);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 (end <= start) return;
|
||||
@@ -1155,74 +1755,7 @@ namespace WordAddIn
|
||||
level = GuessHeadingLevel(text);
|
||||
}
|
||||
|
||||
ApplyParagraphStyle(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 { }
|
||||
}
|
||||
ApplyStyleToParagraph(p, level, styleConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,21 +2,33 @@
|
||||
<ribbon>
|
||||
<tabs>
|
||||
<tab id="tabAiAssistant" label="AI助手">
|
||||
<group id="groupUser" label="用户">
|
||||
<button id="btnLogin" label="登录" size="large" onAction="OnLoginClick" imageMso="Lock" />
|
||||
</group>
|
||||
<group id="groupContent" label="内容创作">
|
||||
<button id="btnCreateOutline" label="创建大纲" size="large" onAction="OnCreateOutlineClick" imageMso="ViewOutlineView" />
|
||||
<button id="btnOutlineSetting" label="大纲配置" size="large" onAction="OnOutlineSettingClick" imageMso="ParagraphDialog" />
|
||||
<button id="btnReadFull" label="通读全文" size="large" onAction="OnReadFullClick" imageMso="FindDialog" />
|
||||
<button id="btnSummarizeOutline" label="总结大纲" size="large" onAction="OnSummarizeOutlineClick" imageMso="GroupSmartArtQuickStyles" />
|
||||
<button id="btnImportReference" label="补充背景" size="large" onAction="OnImportReferenceClick" imageMso="ImportTextFile" />
|
||||
<button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" imageMso="ReviewCompareTwoVersions" />
|
||||
<button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" imageMso="Spelling" />
|
||||
<button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" imageMso="SmartArtInsert" />
|
||||
<button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" />
|
||||
<button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" imageMso="PictureInsertFromFile" />
|
||||
<button id="btnCreateOutline" label="创建大纲" size="large" onAction="OnCreateOutlineClick" getEnabled="GetControlEnabled" imageMso="ViewOutlineView" />
|
||||
<button id="btnReadFull" label="通读全文" size="large" onAction="OnReadFullClick" getEnabled="GetControlEnabled" imageMso="FindDialog" />
|
||||
<button id="btnSummarizeOutline" label="总结大纲" size="large" onAction="OnSummarizeOutlineClick" getEnabled="GetControlEnabled" imageMso="GroupSmartArtQuickStyles" />
|
||||
<button id="btnImportReference" label="补充背景" size="large" onAction="OnImportReferenceClick" getEnabled="GetControlEnabled" imageMso="ImportTextFile" />
|
||||
<button id="btnReferenceGenerate" label="素材写作" size="large" onAction="OnReferenceGenerateClick" getEnabled="GetControlEnabled" imageMso="ReviewCompareTwoVersions" />
|
||||
<button id="btnPolish" label="润色加工" size="large" onAction="OnPolishClick" getEnabled="GetControlEnabled" imageMso="Spelling" />
|
||||
<button id="btnElevate" label="深度升华" size="large" onAction="OnElevateClick" getEnabled="GetControlEnabled" imageMso="SmartArtInsert" />
|
||||
<button id="btnFormat" label="格式美化" imageMso="FontColorCycle" size="large" onAction="OnFormatClick" getEnabled="GetControlEnabled" />
|
||||
<button id="btnImage" label="生成配图" size="large" onAction="OnImageClick" getEnabled="GetControlEnabled" 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 id="groupConfig" label="设置">
|
||||
<labelControl id="lblCurrentModel" getLabel="GetCurrentModelLabel" />
|
||||
<dropDown id="ddlModelSelect" label="模型选择" sizeString="WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" onAction="OnModelSelection" getItemCount="GetModelCount" getItemLabel="GetModelLabel" getSelectedItemIndex="GetSelectedModelIndex" imageMso="ServerConnection" />
|
||||
<labelControl id="lblCurrentModel" getLabel="GetCurrentModelLabel" getEnabled="GetControlEnabled" />
|
||||
<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" />
|
||||
</group>
|
||||
</tab>
|
||||
|
||||
@@ -56,14 +56,14 @@ namespace WordAddIn
|
||||
this.txtTopic.Multiline = true;
|
||||
this.txtTopic.Name = "txtTopic";
|
||||
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;
|
||||
//
|
||||
// btnGenerate
|
||||
//
|
||||
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.Location = new System.Drawing.Point(240, 310);
|
||||
this.btnGenerate.Location = new System.Drawing.Point(260, 310);
|
||||
this.btnGenerate.Name = "btnGenerate";
|
||||
this.btnGenerate.Size = new System.Drawing.Size(100, 35);
|
||||
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.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.Size = new System.Drawing.Size(100, 35);
|
||||
this.btnCancel.TabIndex = 3;
|
||||
@@ -86,6 +86,7 @@ namespace WordAddIn
|
||||
//
|
||||
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
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.ClientSize = new System.Drawing.Size(500, 370);
|
||||
this.MinimumSize = new System.Drawing.Size(400, 300);
|
||||
|
||||
@@ -37,11 +37,15 @@ namespace WordAddIn
|
||||
public string SelectedStyle { get; private set; }
|
||||
|
||||
private ComboBox cmbStyles;
|
||||
private RadioButton rbClipboard;
|
||||
private RadioButton rbInput;
|
||||
private TextBox txtInput;
|
||||
private TextBox txtFinalPrompt;
|
||||
private CheckBox chkOptimize;
|
||||
private Button btnOk;
|
||||
private Button btnCancel;
|
||||
private Label lblStyle;
|
||||
private Label lblSource;
|
||||
private Label lblPrompt;
|
||||
|
||||
private readonly Dictionary<string, string> _styleTemplates = new Dictionary<string, string>();
|
||||
@@ -93,17 +97,22 @@ namespace WordAddIn
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.Text = "生成配图选项 - 支持编辑提示词";
|
||||
this.Size = new Size(500, 520);
|
||||
this.MinimumSize = new Size(400, 400); // 设置最小尺寸
|
||||
this.Text = "生成配图设置";
|
||||
this.Size = new Size(500, 650);
|
||||
this.MinimumSize = new Size(400, 500);
|
||||
this.StartPosition = FormStartPosition.CenterParent;
|
||||
this.AutoScaleMode = AutoScaleMode.Dpi; // 支持 DPI 缩放
|
||||
this.FormBorderStyle = FormBorderStyle.Sizable; // 允许调整大小
|
||||
this.MaximizeBox = true; // 允许最大化
|
||||
this.AutoScaleMode = AutoScaleMode.Dpi;
|
||||
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.FormBorderStyle = FormBorderStyle.Sizable;
|
||||
this.MaximizeBox = true;
|
||||
this.MinimizeBox = true;
|
||||
|
||||
this.lblStyle = new Label();
|
||||
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.txtFinalPrompt = new TextBox();
|
||||
this.chkOptimize = new CheckBox();
|
||||
@@ -115,52 +124,81 @@ namespace WordAddIn
|
||||
// lblStyle
|
||||
this.lblStyle.AutoSize = true;
|
||||
this.lblStyle.Location = new Point(20, 20);
|
||||
this.lblStyle.Text = "图片风格:";
|
||||
this.lblStyle.Text = "1. 图片风格:";
|
||||
|
||||
// cmbStyles
|
||||
this.cmbStyles.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
this.cmbStyles.Location = new Point(20, 45);
|
||||
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;
|
||||
|
||||
// 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
|
||||
this.lblPrompt.AutoSize = true;
|
||||
this.lblPrompt.Location = new Point(20, 85);
|
||||
this.lblPrompt.Text = "提示词预览 (您可以直接修改下面的生成指令):";
|
||||
this.lblPrompt.Location = new Point(20, 255);
|
||||
this.lblPrompt.Text = "3. 最终提示词预览 (可直接修改):";
|
||||
|
||||
// txtFinalPrompt
|
||||
this.txtFinalPrompt.Location = new Point(20, 110);
|
||||
this.txtFinalPrompt.Location = new Point(20, 280);
|
||||
this.txtFinalPrompt.Multiline = true;
|
||||
this.txtFinalPrompt.ScrollBars = ScrollBars.Vertical;
|
||||
this.txtFinalPrompt.Size = new Size(440, 280);
|
||||
this.txtFinalPrompt.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; // 全向自适应
|
||||
this.txtFinalPrompt.Size = new Size(440, 220);
|
||||
this.txtFinalPrompt.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
|
||||
// chkOptimize
|
||||
this.chkOptimize.AutoSize = true;
|
||||
this.chkOptimize.Location = new Point(20, 400);
|
||||
this.chkOptimize.Size = new Size(400, 20);
|
||||
this.chkOptimize.Location = new Point(20, 520);
|
||||
this.chkOptimize.Size = new Size(400, 24);
|
||||
this.chkOptimize.Text = "使用 AI 优化提示词 (自动翻译成英文并丰富细节)";
|
||||
this.chkOptimize.Checked = true;
|
||||
this.chkOptimize.Anchor = AnchorStyles.Bottom | AnchorStyles.Left; // 底部固定
|
||||
this.chkOptimize.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
||||
|
||||
// btnOk
|
||||
this.btnOk.Text = "开始生成";
|
||||
this.btnOk.DialogResult = DialogResult.OK;
|
||||
this.btnOk.Location = new Point(280, 430);
|
||||
this.btnOk.Size = new Size(90, 30);
|
||||
this.btnOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; // 右下固定
|
||||
this.btnOk.Location = new Point(260, 560);
|
||||
this.btnOk.Size = new Size(100, 35);
|
||||
this.btnOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
this.btnOk.Click += BtnOk_Click;
|
||||
|
||||
// btnCancel
|
||||
this.btnCancel.Text = "取消";
|
||||
this.btnCancel.DialogResult = DialogResult.Cancel;
|
||||
this.btnCancel.Location = new Point(380, 430);
|
||||
this.btnCancel.Size = new Size(80, 30);
|
||||
this.btnCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; // 右下固定
|
||||
this.btnCancel.Location = new Point(380, 560);
|
||||
this.btnCancel.Size = new Size(80, 35);
|
||||
this.btnCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
|
||||
this.Controls.Add(this.lblStyle);
|
||||
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.txtFinalPrompt);
|
||||
this.Controls.Add(this.chkOptimize);
|
||||
@@ -174,16 +212,68 @@ namespace WordAddIn
|
||||
protected override void OnLoad(EventArgs 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)
|
||||
{
|
||||
// 尝试找到上次选中的或默认逻辑架构图
|
||||
int index = this.cmbStyles.FindString("逻辑架构图");
|
||||
this.cmbStyles.SelectedIndex = index >= 0 ? index : 0;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace WordAddIn
|
||||
//
|
||||
this.lblMessage.BackColor = System.Drawing.Color.Transparent;
|
||||
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.Location = new System.Drawing.Point(0, 150);
|
||||
this.lblMessage.Name = "lblMessage";
|
||||
@@ -68,7 +68,7 @@ namespace WordAddIn
|
||||
//
|
||||
this.txtProgress.BackColor = System.Drawing.Color.White;
|
||||
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.Location = new System.Drawing.Point(40, 190);
|
||||
this.txtProgress.Name = "txtProgress";
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace WordAddIn
|
||||
// lblTitle
|
||||
//
|
||||
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.Location = new System.Drawing.Point(0, 25);
|
||||
this.lblTitle.Name = "lblTitle";
|
||||
@@ -55,7 +55,7 @@ namespace WordAddIn
|
||||
// lblUser
|
||||
//
|
||||
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.Name = "lblUser";
|
||||
this.lblUser.Size = new System.Drawing.Size(63, 20);
|
||||
@@ -64,7 +64,7 @@ namespace WordAddIn
|
||||
//
|
||||
// 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.Name = "txtUsername";
|
||||
this.txtUsername.Size = new System.Drawing.Size(220, 27);
|
||||
@@ -74,7 +74,7 @@ namespace WordAddIn
|
||||
// lblPass
|
||||
//
|
||||
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.Name = "lblPass";
|
||||
this.lblPass.Size = new System.Drawing.Size(58, 20);
|
||||
@@ -83,7 +83,7 @@ namespace WordAddIn
|
||||
//
|
||||
// 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.Name = "txtPassword";
|
||||
this.txtPassword.PasswordChar = '●';
|
||||
@@ -97,7 +97,7 @@ namespace WordAddIn
|
||||
this.btnLogin.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.btnLogin.FlatAppearance.BorderSize = 0;
|
||||
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.Location = new System.Drawing.Point(110, 220);
|
||||
this.btnLogin.Name = "btnLogin";
|
||||
@@ -111,7 +111,7 @@ namespace WordAddIn
|
||||
//
|
||||
this.btnCancel.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
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.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(120, 40);
|
||||
@@ -124,6 +124,7 @@ namespace WordAddIn
|
||||
this.AcceptButton = this.btnLogin;
|
||||
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
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.CancelButton = this.btnCancel;
|
||||
this.ClientSize = new System.Drawing.Size(500, 320);
|
||||
|
||||
@@ -206,5 +206,14 @@ namespace WordAddIn.Models
|
||||
/// 2: 右对齐
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace WordAddIn
|
||||
// OutlineResultForm
|
||||
//
|
||||
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.Controls.Add(this.btnClose);
|
||||
this.Controls.Add(this.btnCopy);
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace WordAddIn
|
||||
this.AcceptButton = this.btnSave;
|
||||
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
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.ClientSize = new System.Drawing.Size(450, 360);
|
||||
this.MinimumSize = new System.Drawing.Size(350, 300);
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace WordAddIn
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tabControl.Controls.Add(this.tabFile);
|
||||
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.Name = "tabControl";
|
||||
this.tabControl.SelectedIndex = 0;
|
||||
@@ -105,7 +105,7 @@ namespace WordAddIn
|
||||
// lblFileTip
|
||||
//
|
||||
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.Name = "lblFileTip";
|
||||
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)
|
||||
| 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.Name = "txtFilePath";
|
||||
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.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.Name = "btnBrowse";
|
||||
this.btnBrowse.Size = new System.Drawing.Size(100, 35);
|
||||
@@ -152,7 +152,7 @@ namespace WordAddIn
|
||||
this.txtReferenceInput.BackColor = System.Drawing.Color.WhiteSmoke;
|
||||
this.txtReferenceInput.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
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.Name = "txtReferenceInput";
|
||||
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.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.Name = "lblWordCount";
|
||||
this.lblWordCount.Size = new System.Drawing.Size(117, 22);
|
||||
@@ -173,7 +173,7 @@ namespace WordAddIn
|
||||
// numWordCount
|
||||
//
|
||||
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[] {
|
||||
100,
|
||||
0,
|
||||
@@ -246,6 +246,7 @@ namespace WordAddIn
|
||||
this.AcceptButton = this.btnGenerate;
|
||||
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
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.CancelButton = this.btnCancel;
|
||||
this.ClientSize = new System.Drawing.Size(650, 520);
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace WordAddIn
|
||||
private NumericUpDown numSize;
|
||||
private CheckBox chkBold;
|
||||
private ComboBox cmbAlign;
|
||||
private Button btnColor; // 颜色选择按钮
|
||||
private Panel pnlColorPreview; // 颜色预览面板
|
||||
private int _selectedColor = 0; // 存储选中的颜色值 (Word WdColor)
|
||||
|
||||
private bool _showAlign;
|
||||
|
||||
/// <summary>
|
||||
@@ -70,6 +74,17 @@ namespace WordAddIn
|
||||
this.Controls.Add(numSize);
|
||||
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)
|
||||
{
|
||||
@@ -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>
|
||||
/// 将 TextStyle 对象应用到界面控件。
|
||||
/// </summary>
|
||||
@@ -99,6 +143,17 @@ namespace WordAddIn
|
||||
numSize.Value = (decimal)style.FontSize;
|
||||
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 (style.Alignment >= 0 && style.Alignment < cmbAlign.Items.Count)
|
||||
@@ -116,6 +171,8 @@ namespace WordAddIn
|
||||
style.FontName = cmbFont.Text;
|
||||
style.FontSize = (float)numSize.Value;
|
||||
style.IsBold = chkBold.Checked;
|
||||
style.Color = _selectedColor;
|
||||
|
||||
if (_showAlign && cmbAlign != null)
|
||||
{
|
||||
style.Alignment = cmbAlign.SelectedIndex;
|
||||
|
||||
@@ -288,6 +288,9 @@
|
||||
<Compile Include="StyleEditorControl.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AboutForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="AiRibbon.xml" />
|
||||
<None Include="ThisAddIn.Designer.xml">
|
||||
<DependentUpon>ThisAddIn.cs</DependentUpon>
|
||||
|
||||
Binary file not shown.
@@ -166,14 +166,14 @@
|
||||
</dependentAssembly>
|
||||
</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" />
|
||||
<hash>
|
||||
<dsig:Transforms>
|
||||
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
|
||||
</dsig:Transforms>
|
||||
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
|
||||
<dsig:DigestValue>b7Cc32gOO4NDdlCmmAwOKVKIxiGSuuKv6qdRFKUoZo8=</dsig:DigestValue>
|
||||
<dsig:DigestValue>Sv+qgHZFDhjy9IFwv7kNOHU+fY7HZYjsKfxAAPn7OKk=</dsig:DigestValue>
|
||||
</hash>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
@@ -200,4 +200,4 @@
|
||||
</vstov4:customizations>
|
||||
</vstav3:application>
|
||||
</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>
|
||||
Binary file not shown.
@@ -14,8 +14,8 @@
|
||||
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
|
||||
</dsig:Transforms>
|
||||
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
|
||||
<dsig:DigestValue>obQbc7h6zkA0TnoIduOuBc41vNKQMHpPh/AfJA2YISk=</dsig:DigestValue>
|
||||
<dsig:DigestValue>9reCGw0n5BNGpv4nRAlMEl+9KA74gqf2Bi31YDIuVSE=</dsig:DigestValue>
|
||||
</hash>
|
||||
</dependentAssembly>
|
||||
</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>
|
||||
@@ -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.dll
|
||||
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
e154ea9669b13c0b299747f4b6bfc75e5ab40e13fd7d98491977bb58e397c4dc
|
||||
a8dbfbd53c9d2d6a82eb262741605b35dd6e229dda7031b84eeac3678ff78031
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -121,6 +121,102 @@ namespace WpsInstaller
|
||||
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()
|
||||
{
|
||||
Console.WriteLine("\nPress any key to exit...");
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,5 @@
|
||||
D:\dsWork\aiData\WordAddIn\WpsInstaller\bin\Debug\WpsInstaller.exe
|
||||
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.pdb
|
||||
d:\dsWork\aiData\WordAddIn\WpsInstaller\obj\Debug\WpsInstaller.csprojResolveAssemblyReference.cache
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user