为什么Application.Selection.Range.Start有时返回错误的值

本文关键字:返回 错误 Application Selection Range Start 为什么 | 更新日期: 2023-09-27 18:26:08

情境上下文-MS Word插件
语言-C#
问题:

我正在尝试获取当前光标位置。我使用Application.Selection.Range,因为它返回InsertionPoint。每次按下Space,TabEnter键后,我会执行以下操作: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);
        }

为什么Application.Selection.Range.Start有时返回错误的值

在有人按下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.StartSelection.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;