Создание кругового графического интерфейса

Таким образом, один из моих последних побочных проектов разрабатывает помощник по обнаружению приложений и заполнению. Программно я абсолютно точно заполняю бэкэнд-код для того, что хочу. Но я столкнулся с дорожным блоком в графическом интерфейсе. Мне нужен графический интерфейс, который представляет собой круг четверти, который простирается от панели задач до нижнего правого окна стандартной операционной системы Windows. Когда пользователь выполняет двойное нажатие на приложение, круг вращается в представлении. Я могу сделать это с типичной формой окна, которая имеет прозрачный фон и причудливое фоновое изображение. Но квадратные свойства формы будут по-прежнему применяться, когда пользователь открывает приложение. И я не хочу блокировать пользователя из приложений с более высоким приоритетом, когда круг открыт.

The edges must be not be selectable

Я действительно не зацикливаюсь ни на одном конкретном языке программирования. Хотя, я бы предпочел, чтобы он не содержал много 3D-рендеринга, поскольку он должен быть ассистентом вычислений и не должен поддерживать большое потребление ОЗУ/ЦП, пока пользователь просматривает.

Во-вторых, я хотел бы, чтобы вырезы внешних колец были мобильными и простирались за пределы всего сантиметра или около того.

Меня бы здесь не было, если бы я не пробовал интернет для направления этой возможности. Но то, что я нашел, - это графический интерфейс приложения такого типа, который обычно используется в мобильных средах.

Итак, мои вопросы: как я могу это сделать? На каком языке программирования я могу написать это? Возможно ли это в настоящее время? Придется ли мне жертвовать пользовательским контролем для дизайна?

Ответы

Ответ 1

Я написал какой-то код, делающий что-то близкое к тому, что вы описали.

Я не уверен, чтобы понять, как вы хотите, чтобы круг появился, поэтому я просто позволяю его части всегда видеть. И я не получил часть мобильного мобильного кольца.

circle gui

Создание и размещение окна

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

<Window x:Class="circle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Circle"
        Width="250"
        Height="250"
        AllowsTransparency="True"
        Background="Transparent"
        MouseDown="WindowClicked"
        ShowInTaskbar="False"
        WindowStyle="None">
    <Grid Name="Container"/>
</Window>

Чтобы поместить окно в нижнем правом углу, вы можете использовать SystemParameters.WorkArea в конструкторе:

public MainWindow()
{
    InitializeComponent();

    var desktopDim = SystemParameters.WorkArea;
    Left = desktopDim.Right - Width;
    Top = desktopDim.Bottom - Height;
}

Создание формы

Я создаю круг как кучу круговых фигур, которые я генерирую из кода:

private Path CreateCirclePart()
        {
            var circle = new CombinedGeometry
                {
                    GeometryCombineMode = GeometryCombineMode.Exclude,
                    Geometry1 = new EllipseGeometry { Center = _center, RadiusX = _r2, RadiusY = _r2 },
                    Geometry2 = new EllipseGeometry { Center = _center, RadiusX = _r1, RadiusY = _r1 }
                };

            var sideLength = _r2 / Math.Cos((Math.PI/180) * (ItemAngle / 2.0));
            var x = _center.X - Math.Abs(sideLength * Math.Cos(ItemAngle * Math.PI / 180));
            var y = _center.Y - Math.Abs(sideLength * Math.Sin(ItemAngle * Math.PI / 180));
            var triangle = new PathGeometry(
                new PathFigureCollection(new List<PathFigure>{
                    new PathFigure(
                        _center,
                        new List<PathSegment>
                            {
                                new LineSegment(new Point(_center.X - Math.Abs(sideLength),_center.Y), true),
                                new LineSegment(new Point(x,y), true)
                            },
                        true)
                }));

            var path = new Path
                {
                    Fill = new SolidColorBrush(Colors.Cyan),
                    Stroke = new SolidColorBrush(Colors.Black),
                    StrokeThickness = 1,
                    RenderTransformOrigin = new Point(1, 1),
                    RenderTransform = new RotateTransform(0),
                    Data = new CombinedGeometry
                        {
                            GeometryCombineMode = GeometryCombineMode.Intersect,
                            Geometry1 = circle,
                            Geometry2 = triangle
                        }
                };

            return path;
        }

Первый шаг - построить два концентрических круга и объединить их в CombinedGeometry с CombineMode, установленным для исключения. Затем я создаю треугольник, достаточно высокий, чтобы содержать участок кольца, который я хочу, и я сохраняю пересечение этих фигур.

Увидев это со вторым параметром CombineMode, установленным в xor, можно уточнить:

creating the shape

Построение круга

В приведенном выше коде используются некоторые поля экземпляров, которые делают его общим: вы можете изменить количество частей в круге или их радиус; он всегда будет заполнять угол.

Затем я заполняю список с нужным количеством фигур и добавляю их в сетку:

private const double MenuWidth = 80;
private const int ItemCount = 6;
private const double AnimationDelayInSeconds = 0.3;

private readonly Point _center;
private readonly double _r1, _r2;
private const double ItemSpacingAngle = 2;
private const double ItemAngle = (90.0 - (ItemCount - 1) * ItemSpacingAngle) / ItemCount;

private readonly List<Path> _parts = new List<Path>();
private bool _isOpen;

public MainWindow()
{
    InitializeComponent();

    // window in the lower right desktop corner
    var desktopDim = SystemParameters.WorkArea;
    Left = desktopDim.Right - Width;
    Top = desktopDim.Bottom - Height;

    _center = new Point(Width, Height);
    _r2 = Width;
    _r1 = _r2 - MenuWidth;

    Loaded += (s, e) => CreateMenu();
}

private void CreateMenu()
{
    for (var i = 0; i < ItemCount; ++i)
    {
        var part = CreateCirclePart();
        _parts.Add(part);
        Container.Children.Add(part);
    }
}

ItemSpacingAngle определяет пробел между двумя последовательными фрагментами.

Анимация круга

Последний шаг - развернуть круг. Использование rotateAnimation по пути rendertransform облегчает задачу. Помните эту часть функции CreateCirclePart:

RenderTransformOrigin = new Point(1, 1),
RenderTransform = new RotateTransform(0),

RenderTransform сообщает, что анимация, которую мы хотим выполнить, - это вращение, а RenderTransformOrigin задает начало вращения в правом нижнем углу формы (единица процента). Теперь мы можем анимировать его при событии click:

private void WindowClicked(object sender, MouseButtonEventArgs e)
        {
            for (var i = 0; i < ItemCount; ++i)
            {
                if (!_isOpen)
                    UnfoldPart(_parts[i], i);
                else
                    FoldPart(_parts[i], i);
            }
            _isOpen = !_isOpen;
        }

        private void UnfoldPart(Path part, int pos)
        {
            var newAngle = pos * (ItemAngle + ItemSpacingAngle);
            var rotateAnimation = new DoubleAnimation(newAngle, TimeSpan.FromSeconds(AnimationDelayInSeconds));
            var tranform = (RotateTransform)part.RenderTransform;
            tranform.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
        }

        private void FoldPart(Path part, int pos)
        {
            var rotateAnimation = new DoubleAnimation(0, TimeSpan.FromSeconds(AnimationDelayInSeconds));
            var tranform = (RotateTransform)part.RenderTransform;
            tranform.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
        }

Ответ 2

На самом деле я не ответил на этот вопрос, но мне очень понравился ваш вопрос, что я хотел получить минимальное доказательство концепции вместе для удовольствия, и мне очень понравилось это делать, поэтому я подумал, что поделюсь с вами xaml:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" x:Class="WpfApplication1.Window2"
        Title="Window2" Height="150" Width="150" Topmost="True" MouseLeftButtonDown="Window2_OnMouseLeftButtonDown"
        AllowsTransparency="True" 
OpacityMask="White" 
WindowStyle="None" 
Background="Transparent" >
    <Grid>
        <ed:Arc ArcThickness="40" 
        ArcThicknessUnit="Pixel" EndAngle="0" Fill="Blue" HorizontalAlignment="Left" 
        Height="232" Margin="33,34,-115,-116" Stretch="None" 
        StartAngle="270" VerticalAlignment="Top" Width="232" RenderTransformOrigin="0.421,0.471"/>
        <Button HorizontalAlignment="Left" VerticalAlignment="Top" Width="41" Margin="51.515,71.385,0,0" Click="Button_Click" RenderTransformOrigin="0.5,0.5">
            <Button.Template>
                <ControlTemplate>
                    <Path Data="M50.466307,88.795148 L61.75233,73.463763 89.647286,102.42368 81.981422,113.07109 z" 
                          Fill="DarkBlue" HorizontalAlignment="Left" Height="39.606" 
                          Stretch="Fill" VerticalAlignment="Top" Width="39.181"/>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>
</Window>

И это выглядит так: enter image description here