Страницы

Поиск по вопросам

суббота, 14 декабря 2019 г.

Как сделать двойное(тройное) отрицание на wpf или windows forms?

#c_sharp #wpf #winforms




Например, как на картинке. Чтобы при нажатии на кнопку над выделенным элементом(или
группой элементов) появлялся знак отрицания(двойное/тройное).
Если нельзя реализовать на данных языках, то может хоть какие-нибудь другие идеи есть..
    


Ответы

Ответ 1



Ну, можно сделать, хотя намного менее удобно, чем в TeX'е. Вам придётся самостоятельно измерять символы и работать со свойствами шрифтов. Вот вам простой вариант: он не учитывает курсив и строчные буквы. XAML: Заведём маленький вспомогательный класс: class LevelDescriptor { public double Y; public List<(double from, double to)> Lines; } Наш код: string text = "(X & Y) & (X & Y) & (X & Z)"; // описание линий var lines = new List>() { new List<(int from, int to)>() { (1, 2), (15, 16), (25, 26) }, // уровень 1 new List<(int from, int to)>() { (1, 6), (11, 16), (21, 26) }, // уровень 2 new List<(int from, int to)>() { (0, 27) }, // уровень 3 }; // вертикальное расстояние между линиями const double vgap = 4; // разрешение вашего монитора. (если оно изменяется, например, у вас их несколько, то // надо подписаться на его изменение) var pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; // куда пишем TextBlock tb = Target; tb.Text = text; // отбираем у текстбокса шрифт var font = new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch); // форматируем текст FormattedText formattedText = new FormattedText( text, CultureInfo.GetCultureInfo("en-US"), FlowDirection.LeftToRight, font, tb.FontSize, Brushes.Black, // конкретная кисть нам не важна, мы используем только геометрию pixelsPerDip); // на какой высоте начинается большая буква? double vstart = formattedText.Baseline - font.CapsHeight * tb.FontSize; // описатели линий List result = new List(); // текущая высота double height = vstart; foreach (var line in lines) { // получаем окружающие прямоугольники для всех подстрок var boundingBoxes = line.Select(d => formattedText.BuildHighlightGeometry(new Point(), d.from, d.to - d.from).Bounds); height -= vgap; // запомнили высоту, и левую/правую границу для каждого отрезка result.Add(new LevelDescriptor() { Y = height, Lines = boundingBoxes.Select(bb => (from: bb.Left, to: bb.Right)).ToList() }); } // теперь создаём линии var brush = tb.Foreground; // цвет такой же, как и у строки foreach (var level in result) { foreach (var d in level.Lines) Host.Children.Add( new Line() { X1 = d.from, X2 = d.to, Y1 = level.Y, Y2 = level.Y, StrokeThickness = 1, // толщина Stroke = brush, Fill = brush }); } Вот и всё. Вам придётся на основе своих данных самостоятельно строить таблицу lines. У меня вышел вот такой результат:

Комментариев нет:

Отправить комментарий