Exemplo da coleção de tinta RealTimeStylus
Este aplicativo demonstra a coleta e a renderização de tinta ao usar a classe RealTimeStylus .
O Projeto InkCollection
Este exemplo consiste em uma única solução que contém um projeto, InkCollection. O aplicativo define o InkCollection
namespace que contém uma única classe, também chamada InkCollection
. A classe herda da classe Form e implementa a interface IStylusAsyncPlugin .
namespace InkCollection
{
public class InkCollection : Form, IStylusAsyncPlugin
{
//...
A Classe InkCollection define um conjunto de constantes privadas usadas para especificar várias espessuras de tinta. A classe também declara instâncias privadas da classe RealTimeStylus, myRealTimeStylus
, a classe DynamicRenderer e myDynamicRenderer
a classe myRenderer
Renderer . O DynamicRenderer renderiza o Traço que está sendo coletado no momento. O objeto Renderer, myRenderer
, renderiza objetos Stroke que já foram coletados.
private const float ThinInkWidth = 10;
private const float MediumInkWidth = 100;
private const float ThickInkWidth = 200;
private RealTimeStylus myRealTimeStylus;
private DynamicRenderer myDynamicRenderer;
private Renderer myRenderer;
A classe também declara um objeto Hashtable , myPackets
, que é usado para armazenar dados de pacotes que estão sendo coletados por um ou mais objetos Cursor . Os valores de ID do objeto Stylus são usados como a chave de tabela de hash para identificar exclusivamente os dados de pacote coletados para um determinado objeto Cursor.
Uma instância privada do objeto Ink , myInk
, armazena objetos Stroke coletados por myRealTimeStylus
.
private Hashtable myPackets;
private Ink myInk;
O evento de carregamento de formulário
No manipulador de eventos Load para o formulário, myDynamicRenderer
é instanciado usando o DynamicRenderer que assume um controle como argumento e myRenderer
é construído com um construtor sem argumento.
private void InkCollection_Load(object sender, System.EventArgs e)
{
myDynamicRenderer = new DynamicRenderer(this);
myRenderer = new Renderer();
// ...
Preste atenção ao comentário que segue a instanciação dos renderizadores, pois myDynamicRenderer
usa os valores padrão para DrawingAttributes ao renderizar a tinta. Esse é o comportamento padrão. No entanto, se você quiser fornecer a tinta renderizada por myDynamicRenderer
uma aparência diferente da tinta renderizada por myRenderer
, poderá alterar a propriedade DrawingAttributes em myDynamicRenderer
. Para fazer isso, remova o comentário das linhas a seguir antes de compilar e executar o aplicativo.
// myDynamicRenderer.DrawingAttributes.PenTip = PenTip.Rectangle;
// myDynamicRenderer.DrawingAttributes.Height = (.5F)*MediumInkWidth;
// myDynamicRenderer.DrawingAttributes.Transparency = 128;
Em seguida, o aplicativo cria o objeto RealTimeStylus que é usado para receber notificações de caneta e adiciona o objeto DynamicRenderer à fila de notificação de plug-in síncrona. Especificamente, myRealTimeStylus
adiciona myDynamicRenderer
à propriedade SyncPluginCollection .
myRealTimeStylus = new RealTimeStylus(this, true);
myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);
Em seguida, o formulário é adicionado à fila de notificação de plug-in assíncrona. Especificamente, InkCollection
é adicionado à propriedade AsyncPluginCollection . Por fim, myRealTimeStylus
e myDynamicRenderer
estão habilitados, e myPackets e myInk são instanciados.
myRealTimeStylus.AsyncPluginCollection.Add(this);
myRealTimeStylus.Enabled = true;
myDynamicRenderer.Enabled = true;
myPackets = new Hashtable();
myInk = new Ink();
}
Além de conectar os manipuladores de menu para alterar a cor e o tamanho da tinta, mais um breve bloco de código é necessário antes de implementar a interface. O exemplo deve manipular o evento Paint do formulário. No manipulador de eventos, o aplicativo deve ser atualizado myDynamicRenderer
porque é possível que um objeto Stroke esteja sendo coletado no momento em que o evento Paint ocorre. Nesse caso, a parte do objeto Stroke que já foi coletada precisa ser redesenhada. O Renderizador estático é usado para desenhar novamente objetos Stroke que já foram coletados. Esses traços estão no objeto Ink porque são colocados lá quando desenhados, conforme mostrado na próxima seção.
private void InkCollection_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
myDynamicRenderer.Refresh();
myRenderer.Draw(e.Graphics, myInk.Strokes);
}
Implementando a interface IStylusAsyncPlugin
O aplicativo de exemplo define os tipos de notificações que tem interesse em receber na implementação da propriedade DataInterest . Portanto, a propriedade DataInterest define quais notificações o objeto RealTimeStylus encaminha para o formulário. Para este exemplo, a propriedade DataInterest define o interesse nas notificações StylusDown, Packets, StylusUp e Error por meio da enumeração DataInterestMask .
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
A notificação StylusDown ocorre quando a caneta toca na superfície do digitalizador. Quando isso acontece, o exemplo aloca uma matriz usada para armazenar os dados do pacote para o objeto Stylus . O StylusDownData do método StylusDown é adicionado à matriz e a matriz é inserida no hashtable usando a propriedade Id do objeto Stylus como uma chave.
public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
ArrayList collectedPackets = new ArrayList();
collectedPackets.AddRange(data.GetData());
myPackets.Add(data.Stylus.Id, collectedPackets);
}
A notificação pacotes ocorre quando a caneta se move na superfície do digitalizador. Quando isso ocorre, o aplicativo adiciona o novo StylusDownData à matriz de pacotes para o objeto Stylus . Ele faz isso usando a propriedade Id do objeto Stylus como a chave para recuperar a matriz de pacotes para a caneta do hash. Em seguida, os novos dados de pacote são inseridos na matriz recuperada.
public void Packets(RealTimeStylus sender, PacketsData data)
{
((ArrayList)(myPackets[data.Stylus.Id])).AddRange(data.GetData());
}
A notificação stylusUp ocorre quando a caneta deixa a superfície do digitalizador. Quando essa notificação ocorre, o exemplo recupera a matriz de pacotes para esse objeto Stylus do hashtable-removendo-o do hashtable, pois ele não é mais necessário, adiciona os novos dados de pacote e usa a matriz de dados de pacote para criar um novo objeto Stroke , stroke
.
public void StylusUp(RealTimeStylus sender, StylusUpData data)
{
ArrayList collectedPackets = (ArrayList)myPackets[data.Stylus.Id];
myPackets.Remove(data.Stylus.Id);
collectedPackets.AddRange(data.GetData());
int[] packets = (int[])(collectedPackets.ToArray(typeof(int)));
TabletPropertyDescriptionCollection tabletProperties =
myRealTimeStylus.GetTabletPropertyDescriptionCollection(data.Stylus.TabletContextId);
Stroke stroke = myInk.CreateStroke(packets, tabletProperties);
if (stroke != null)
{
stroke.DrawingAttributes.Color = myDynamicRenderer.DrawingAttributes.Color;
stroke.DrawingAttributes.Width = myDynamicRenderer.DrawingAttributes.Width;
}
}
Para obter um exemplo que mostra um uso mais robusto da classe RealTimeStylus , incluindo o uso da criação de plug-in personalizado, consulte Exemplo de plug-in RealTimeStylus.
Tópicos relacionados