开发者

Trying to use the C# SpellCheck class

开发者 https://www.devze.com 2023-01-21 20:44 出处:网络
I am trying to use the SpellCheck class C# provides (in PresentationFramework.dll). But, I am experiencing problems when trying to bind the spelling to my textbox:

I am trying to use the SpellCheck class C# provides (in PresentationFramework.dll). But, I am experiencing problems when trying to bind the spelling to my textbox:

SpellCheck.SetIsEnabled(txtWhatever, true);

The problem is that my txtWhatever is of type System.Windows.Forms and the parameter this function is looking for is System.Windows.Controls, and simple converting failed. I also tried to make my TextBox of this typ开发者_Go百科e, but... couldn't. Does anyone know how to use this SpellCheck object? (MSDN wasn't that helpful...)

Thanks


You have to use a WPF TextBox to make spell checking work. You can embed one in a Windows Forms form with the ElementHost control. It works pretty similar to a UserControl. Here's a control that you can drop straight from the toolbox. To get started, you need Project + Add Reference and select WindowsFormsIntegration, System.Design and the WPF assemblies PresentationCore, PresentationFramework and WindowsBase.

Add a new class to your project and paste the code shown below. Compile. Drop the SpellBox control from the top of the toolbox onto a form. It supports the TextChanged event and the Multiline and WordWrap properties. There's a nagging problem with the Font, there is no easy way to map a WF Font to the WPF font properties. The easiest workaround for that is to set the form's Font to "Segoe UI", the default for WPF.

using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Forms.Design;

[Designer(typeof(ControlDesigner))]
//[DesignerSerializer("System.Windows.Forms.Design.ControlCodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
class SpellBox : ElementHost {
    public SpellBox() {
        box = new TextBox();
        base.Child = box;
        box.TextChanged += (s, e) => OnTextChanged(EventArgs.Empty);
        box.SpellCheck.IsEnabled = true;
        box.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
        this.Size = new System.Drawing.Size(100, 20);
    }
    public override string Text {
        get { return box.Text; }
        set { box.Text = value; }
    }
    [DefaultValue(false)]
    public bool Multiline {
        get { return box.AcceptsReturn; }
        set { box.AcceptsReturn = value; }
    }
    [DefaultValue(false)]
    public bool WordWrap {
        get { return box.TextWrapping != TextWrapping.NoWrap; }
        set { box.TextWrapping = value ? TextWrapping.Wrap : TextWrapping.NoWrap; }
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new System.Windows.UIElement Child {
        get { return base.Child; }
        set { /* Do nothing to solve a problem with the serializer !! */ }
    }
    private TextBox box;
}

By popular demand, a VB.NET version of this code that avoids the lambda:

Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Forms.Integration
Imports System.Windows.Forms.Design

<Designer(GetType(ControlDesigner))> _
Class SpellBox
    Inherits ElementHost

    Public Sub New()
        box = New TextBox()
        MyBase.Child = box
        AddHandler box.TextChanged, AddressOf box_TextChanged
        box.SpellCheck.IsEnabled = True
        box.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
        Me.Size = New System.Drawing.Size(100, 20)
    End Sub

    Private Sub box_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
        OnTextChanged(EventArgs.Empty)
    End Sub

    Public Overrides Property Text() As String
        Get
            Return box.Text
        End Get
        Set(ByVal value As String)
            box.Text = value
        End Set
    End Property

    <DefaultValue(False)> _
    Public Property MultiLine() As Boolean
        Get
            Return box.AcceptsReturn
        End Get
        Set(ByVal value As Boolean)
            box.AcceptsReturn = value
        End Set
    End Property

    <DefaultValue(False)> _
    Public Property WordWrap() As Boolean
        Get
            Return box.TextWrapping <> TextWrapping.NoWrap
        End Get
        Set(ByVal value As Boolean)
            If value Then
                box.TextWrapping = TextWrapping.Wrap
            Else
                box.TextWrapping = TextWrapping.NoWrap
            End If
        End Set
    End Property

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
    Public Shadows Property Child() As System.Windows.UIElement
        Get
            Return MyBase.Child
        End Get
        Set(ByVal value As System.Windows.UIElement)
            '' Do nothing to solve a problem with the serializer !!
        End Set
    End Property
    Private box As TextBox
End Class


Have you tried just setting the property on the actual TextBox your attempting to spellcheck. e.g.

txtWhatever.SpellCheck.IsEnabled = true;


You're trying to use a spell-check component designed for WPF on a WinForms application. They're incompatible.

If you want to use the .NET-provided spell check, you'll have to use WPF as your widget system.

If you want to stick with WinForms, you'll need a third-party spell check component.


Free .NET spell checker based around a WPF text box that can be used client or server side can be seen here. It will wrap the text box for you although you still need the assembly includes to Presentation framework etc.

Full disclosure...written by yours truly


I needed to add a background colour to the textbox in winforms that reflected the colour selected in the designer:

public override System.Drawing.Color BackColor
{
    get
    {
        if (box == null) { return Color.White; }
        System.Windows.Media.Brush br = box.Background;
        byte a = ((System.Windows.Media.SolidColorBrush)(br)).Color.A;
        byte g = ((System.Windows.Media.SolidColorBrush)(br)).Color.G;
        byte r = ((System.Windows.Media.SolidColorBrush)(br)).Color.R;
        byte b = ((System.Windows.Media.SolidColorBrush)(br)).Color.B;
        return System.Drawing.Color.FromArgb((int)a, (int)r, (int)g, (int)b);
    }
    set 
    {
        box.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromArgb(value.A, value.R, value.G, value.B));
    }
}


If you want to enable the TextChanged Event write the code like this.

using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Forms.Design;

[Designer(typeof(ControlDesigner))]
//[DesignerSerializer("System.Windows.Forms.Design.ControlCodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
class SpellBox : ElementHost
{    
    public SpellBox()
    {
        box = new TextBox();
        base.Child = box;
        box.TextChanged += (s, e) => OnTextChanged(EventArgs.Empty);
        box.SpellCheck.IsEnabled = true;
        box.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
        box.TextChanged += new System.Windows.Controls.TextChangedEventHandler(SpellBox_TextChanged);
        this.Size = new System.Drawing.Size(100, 20);
    }

    [Browsable(true)]
    [Category("Action")]
    [Description("Invoked when Text Changes")]
    public new event EventHandler TextChanged;
    protected void SpellBox_TextChanged(object sender, EventArgs e)
    {        
        if (this.TextChanged!=null)
            this.TextChanged(this, e);
    }
    public override string Text
    {
        get { return box.Text; }
        set { box.Text = value; }
    }
    [DefaultValue(false)]
    public bool Multiline
    {
        get { return box.AcceptsReturn; }
        set { box.AcceptsReturn = value; }
    }
    [DefaultValue(false)]
    public bool WordWrap
    {
        get { return box.TextWrapping != TextWrapping.NoWrap; }
        set { box.TextWrapping = value ? TextWrapping.Wrap : TextWrapping.NoWrap; }
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new System.Windows.UIElement Child
    {
        get { return base.Child; }
        set { /* Do nothing to solve a problem with the serializer !! */ }
    }
    private TextBox box;
}


what about getting a list of words in the english language and copying that to a text file. add the reference. then use streamreader class to analyze the list against textbox.text. any words not found in the text file could be set to be highlighted or displayed in a dialog box with options to replace or ignore. this is a shotgun suggestion with many missing steps and i am 2 months into programming but....its what im going to attempt anyway. i am making a notepad project (rexpad on idreamincode.com). hope this helped!

0

精彩评论

暂无评论...
验证码 换一张
取 消