Introduction
In the previous article, we created a game pad service. Here, we will create another service that will provide graphical feedback about the pad. Even for this article, remember that this is not a CCR or a DSS tutorial, and a good knowledge of these technologies will be very useful. In this article, I assume you know what messages, queues and services are. I will also skip all the actions that are similar to the previous service: service creation, message definition and message handling.
The base idea is this: the GUI service can receive some kinds of messages and in the corresponding message handlers, the UI forms elements are modified.
Architecture
I decided to create a service rather than modify the pad service form to avoid tight coupling modules. A GUI service is always more reusable than a single form. It can also be used to handle different hardwares such as a joystick. Few words about messages: in this, services are defined as ALL the Pad service messages so that we have a 1 to 1 relationship between the two services messages. I don't think this is a coupling to "Pad Service" because the message definition is quite abstract. Remember that this service assumes that stick ranges are in [-1,1]
. Remember that Service Messages have the same class name but are defined inside two different namespaces.
The GUI
The Solution has two projects:
Pad.Controls
: contains a simple stick gauge user control PadGui
: the service with messages definitions and the main form.
The main form has two stick controls and 4 labels which will be red when a button is pressed. We also have an About box. Inside the main form, several properties are declared to handle pad state. Inside the StickGauge
class, two properties are defined to handle x
and y
stick position. Whenever the values change, an Invalidate()
is performed and the corresponding OnPaint
code is as follows:
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));
}
This is not a really amazing graphic experience, but it is perfect to have device feedback.
The service
Inside the service startup phase, I use this snippet to start a Window. Remember to add a reference to the assembly Ccr.Adapters.WinForms.dll:
using Microsoft.Ccr.Adapters.WinForms;
...
PadInfoForm _form = new PadInfoForm();
WinFormsServicePort.Post(new RunForm(
delegate()
{
return _form;
}
));
And whenever a message is received, we perform the following actions:
[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;
}
The assignment to form property causes the stick update.
Conclusion
If you are asking who notifies messages to the GUI Service, you are on the right path. Right here, we created an Active Service that sends notifications to other services. This service instead is something like a "Passive Service". It receives only messages so that we can compile and run this service but we won't get any feedback as long as we don't send messages to this service. This is the aim of the next article that I'll write. I will use VPL to connect the pad service and the pad GUI service. The next improvement for this service will be a WPF Interface.
That's it!
History
- September 2007: First release