Если бы microsoft не была такой ленивой...
Как-то в предыдущих статьях я уже упоминал о прекрасной (и полезной!) возможности операционной системе линукс, суть которой заключается в том, что можно окну любого приложения придать статус "Поверх всех". Казалось бы мелочь, но в реальной жизни очень удобно. И очень жаль, что в Windows такой возможности нет. Даже подумываю утилитку написать, которая будет это реализовывать.
Сегодня возникла еще одна идея, реализовав которую, microsoft смогла бы заработать нехилую благодарность, как от пользователей, так и от программистов. Особенно от программистов.
Дело в том, что рано или поздно перед разработчиками прикладных программ встает проблема проверки этого самого правописания в вводимом пользователями тексте. Вот и я тоже наступил на эти грабли.
Искать сторонние компоненты, проверяющие синтаксис по своим словарям я не стал, т.к. подобные библиотеки-модули как правило платные и разработаны где-нить на западе. Да и сами алгоритмы проверки, которые отлично справляются с английским языком, при переходе на великий-могучий обычно начинают откровенно глючить и косячить. На то он великий и могучий. В нем одних только приставок и суффиксов столько, что ни один буржуйский рядом не стоял. Потому западные алгоритмы терпят такое же фиаско, как французы под Полтавой.
Отечественные наработки не сильно лучше. Причина, видимо, в том, что они в основе своей содержат все те же западные поделки, которые наши умельцы слегка "адаптировали" под русский. В результате получаем тот же косяк, только вид "с боку".
Наилучшим решением в данной ситуации является использование механизма из уже упомянутого microsoft Office. Как ни странно, но офисный алгоритм от майкрософта справляется с русским гораздо лучше всяких сторонних изобретений. Даже странно как-то. Но факт.
Ну что ж, офис, так офис! Тем более, что большинство разработчиков именно его модули и использует.
Начинаю копать. Первым делом естественно MSDN. Попытка найти нужное решение "в лоб" терпит крах (как обычно), потому начинаю думать головой.
Теоретически к офису обратиться можно через технологию COM (Component Object Model), значит роем MSDN на тему привязки COM-объектов к C#-коду. И тут же получаем готовый пример именно проверки правописания в свобственной программе, используя механизм из microsoft Word. Вот это удача!
Правда без косяков не обошлось. Пример, описанный во всех деталях в MSDN, у меня просто не откомпилировался. :)
Пришлось снова подумать головой, и снова покопаться в доках, и даже переустановить Office. Наконец мое рвение получило по заслугам - "оно" наконец заработало. Но радости, как и следовало ожидать, не принесло. Как это обычно делает мелко-мягкая контора, пример оказался хоть и рабочим (правда с натяжками), но совершенно неприменимым в практической жизни.
Замеченные в первые минуты неудобства:
- Проверка осуществляется только над всем текстом целиком и состоит в вызове стандартного окна замены неверно написанных слов. Следствие – очень ограниченная функциональность.
- При каждой проверке запускается сам Word (хоть и в фоне в невидимом окне) и по окончании проверки убивается. Следствие – тормоза.
- После окончания проверки и перед тем как окно Ворда будет убито, оно странным образом появляется на экране, хотя при создании ему ясно указали быть невидимым. Следствие – моргание полноэкранного окна ворда поверх вашей программы при каждой проверке орфографии.
- Для связи с вордом используется промежуточная сборка (в умных книжках ее зовут RCW – Runtime COM Wrapper или "COM-оболочка времени выполнения" - на мой взгляд весьма жудкое название). Т.е. связь с вордом устанавливается еще в момент запуска программы (ранне связывание) и, если на машине клиента вдруг ворда не кажется или окажется, но другой версии, то ваша программа покажет пользователю большую фигу в виде фолта. А пользователи фиг очень не любят. Следствие – катастрофическая зависимость от наличия определенной версии ворда в системе.
- Сама RCW представляет собой не что иное как DLL-файл, который придется таскать вместе с программой (без него тоже получите фолт, причем уже вне зависимости от наличия ворда на машине клиента). Размер у этой библиотеки ни много, ни мало, а целых пол-мегабайта. И это лишь для передачи вызовов из NET в COM и обратно. Стоит задуматься.
Короче, предлагаемый майкрософтом вариант меня полностью не устроил. Мне бы хотелось, чтоб выполнялись следующие условия:
- Была возможность определять правильность отдельных слов, без окон замены и т.д. Программе нужно лишь определить, правильно написано это слово или неправильно. Весь остальной механизм с заменами и словарями – дело техники.
- Для работы программа использовала бы только одну копию ворда, т.е. при старте программы он загружается, при завершении программы – выгружается
- Никаких внешних признаков присутствия ворда – окошек, мограний и т.д.
- Нормальная обработка отсутствия ворда в системе. Т.е. даже если офис не установлен, программа должна корректно работать (естественно уже без проверки орфографии).
- Отсутствие потребности в каких бы то ни было дополнительных сборках-библиотеках. Тем более таких диких размеров.
Согласитесь, требования весьма скромные. Значит и реализация должна быть достаточно простой. А вот собственно и она:
/*********************************/
/* Simple Spell Checker */
/* Copyright (C) FIT-Media, 2008 */
/* http://fit-media.com */
/*********************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
public class SpellChecker : IDisposable
{
System.Type TWord = null; object com_app = null;
private static SpellChecker Checker = new SpellChecker();
private SpellChecker()
{
try {
TWord = Type.GetTypeFromProgID("Word.Application");
com_app = Activator.CreateInstance(TWord);
}
catch { com_app = null;}
}
public static SpellChecker GetChecker() { return Checker; }
public void Dispose()
{
if (com_app != null) {
object[] arg = { null, null, null };
TWord.InvokeMember("Quit", BindingFlags.InvokeMethod,
null, com_app, arg);
com_app = null;
}
}
public bool CheckWord(string word)
{
object[] arg = { word };
return (bool)TWord.InvokeMember("CheckSpelling",
BindingFlags.InvokeMethod, null, com_app, arg);
}
}
Пример настолько прост, что в пояснениях не нуждается. Он реализует лишь минимальный базовый уровень - проверку единственного слова. Весь остальной функционал допишите сами (кому нужно) - там уже ничего сложного нет.
Единственное, на что стоит обратить внимание, это необходимость вызова метода SpellChecker.Dispose() при завершении работы вашей программы. Иначе запущенная копия ворда останется в памяти (привет нормальным пацанам из microsoft и их гениальному сборщику мусора) и будет болтаться там до перезапуска системы.
А-а-а, сейчас глянул на начало статьи и понял, что начал об одном, а потом как-то незаметно пришел совсем к другому. :)
Если вы не против, то я все же вернусь к рассказу о моей идее и лени мелко-мягких.
Суть идеи сводится к "глобализации" системы проверки правописания, которая уже встроена в microsoft Office. Прикол в том, что практически 100% программ используют для ввода текста элементы управления, встроенные в операционную систему.
Так вот, достаточно встроить механизм проверки орфографии в саму ОС и подключить его к двум основным средствам ввода текста (в терминах NET Framework это TextBox и RichTextBox), как абсолютно все программы, без какого бы то ни было вмешательства разработчиков, приобретут возможность отображения неверно написанных слов. А перед счастливыми программистами больше никогда не встанет задача реализации в своих программах этой самой "проверки грамотности ввода".
Кстати, при таком подходе словари тоже окажутся глобальными, т.е. добавили вы в словарь слово в ворде и его уже опознают все остальные программы. Здорово? Конечно!
Вот только дети дяди Билла толи сильно ленивые, толи очень жадные (что скорее всего) и ни за что не хотят дать нам всем такую замечательную возможность. :(