创建循环GUI

时间:2014-03-10 23:21:18

标签: wpf visual-studio-2012 user-interface

因此,我最近的一个项目是开发应用程序检测和填充助手。以编程方式我绝对很好地填充后端代码以实现我想要的功能。但是我在GUI上遇到了障碍。我需要一个GUI,它是一个Quarter圆,从任务栏延伸到标准Windows操作系统的右下角。当用户双击应用程序时,圆圈将旋转到视图中。我可以使用具有透明背景和精美背景图像的典型窗体来完成此操作。但是,当用户打开应用程序时,表单的方形属性仍将适用。当圈子打开时,我不想阻止用户使用优先级较高的应用程序。

The edges must be not be selectable

我并没有真正陷入任何一种特定的编程语言。虽然,我希望它不包含太多的3d渲染,因为它应该是一个计算助手,并且在用户浏览时不应该保持大量的RAM / CPU消耗。

其次,我希望外圈的凹槽可以移动并延伸超过gui仅一厘米左右。

如果我没有在互联网上搜索此功能的方向,我就不会在这里。但我发现应用程序GUI这种性质往往最常用于移动环境。

所以我的问题是:我怎样才能做到这一点?我可以用什么编程语言编写?这是目前可用的功能吗?我是否必须牺牲用户对设计的控制?

2 个答案:

答案 0 :(得分:15)

我写了一些代码,做了一些接近你所描述的事情。

我不确定你是怎么想要圆圈出现的,所以我只是让它的一部分始终可见。 我没有得到关于移动外圈的部分。

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设置为exclude。然后我创建一个足够高的三角形,以包含我想要的环的部分,并保持这些形状的交集。

使用设置为xor的第二个CombineMode查看它可能会澄清:

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定义两个连续片段之间的空白。

动画圆圈

最后一步是展开圆圈。在路径rendertransform上使用rotateAnimation可以轻松实现。 记住CreateCirclePart函数的这一部分:

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

RenderTransform告诉我们要执行的动画是旋转,RenderTransformOrigin将旋转原点设置为形状的右下角(单位为百分比)。 我们现在可以在点击事件中为其设置动画:

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);
        }

答案 1 :(得分:9)

实际上并没有回答这个问题,但我非常喜欢你的问题,我希望得到一个简单的概念证明,以获得乐趣,我真的很喜欢这样做,所以我想我会和你分享我的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