WPF 中的牙科椅自动化






4.88/5 (67投票s)
演示了如何使用 WPF 和 C# 在图形化设备或设备自动化中。

引言
本文简要介绍了如何以牙科椅为例来自动化任何设备。我的目标是概述 WPF 和 C# 如何最终用于任何自动化项目的图形设计和呈现。
要求
要运行项目,您需要以下条件
- Visual Studio 2008 或
- Expression Blend 4
背景
突然,我的脑海里闪过一个关于在自动化项目中使用 WPF 的想法。然后,我开始思考哪种设备可以更好地自动化。所以我考虑使用牙科椅作为要自动化的设备。这个项目需要少量艺术技能来设计演示所需的物体。您需要列出您的设备应执行的活动,然后继续设计图形对象。所以,在不进行太多修改的情况下更好地使用它会更合适。该项目展示了 WPF 中的转换对象如何更好地用于演示和自动化过程。
工作原理
要查看牙科椅和风扇如何自动化,只需观看项目中运行的动画中显示的说明。
可自动化的对象
壁扇:单击风扇上的按钮。左按钮用于打开,右按钮用于关闭。

灯:单击灯具中的开关,将灯切换到开和关状态。

灯柄:按住鼠标左键单击灯柄,然后向上和向下移动手柄。

水龙头:点击水龙头使水向下流,反之则停止水流。

椅子:单击椅子底部的按钮,将椅子向前(下按钮)和向后(上按钮)移动。

头枕:单击头枕上的按钮,将头枕向前和向后移动。

仪表:按住鼠标左键单击仪表并移动仪表。

设计和布局
牙科椅和风扇的设计使用 Microsoft Expression Design 完成。房间布局和说明动画在 Expression Blend 中完成。编码部分在 Visual Studio 2008 中完成。自动化过程(移动)是通过 WPF 中的转换类实现的。
椅子移动

椅子的移动是使用旋转变换实现的。屏幕截图所示的旋转中心是在 x 和 y 轴方向上的座椅底座的中心。正如屏幕截图所示,中心不完全符合实际,但我们需要将中心设为该点。在该点的旋转将产生前后移动座椅的感觉。下面的代码将使椅子前后移动。每次单击椅子按钮时,椅子都会移动到指定角度。角度根据用户单击的按钮进行增减。如果用户单击顶部按钮,则角度减 0.5,单击底部按钮时则角度增 0.5。
//Check if the angle less than -2 for backwards bend.
if (angle > -2)
{
//Decrease the angle by .5 for each click
angle -= 0.5f;
//The angle is assigned to rotation transform object.
chairRotate.Angle = angle;
//Assign the x and y axis to 0 to rotate the chair at that point.
chairRotate.CenterX = 0;
chairRotate.CenterY = 0;
//Finally assign the transform object to be rendered to the seatbase that is midstand.
MidStand.RenderTransform = chairRotate;
}
///Check if the angle less than or equal to 12.
if (angle <= 12)
{
//Increment the angle by .5 if user clicks the down button
angle += 0.5f;
//The angle is assigned to rotation transform object.
chairRotate.Angle = angle;
//Assign the x and y axis to 0 to rotate the chair at that point.
chairRotate.CenterX = 0;
chairRotate.CenterY = 0;
//Finally assign the transform object to be rendered to the seatbase that is midstand.
MidStand.RenderTransform = chairRotate;
}
...
注意:头枕的旋转也采用了相同的策略。
灯柄移动

灯柄的移动是通过旋转变换实现的。标记为旋转中心的点是灯柄连接的点。灯柄以该点为中心旋转。因此,它会产生灯柄连接处可以上下转动的视图。这里需要注意的点是捕获灯柄上的鼠标点。捕获鼠标点是为了确定灯柄是应该向上还是向下移动。因此,每次鼠标移动时,角度都会增加或减少 1。这使用户能够通过鼠标看到灯柄向上和向下移动。下面提供的代码显示了有助于灯柄移动的鼠标移动计算。
//Capture the previous mouse point to decide whether to move up or down
previousheight = height;
//Capture the mouse movement at that point
MouseDevice d = e.MouseDevice;
Point p = d.GetPosition(this);
height = p.Y;
//Check whether the left button of the mouse is pressed or not.
if (e.LeftButton == MouseButtonState.Pressed)
{
//Check if the angle less than 25 to limit the rotation
if (lightHandleangle < 25)
{
//If previous mouse point is greater than current
if (previousheight >= height)
{
//Increment the angle by 1.
lightHandleangle += 1;
//Assign the angle to the rotate transform object
lightHandleRotate.Angle = lightHandleangle;
//Assign the x and y axis to 0
lightHandleRotate.CenterX = 0;
lightHandleRotate.CenterY = 0;
//Assign the rotate trans object to handle to transform to that angle specified.
LightHandle.RenderTransform = lightHandleRotate;
}
//Perform the check to see if previous is less than current mouse
//position to move the light handle down and above the minimum height.
if (previousheight <= height && previousheight != 0 && lightHandleangle > -15)
{
//Decrement the angle by 1
lightHandleangle -= 1;
lightHandleRotate.Angle = lightHandleangle;
lightHandleRotate.CenterX = 0;
lightHandleRotate.CenterY = 0;
LightHandle.RenderTransform = lightHandleRotate;
return;
}
}
//Check if the angle is greater then the minimum height that is -15(downwards)
else
{
if (lightHandleangle > -15)
{
if (previousheight <= height && previousheight != 0)
{
lightHandleangle -= 1;
lightHandleRotate.Angle = lightHandleangle;
lightHandleRotate.CenterX = 0;
lightHandleRotate.CenterY = 0;
LightHandle.RenderTransform = lightHandleRotate;
return;
}
}
}
}
水龙头出水

水龙头中的水是使用 WPF 动画对象,即 Storyboard 来模拟的。设计部分在 Expression Design 中完成。观察水中的小颗粒黑点。在动画过程中,水线中的黑色物体向下移动。这产生了水从水龙头流下的视图。动画的 XAML 代码如下:
<Storyboard x:Key="WaterFall" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop8">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="3.375"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="10.75"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="13.25"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop3">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1.25"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="2.75"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="6.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="9.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop6">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="2.5"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="4.75"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="8.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="11.75"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop2">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="2.5"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="4.5"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="8.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="11.375"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop7">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="2.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="4.875"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="9.375"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="11.875"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop1">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="2"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="5.25"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="8.25"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="12.375"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop4">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="3.875"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="7.25"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="8.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="-23.25"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.Y)" Storyboard.TargetName="Drop5">
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="3.625"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="-28.75"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="-22.5"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="-21.25"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.X)" Storyboard.TargetName="Drop5">
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="0.125"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="-1.25"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
"(UIElement.RenderTransform).(TransformGroup.Children)[3].
(TranslateTransform.X)" Storyboard.TargetName="Drop4">
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="0.125"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
注意:风扇旋转和面板上的说明也是使用 WPF 动画完成的,这在源代码文件中清晰可见。
关注点
开发这篇文章非常有趣,因为它包括设计、编程、动画以及更多设计图形对象的逻辑内容。在设计图形对象之前,应在脑海中构思好,因为它是一种分层方法。在设计中放置图层是一个非常有挑战性的方面。在设计时,您需要同时考虑编程方面和演示方面。如果忽略任何一个方面,就需要进行大量返工。在进行 Expression Design 之前,请先练习小对象。
结论
感谢您花时间阅读本文。这可能在某种程度上对您有所帮助,至少可以以某种方式实现策略。您仍然可以为这个项目添加许多功能,这取决于您的想象力和逻辑思维。这是我的开始,我永远不会停止发布文章。您将来会发现我发布非常有趣的文章。