Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way I can integrate the MS Office Smooth Typing in a C# application?

In my opinion the MS Office Smooth Typing is a very innovative feature in the Office Suite, and I'd like to know if this feature is available for programmers in the .NET Framework, specifically in the C# language.

If so, could you please post in your answer a usage example and link to the documentation?

Thanks.

By "smooth typing" I'm referring to the typing animation, that makes the cursor slide during typing.

like image 264
Zignd Avatar asked Mar 10 '13 20:03

Zignd


2 Answers

I don't own Office, so I can't look at the feature, but I needed to fiddle around with the caret in RichTextBoxes a while ago and decided that it wasn't worth the effort. Basically you are on your own. No helper functions from .NET, but everything is handled by the backing Win32 control. You will have a hard time defeating what already happens under the hood. And probably ending up intercepting window messages and lots of ugly code.

So my basic advice is: Don't do it. At least for basic form controls like the TextBox or RichTextBox. You may have more luck trying to remote access an running office from within .NET, but that is a totally different can of worms.

If you really insist on going the SetCaretPos - route, here is some code to get you up and running with a basic version where you can improve upon:

// 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();
}
like image 82
Imi Avatar answered Oct 28 '22 03:10

Imi


Use SetCaretPos with your own animation timing function. Create a new thread that interpolates the caret's position based on the previous location and the new desired location.

like image 43
Dai Avatar answered Oct 28 '22 05:10

Dai