Did Win8 add built-in spell checker for legacy apps too?

馋奶兔 提交于 2019-12-05 20:09:09

It is built-in only for Rich Edit controls, EM_SETLANGOPTIONS, IMF_SPELLCHECKING option. You need to use the later version of Rich Edit, the one in MsftEdit.dll instead of the more common v2.0 version that you get by default.

I tried it out in a Winforms control, worked well. Do note that it doesn't make spell-checking inter-active, nothing resembling a dialog that lets you pick from a set of suggested alternatives. Anything that can be auto-corrected, like "teh" to "the" and "spelll" to "spell" is immediately applied, words that don't have an auto-correction are underlined in red. Ctrl+Z turns an auto-corrected word back into its original.

You shouldn't have to much trouble working from this C# code to your otherwise unspecified language. There's some boilerplate Winforms plumbing present, key take-aways is to use LoadLibrary to get the v5 version of the control initialized so you can use the RichEdit50W window class name. And use SendMessage() to turn the option on:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class RichTextBoxEx : RichTextBox {

    protected override CreateParams CreateParams {
        get {
            if (moduleHandle == IntPtr.Zero) {
                moduleHandle = LoadLibrary("msftedit.dll");
                if (moduleHandle == IntPtr.Zero) throw new Win32Exception("Could not load Msftedit.dll");
            }
            CreateParams createParams = base.CreateParams;
            createParams.ClassName = "RichEdit50W";
            if (this.Multiline) {
                if (((this.ScrollBars & RichTextBoxScrollBars.Horizontal) != RichTextBoxScrollBars.None) && !base.WordWrap) {
                    createParams.Style |= 0x100000;
                    if ((this.ScrollBars & ((RichTextBoxScrollBars)0x10)) != RichTextBoxScrollBars.None) {
                        createParams.Style |= 0x2000;
                    }
                }
                if ((this.ScrollBars & RichTextBoxScrollBars.Vertical) != RichTextBoxScrollBars.None) {
                    createParams.Style |= 0x200000;
                    if ((this.ScrollBars & ((RichTextBoxScrollBars)0x10)) != RichTextBoxScrollBars.None) {
                        createParams.Style |= 0x2000;
                    }
                }
            }
            if ((BorderStyle.FixedSingle == base.BorderStyle) && ((createParams.Style & 0x800000) != 0)) {
                createParams.Style &= -8388609;
                createParams.ExStyle |= 0x200;
            }
            return createParams;
        }
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        if (Environment.OSVersion.Version.Major > 6 ||
            Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2) {
            int opts = (int)SendMessage(this.Handle, EM_GETLANGOPTIONS, IntPtr.Zero, IntPtr.Zero);
            opts |= IMF_SPELLCHECKING;
            SendMessage(this.Handle, EM_SETLANGOPTIONS, IntPtr.Zero, new IntPtr(opts));
        }
    }

    private static IntPtr moduleHandle;

    private const int IMF_SPELLCHECKING = 0x0800;
    private const int EM_SETLANGOPTIONS = 0x0400 + 120;
    private const int EM_GETLANGOPTIONS = 0x0400 + 121;

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr LoadLibrary(string lpFileName);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}

UPDATE, you need a lot less of this code today when you target .NET 4.7 or higher. It already takes care of the CreateParams override to also use msftedit.dll: https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/RichTextBox.cs,d2aebb12b70acde0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!