因此,我最近的一个项目是开发应用程序检测和填充助手。以编程方式我绝对很好地填充后端代码以实现我想要的功能。但是我在GUI上遇到了障碍。我需要一个GUI,它是一个Quarter圆,从任务栏延伸到标准Windows操作系统的右下角。当用户双击应用程序时,圆圈将旋转到视图中。我可以使用具有透明背景和精美背景图像的典型窗体来完成此操作。但是,当用户打开应用程序时,表单的方形属性仍将适用。当圈子打开时,我不想阻止用户使用优先级较高的应用程序。
我并没有真正陷入任何一种特定的编程语言。虽然,我希望它不包含太多的3d渲染,因为它应该是一个计算助手,并且在用户浏览时不应该保持大量的RAM / CPU消耗。
其次,我希望外圈的凹槽可以移动并延伸超过gui仅一厘米左右。
如果我没有在互联网上搜索此功能的方向,我就不会在这里。但我发现应用程序GUI这种性质往往最常用于移动环境。
所以我的问题是:我怎样才能做到这一点?我可以用什么编程语言编写?这是目前可用的功能吗?我是否必须牺牲用户对设计的控制?
答案 0 :(得分:15)
我写了一些代码,做了一些接近你所描述的事情。
我不确定你是怎么想要圆圈出现的,所以我只是让它的一部分始终可见。 我没有得到关于移动外圈的部分。
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查看它可能会澄清:
上面的代码使用了一些使其具有通用性的实例字段:您可以更改圆圈中的碎片数量或其半径;它将永远填补角落。
然后我填充一个包含所需形状数量的列表,并将它们添加到网格中:
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>
它看起来像这样: