65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的牙科椅自动化

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (67投票s)

2011年6月17日

CPOL

5分钟阅读

viewsIcon

85179

downloadIcon

4388

演示了如何使用 WPF 和 C# 在图形化设备或设备自动化中。

DentalChair1.png

引言

本文简要介绍了如何以牙科椅为例来自动化任何设备。我的目标是概述 WPF 和 C# 如何最终用于任何自动化项目的图形设计和呈现。

要求

要运行项目,您需要以下条件

  • Visual Studio 2008 或
  • Expression Blend 4

背景

突然,我的脑海里闪过一个关于在自动化项目中使用 WPF 的想法。然后,我开始思考哪种设备可以更好地自动化。所以我考虑使用牙科椅作为要自动化的设备。这个项目需要少量艺术技能来设计演示所需的物体。您需要列出您的设备应执行的活动,然后继续设计图形对象。所以,在不进行太多修改的情况下更好地使用它会更合适。该项目展示了 WPF 中的转换对象如何更好地用于演示和自动化过程。

工作原理

要查看牙科椅和风扇如何自动化,只需观看项目中运行的动画中显示的说明。

可自动化的对象

壁扇:单击风扇上的按钮。左按钮用于打开,右按钮用于关闭。

DentalChair2.png

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

DentalChair3.png

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

DentalChair4.png

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

DentalChair5.png

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

DentalChair6.png

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

DentalChair7.png

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

DentalChair8.png

设计和布局

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

椅子移动

DentalChair9.png

椅子的移动是使用旋转变换实现的。屏幕截图所示的旋转中心是在 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;
}

...

注意:头枕的旋转也采用了相同的策略。

灯柄移动

DentalChair10.png

灯柄的移动是通过旋转变换实现的。标记为旋转中心的点是灯柄连接的点。灯柄以该点为中心旋转。因此,它会产生灯柄连接处可以上下转动的视图。这里需要注意的点是捕获灯柄上的鼠标点。捕获鼠标点是为了确定灯柄是应该向上还是向下移动。因此,每次鼠标移动时,角度都会增加或减少 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;
            }
        }
    }
}

水龙头出水

DentalChair11.png

水龙头中的水是使用 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 之前,请先练习小对象。

结论

感谢您花时间阅读本文。这可能在某种程度上对您有所帮助,至少可以以某种方式实现策略。您仍然可以为这个项目添加许多功能,这取决于您的想象力和逻辑思维。这是我的开始,我永远不会停止发布文章。您将来会发现我发布非常有趣的文章。

© . All rights reserved.