Разработка программы, динамически подсвечивающей ключевые слова из загружаемого пользователем словаря

Курсовой проект - Компьютеры, программирование

Другие курсовые по предмету Компьютеры, программирование

d, stMatchCase);

TSearchTypes = set of TSearchType;

Данный тип определяет, каким образом должен происходить поиск. Если установлен stMatchCase, то при поиске необходимо учитывать регистр букв (большие или маленькие). Если установлен stWholeWord, то необходимо, чтобы найденная последовательность была ограничена разделителями (например, пробелами). В OSR2rus это называется "только слово целиком", хотя слов может быть несколько.

 

TCustomRichEdit = class(TCustomMemo)FindText(const SearchStr:string; StartPos, Length:Integer; Options:TSearchTypes): Integer;

 

Это описательная часть класса и далее в разделе реализации:

 

function TCustomRichEdit.FindText(const SearchStr:string; StartPos, Length:Integer; Options:TSearchTypes): Integer;: TFindText;: Integer;Find.chrg do:= StartPos;:= cpMin + Length;;:= 0;stWholeWord in Options then Flags := Flags or FT_WHOLEWORD;stMatchCase in Options then Flags := Flags or FT_MATCHCASE;.lpstrText := PChar(SearchStr);:= SendMessage(Handle, EM_FINDTEXT, Flags, LongInt(@Find));

end;

Сначала устанавливаются границы диапазона поиска, причем вместо длины используется номер последнего символа для поиска (cpMax := cpMin + Length). Затем устанавливается флаг поиска. Далее устанавливается ссылка на Pchar строку-образец. И, наконец, посылается сообщение EM_FINDTEXT самому себе..Add добавляет строку в конец текста

Класс TRichEdit наследует метод Add от класса TStrings, т.к. именно такой тип имеет свойство Lines. Из файла Source\VCL\classes.pas:

 

function TStrings.Add(const S:string) :Integer;:= GetCount;(Result, S);

end;

 

Запрашиваем количество строк в тексте и вызываем метод Insert для вставки строки в конец текста. Обе используемые функции описаны там же, как:

= class(TPersistent)

protectedGetCount: Integer; virtual; abstract;Insert(Index:Integer; const S:string); virtual; abstract;

 

То есть, абстрактны и виртуальны, а значит, в обязательном порядке должны быть переопределены в потомках. Таким потомком является класс TRichEditStrings, конструктор которого и вызывается для создания свойства Lines в конструкторе TCustomRichEdit, ближайшем родителе TRichEdit.

Из файла Source\VCL\comctrls.pas= class(TStrings)GetCount: Integer; override;Insert(Index: Integer; const S: string); override;TRichEditStrings.GetCount: Integer;:= SendMessage(RichEdit.Handle, EM_GETLINECOUNT, 0, 0);SendMessage (RichEdit.Handle, EM_LINELENGTH, SendMessage (RichEdit.Handle, EM_LINEINDEX, Result - 1, 0), 0) = 0 then Dec(Result);

end;

 

Запрашиваем количество строк в тексте и сохраняем его в служебной переменной Result. Если длина последней строки равна нулю (т.е. пуста) вычитаем ее из результата (Result).

 

=0then.cpMin:=SendMessage(RichEdit.Handle,EM_LINEINDEX,Index,0);Selection.cpMin>=0thenFmt:=%s#13#10begin.cpMin:=SendMessage(RichEdit.Handle,EM_LINEINDEX,Index-1,0);Selection.cpMin (Selection.cpMax + Length(Str)) thenEOutOfResources.Create(sRichEditInsertError);;

end;

 

Используя номер строки, перед которой мы собираемся произвести вставку, определяем номер символа, с которого начинается строка, и сохраняем его в переменной Selection.cpMin. Если номер символа не отрицательный, то это значит, что строка с таким номером существует и в конец добавляемой строки необходимо включить признак конца строки. Если номер символа отрицательный, значит, такой строки нет. Но возможно предпринимается попытка вставить после последней строки, так что запросим номер символа для предыдущей строки. Если и теперь номер отрицательный или длина этой строки нулевая, прекращаем дальнейшее выполнение. При благоприятном исходе увеличиваем Selection.cpMin на длину последней строки, таким образом, теперь она указывает на последний символ в тексте (сюда и будем вставлять). Наличие не нулевой длины у последней строки говорит о том, что строка не завершена. Чтобы завершить ее необходимо передать в текст сначала, признак конца строки, а потом саму добавляемую строку, по этому признак конца строки включается в ее начало. Далее устанавливаем конец выделения на начало выделения (переменная Selection.cpMax) и перемещаем туда курсор посылкой сообщения EM_EXSETSEL. Форматируем строку и отправляем сообщение EM_REPLACESEL для размещения вставляемой строки. После удачной вставки новое положение курсора должно ровняться положению перед вставкой плюс длина вставляемой строки (Selection.cpMax + Length(Str)). Если нет, то вызывается исключительная ситуация (raiseEOutOfResources.Create(sRichEditInsertError)).

Ошибка возникает потому, что сообщение EM_LINELENGTH использует только младшие 16 разрядов параметра. Этот параметр должен содержать номер любого символа из строки длину, которой надо определить. Если передается номер более 65 535, ну, например 65 536, то сообщение возвращает длину строки, содержащую символ с номером 0. Таким образом, в методе Add при запросе функции GetCount может быть получено значение на единицу большее, если попадется строка не нулевой длины. И тогда процедуре Insert будет передано значение на единицу большее, чем номер последней строки. Это первая ошибка.

Свойство Count, которое обращается к функции GetCount, может давать на одну строку больше при превышении размера текста в 65 535 байт. Ошибка возникает только если строка, содержащая усеченный номер символа, не пуста, то есть ошибка будет иметь плавающий характер.

Возвращаясь к методу Add, замечу, что эта ошибка не влияет на процедуру Insert. Потому что процедура Insert пробует не только указанную строку, но и, в случае не успеха, предыдущую, а это