CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 04.08.14 14:15
Оценка:
Возможно ли при использовании ричэдита 3 или выше версии использовать подчеркивание другим цветом, чем цвет текста?
Как такое реализовать в своем тексте?
.
Re: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 05.08.14 06:15
Оценка:
Неужто такая задача никому не встречалась?
.
Re[2]: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 05.08.14 07:58
Оценка:
Вижу, что есть вариант через WM_PAINT прорисовывать, но не выходит.
Буду ипользовать библиотеку Hunspell для проверки орфографии, но как оптимизировать, чтобы при любой прорисовке не искать заново проверенные слова?
.
Re[3]: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 05.08.14 11:26
Оценка:
Немного поковырявшись нашел, что в новых версиях richedit есть в структуре CHARFORMAT2 bUnderlineType, в котором можно указать цвет для подчеркивания.
Но я использую Visual C++ 6, где CHARFORMAT2 максимально 2 версии. Как правильно определить такую структуру?
Выдернуто с Visual C++ 2010:
typedef struct _charformat2w
{
    UINT        cbSize;
    DWORD        dwMask;
    DWORD        dwEffects;
    LONG        yHeight;
    LONG        yOffset;            // > 0 for superscript, < 0 for subscript 
    COLORREF    crTextColor;
    BYTE        bCharSet;
    BYTE        bPitchAndFamily;
    WCHAR        szFaceName[LF_FACESIZE];
    WORD        wWeight;            // Font weight (LOGFONT value)        
    SHORT        sSpacing;            // Amount to space between letters    
    COLORREF    crBackColor;        // Background color                 
    LCID        lcid;                // Locale ID                        
#if (_RICHEDIT_VER >= 0x0500)
    union
    {
        DWORD        dwReserved;            // Name up to 5.0
        DWORD        dwCookie;             // Client cookie opaque to RichEdit
    };
#else
    DWORD        dwReserved;            // Name up to 5.0
#endif
    SHORT        sStyle;             // Style handle                     
    WORD        wKerning;            // Twip size above which to kern char pair
    BYTE        bUnderlineType;     // Underline type                    
    BYTE        bAnimation;         // Animated text like marching ants 
    BYTE        bRevAuthor;         // Revision author index            
#if (_RICHEDIT_VER >= 0x0800)
    BYTE        bUnderlineColor;    // Underline color
#endif
} CHARFORMAT2W;
.
Re[4]: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 05.08.14 11:28
Оценка:
Может подключить richedit.h с новой студии VC 2010 в VC 6?
.
Re[5]: CRichEditCtrl + подчеркивание
От: rus blood Россия  
Дата: 05.08.14 14:10
Оценка: +1
Здравствуйте, kondrik, Вы писали:

K>Может подключить richedit.h с новой студии VC 2010 в VC 6?


А зачем?
Нужна только структура.
Класс CRichEditCtrl просто кидает сообщения в окно контрола.
Скопируйте себе новое определение структуры и пользуйтесь.
Виндовый контрол определит "версию" структуры по ее размеру, указанному в поле cbSize.
Имею скафандр — готов путешествовать!
Re[3]: CRichEditCtrl + подчеркивание
От: Carc Россия https://vk.com/gosha_mazov
Дата: 07.08.14 19:59
Оценка: 1 (1)
Здравствуйте, kondrik, Вы писали:

K>Вижу, что есть вариант через WM_PAINT прорисовывать, но не выходит.

K>Буду ипользовать библиотеку Hunspell для проверки орфографии, но как оптимизировать, чтобы при любой прорисовке не искать заново проверенные слова?
Я когда маялся с проверкой орфографии, то как-то постепенно пришел к тому, что реализовывалось подчеркивание ручками, в EN_UPDATE. Там что хошь делай, и какие хошь используй цвета. С перепроверкой слов я не парился. Просто проверялись слова в фоновом режиме, и только из видимого на экране фрагмента текста, дабы избежать лишнего оверхеда.
Aml Pages Home
Re[4]: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 10.09.14 07:43
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, kondrik, Вы писали:


K>>Вижу, что есть вариант через WM_PAINT прорисовывать, но не выходит.

K>>Буду ипользовать библиотеку Hunspell для проверки орфографии, но как оптимизировать, чтобы при любой прорисовке не искать заново проверенные слова?
C>Я когда маялся с проверкой орфографии, то как-то постепенно пришел к тому, что реализовывалось подчеркивание ручками, в EN_UPDATE. Там что хошь делай, и какие хошь используй цвета. С перепроверкой слов я не парился. Просто проверялись слова в фоновом режиме, и только из видимого на экране фрагмента текста, дабы избежать лишнего оверхеда.

Можешь выложить функцию со своего проекта, которая отвечает за этот функционал?
Я попробовал реализовать через отлавливание EN_MSGFILTER в самом контроле.
Для инициализации использовал:
RTFCtrl.SetEventMask(lEvMask | EN_MSGFILTER | ENM_SELCHANGE | ENM_KEYEVENTS);

У меня сейчас очень неоптимально вышло и при любом изменении весь текст проверяется. Соответственно нагрузка на процессор большая и притормаживания в контроле большие.
Может более оптимальнее выйдет подчеркивать при отрисовке? Очень хотелось бы посмотреть на пример реализации.
.
Re[5]: CRichEditCtrl + подчеркивание
От: Carc Россия https://vk.com/gosha_mazov
Дата: 10.09.14 08:42
Оценка: 2 (1)
K>Можешь выложить функцию со своего проекта, которая отвечает за этот функционал?
K>Я попробовал реализовать через отлавливание EN_MSGFILTER в самом контроле.
K>Для инициализации использовал:
K>
K>RTFCtrl.SetEventMask(lEvMask | EN_MSGFILTER | ENM_SELCHANGE | ENM_KEYEVENTS);
K>

K>У меня сейчас очень неоптимально вышло и при любом изменении весь текст проверяется. Соответственно нагрузка на процессор большая и притормаживания в контроле большие.
K>Может более оптимальнее выйдет подчеркивать при отрисовке? Очень хотелось бы посмотреть на пример реализации.

Вот функция, она по сути только рисует подчеркивание.

void CSpellRichEdit::ColorRange2(const int nMin //стартовый символ проверки
                                 , const int nMax//конец проверки
                                 , const HWND hwnd //HWND ричэдита
)
{
    ASSERT(IsWindow(hwnd));

    CComPtr<ITextRange> Range;
    {
    CHARRANGE cr;
    cr.cpMin=nMin;
    cr.cpMax=nMax;

//получаем диапазон проверки
    Range=(CTomUtil::GetITextRange(hwnd,cr));
    
    ASSERT(Range);
    if (!Range)
        return;

//выровняли диапазон по слову,
    NormalizeWordEnd(Range);

#ifdef _DEBUG
    long lTemp1, lTemp2;
    ASSERT(S_OK == Range->GetEnd(&lTemp2));
    ASSERT(S_OK == Range->GetStart(&lTemp1));
    ASSERT(lTemp2 > lTemp1);
#endif
    }

        //поехали черкать подчеркивание
    long x1, y1;
    if (S_OK != Range->GetPoint(tomStart|TA_BOTTOM|TA_LEFT,&x1,&y1))
        return;
    
    long x2, y2;
    if (S_OK != Range->GetPoint(tomEnd|TA_BOTTOM|TA_RIGHT,&x2,&y2))
        return;
    
    const HDC hdc=GetWindowDC(hwnd);
    ASSERT(hdc);
    if (!hdc)
        return;

    ASSERT(GetRedPen());
    const HPEN hOldPen=(HPEN)::SelectObject(hdc,GetRedPen());

    CPoint pt1(x1,y1);
    ScreenToClient(hwnd,&pt1);
    x1=pt1.x; y1=pt1.y;

    CPoint pt2(x2,y2);
    ScreenToClient(hwnd,&pt2);
    x2=pt2.x; y2=pt2.y;

    y1++; y2++;

    const int nWidth=x2 - x1;
    if (nWidth <= 0)
        return;
    
    enum {DELTA=2};
    const int nPointCount=nWidth/DELTA + 1;
    ASSERT(nPointCount > 0);
    
    {
    POINT* const pArray=new POINT[nPointCount];
    ASSERT(!IsBadWritePtr(pArray,  sizeof(POINT)*nPointCount));
    memset(pArray,0, sizeof(POINT)*nPointCount);

    for (int i=0; i<nPointCount; i++ )    {
        POINT& pt=*(pArray+i);
        pt.x=x1 + DELTA*i;
        const int DELTA_Y= i % 2 ? 1 : -1;
        pt.y=y1+DELTA_Y;
    }
    const BOOL b=Polyline(hdc, pArray,nPointCount);
    delete[] pArray;
    }

    SelectObject(hdc,hOldPen);
    ReleaseDC(hwnd,hdc);
}

По сути эта функция только подчеркивает неверное слово. Она несколько вырвана из контекста, т.к. это кусок какого-то моего древнего плагина для Aml Pages. Но суть там проста. По всяким EN_UPDATE, EN_CHANGE проверяет минимальный диапазон на орфографию. Вроде текста строки, или видимого диапазона. Потом в фоне функцией выше рисуется подчеркивание.

На память я точно не помню на что реагировал плагин. Но он точно получает всякие события от хостовой Aml Pages, вроде EN_UPDATE (перерисовка текста в видимом диапазоне), EN_CHANGE (по умолчанию считалось что меняется текущая строка, WM_NULL (периодически Aml Pages передает это событие плагину, когда ей особо нечего делать). Ну и плагин уже в фоне все это рисует. Ключевой момент: ни при каких обстоятельствах не проверять весь текст (кроме явной команды пользователя). Только строка, абзац, видимый диапазон. Тогда более-менее все сносно работает. По крайней мере этим функционалом пользователи были довольны.
Aml Pages Home
Re[6]: CRichEditCtrl + подчеркивание
От: kondrik  
Дата: 11.09.14 15:18
Оценка:
Спасибо за напутствие.
Во всех примерах, что удалось найти на просторах интернета прорисовка выполняется в фоне, но если набирается текст, то во время набора текста подчеркивание пропадает.
Как правильно реализовать прорисовывание без этого 'артефакта'?

Можно использовать изменение формата текста, но тогда при сохранении или копировании нужно убирать подчеркивание. Вариант изменения формата для меня крайне нежелателен, т.к. я обрабатываю текст и при этом учитываю формат набранного текста. Если буду его подчеркивать, то мой алгоритм обработки некорректно будет работать.
.
Re[7]: CRichEditCtrl + подчеркивание
От: Carc Россия https://vk.com/gosha_mazov
Дата: 14.09.14 16:41
Оценка:
Здравствуйте, kondrik, Вы писали:

K>Спасибо за напутствие.

K>Во всех примерах, что удалось найти на просторах интернета прорисовка выполняется в фоне, но если набирается текст, то во время набора текста подчеркивание пропадает.
K>Как правильно реализовать прорисовывание без этого 'артефакта'?
Ну дык повторно прорисовать на EN_UPDATE? Разве нет?

K>Можно использовать изменение формата текста, но тогда при сохранении или копировании нужно убирать подчеркивание. Вариант изменения формата для меня крайне нежелателен, т.к. я обрабатываю текст и при этом учитываю формат набранного текста. Если буду его подчеркивать, то мой алгоритм обработки некорректно будет работать.

С чего тут вдруг подчеркивание будет влиять на формат? Я же писал в функции выше, что все подчеркивание делается исключительно ручками на HDC RichEdit`а. И сами данные RichEdit`а при этом понятия даже не имеют, подчеркнуты они или нет. Все подчеркивается поверх, что называется сбоку-припеку. На сами данные такое подчеркивание ну никак не влияет. Чего-то я не пойму в чем трудность!?! У меня в том вся фишка и была, что проверяться мог простой plain текст, и там можно было что угодно вытворять с форматированием текста, все равно все слетит при сохранении. Но может быть и текст с форматированием (RTF), и тут уже танцы с бубнами про подчеркивание недопустимы. Поэтому и писалось универсально, чтобы не трогать само форматирование RTF-данных.
Aml Pages Home
Re[8]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 15.09.14 09:40
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, kondrik, Вы писали:


K>>Спасибо за напутствие.

K>>Во всех примерах, что удалось найти на просторах интернета прорисовка выполняется в фоне, но если набирается текст, то во время набора текста подчеркивание пропадает.
K>>Как правильно реализовать прорисовывание без этого 'артефакта'?
C>Ну дык повторно прорисовать на EN_UPDATE? Разве нет?

K>>Можно использовать изменение формата текста, но тогда при сохранении или копировании нужно убирать подчеркивание. Вариант изменения формата для меня крайне нежелателен, т.к. я обрабатываю текст и при этом учитываю формат набранного текста. Если буду его подчеркивать, то мой алгоритм обработки некорректно будет работать.

C>С чего тут вдруг подчеркивание будет влиять на формат? Я же писал в функции выше, что все подчеркивание делается исключительно ручками на HDC RichEdit`а. И сами данные RichEdit`а при этом понятия даже не имеют, подчеркнуты они или нет. Все подчеркивается поверх, что называется сбоку-припеку. На сами данные такое подчеркивание ну никак не влияет. Чего-то я не пойму в чем трудность!?! У меня в том вся фишка и была, что проверяться мог простой plain текст, и там можно было что угодно вытворять с форматированием текста, все равно все слетит при сохранении. Но может быть и текст с форматированием (RTF), и тут уже танцы с бубнами про подчеркивание недопустимы. Поэтому и писалось универсально, чтобы не трогать само форматирование RTF-данных.

Спасибо. Я в принципе и раньше понимал, что при прорисовке — форматирование изменяться не будет.
Я пока экспериментирую с тонкостью реализации. Например мне интересно как работает проверка орфографии в хроме, если сразу же при наборе неправильных символов — будет подчеркнуто ошибочное слово и предыдущие слова при этом не перерисовываются и не мигают (возможно проверяется только минимальный блок текста, такой как строка, абзац или несколько последних слов и т.п.). Все равно как-то нужно анализировать что проверять или нужно иметь историю набранного текста со времени последней проверки.
Буду дальше экспериментировать...
Re[9]: CRichEditCtrl + подчеркивание
От: Carc Россия https://vk.com/gosha_mazov
Дата: 15.09.14 09:52
Оценка: +1
V>Спасибо. Я в принципе и раньше понимал, что при прорисовке — форматирование изменяться не будет.
V>Я пока экспериментирую с тонкостью реализации. Например мне интересно как работает проверка орфографии в хроме, если сразу же при наборе неправильных символов — будет подчеркнуто ошибочное слово и предыдущие слова при этом не перерисовываются и не мигают (возможно проверяется только минимальный блок текста, такой как строка, абзац или несколько последних слов и т.п.). Все равно как-то нужно анализировать что проверять или нужно иметь историю набранного текста со времени последней проверки.
V>Буду дальше экспериментировать...
В прямую ричэдит не поддерживает такой истории. Как показывает опыт, проще и быстрее реализовать проверку последней набранной строки. Ну и что, что там некоторые слова будут повторно проверяться. Пофиг. Там всего то слов будет на пяток, ну десяток. В рамках проверки это сущие копейки. Нагрузки не будет давать.

Там несколько сложнее будет определять этот самый пресловутый диапазон для проверки. EN_CHANGE будет приходить по поводу и без повода — это и вставка из буфера обмена, и вообще изменение форматирования. Сам процесс набора текста лучше отлавливать через сообщения WM_KEYDOWN\UP и предполагать что идет именно набор. Всякие WM_PASTE, EN_CHANGE, EN_VSCROLL обрабатывать придется сложнее. В общем случае приходится предполагать, что (возможно) изменился весь видимый диапазон текста. Каких-то скрытых возможностей RichEdit для учета набранных слов нету просто. И в основном вся задача сводится к тому, чтобы не мешать пользователю набирать текст — по возможности наименьший диапазон слов, и главное проверять в фоне.

Фоновый момент можно как-то проще отслеживать — тупо заводим таймер с каким-нить таймаутом, и запоминаем время последнего события пользовательского ввода (ну те же GetTickCount на EN_CHANGE, WM_KEYUP). Если по WM_TIMER прошло больше определенной дельты с последнего события ввода (ну скажем, секунда или две — подбирается эмпирически), то значит пользователь угомонился с вводом текста, и можно пошаманить с проверкой орфографии где-то в текущей строке или видимом диапазоне текста.

Ну это так.... Иллюстрация к мыслям. Понятно, можно и не через таймер, можно как-то иначе. Я скорее про само общее решение.
Aml Pages Home
Re[10]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 19.05.17 07:15
Оценка:
Опять возвращаюсь к задачи проверки правописания и подчеркивания неправильно набранных слов. Задача еще актуальна. Продолжаю дальше эксперименты.
Re[11]: CRichEditCtrl + подчеркивание
От: Carc Россия https://vk.com/gosha_mazov
Дата: 21.05.17 07:39
Оценка:
Здравствуйте, Vlads, Вы писали:

V>Опять возвращаюсь к задачи проверки правописания и подчеркивания неправильно набранных слов. Задача еще актуальна. Продолжаю дальше эксперименты.

А чего там экспериментить-то!?! Все уже украдено до нас. Перехватывается WM_PAINT (насколько я помню, а может и EM_FORMATRANGE), а дальше подчеркивание просто банально рисуется ручками на HDC RichEdit`а.

И всё. На экране подчеркивание есть, а в данных RichEdit и в помине ничего такого нет (а не нужно, если текст с форматированием, то иначе при сохранении вовне и подчеркивание уйдет). Я так делал в каком-то старинном SpellChecker плагине для своей Aml Pages. Все прекрасно работало.
Aml Pages Home
Re[12]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 26.05.17 14:21
Оценка:
Насколько понимаю, то нужно в OnPaint получить список всех слов видимых в окне и для каждого слова вызывать функцию проверки?
Re[12]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 26.05.17 18:07
Оценка:
Может есть исходник плагина для Aml Pages ?
Re[12]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 26.05.17 18:24
Оценка:
Разбираюсь как через TOM получить текст. Понимаю, что нужно получить ITextRange начала видимого текста и двигаться по 1 слову до конца видимого текста. Каждое слово в WM_PAINT проверять и если оно неправильное, то подчеркивать. Для подчеркивания необходимо найти координаты начала и конца слова. А как быть со словами с переносами?
Очень много нюансов. Кажется, что изобретаю велосипед.
Re[12]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 30.05.17 12:32
Оценка:
Сейчас разбираюсь парсингом текста для спелчекера. Выполняю парсинг с помощью ITextRange::Expand(tomWord,...) и ITextRange::Move(tomWord,...), но тогда попадает куча лишнего мусора в парсинге. Нужно как-то фильтровать то что получилось. Как сделать правильный парсинг, чтобы проверялись только слова а не всякий мусор?
Re[12]: CRichEditCtrl + подчеркивание
От: Vlads  
Дата: 01.06.17 05:46
Оценка:
Carc, в вашем AmlPages я не вижу, чтобы слова с ошибками подчеркивались. Или это было реализовано в старых плагинах?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.