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

Microsoft Robotics Pad GUI 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.61/5 (9投票s)

2007年9月9日

3分钟阅读

viewsIcon

34830

downloadIcon

603

一篇关于创建将使用 Microsoft Robotics Environment 的游戏手柄图形用户界面服务的文章。

The main form

引言

之前的文章中,我们创建了一个游戏手柄服务。在这里,我们将创建另一个服务,该服务将提供关于手柄的图形反馈。即使对于这篇文章,请记住,这并不是一个CCRDSS教程,并且对这些技术的良好了解将非常有用。在本文中,我假设您知道什么是消息、队列和服务。我也会跳过与之前服务相似的所有操作:服务创建、消息定义和消息处理。

基本思路是这样的:GUI服务可以接收一些消息,在相应的消息处理程序中,UI表单元素会被修改。

架构

我决定创建一个服务而不是修改手柄服务表单,以避免模块之间的紧耦合。GUI服务总是比单个表单更可重用。它也可以用于处理不同的硬件,例如操纵杆。关于消息的几句话:在此,服务被定义为所有Pad服务消息,因此我们在两个服务消息之间存在一对一的关系。我不认为这是与“手柄服务”的耦合,因为消息定义是相当抽象的。请记住,此服务假定摇杆范围在[-1,1]中。请记住,服务消息具有相同的类名,但定义在两个不同的命名空间内。

图形用户界面

解决方案有两个项目

  • Pad.Controls:包含一个简单的摇杆仪表用户控件
  • PadGui:包含消息定义和主窗体的服务。

主窗体有两个摇杆控件和 4 个标签,当按下按钮时,这些标签将变为红色。我们还有一个关于框。在主窗体内部,声明了几个属性来处理手柄状态。在StickGauge类中,定义了两个属性来处理xy摇杆位置。每当值更改时,都会执行Invalidate(),并且相应的OnPaint代码如下

private void panelPainter_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawEllipse(
        new Pen(Brushes.Red), 5, 5, panelPainter.Width - 10, 
                        panelPainter.Height - 10);

    e.Graphics.FillEllipse(
        Brushes.Red,
        panelPainter.Width / 2 - 5, panelPainter.Height / 2 - 5, 10f, 10f);

    int x = Convert.ToInt32((_x + 1) * panelPainter.Width / 2);
    int y = Convert.ToInt32((_y + 1) * panelPainter.Height / 2);

    e.Graphics.FillEllipse(Brushes.Blue, x - 5, y - 5, 10, 10);

    e.Graphics.DrawCurve(new Pen(Brushes.Blue),
        new Point[]{
            new Point(panelPainter.Width/2,0),
            new Point(x,y),
            new Point(panelPainter.Width/2,panelPainter.Height),
        });

    e.Graphics.DrawCurve(new Pen(Brushes.Blue),
       new Point[]{
            new Point(0,panelPainter.Height/2),
            new Point(x,y),
            new Point(panelPainter.Width,panelPainter.Height/2),
        });

    txtXY.Text = string.Format("X({0})       
            Y({1})",Math.Round(_x,4),Math.Round(_y,4));
}

这并不是一个真正令人惊叹的图形体验,但它非常适合进行设备反馈。

服务

在服务启动阶段,我使用这个代码片段来启动一个窗口。请记住添加对程序集Ccr.Adapters.WinForms.dll的引用

using Microsoft.Ccr.Adapters.WinForms;

...

//Create Form

PadInfoForm _form = new PadInfoForm();


WinFormsServicePort.Post(new RunForm(
    delegate()
    {
        return _form;
    }
));

并且每当收到消息时,我们执行以下操作

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
public IEnumerator<ITask> RightStickUpdateHandler(RightStickUpdate rsUpd)
{
    _form.RX = rsUpd.Body.Stick.StickValueX;
    _form.RY = rsUpd.Body.Stick.StickValueY;
    rsUpd.ResponsePort.Post(DefaultUpdateResponseType.Instance);
    yield break;
}

分配给表单属性会导致摇杆更新。

结论

如果您正在询问谁向GUI服务发送消息,那么您就走对了路。在这里,我们创建了一个活动服务,该服务向其他服务发送通知。相反,这个服务有点像一个“被动服务”。它只接收消息,这样我们就可以编译和运行这个服务,但是只要我们不向这个服务发送消息,我们就不会得到任何反馈。这是我将要写的下一篇文章的目的。我将使用VPL来连接手柄服务和手柄GUI服务。这个服务的下一个改进将是一个WPF界面。

就是这样!

历史

  • 2007年9月:首次发布
© . All rights reserved.