Rendering Collected Information
One of the simplest things to do with the information you get from the plug-in is custom rendering of the received information. The following example draws a small circle at the pen coordinates you received. Pressure information is used to determine the radius of the circle.
Public Sub Packets(ByVal s As RealTimeStylus, _
ByVal data As PluginData.PacketsData) _
Dim g As Graphics = _
Dim packetCounter As Integer
For packetCounter = 0 To _
data.Count - data.PacketPropertyCount _
Dim iX As Integer
Dim iY As Integer
Dim iPressure As Integer = 10
iX = g.DpiX * data(packetCounter) / 2540
iY = g.DpiY * data(packetCounter+1) / 2540
If data.PacketPropertyCount > 2 Then
iPressure = data(packetCounter+2) / 20
iX - iPressure, iY - iPressure, _
iPressure * 2, iPressure * 2)
|Figure 1: Custom Rendering: The figure shows custom circles being rendered at the point of pen contact with the screen, using pressure information to determine the radius of the circle.|
You can see the results of the preceding code in Figure 1
. At this point, you have reproduced many of the features a normal InkCollector provides, replacing them with custom functionality. The advantage of this approach is that you have full control and can thus create completely different renderings of Ink "written" or "drawn" with the stylus.
This can be used for much more sophisticated effects than drawing circles of different sizes. Charles Petzold has a nice example
, where the "Ink" automatically has a drop-shadow. A similar example adds a glow effect to the Ink. Larry O'Brien has an interesting example
that uses pen information to draw Ink in 3D space, using pressure or elapsed time as the third dimension. Limits are set only by your imagination.
|Figure 2: Beyond Ink: This figure shows a kaleidoscopic effect produced by mirroring the drawing actions on three different axes.|
Another option is to go beyond drawing "Ink" wherever the pen touches the display. The example in Listing 6
shows a simple kaleidoscope, where the drawing is automatically mirrored on three axes. The code change in this example is that you now store references to four controls rather than just one. The first is the one you actually draw on. It is a panel on a form, rather than the form itself, as in the previous examples. The other three controls are simply used to draw each drawing point at a mirrored position. Figure 2
shows the result.
Modifying Collected Information
One of the great advantages of the Real Time Stylus is that you have full control over the data received from the API. This includes the ability to modify data as it is being received. A simple example that demonstrates that capability is the restriction of Inking to a specific area within a control. To keep this example simple, use a rectangle as the allowed Ink area, although the same concept can be used for any shape. Figure 3
shows the example at work.
|Figure 3: Restricting the Ink Area: Here's an example of restricting the rectangle within which Ink appears.|
shows the implementation of that functionality. The main difference between this example and the version that collected data and drew circles at the pen position is the ModifyData()
method. This method is called from the Packet()
method before any other processing happens. It compared the X and Y coordinates received from the stylus plug-in and checks whether they fall within the boundaries of a rectangle you define in the constructor of the plug-in (that's what I did to keep things simple for this example-the confining rectangle could be created or modified anywhere).
The tricky part is that in most scenarios, the inkable area is more easily defined in screen coordinates. You first need to map the X and Y coordinates from digitizer resolution to screen resolution, then check whether they are in a valid area; if not, move them into a valid area and translate them back to digitizer resolution. Luckily, this sounds more difficult than it really is, as you can see in Listing 7
Note that you didn't just translate the values before you drew on the screen, but you changed the data in the actual packet data object. This means that other code (plug-ins) using the same data gets the modified version.