【问题标题】:Is there any way I can integrate the MS Office Smooth Typing in a C# application?有什么方法可以将 MS Office Smooth Typing 集成到 C# 应用程序中?
【发布时间】:2013-02-25 23:18:46
【问题描述】:

在我看来,MS Office Smooth Typing 是 Office 套件中一项非常创新的功能,我想知道 .NET Framework 中的程序员是否可以使用此功能,特别是 C# 语言。

如果是这样,您能否在回答中发布用法示例文档链接

谢谢。

我所说的“流畅打字”是指打字动画,它使光标在打字时滑动。

【问题讨论】:

    标签: c# .net ms-office text-cursor


    【解决方案1】:

    我没有 Office,因此无法查看该功能,但我需要在不久前摆弄 RichTextBoxes 中的插入符号,并认为这不值得。基本上你是靠自己的。 .NET 没有辅助函数,但一切都由支持的 Win32 控件处理。您将很难击败已经在幕后发生的事情。并且可能最终会拦截窗口消息和大量丑陋的代码。

    所以我的基本建议是:不要这样做。至少对于像 TextBox 或 RichTextBox 这样的基本表单控件。尝试从 .NET 中远程访问正在运行的办公室可能会更幸运,但这是完全不同的蠕虫。

    如果您真的坚持使用 SetCaretPos - 路线,这里有一些代码可以帮助您启动并运行基本版本,您可以在其中改进:

    // import the functions (which are part of Win32 API - not .NET)
    [DllImport("user32.dll")] static extern bool SetCaretPos(int x, int y);
    [DllImport("user32.dll")] static extern Point GetCaretPos(out Point point);
    
    public Form1()
    {
        InitializeComponent();
    
        // target position to animate towards
        Point targetCaretPos; GetCaretPos(out targetCaretPos);
    
        // richTextBox1 is some RichTextBox that I dragged on the form in the Designer
        richTextBox1.TextChanged += (s, e) =>
            {
                // we need to capture the new position and restore to the old one
                Point temp;
                GetCaretPos(out temp);
                SetCaretPos(targetCaretPos.X, targetCaretPos.Y);
                targetCaretPos = temp;
            };
    
        // Spawn a new thread that animates toward the new target position.
        Thread t = new Thread(() => 
        {
            Point current = targetCaretPos; // current is the actual position within the current animation
            while (true)
            {
                if (current != targetCaretPos)
                {
                    // The "30" is just some number to have a boundary when not animating
                    // (e.g. when pressing enter). You can experiment with your own distances..
                    if (Math.Abs(current.X - targetCaretPos.X) + Math.Abs(current.Y - targetCaretPos.Y) > 30)
                        current = targetCaretPos; // target too far. Just move there immediately
                    else
                    {
                        current.X += Math.Sign(targetCaretPos.X - current.X);
                        current.Y += Math.Sign(targetCaretPos.Y - current.Y);
                    }
    
                    // you need to invoke SetCaretPos on the thread which created the control!
                    richTextBox1.Invoke((Action)(() => SetCaretPos(current.X, current.Y)));
                }
                // 7 is just some number I liked. The more, the slower.
                Thread.Sleep(7);
            }
        });
        t.IsBackground = true; // The animation thread won't prevent the application from exiting.
        t.Start();
    }
    

    【讨论】:

    • 非常棒的代码!正如@newStackExchangeInstance 所说,但是当您按回车键进入新行时会出现问题,光标花费的时间与走得更远所需的时间相同,您认为您可以解决这个问题,以便光标返回默认速度?我认为这会解决问题,如果是这样,我会给你赏金。
    • 谢谢。如果这是您看到的唯一问题,那很好:)。我想说还有一些其他不太好的事情,比如如果你打字太快,字母会出现在插入符号“到达”之前,等等。无论如何,我更新了代码,所以它不会为插入符号设置动画当距离太远时,它现在应该“跳”到下一行,而不是在那里缓慢移动。享受代码的乐趣;)
    • 出于好奇,是否有任何理由使用线程而不是计时器来为新目标位置设置动画?
    • "是否有任何理由使用线程而不是计时器" - 没有理由。计时器(或在 C#5 中使用是异步的)可能更容易并且使用更少的内存。线程只是我想到的第一件事。
    【解决方案2】:

    将 SetCaretPos 与您自己的动画计时函数一起使用。创建一个新线程,根据先前的位置和新的所需位置插入插入符号的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 2019-05-23
      • 2013-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多