【问题标题】:Did Win8 add built-in spell checker for legacy apps too?Win8 是否也为旧版应用程序添加了内置拼写检查器?
【发布时间】:2014-05-18 01:27:11
【问题描述】:

根据MSDN:

在 Windows 8 中,拼写检查内置于编辑控件中。

好吧,我在我的设置中启用了该选项(突出显示和自动更正),但我在 Notepad.exe 或我自己的旧版 Win32 应用程序中没有看到此选项。

我需要做什么才能为我的应用程序启用(希望它就这么简单)?我确实尝试遵循文章中的信息并阅读了很多参考资料,但它真的不清楚,似乎是为了创建自定义提供程序/解决方案,但我会对任何“内置”行为感到满意。

【问题讨论】:

标签: windows winapi windows-8


【解决方案1】:

它仅适用于 Rich Edit 控件、EM_SETLANGOPTIONS、IMF_SPELLCHECKING 选项。您需要使用更高版本的 Rich Edit,即 MsftEdit.dll 中的那个,而不是您默认获得的更常见的 v2.0 版本。

我在 Winforms 控件中试了一下,效果很好。请注意,它不会使拼写检查具有交互性,没有类似于让您从一组建议的替代方案中进行选择的对话框。任何可以自动更正的内容,例如“teh”到“the”和“spell”到“spell”,都会立即应用,没有自动更正的单词会用红色下划线标出。 Ctrl+Z 将自动更正的单词恢复为原始单词。

从这个 C# 代码转换为其他未指定的语言应该不会有太多麻烦。存在一些样板的 Winforms 管道,关键是使用 LoadLibrary 来初始化 v5 版本的控件,以便您可以使用 RichEdit50W 窗口类名称。并使用 SendMessage() 打开选项:

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);
}

更新,当您面向 .NET 4.7 或更高版本时,您现在需要的代码要少得多。它已经处理了 CreateParams 覆盖以也使用 msftedit.dll:https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/RichTextBox.cs,d2aebb12b70acde0

【讨论】:

  • 哇,感谢您的精彩回答和好消息!我的应用程序已经有一个弹出对话框类型的拼写检查器,所以这可能是我所需要的,并且在此之前几乎不可能添加自己(以任何稍微优化的方式)。
  • 我不确定在 Windows 8 下是否仍然需要这样做,但根据this article 还需要通过执行DWORD dwSESFlags = SES_USECTF | SES_CTFALLOWEMBED | SES_CTFALLOWSMARTTAG | SES_CTFALLOWPROOFING; SendMessage(hRichEdit, EM_SETEDITSTYLE, dwSESFlags, dwSESFlags); 来启用Text Foundation Services
猜你喜欢
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 2015-02-14
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多