为什么Application.Selection.Range.Start有时返回错误的值
本文关键字:返回 错误 Application Selection Range Start 为什么 | 更新日期: 2023-09-27 18:26:08
情境上下文-MS Word插件
语言-C#
问题:
我正在尝试获取当前光标位置。我使用Application.Selection.Range
,因为它返回InsertionPoint
。每次按下Space,Tab
或Enter
键后,我会执行以下操作:MessageBox.Show(Application.Selection.Range.Start.ToString());
有时我会看到具有正确值的MessageBox,有时actual_value_of_insertion_point_position+128
。为什么插入点索引有时会增加到128?我没有做任何具体的事情——我只是键入一些文本,按空格键,有时会看到预期的正确值,有时则不然。
更新事实上,我的问题更深——这里是我的另一个SO问题,并有详细的描述。我的计划:
1) 当用户键入Space
记住插入点时,它会返回下一个未来字母的位置
2)如果用户键入了某个字母,并且上一个键为Space,则表示用户键入了新单词的第一个字母。将范围创建为以下Application.ActiveDocument.Range(remembered_pos,rem_pos+1)
,并根据需要设置样式。
我的代码
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int pointerCode = Marshal.ReadInt32(lParam);
string pressedKey = ((Keys)pointerCode).ToString();
IntPtr curHandle = GetForegroundWindow();
if(curHandle==wordHandle)
{
//MessageBox.Show(app.ActiveDocument.Content.LanguageID +" "+ WdLanguageID.wdKazakh);
if(pressedKey.Equals("Space")||pressedKey.Equals("Return")||pressedKey.Equals("Tab"))
{
Word.Range r = app.Application.Selection.Range;
MessageBox.Show(app.Application.Selection.Type.ToString());
MessageBox.Show("-"+r.Start.ToString()+"-"+r.End.ToString()); // sometimes +128!
}
else if(firstAfterSpace!=-1)
{ // right now doesn't make sense
MessageBox.Show(firstAfterSpace.ToString());
//Word.Range rng = app.Application.ActiveDocument.Range(firstAfterSpace,firstAfterSpace+1);
//MessageBox.Show("-"+rng.Text+"-");
//rng.Underline = Word.WdUnderline.wdUnderlineNone;
firstAfterSpace = -1;
}
}
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
在有人按下Space, Return or Tab
后,您可以尝试不同的设置范围的方法,假设您在这些"字符"之前搜索单词。
这是您可以放入If statement
:的代码
Word.Range r = appWRD.Application.Selection.Range;
Word.Range tmpR = r.Previous(Word.WdUnits.wdWord,2);
MessageBox.Show("-" + tmpR.Start.ToString() + "-" + (r.Start-1).ToString());
//set temporarily for checking word text
tmpR = appWRD.ActiveDocument.Range(tmpR.Start, r.Start -1 );
MessageBox.Show(string.Format("Word found: {0}!", tmpR.Text));
//this shows it doesn't include any tab or space
提示Word中有很多Range modification methods
,但其中一些不能正常工作。根据我的测试,Previous
在这种情况下运行良好。
我相信这是因为您使用了全局钩子事件。但我不知道原因。我刚刚试验过。当我使用全局钩子时,范围的索引似乎增加了128。
从System.Windows.Forms.Timer
访问Selection.Start
和Selection.End
时,会观察到相同的行为。
我认为原因是Word中文本缓冲区操作的优化。它不插入一个字符,而是插入一个128个字符的块,但推迟了Selection.Start
值的更新。
但幸运的是,我们总能从selection.Previous(WdUnits.wdCharacter, 1).End
中获得正确的Selection.Start
值。
因此,获得正确选择开始和结束的代码看起来是这样的:
var selection = app.Selection.Range;
var selStart = selection.Previous(WdUnits.wdCharacter, 1)?.End ?? 0;
var selEnd = selStart + selection.End - selection.Start;