Desenvolvendo Aplicações Multitoque Desktop para Windows* 8 com Windows* Presentation Foundation

Por Bruno Sonnino

O lançamento do Sistema operacional Windows 8 transformou o toque em um cidadão de primeira classe, e os fabricantes de dispositivos iniciaram a introdução de novos dispositivos, com telas sensíveis ao toque, que estão ficando mais comuns e baratos. Além disso, os fabricantes introduziram uma nova categoria de dispositivos, os Ultrabook™ 2 em 1, que são leves e tem potência suficiente para serem usados como notebooks tradicionais, com teclado e mouse, ou como um tablet usando toque ou canetas para toque.

Estas máquinas abrem novas oportunidades para os desenvolvedores. Você pode habilitar suas aplicações para toque, fazendo-as mais fáceis de usar e mais amigáveis. Quando você cria um aplicativo Windows Store, esta funcionalidade vem de graça. Mas e as aplicações Desktop, o dia-a-dia de desenvolvedores de aplicações cliente? Vocês não foram esquecidos.

Na realidade, aplicações desktop já permitem usar toque, e o Windows Presentation Foundation (WPF) tem suporte a isso desde a versão 4.0, como você verá nesse artigo.

Design para Aplicações Multitoque

A Microsoft categorizou o toque para aplicações desktop usando três cenários: bom, melhor e ótimo.

Aplicações Boas

Com o Windows 8, toda aplicação desktop tem suporte a toque. Toda entrada de toque é traduzida em cliques de mouse e você não precisa mudar sua aplicação para isso. Uma vez que você criou um aplicativo desktop, ele funciona com toque. Usuários podem clicar nos botões, selecionar itens de lista ou caixas de texto com o dedo ou caneta e podem, inclusive, usar um teclado virtual se não houver um teclado físico disponível. Você pode ver este comportamento com o Gerenciador de Arquivos, a Calculadora, o Bloco de Notas ou qualquer uma de usas aplicações desktop.

Aplicações Melhores

O comportamento de toque do Windows 8 é bom e não necessita de muito esforço para desenvolvimento, mas não é o suficiente. Você pode ir um passo adiante ao adicionar suporte a gestos na aplicação. Gestos são ações que são executadas com um ou dois dedos e executam operações pré-definidas – por exemplo, um toque para selecionar, arrastar para movimentar, flick para selecionar o próximo item ou o anterior, pinçar para zoom e girar. Veja a Figura 1.



Figura 1. Gestos comuns

O Sistema operacional traduz estes gestos em mensagens WM_GESTURE. Você pode desenvolver um programa para manipular esta mensagem e processar os gestos, o que dará a suas aplicações um bônus, devido ao fato de que você pode suportar ações exclusivas de dispositivos habilitados ao toque.

Aplicações Ótimas

No melhor cenário, você pode desenvolver a melhor aplicação para toque, projetando-a para suportar toda a funcionalidade multitoque. Agora, você pode perguntar: “O meu projeto atual não é suficiente para toque? A minha aplicação já não funciona bem com toque?” A resposta, na maior parte das vezes, é não.

As aplicações desenvolvidas para toque são diferentes das aplicações convencionais em muitas coisas:

  • O dedo não é um mouse. Ele não tem a precisão de um mouse e, assim, a interface do usuário necessita de um reestudo. Botões, caixas de checagem e itens de lista devem ser grandes o suficiente, de maneira que os usuários possam selecioná-los com erro mínimo.
  • Aplicações multitoque podem não ter um teclado disponível. Embora os usuários possam usar um teclado virtual, isso não é o mesmo que usar o teclado físico. Repensar a interface do usuário para minimizar o uso de teclado pode fazer as aplicações mais fáceis de usar.
  • Podem ocorrer vários contatos de toque simultâneos. Com um mouse, o programa tem apenas um ponto de entrada, mas com aplicações multitoque, pode haver mais de uma entrada. Dependendo do dispositivo, o programa poderia aceitar 40 a 50 toques simultâneos (imagine uma mesa sensível ao toque com cinco ou seis jogadores).
  • Os usuários podem executar a aplicação em diversas orientações. Aplicações tradicionais são executadas em modo paisagem, mas isto não é verdadeiro em aplicações multitoque. O usuário pode girar o dispositivo e, em alguns casos, pode até haver mais de um usuário, como um em cada lado do dispositivo.
  • Os usuários não tem acesso fácil a toda a área do dispositivo. Se um usuário estiver segurando um tablete em suas mãos, pode ser difícil de acessar o centro do dispositivo, pois o usuário deverá segurá-lo com uma mão e usar a outra para tocá-lo.

Uma aplicação multitoque “ótima” deve suprir todos estes pontos, sem esquecer a entrada de dados tradicional, com mouse e teclado, ou as aplicações não funcionarão em dispositivos que não tem toque.

Suporte a Toque em WPF

Com o WPF, você pode criar aplicações que permitem o toque de maneira muito simples. Você pode adicionar gestos ou mesmo suporte completo a toque, com manipulações e inércia.

Adicionando Gestos a Sua Aplicação

Uma maneira de adicionar gestos a suas aplicações é processar a mensagem WM_GESTURE. O exemplo MTGestures, no Windows* 7 software development kit (SDK) mostra como fazer isso. Instale o Windows 7 SDK e vá para o diretório de exemplos (o link está na seção “Para Mais Informações”, ao final). A listagem 1 mostra o código.

Listagem 1. Processamento da mensagem WM_GESTURE no exemplo MTGesture

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
    bool handled;
    handled = false;

    switch (m.Msg)
    {
        case WM_GESTURENOTIFY:
            {
                // This is the right place to define the list of gestures
                // that this application will support. By populating 
                // GESTURECONFIG structure and calling SetGestureConfig 
                // function. We can choose gestures that we want to 
                // handle in our application. In this app we decide to 
                // handle all gestures.
                GESTURECONFIG gc = new GESTURECONFIG();
                gc.dwID = 0;                // gesture ID
                gc.dwWant = GC_ALLGESTURES; // settings related to gesture
                                            // ID that are to be turned on
                gc.dwBlock = 0; // settings related to gesture ID that are
                                // to be     

                // We must p/invoke into user32 [winuser.h]
                bool bResult = SetGestureConfig(
                    Handle, // window for which configuration is specified
                    0,      // reserved, must be 0
                    1,      // count of GESTURECONFIG structures
                    ref gc, // array of GESTURECONFIG structures, dwIDs 
                            // will be processed in the order specified 
                            // and repeated occurrences will overwrite 
                            // previous ones
                    _gestureConfigSize // sizeof(GESTURECONFIG)
                );

                if (!bResult)
                {
                   throw new Exception("Error in execution of SetGestureConfig");
                }
            }
            handled = true;
            break;

        case WM_GESTURE:
            // The gesture processing code is implemented in 
            // the DecodeGesture method
            handled = DecodeGesture(ref m);
            break;

        default:
            handled = false;
            break;
    }

    // Filter message back up to parents.
    base.WndProc(ref m);

    if (handled)
    {
        // Acknowledge event if handled.
        try
        {
            m.Result = new System.IntPtr(1);
        }
        catch (Exception excep)
        {
            Debug.Print("Could not allocate result ptr");
            Debug.Print(excep.ToString()); 
        }
    }
}

Você deve sobrepor o processamento de mensagens da janela, configurar os tipos de gestos que deseja, ao receber a mensagem WM_GESTURENOTIFY e processar a mensagem WM_GESTURE.

Como você pode ver, adicionar gestos ao uma aplicação C# não é uma tarefa simples. Felizmente, há maneiras melhores de fazer isso em WPF. WPF tem suporte à caneta e ativa o evento StylusSystemGesture quando o Sistema detecta um gesto de toque. Vamos criar agora um álbum de fotos que mostra todas as fotos na pasta de Imagens e permite movimentar entre as imagens com flicks para a direita ou para a esquerda.

Crie uma nova aplicação WPF e adicione à janela três colunas, dois botões e um controle Image. A Listagem 2 mostra o código.

Listagem 2. Markup XAML para a nova aplicação WPF

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="40" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="40" />
    </Grid.ColumnDefinitions>
    <Button Grid.Column="0" Width="30" Height="30" Content="<" />
    <Button Grid.Column="2" Width="30" Height="30" Content=">" />
    <Image x:Name="MainImage" Grid.Column="1" />
</Grid>

Então, crie um campo chamado _filesList e outro chamado _currentFile. Veja a Listagem 3.

Listagem 3. Criando os campos _filesList e _currentFile

private List<string> _filesList;
private int _currentFile;

No construtor da janela principal, inicialize FilesList com a lista de arquivos da pasta Minhas Imagens. Veja a Listagem 4.

Listagem 4. Construtor da janela principal

public MainWindow()
{
    InitializeComponent();
    _filesList = Directory.GetFiles(Environment.GetFolderPath(
        Environment.SpecialFolder.MyPictures)).ToList();
    _currentFile = 0;
    UpdateImage();
}

UpdateImage atualiza a imagem com a imagem atual, como mostrado na Listagem 5.

Listagem 5. Atualizando a imagem

private void UpdateImage()
{
    MainImage.Source = new BitmapImage(new Uri(_filesList[_currentFile]));
}

Em seguida, você deve criar duas funções para chamar a próxima imagem e a anterior. A Listagem 6 mostra o código.

Listagem 6. Funções para mostrar as imagens próxima e anterior

private void NextFile()
{
    _currentFile = _currentFile + 1 == _filesList.Count ? 0 : _currentFile + 1;
    UpdateImage();
}

private void PreviousFile()
{
    _currentFile = _currentFile == 0 ? _filesList.Count-1 : _currentFile - 1;
    UpdateImage();
}

O próximo passo é criar os manipuladores para o evento Click para os dois botões, que chamam estas funções.

Em MainWindow.xaml, digite o código da Listagem 7.

Listagem 7. Declarando os manipuladores de eventos Click em MainWindow.xaml

<Button Grid.Column="0" Width="30" Height="30" Content="<" Click="PrevClick"/>
<Button Grid.Column="2" Width="30" Height="30" Content=">" Click="NextClick"/>

Em MainWindow.xaml.cs, digite o código na Listagem 8.

Listagem 8. Criando os manipuladores de eventos Click em MainWindow.xaml.cs

private void PrevClick(object sender, RoutedEventArgs e)
{
    PreviousFile();
}

private void NextClick(object sender, RoutedEventArgs e)
{
    NextFile();
}

Ao executar o programa, você verá que ele mostra as imagens de Minhas Imagens. Clicando os botões você pode trocar as imagens. Agora, você deve adicionar suporte a gestos, o que é simples. Adicione o manipulador para o evento StylusSystemGesture na grid:

Listagem 9. Declarando o manipulador de evento StylusSystemGesture em MainWindow.xaml

<Grid Background="Transparent" StylusSystemGesture="GridGesture" /> 

Note que coloquei um fundo para a grid. Se você não fizer isso, a grid não irá receber os eventos de caneta. O código para o manipulador está mostrado na Listagem 10.

Listagem 10. Manipulador para StylusSystemGesture

private void GridGesture(object sender, StylusSystemGestureEventArgs e)
{
    if (e.SystemGesture == SystemGesture.Drag)
        NextFile();
}

Se você está acompanhando o artigo e executando os passos, deve ter verificado que existe um SystemGesture.Flick que não foi usado. Este gesto funciona apenas em Windows Vista*. As versões mais novas usam o gesto Drag. Você deve também ter notado que eu não diferencio de um flick para a frente do para trás (ou mesmo de um horizontal de um vertical). Isto é devido ao fato de não haver suporte a isso, mas cuidaremos disso em seguida. Execute o programa e veja que um flick em qualquer direção mostra a próxima imagem.

Para determinar a direção do flick, você deve verificar o ponto de início e o final. Se a distância for maior na horizontal que na vertical, então o flick é horizontal. O sinal da diferença entre as coordenadas X dos dois pontos mostra a direção. Declare o manipulador para o evento StylusDown para a grid no arquivo .xaml, como mostrado na Listagem 11.

Listagem 11. Declarando eo evento StylusDown para a grid

<Grid Background="Transparent" 
      StylusSystemGesture="GridGesture"
      StylusDown="GridStylusDown">

O código para este manipulado está mostrado na Listagem 12.

Listagem 12. Criando o manipulador

private void GridStylusDown(object sender, StylusDownEventArgs e)
{
    _downPoints = e.GetStylusPoints(MainImage);
}

Quando a caneta está em contato, nós adicionamos os pontos de contato no vetor _downPoints. Você deve modificar o evento StylusSystemGesture para obter a direção do flick. Veja a Listagem 13.

Listagem 13. Modificando o evento StylusSystemGesture

private void GridGesture(object sender, StylusSystemGestureEventArgs e)
{
    if (e.SystemGesture != SystemGesture.Drag)
        return;
    var newPoints = e.GetStylusPoints(MainImage);
    bool isReverse = false;
    if (newPoints.Count > 0 && _downPoints.Count > 0)
    {
      var distX = newPoints[0].X - _downPoints[0].X;
      var distY = newPoints[0].Y - _downPoints[0].Y;
      if (Math.Abs(distX) > Math.Abs(distY))
      {
        isReverse = distX < 0; // Horizontal
      }
      else
      {
        return;  // Vertical
      }
    }
    if (isReverse)
        PreviousFile();
    else
        NextFile();
}

Quando o gesto Drag é detectado, o programa cria os novos pontos e verifica a maior distância, para determinar se é horizontal ou vertical. Se for vertical, o programa não faz nada. Se for horizontal e a distância for negativa, o flick é para trás. Desta maneira, o programa pode determinar o tipo de flick e sua direção, trocando para a imagem seguinte ou anterior, dependendo da direção. A aplicação agora pode funcionar com toque ou com o mouse.

Adicionando Manipulações de Toque em uma Aplicação WPF

Adicionar gestos em sua aplicação é um passo na direção certa, mas não é suficiente. Os usuários podem querer executar manipulações complexas, usar mais de um ou dois dedos ou querer um comportamento que simula o mundo real. Para isso, o WPF oferece as manipulações de toque. Vamos criar uma aplicação WPF para ver como isso funciona.

No Microsoft Visual Studio*, crie uma nova aplicação WPF e mude a largura e altura da janela para 800 e 600, respectivamente. Mude o componente principal para um Canvas. Você deve ter algo semelhante à Listagem 14, em MainWindow.xaml.

Listagem 14. A nova aplicação WPF, no Visual Studio

<Window x:Class="ImageTouch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="600" Width="800">
    <Canvas x:Name=”LayoutRoot”>
        
    </Canvas>
</Window>

Vá para o Solution Explorer e adicione uma imagem ao projeto (clique com o botão direito no projeto, clique em Add/Existing Item e selecione uma imagem do seu disco). Adicione um componente Image ao Canvas principal, atribuindo a imagem adicionada à propriedade Source do componente:

Listagem 15. Imagem adicionada ao Canvas principal

[cpxmlp]
<Image x:Name="MainImage" Source="seattle.bmp" Width="400" />
[/xml]

Se você executar este programa, verá que ele já está habilitado ao toque. Você pode redimensionar e mover a janela e a entrada de toque é convertida automaticamente para entrada de mouse. Mas não é isso que queremos. Você quer usar o toque para mover, girar e redimensionar a imagem.

Para isso, devemos usar a propriedade IsManipulationEnabled. Quando você configura esta propriedade para true, o controle recebe os eventos de toque. O evento ManipulationDelta é disparado quando ocorre uma manipulação no controle. Você deve manipulá-la e configurar as novas propriedades da imagem. No arquivo .xaml, configure a propriedade IsManipulationEnabled para true e declare um evento ManipulationDelta, como mostrado na Listagem 16.

Listagem 16. Habilitando manipulações de toque

<Image x:Name="MainImage" Source="seattle.bmp" Width="400" 
       IsManipulationEnabled="True" 
       ManipulationDelta="MainImageManipulationDelta">
    <Image.RenderTransform>
        <MatrixTransform />
    </Image.RenderTransform>
</Image> 

Eu adicionei uma MatrixTransform à propriedade RenderTransform. Esta transformação será alterada quando o usuário manipula a imagem. O gerenciador de eventos deve ser semelhante à Listagem 17.

Listagem 17. Adicionando um gerenciador de eventos para a manipulação da imagem

private void MainImageManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    if (element != null)
    {
        var transformMatrix = element.RenderTransform
            as MatrixTransform;
        var matrix = transformMatrix.Matrix;
        matrix.Translate(e.DeltaManipulation.Translation.X,
            e.DeltaManipulation.Translation.Y);
        ((MatrixTransform)element.RenderTransform).Matrix = matrix;
        e.Handled = true;
    }
} 

Inicialmente, você deve obter o RenderTransform atual da imagem, usar o método Translate para movimentá-la para a nova posição determinada pela manipulação e atribuí-la como sendo a propriedade Matrix de RenderTransform da imagem. Ao final, você deve configurar a propriedade Handled para true, de maneira a dizer ai WPF que este método já tratou o evento de toque e que ele não deve ser passado aos outros controles. Isto permite que a imagem seja movimentada quando o usuário toca nela.

Se você executar a aplicação e tentar mover a imagem, verá que funciona, mas não como esperado – a imagem treme quando é movida. Todas as manipulações são calculadas relativas à imagem, mas como ela está se movendo, os cálculos ficam recursivos. Para mudar este comportamento, você deve indicar ao WPF que os cálculos devem ser feitos relativos à janela principal. Isso deve ser feito usando o evento ManipulationStarting e configurando a propriedade ManipulationContainer dos argumentos do evento apontando para o Canvas.

Em MainWindow.xaml, entre com o código da Listagem 18.

Listagem 18. Corrigindo o movimento da imagem em MainWindow.xaml

<Image x:Name="MainImage" Source="seattle.bmp" Width="400" 
       IsManipulationEnabled="True" 
       ManipulationDelta="MainImageManipulationDelta"
       ManipulationStarting="MainImageManipulationStarting">

Em MainWindow.xaml.cs, entre com o código da Listagem 19.

Listagem 19. Corrigindo o movimento da imagem em MainWindow.xaml.cs

private void MainImageManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
    e.ManipulationContainer = LayoutRoot;
}

Agora, quando você executa a aplicação e move a imagem, ela não treme mais.

Adicionando Redimensionamento e Rotação

Para habilitar redimensionamento e rotação, você deve usar as propriedades Scale e Rotation de DeltaManipulation. Estas manipulações precisam de um ponto central fixo. Por exemplo, se você fixar o ponto central no topo, à esquerda da imagem, ela será redimensionada e girada ao redor deste ponto. Para se obter um redimensionamento e rotação corretos, devemos configurar este ponto para a origem da manipulação. O redimensionamento e rotação corretos são configurados usando um código semelhante à Listagem 20.

Listagem 20. Configurando redimensionamento e rotação

private void MainImageManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    if (element != null)
    {
        var transformMatrix = element.RenderTransform
            as MatrixTransform;
        var matrix = transformMatrix.Matrix;
        matrix.Translate(e.DeltaManipulation.Translation.X,
            e.DeltaManipulation.Translation.Y);
        var centerPoint = LayoutRoot.TranslatePoint(
            e.ManipulationOrigin, element);
        centerPoint = matrix.Transform(centerPoint);
        matrix.RotateAt(e.DeltaManipulation.Rotation,
          centerPoint.X, centerPoint.Y);
        matrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y,
          centerPoint.X, centerPoint.Y);
        ((MatrixTransform)element.RenderTransform).Matrix = matrix;
        e.Handled = true;
    }
}

Adicionando Inércia

Ao executar a aplicação, você pode ver que a imagem é movimentada, redimensionada e girada, mas assim que você para de move-la, ela para. Este não é o comportamento desejado. Queremos o mesmo comportamento obtido ao movimentar uma foto em uma mesa lisa. Ela deveria continuar o movimento cada vez mais lentamente, até parar completamente. Você pode obter este comportamento usando o evento ManipulationInertiaStarting. Neste evento, você indica a desaceleração que deseja, em pixels (ou graus) por milissegundo ao quadrado. Se o valor for pequeno, o elemento demora mais para parar (como em uma mesa de gelo); se a desaceleração tiver um valor maior, o objeto para em menos tempo (como em uma mesa rugosa). Configure este valor para 0.005.

Em MainWindow.xaml, entre com o código da Listagem 21.

Listagem 21. Configurando a desaceleração em MainWindow.xaml

<Image x:Name="MainImage" Source="seattle.bmp" Width="400" 
       IsManipulationEnabled="True" 
       ManipulationDelta="MainImageManipulationDelta"
       ManipulationStarting="MainImageManipulationStarting"
       ManipulationInertiaStarting="MainImageManipulationInertiaStarting"/>

Em MainWindow.xaml.cs, entre o código da Listagem 22.

Listagem 22. Configurando a desaceleração em MainWindow.xaml.cs

private void MainImageManipulationInertiaStarting(object sender, 
    ManipulationInertiaStartingEventArgs e)
{
    e.RotationBehavior.DesiredDeceleration = 0.005; // degrees/ms^2 
    e.TranslationBehavior.DesiredDeceleration = 0.005; // pixels/ms^2
}

Limitando o Movimento Inercial

Agora, ao executar a aplicação, você verifica que as manipulações tem um comportamento parecido com o comportamento físico. Mas, se você der à imagem um flick muito grande, ele sairá da janela e você terá que reiniciar o programa. Para limitar o movimento inercial, devemos determinar se a manipulação é inercial (o usuário já levantou seu dedo) e pará-lo se atingir a borda. Fazemos isso usando o código do manipulador do evento ManipulationDelta, mostrado na Listagem 23.

Listagem 23. Limitando o movimento inercial

private void MainImageManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    if (element != null)
    {
        Matrix matrix = new Matrix();
        MatrixTransform transformMatrix = element.RenderTransform
            as MatrixTransform;
        if (transformMatrix != null)
        {
            matrix = transformMatrix.Matrix;
        }
        matrix.Translate(e.DeltaManipulation.Translation.X,
            e.DeltaManipulation.Translation.Y);
        var centerPoint = new Point(element.ActualWidth / 2, 
            element.ActualHeight / 2);
        matrix.RotateAt(e.DeltaManipulation.Rotation,
          centerPoint.X, centerPoint.Y);
        matrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y,
          centerPoint.X, centerPoint.Y);
        element.RenderTransform = new MatrixTransform(matrix);

        var containerRect = new Rect(LayoutRoot.RenderSize);
        var elementRect = element.RenderTransform.TransformBounds(
                          VisualTreeHelper.GetDrawing(element).Bounds);
        if (e.IsInertial && !containerRect.Contains(elementRect))
            e.Complete();
        e.Handled = true;
    }
}

Este código determina se o retângulo transformado da imagem está contido na janela. Se não estiver e o movimento for inercial, a manipulação é parada. Desta maneira o movimento para e a imagem não sai da janela.

Conclusão

Como você pode ver, adicionar manipulações de toque a uma aplicação WPF é relativamente fácil. Você pode iniciar com o comportamento padrão e adicionar gestos ou suporte completo a toque com poucas mudanças em seu código. Uma coisa importante a ser feita em uma aplicação que suporta toque é repensar a Interface de Usuário, de maneira que os usuários sintam-se confortáveis usando-a. Você pode inclusive usar estilos diferentes para os controles, nos dispositivos em que o toque é suportado, de maneira que os botões fiquem maiores e as listas estejam mais espaçadas somente quando o toque for usado. À medida que o número de dispositivos que suportam toque fica cada vez maior, vale a pena otimizar suas aplicações para toque: elas ficarão mais fáceis de usar, agradando seus usuários atuais e atraindo novos usuários.

Para Mais Informações

Sobre o Autor

Bruno Sonnino é um Microsoft Most Valuable Professional (MVP) no Brasil. Ele é desenvolvedor, consultor e autor, tendo escrito 5 livros de Delphi, publicados em português pela editor Pearson Education Brazil, e muitos artigos para revistas e websites brasileiros e americanos.

Copyright © 2013 Intel Corporation. All rights reserved.

*Other names and brands may be claimed as the property of others.

Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.