I found this , but unfortunately there is no Russian ...
Interested in free solutions.
It seems to somehow take advantage of the MS Office API and get results, but the interop is braking.
I found this , but unfortunately there is no Russian ...
Interested in free solutions.
It seems to somehow take advantage of the MS Office API and get results, but the interop is braking.
You can use the standard Spell Checking API . Spelling dictionaries are installed with the language pack, so if you have Russian-language Windows, the Russian language will be supported.
Declare the required interfaces:
using System.Runtime.InteropServices; namespace ConsoleApplication1 { public class SpellCheckAPI { public enum WORDLIST_TYPE { WORDLIST_TYPE_IGNORE, WORDLIST_TYPE_ADD, WORDLIST_TYPE_EXCLUDE, WORDLIST_TYPE_AUTOCORRECT, } public enum CORRECTIVE_ACTION { CORRECTIVE_ACTION_NONE, CORRECTIVE_ACTION_GET_SUGGESTIONS, CORRECTIVE_ACTION_REPLACE, CORRECTIVE_ACTION_DELETE, } [Guid("B7C82D61-FBE8-4B47-9B27-6C0D2E0DE0A3")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport] public interface ISpellingError { uint StartIndex { get; } uint Length { get; } SpellCheckAPI.CORRECTIVE_ACTION CorrectiveAction { get; } string Replacement { [return: MarshalAs(UnmanagedType.LPWStr)] get; } } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("803E3BD4-2828-4410-8290-418D1D73C762")] [ComImport] public interface IEnumSpellingError { [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.ISpellingError Next(); } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("00000101-0000-0000-C000-000000000046")] [ComImport] public interface IEnumString { void Next([In] uint celt, [MarshalAs(UnmanagedType.LPWStr)] out string rgelt, out uint pceltFetched); void Skip([In] uint celt); void Reset(); void Clone([MarshalAs(UnmanagedType.Interface)] out SpellCheckAPI.IEnumString ppenum); } [Guid("432E5F85-35CF-4606-A801-6F70277E1D7A")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport] public interface IOptionDescription { string Id { [return: MarshalAs(UnmanagedType.LPWStr)] get; } string Heading { [return: MarshalAs(UnmanagedType.LPWStr)] get; } string Description { [return: MarshalAs(UnmanagedType.LPWStr)] get; } SpellCheckAPI.IEnumString Labels { [return: MarshalAs(UnmanagedType.Interface)] get; } } [Guid("0B83A5B0-792F-4EAB-9799-ACF52C5ED08A")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport] public interface ISpellCheckerChangedEventHandler { void Invoke([MarshalAs(UnmanagedType.Interface), In] SpellCheckAPI.ISpellChecker sender); } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("B6FD0B71-E2BC-4653-8D05-F197E412770B")] [ComImport] public interface ISpellChecker { string languageTag { [return: MarshalAs(UnmanagedType.LPWStr)] get; } [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.IEnumSpellingError Check([MarshalAs(UnmanagedType.LPWStr), In] string text); [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.IEnumString Suggest([MarshalAs(UnmanagedType.LPWStr), In] string word); void Add([MarshalAs(UnmanagedType.LPWStr), In] string word); void Ignore([MarshalAs(UnmanagedType.LPWStr), In] string word); void AutoCorrect([MarshalAs(UnmanagedType.LPWStr), In] string from, [MarshalAs(UnmanagedType.LPWStr), In] string to); byte GetOptionValue([MarshalAs(UnmanagedType.LPWStr), In] string optionId); SpellCheckAPI.IEnumString OptionIds { [return: MarshalAs(UnmanagedType.Interface)] get; } string Id { [return: MarshalAs(UnmanagedType.LPWStr)] get; } string LocalizedName { [return: MarshalAs(UnmanagedType.LPWStr)] get; } uint add_SpellCheckerChanged([MarshalAs(UnmanagedType.Interface), In] SpellCheckAPI.ISpellCheckerChangedEventHandler handler); void remove_SpellCheckerChanged([In] uint eventCookie); [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.IOptionDescription GetOptionDescription([MarshalAs(UnmanagedType.LPWStr), In] string optionId); [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.IEnumSpellingError ComprehensiveCheck([MarshalAs(UnmanagedType.LPWStr), In] string text); } [Guid("8E018A9D-2415-4677-BF08-794EA61F94BB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport] public interface ISpellCheckerFactory { SpellCheckAPI.IEnumString SupportedLanguages { [return: MarshalAs(UnmanagedType.Interface)] get; } int IsSupported([MarshalAs(UnmanagedType.LPWStr), In] string languageTag); [return: MarshalAs(UnmanagedType.Interface)] SpellCheckAPI.ISpellChecker CreateSpellChecker([MarshalAs(UnmanagedType.LPWStr), In] string languageTag); } [Guid("AA176B85-0E12-4844-8E1A-EEF1DA77F586")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport] public interface IUserDictionariesRegistrar { void RegisterUserDictionary([MarshalAs(UnmanagedType.LPWStr), In] string dictionaryPath, [MarshalAs(UnmanagedType.LPWStr), In] string languageTag); void UnregisterUserDictionary([MarshalAs(UnmanagedType.LPWStr), In] string dictionaryPath, [MarshalAs(UnmanagedType.LPWStr), In] string languageTag); } [Guid("7AB36653-1796-484B-BDFA-E74F1DB7C1DC")] [ComImport] public class SpellCheckerFactoryClass { } } } Then the method for checking spelling can be implemented as follows:
public static string SpellCheck(string s) { SpellCheckAPI.SpellCheckerFactoryClass factory = null; SpellCheckAPI.ISpellCheckerFactory ifactory = null; SpellCheckAPI.ISpellChecker checker = null; SpellCheckAPI.ISpellingError error = null; SpellCheckAPI.IEnumSpellingError errors = null; SpellCheckAPI.IEnumString suggestions = null; StringBuilder sb = new StringBuilder(s.Length * 10); try { factory = new SpellCheckAPI.SpellCheckerFactoryClass(); ifactory = (SpellCheckAPI.ISpellCheckerFactory)factory; //ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΡΡΡΠΊΠΎΠ³ΠΎ ΡΠ·ΡΠΊΠ° int res = ifactory.IsSupported("ru-RU"); if (res == 0) { throw new Exception("Fatal error: russian language not supported!"); } checker = ifactory.CreateSpellChecker("ru-RU"); errors = checker.Check(s); while (true) { if (error != null) { Marshal.ReleaseComObject(error); error = null; } error = errors.Next(); if (error == null) break; //ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠ»ΠΎΠ²ΠΎ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ string word = s.Substring((int)error.StartIndex, (int)error.Length); sb.AppendLine("ΠΡΠΈΠ±ΠΊΠ° Π² ΡΠ»ΠΎΠ²Π΅: " + word); //ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ switch (error.CorrectiveAction) { case SpellCheckAPI.CORRECTIVE_ACTION.CORRECTIVE_ACTION_DELETE: sb.AppendLine("Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅: ΡΠ΄Π°Π»ΠΈΡΡ"); break; case SpellCheckAPI.CORRECTIVE_ACTION.CORRECTIVE_ACTION_REPLACE: sb.AppendLine("Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅: Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π½Π° " + error.Replacement); break; case SpellCheckAPI.CORRECTIVE_ACTION.CORRECTIVE_ACTION_GET_SUGGESTIONS: sb.AppendLine("Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅: Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π½Π° ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΠ»ΠΎΠ²"); if (suggestions != null) { Marshal.ReleaseComObject(suggestions); suggestions = null; } //ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠΏΠΈΡΠΎΠΊ ΡΠ»ΠΎΠ², ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½Π½ΡΡ
Π΄Π»Ρ Π·Π°ΠΌΠ΅Π½Ρ suggestions = checker.Suggest(word); sb.Append("[ "); while (true) { string suggestion; uint count = 0; suggestions.Next(1, out suggestion, out count); if (count == 1) sb.Append(suggestion + " "); else break; } sb.Append("] "); sb.AppendLine(); break; } sb.AppendLine(); } } finally { if (suggestions != null) { Marshal.ReleaseComObject(suggestions); } if (factory != null) { Marshal.ReleaseComObject(factory); } if (ifactory != null) { Marshal.ReleaseComObject(ifactory); } if (checker != null) { Marshal.ReleaseComObject(checker); } if (error != null) { Marshal.ReleaseComObject(error); } if (errors != null) { Marshal.ReleaseComObject(errors); } } return sb.ToString(); } You can use TextFox from WPF, tests showed that it works fine in a non-WPF project without the need to create a message loop and add it to the window. You just need to add links to PresentationCore, PresentationFramework, WindowsBase and System.Xaml, as well as mark the stream STAThread. Russian is not supported out of the box, so you will have to download a dictionary, for example, here , and add it as non-standard. It is advisable to transcode the dictionary file to UTF-16 LE with BOM (this encoding is marked as "Unicode" in a notebook), since dictionaries in other encodings seem to be processed incorrectly.
Example:
using System.Windows.Controls; //... public static string SpellCheckWPF(string s) { StringBuilder sb = new StringBuilder(s.Length * 10); TextBox textbox = new TextBox(); textbox.Text = s; textbox.Language = System.Windows.Markup.XmlLanguage.GetLanguage("en-US"); textbox.SpellCheck.IsEnabled = true; //Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π½Π΅ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΡΠ»ΠΎΠ²Π°ΡΡ ΠΈΠ· ΡΠ°ΠΉΠ»Π° textbox.SpellCheck.CustomDictionaries.Add(new Uri(@"ru-RU.dic", UriKind.Relative)); int index = 0; while (true) { //Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌ ΠΎΡΠΈΠ±ΠΊΡ index = textbox.GetNextSpellingErrorCharacterIndex(index, System.Windows.Documents.LogicalDirection.Forward); if (index > s.Length || index < 0) break; var error = textbox.GetSpellingError(index); int len = textbox.GetSpellingErrorLength(index); string word = textbox.Text.Substring(index, len); sb.AppendFormat("ΠΡΠΈΠ±ΠΊΠ° Π² ΡΠ»ΠΎΠ²Π΅ {0}, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π½Π° ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΠ»ΠΎΠ²: ", word); //Π²ΡΠ²ΠΎΠ΄ΠΈΠΌ ΡΠΏΠΈΡΠΎΠΊ ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅ΠΌΡΡ
Π·Π°ΠΌΠ΅Π½ foreach (string x in error.Suggestions) { sb.Append(x + "; "); } sb.AppendLine(); //ΠΏΠ΅ΡΠ΅Ρ
ΠΎΠ΄ ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ ΡΠ»ΠΎΠ²Ρ index += len; } return sb.ToString(); } Since loading a large dictionary takes significant time, you need to create one TextBox, load the dictionary into it once when you start the application and use it in the following code (and not load the dictionary every time you need to check something).
This code will not work in Windows 8.1+ and .NET 4.6.1+, since in these versions WPF also uses the standard API described above. The mechanism for loading dictionaries has changed a lot due to this, and large dictionaries are not supported. In order for everything to work properly in this case, you need to remove the non-standard dictionary and install the Russian language in TextBox, not English.
Using the C ++ Spell Checking API
Spelling checker not supported in the .NET 4.6.1 in some conditions
Source: https://ru.stackoverflow.com/questions/891355/
All Articles