×
Namespaces

Variants
Actions

Como gerar e ler códigos de barras em Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search

Este artigo explica como gerar e ler códigos de barras em aplicações Windows Phone, usando a biblioteca ZXing.Net.

WP Metro Icon Multimedia.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata

Exemplo de código
Código fonte: Media:WPBarcodes.zip

Testado com
Aparelho(s): Nokia Lumia 800, Windows Phone 8 Emulator

Compatibilidade
Platform Security
Capabilities: ID_CAP_ISV_CAMERA

Artigo
Tradução:
Por PedroQ
Última alteração feita por lpvalente em 25 Aug 2013
See Also

Contents

Introdução

Um código de barras é uma forma de representar informação de modo a que possa ser lida por uma máquina. É bastante comum encontrar códigos de barra no dia a dia, seja numa embalagem de comida, num livro, num CD. Em geral, o esse código de barras pode ser usado para identificar o objeto ao qual está anexado. Existem vários tipos e formatos de códigos de barras. Alguns são simplesmente grupos de linhas verticais paralelas, onde a informação é codificada ao variar a largura de cada linha. Estes são chamados os códigos de barras 1D (uma dimensão). Outros codificam a informação utilizando um conjunto de padrões geométricos. Estes são os códigos de barras 2D (ou códigos de matriz) e podem conter uma maior quantidade de informação. Um exemplo comum de um código de barras 2D é um formato chamado QR Code QR Code. Com a revolução dos smartphones, os QR Codes tornaram-se bastante populares. Em publicidade, por exemplo, é possível visitar o site do produto ao ler um QR Code com o aparelho. Outro exemplo é a possibilidade de partilhar o seu cartão de visita de forma virtual.

Por defeito, tanto o Windows Phone 7 como o Windows Phone 8 são capazes de ler alguns tipos de códigos de barras (QR Code, EAN-13, Microsoft Tag) usando a aplicação Bing Vision (para usar, carregue no botão de pesquisa e depois escolha o ícone de um olho na application bar). Contudo, é por vezes necessário ler um código de barras que a Bing Vision não é capaz de ler. Ou pode querer adicionar esta funcionalidade diretamente dentro da sua aplicação (por exemplo, numa aplicação para gerir os DVD's que emprestou a amigos). Bibliotecas como a ZXing.Net podem ajudar nestas tarefas.

Neste artigo é explicado como pode adicionar a capacidade de gerar e ler códigos de barras usando a câmara do telemóvel a uma aplicação Windows Phone. Para exe exemplo vamos criar uma simples aplicação que:

  • Gera um QR Code que contém o número de telemóvel de um contacto escolhido pelo utilizador.
  • É capaz de ler códigos de barras e mostrar a informação neles contida.

Bibliotecas

Vamos usar uma biblioteca chamada ZXing.Net, uma implementação .Net da popular biblioteca ZXing, que permite trabalhar com códigos de barras. A ZXing.Net está disponível como um pacote NuGet, portanto vamos usar este método para adicionar esta referência ao nosso projeto.

Na janela Solution Explorer, clique com o botão direito no ficheiro do projeto e selecione Manage NuGet Packages. Procure por ZXing.Net e clique em Install. Pode também usar a Package Manager Console para adicionar esta referência. Basta para isso executar o seguinte comando: PM> Install-Package ZXing.Net.

Gerar códigos de barras

Para exemplificar como gerar um código de barras, vamos criar um QR Code que contenha o número de telefone. Vamos usar a PhoneNumberChooserTask para permitir permitir ao utilizador escolher o número de telefone de um dos contactos.

PhoneNumberChooserTask phoneNumberChooserTask;
phoneNumberChooserTask = new PhoneNumberChooserTask();
phoneNumberChooserTask.Completed += phoneNumberChooserTask_Completed;


E depois geramos o QR Code com o número de telefone escolhido:

private static WriteableBitmap GenerateQRCode(string phoneNumber)
{
BarcodeWriter _writer = new BarcodeWriter();
 
_writer.Renderer = new ZXing.Rendering.WriteableBitmapRenderer()
{
Foreground = System.Windows.Media.Color.FromArgb(255, 0, 0, 255) // blue
};
 
_writer.Format = BarcodeFormat.QR_CODE;
 
 
_writer.Options.Height = 400;
_writer.Options.Width = 400;
_writer.Options.Margin = 1;
 
var barcodeImage = _writer.Write("tel:" + phoneNumber); //tel: prefix for phone numbers
 
return barcodeImage;
}

A classe BarcodeWriter possui várias propriedades que permitem personalizar o código de barras gerado:

  • A propriedade Renderer define o aspeto do código de barras, tal como a sua cor, a cor de fundo, tipo de letra e o seu tamanho. Neste exemplo escolhemos gerar um código de barras azul sobre um fundo branco (por omissão).
  • A propriedade Format define o tipo de código de barras que será gerado. Para este exemplo escolhemos QR Code.
  • A propriedade Options permite definir as dimensões do código de barras que será gerado, bem como as suas margens.

Deverá ter reparado que neste caso foi colocado um prefixo tel: antes da informação que se pretende codificar. Isto permite aos leitores de QR Code entender que a informação contida neste código de barras é um número de telefone. Este tipo de códigos de barras, o QR Code, permite vários prefixos deste género. Uma lista detalhada destes prefixos pode ser consultada aqui.

Aqui fica o exemplo do QR Code gerado:

Exemplo de QR Code que contém um número de telefone

Estes são outros exemplos de códigos de barras que podem ser gerados:

Ler códigos de barras

Adicionar a funcionalidade de leitura de códigos de barras a uma aplicação pode por vezes ser bastante útil. Por exemplo, numa aplicação de pesquisa de preços, seria muito mais fácil para o utilizador apontar a câmara do telemóvel para o código de barras e clicar em Pesquisar.

Na aplicação exemplo esta funcionalidade encontra-se no ficheiro Scan.xaml. Esta página contém um visor para que o utilizador possa ver para onde a câmara está a apontar e uma área onde são mostradas as informações sobre os códigos de barras lidos. Partes deste exemplo foram retiradas dos seguintes artigos: How to create a base camera app for Windows Phone e How to use camera focus in an app for Windows Phone.

Este é o código XAML da página:

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
 
<Canvas x:Name="viewfinderCanvas">
 
<!--Camera viewfinder -->
<Canvas.Background>
 
<VideoBrush x:Name="viewfinderBrush">
<VideoBrush.RelativeTransform>
<CompositeTransform
x:Name="viewfinderTransform"
CenterX="0.5"
CenterY="0.5"
Rotation="90"/>
</VideoBrush.RelativeTransform>
</VideoBrush>
</Canvas.Background>
<TextBlock
x:Name="focusBrackets"
Text="[ ]"
FontSize="40"
Visibility="Collapsed"/>
</Canvas>
<!--Used for debugging >-->
<StackPanel Grid.Row="1" Margin="20, 0">
<TextBlock x:Name="tbBarcodeType" FontWeight="ExtraBold" />
<TextBlock x:Name="tbBarcodeData" FontWeight="ExtraBold" TextWrapping="Wrap" />
</StackPanel>
</Grid>

E este é o código:

public partial class Scan : PhoneApplicationPage
{
private PhotoCamera _phoneCamera;
private IBarcodeReader _barcodeReader;
private DispatcherTimer _scanTimer;
private WriteableBitmap _previewBuffer;
 
public Scan()
{
InitializeComponent();
}
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Initialize the camera object
_phoneCamera = new PhotoCamera();
_phoneCamera.Initialized += cam_Initialized;
_phoneCamera.AutoFocusCompleted += _phoneCamera_AutoFocusCompleted;
 
CameraButtons.ShutterKeyHalfPressed += CameraButtons_ShutterKeyHalfPressed;
 
//Display the camera feed in the UI
viewfinderBrush.SetSource(_phoneCamera);
 
 
// This timer will be used to scan the camera buffer every 250ms and scan for any barcodes
_scanTimer = new DispatcherTimer();
_scanTimer.Interval = TimeSpan.FromMilliseconds(250);
_scanTimer.Tick += (o, arg) => ScanForBarcode();
 
viewfinderCanvas.Tap += new EventHandler<GestureEventArgs>(focus_Tapped);
 
base.OnNavigatedTo(e);
}
 
void _phoneCamera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
focusBrackets.Visibility = Visibility.Collapsed;
});
}
 
void focus_Tapped(object sender, GestureEventArgs e)
{
if (_phoneCamera != null)
{
if (_phoneCamera.IsFocusAtPointSupported == true)
{
// Determine the location of the tap.
Point tapLocation = e.GetPosition(viewfinderCanvas);
 
// Position the focus brackets with the estimated offsets.
focusBrackets.SetValue(Canvas.LeftProperty, tapLocation.X - 30);
focusBrackets.SetValue(Canvas.TopProperty, tapLocation.Y - 28);
 
// Determine the focus point.
double focusXPercentage = tapLocation.X / viewfinderCanvas.ActualWidth;
double focusYPercentage = tapLocation.Y / viewfinderCanvas.ActualHeight;
 
// Show the focus brackets and focus at point.
focusBrackets.Visibility = Visibility.Visible;
_phoneCamera.FocusAtPoint(focusXPercentage, focusYPercentage);
}
}
}
 
void CameraButtons_ShutterKeyHalfPressed(object sender, EventArgs e)
{
_phoneCamera.Focus();
}
 
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
//we're navigating away from this page, we won't be scanning any barcodes
_scanTimer.Stop();
 
if (_phoneCamera != null)
{
// Cleanup
_phoneCamera.Dispose();
_phoneCamera.Initialized -= cam_Initialized;
CameraButtons.ShutterKeyHalfPressed -= CameraButtons_ShutterKeyHalfPressed;
}
}
 
void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
{
if (e.Succeeded)
{
this.Dispatcher.BeginInvoke(delegate()
{
_phoneCamera.FlashMode = FlashMode.Off;
_previewBuffer = new WriteableBitmap((int)_phoneCamera.PreviewResolution.Width, (int)_phoneCamera.PreviewResolution.Height);
 
_barcodeReader = new BarcodeReader();
 
// By default, BarcodeReader will scan every supported barcode type
// If we want to limit the type of barcodes our app can read,
// we can do it by adding each format to this list object
 
//var supportedBarcodeFormats = new List<BarcodeFormat>();
//supportedBarcodeFormats.Add(BarcodeFormat.QR_CODE);
//supportedBarcodeFormats.Add(BarcodeFormat.DATA_MATRIX);
//_bcReader.PossibleFormats = supportedBarcodeFormats;
 
_barcodeReader.TryHarder = true;
 
_barcodeReader.ResultFound += _bcReader_ResultFound;
_scanTimer.Start();
});
}
else
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Unable to initialize the camera");
});
}
}
 
void _bcReader_ResultFound(Result obj)
{
// If a new barcode is found, vibrate the device and display the barcode details in the UI
if (!obj.Text.Equals(tbBarcodeData.Text))
{
VibrateController.Default.Start(TimeSpan.FromMilliseconds(100));
tbBarcodeType.Text = obj.BarcodeFormat.ToString();
tbBarcodeData.Text = obj.Text;
}
}
 
private void ScanForBarcode()
{
//grab a camera snapshot
_phoneCamera.GetPreviewBufferArgb32(_previewBuffer.Pixels);
_previewBuffer.Invalidate();
 
//scan the captured snapshot for barcodes
//if a barcode is found, the ResultFound event will fire
_barcodeReader.Decode(_previewBuffer);
 
}
 
}

Depois de ter implementadas as funcionalidades de acesso à câmara, a leitura de códigos de barras é bastante simples. A biblioteca ZXing.Net contém uma classe chamada BarcodeReader. É possível usar o método Decode para extrair a informação de um código de barras contido numa imagem, neste caso WriteableBitmap. Caso seja encontrado um código de barras, o evento ResultFound é disparado.

Neste caso, o DispatcherTimer _scanTimer é usado para obter uma imagem da câmara a cada 250ms que depois é usada pela classe BarcodeReader.

Por defeito, a classe BarcodeReader vai procurar por todos os tipos de códigos de barras suportados. Caso queira limitar este processo a apenas alguns formatos, tudo o que é necessário é definir a propriedade PossibleFormats. Caso verifique algumas dificuldades a ler códigos de barras, especialmente códigos 1D, pode tentar definir a propriedade TryHarder como true. Note que este modo pode ter algum impacto no desempenho. No entanto nos testes feitos com o meu Lumia 800, este impacto não é notório.

Aqui ficam alguns exemplos de códigos de barras lidos:

Sumário

Neste artigo vimos como é possível ler e gerar códigos de barras na plataforma Windows Phone usando a biblioteca ZXing.Net. Esta biblioteca suporta um vasto número de plataformas, o que poderá ser útil caso não esteja apenas a desenvolver para Windows Phone. Como esta é uma implementação de uma biblioteca muito usada em aplicações Android, encontrará muita documentação e exemplos que podem ajudar. Pode descarregar a aplicação de exemplo (File:WPBarcodes.zip) e experimentar. Existem outras bibliotecas que oferecem estas funcionalidades, por exemplo a suite Telerik RadControls for Windows Phone. Membros do Nokia Premium Developer Program for Lumia têm acesso gratuito a esta biblioteca.

This page was last modified on 25 August 2013, at 02:38.
273 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×