Гайд - Исходники - WPF создание графического элемента | End Way - форум программирования и сливов различных скриптов
  • Присоединяйтесь к нам в телеграм канал! EndWay канал | EndSoft канал | EWStudio канал
  • Хочешь поставить скрипт, но не умеешь?
    А может ты хочешь свой скрипт на основе слитого?

    Тогда добро пожаловать в нашу студию разработки!

    Телеграм бот: EWStudioBot
    Телеграм канал: EWStudio

Гайд Исходники WPF создание графического элемента

Jopa

Бот
Автор темы
8 Янв 2023
50
149
33
Краткий листинг программного кода класса Digit:
public class Digit : Panel
{
    #region Поля и свойства

    // Ширина цифры без фаски и промежутков.
    double widthBlankSegment = 100;

    // Высота квадрата верхней или нижней половинок цифры.
    // Цифра состоит из верхней и нижней половинок.
    public double heightBlankSegment = 100;

    // Толщина сегментов - обрезанных (клипированных) полигонов.
    double thicknessSegment = 30;

    // Смещение точек линий смежных полигонов
    // к центральному полигону (элементу).
    // Для уравнивания толщины центрального сегмента
    double correctCenter = 10;

    // Смещение сегментов цифры друг от друга,
    // значение изменяет промежуток между сегментами.
    double _strokeThickness = 1;
    public double StrokeThickness
    {
        get { return _strokeThickness; }
        set { _strokeThickness = value; }
    }

    // Цвет сегментов цифры.
    SolidColorBrush _colorDigit = Brushes.Black;
    public SolidColorBrush ColorDigit
    {
        get { return _colorDigit; }
        set
        {
            _colorDigit = value;
            // Если в XAML был сброс или в других случаях,
            // то восстанавливаем кисть по умолчанию.
            if (value == null) _colorDigit = Brushes.Black;

            // Перерисовываем сегменты.
            DrawDigit(0, 0);
        }
    }

    #endregion


    #region Инициализация

    public Digit() : base()
    {
        // Размер цифры по умолчанию
        Width = 100;

        // Инициализация полигонов - сегментов цифры,
        // и добавления их в коллекцию дочерних сегментов
        // родительской панели.
        for (int i = 0; i < 7; i++)
        {
            Children.Add(new Polygon());
        }
    }

    #endregion


    #region Управление значением цифры

    // Визуализация значений цифры.
    public void ValueDigit(int digit)
    {
        switch (digit)
        {
            case 0:
                // Left
                Children[0].Opacity = 1;
                // Top
                Children[1].Opacity = 1;
                // Right
                Children[2].Opacity = 1;
                // Center
                Children[3].Opacity = 0;
                // LeftBottom
                Children[4].Opacity = 1;
                // Bottom
                Children[5].Opacity = 1;
                // RightBottom
                Children[6].Opacity = 1;

                break;
            case 1:
                // Left
                Children[0].Opacity = 0;
                // Top
                Children[1].Opacity = 0;
                // Right
                Children[2].Opacity = 1;
                // Center
                Children[3].Opacity = 0;
                // LeftBottom
                Children[4].Opacity = 0;
                // Bottom
                Children[5].Opacity = 0;
                // RightBottom
                Children[6].Opacity = 1;

                break;
            case 2:
                ...
                break;
            case 3:
                ...
                break;
            case 4:
                ...
                break;
            case 5:
                ...
                break;
            case 6:
                ...
                break;
            case 7:
                ...
                break;
            case 8:
                ...
                break;
            case 9:
                ...
                break;
        }
    }

    #endregion


    #region Вычисление размеров для сегментов цифры

    private void ComputeSize()
    {
        // Вычисление ширины цифры на основе заданной пользователем общей ширины.
        widthBlankSegment = Width - (2 * thicknessSegment / 3 +
            _strokeThickness * 2);

        // Высота сегментов половинки и ширина цифры всегда одинаковые.
        // Цифра состоит из верхней половинки и нижней половинки.
        heightBlankSegment = widthBlankSegment;

        // Корректировка толщины центрального сегмента,
        // для уравнивания с толщинами других сегментов.
        correctCenter = widthBlankSegment / 8;

        // Корректировка толщины сегментов цифры.
        thicknessSegment = widthBlankSegment / 4;

        // Вычисление общей высоты цифры с верхней и нижней половинками.
        Height = heightBlankSegment * 2 + 2 * thicknessSegment / 3 +
            _strokeThickness * 2 + _strokeThickness * 2;

        // Рисование полной цифры с новыми размерами.
        DrawDigit(0, 0);
    }

    #endregion


    #region Рисование графики элементов цифры

    void DrawDigit(double x, double y)
    {
        x = x +
            // Смещение вправо на фаску левых сегментов
            thicknessSegment / 3 +
            // Смещение вправо на толщину промежутка
            // (смещение левых сегментов вправо для создания промежутка).
            _strokeThickness;

        // Смещение по высоте на фаску сегмента и
        // межсегментного промежутка
        // (смещения верхнего элемента вверх для создания промежутка между сегментами).
        y = y + thicknessSegment / 3 + _strokeThickness;

        // Рисование сегментов цифры.
        SegmentLeft(x, y, _colorDigit, _strokeThickness);
        SegmentTop(x, y, _colorDigit, _strokeThickness);
        SegmentRight(x, y, _colorDigit, _strokeThickness);
        SegmentCenter(x, y, _colorDigit, _strokeThickness);
        SegmentLeftBottom(x, y, _colorDigit, _strokeThickness);
        SegmentBottom(x, y, _colorDigit, _strokeThickness);
        SegmentRightBottom(x, y, _colorDigit, _strokeThickness);
    }

    void SegmentLeft(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        Polygon pg = (Polygon)Children[0];
        PointCollection Points = new()
        {
            // left
            new System.Windows.Point(x - widthBlankSegment / 2, y +
                heightBlankSegment / 2),
            // top
            new Point(x, y),
            // right
            new Point(x + widthBlankSegment / 2, y + heightBlankSegment / 2),
            // right2
            new Point(x + widthBlankSegment / 2, y + heightBlankSegment / 2 +
                correctCenter /*корректирвка центрального*/),
            // bottom
            new Point(x, y + heightBlankSegment)
        };
        pg.Points = Points;
        pg.Fill = color;

        TranslateTransform tt = new()
        {
            X = -strokeThickness
        };
        pg.RenderTransform = tt;

        // Обрезание прямоугольного полигона до трапеции.
        RectangleGeometry rg = new()
        {
            Rect = new Rect(x - thicknessSegment / 3, y,
                thicknessSegment, heightBlankSegment)
        };
        pg.Clip = rg;
    }

    void SegmentTop(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    void SegmentRight(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    void SegmentCenter(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    void SegmentLeftBottom(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    void SegmentBottom(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    void SegmentRightBottom(double x, double y, SolidColorBrush color, double strokeThickness)
    {
        ...
    }

    #endregion


    #region Переопределенные  методы класса Panel


    // Измерение дочерних элементов
    protected override Size MeasureOverride(Size availableSize)
    {
        Size panelDesiredSize = new();

        foreach (UIElement child in InternalChildren)
        {
            // Метод измерения Measure должен вызываться для
            // каждого дочернего элемента Panel,
            // в противном случае дочерние элементы
            // не будут иметь правильного размера или упорядочения.
            child.Measure(availableSize);
            panelDesiredSize = child.DesiredSize;
        }

        return panelDesiredSize;
    }


    // Размещение дочерних элементов
    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement child in InternalChildren)
        {
            // Родительский класс Panel будет вызывать Arrange(Rect)
            // для каждого дочернего элемента,
            // в противном случае дочерние элементы не будут отображаться правильно.
            child.Arrange(new Rect(new Point(), child.DesiredSize));
        }

        // Вычисление размеров всей цифры в зависимости от ширины панели.
        ComputeSize();

        return finalSize;
    }

    #endregion
}


Счетчик на графическом элементе Digit:
// Таймер счетчика
readonly DispatcherTimer dispatcherTimer;

public MainWindow()
{
    InitializeComponent();

    // Инициализация и запуск таймера.
    dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
    dispatcherTimer.Tick += DispatcherTimer_Tick; ;
    dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
}

int count = 0;
private void DispatcherTimer_Tick(object? sender, EventArgs e)
{
    // Разряд - десятки
    int pos1 = count / 10;
    // Разряд - единицы
    int pos2 = count % 10;

    digit1.ValueDigit(pos1);
    digit2.ValueDigit(pos2);

    // Периодические изменения цвета цифр.
    if (pos1 % 4 == 0) digit1.ColorDigit = digit2.ColorDigit = Brushes.Red;
    else if (pos1 % 3 == 0) digit1.ColorDigit = digit2.ColorDigit = Brushes.Green;
    else if (pos1 % 2 == 0) digit1.ColorDigit = digit2.ColorDigit = Brushes.Black;
    else digit1.ColorDigit = digit2.ColorDigit = Brushes.Blue;

    // Считаем до 100
    // и сброс в начало отсчета.
    count++;
    if (count == 100) count = 0;
}

// Обработчик события нажатия на кнопки управления.
private void Button_Click(object sender, RoutedEventArgs e)
{
    if(sender is Button button)
    {
        string? text = button.Content.ToString();

        switch (text)
        {
            case "Start":
                if (dispatcherTimer.IsEnabled == false) dispatcherTimer.Start();
                else dispatcherTimer.Stop();
                break;
            case "Zoom":
                if (digit1.Width == 80) digit1.Width = digit2.Width = 200;
                else digit1.Width = digit2.Width = 80;
                break;
        }
    }
}
 
Активность:
Пока что здесь никого нет