/* * TODO * добавить случай, когда требуется scroll и, соответственно, поправить для * этого GetNearestCaretPosition, чтобы возвращалось что-то осмысленное, если точка за пределами текста * выделение влево и вправо - работает * выделение вверх и вниз - какая-то херь с индексами */ private void mouse_select_do(Point mice_location) { int ind = 0; HitTextResult hit_test = text_area.HitTest(mice_location); ind = hit_test.CharacterIndex; long char_under_mice = ind + screen_first_char; if ((hit_test.HitTextType == HitTextType.Glyph) && (char_under_mice >= selection_first) && (char_under_mice < selection_last)) { //выходим, если char под указателем уже выделен return; } //если char под указаьелем не выделен //смторим как он располагается относительно существующего выделения long pre_char = -1; //левый char выделен? pre_char = char_under_mice - 1; if ((pre_char >= selection_first) && (pre_char < selection_last)) { //добавляем к выделению, char под указателем - конец выделения selection_set(selection_first, char_under_mice + 1); return; } //правый char выделен? pre_char = char_under_mice + 1; if ((pre_char >= selection_first) && (pre_char < selection_last)) { //char под указателем - начало выделения selection_set(char_under_mice, selection_last); return; } //верхний char выделен? int line_height = (int)Math.Ceiling(Font.GetHeight()); Point pre_point = new Point(); pre_point.X = mice_location.X; pre_point.Y = mice_location.Y - line_height; HitTextResult neibo_hit = text_area.HitTest(pre_point); ind = neibo_hit.CharacterIndex; pre_char = ind + screen_first_char; if ((hit_test.HitTextType == HitTextType.Glyph) && (pre_char >= selection_first) && (pre_char < selection_last)) { //char под указателем - конец выделения selection_set(selection_first, char_under_mice + 1); return; } if ((hit_test.HitTextType == HitTextType.AfterText) && (pre_char >= selection_first) && (pre_char < selection_last)) { //указатель ниже текста - прокрутка scroll_line_down(); //теперь char под указателем - конец выделения hit_test = text_area.HitTest(mice_location); char_under_mice = hit_test.CharacterIndex + screen_first_char; //если и после прокрутки под указатедем - пусто, выходим if (hit_test.HitTextType == HitTextType.Glyph) { selection_set(selection_first, char_under_mice + 1); return; } else { return; } } //нижний char выдеден? pre_point.Y = mice_location.Y + line_height; text_area.GetNearestCaretPosition(pre_point, out ind); pre_char = ind + screen_first_char; if ((hit_test.HitTextType == HitTextType.Glyph) && (pre_char >= selection_first) && (pre_char < selection_last)) { //char под указателем - начало выделения selection_set(char_under_mice, selection_last); return; } if ((hit_test.HitTextType == HitTextType.BeforeText) && (pre_char >= selection_first) && (pre_char < selection_last)) { //нужна прокрутка вверх scroll_line_up(); //теперь char под указателем - насчало выделения hit_test = text_area.HitTest(mice_location); char_under_mice = hit_test.CharacterIndex + screen_first_char; //если и после прокрутки под указатедем - пусто, выходим if (hit_test.HitTextType == HitTextType.Glyph) { selection_set(char_under_mice, selection_last); return; } else { return; } } //иначе начинаем новое выделение if (hit_test.HitTextType == HitTextType.Glyph) { selection_set(char_under_mice, char_under_mice + 1); } }
public HitTextResult HitTest(Point pt) { HitTextResult ret = new HitTextResult(); if (LinesCount == 0) { ret.CharacterIndex = -1; ret.CharacterIndexInLine = -1; ret.LineIndex = -1; ret.HitTextType = HitTextType.BeforeText; return(ret); } if (pt.Y < lines_info[0].ReferensePoint.Y) { ret.CharacterIndex = -1; ret.CharacterIndexInLine = -1; ret.LineIndex = -1; ret.HitTextType = HitTextType.BeforeText; return(ret); } if (pt.Y > lines_info[LinesCount - 1].ReferensePoint.Y + lines_info[LinesCount - 1].Extent.Height) { ret.CharacterIndex = -1; ret.CharacterIndexInLine = -1; ret.LineIndex = -1; ret.HitTextType = HitTextType.AfterText; return(ret); } int line_index = GetLineIndexFromPoint(pt); if (line_index == -1) { ret.CharacterIndex = -1; ret.CharacterIndexInLine = -1; ret.LineIndex = -1; ret.HitTextType = HitTextType.Undefined; return(ret); } CharacterPositionInfo cpi = lines_info[line_index].GetCharacterIndexAtX(pt.X - lines_info[line_index].ReferensePoint.X); ret.CharacterIndex = cpi.CharIndex + lines_info[line_index].CharFirst; ret.CharacterIndexInLine = cpi.CharIndex; ret.LineIndex = line_index; switch (cpi.PositionType) { case CharacterPositionType.LeadingEdge: case CharacterPositionType.TrailingEdge: case CharacterPositionType.ClusterPart: ret.HitTextType = HitTextType.Glyph; break; case CharacterPositionType.BeforeBeginning: ret.HitTextType = HitTextType.BeforeOfLine; break; case CharacterPositionType.AfterEnd: ret.HitTextType = HitTextType.AfterOfLine; break; } return(ret); }