Compartilhar via


Como aplicar transformações 2D

Observação

Para aplicativos no Windows 10, é recomendável usar APIs Windows.UI.Composition em vez de DirectComposition. Para obter mais informações, consulte Modernizar seu aplicativo da área de trabalho usando a camada Visual.

Este tópico demonstra como aplicar transformações 2D a um visual usando o Microsoft DirectComposition. O exemplo neste tópico aplica um grupo de transformações que:

  1. Gire o visual em 180 graus.
  2. Escale verticalmente o visual para três vezes o tamanho original.
  3. Traduza (mova) o visual de 150 pixels à direita de sua posição original.

As capturas de tela a seguir mostram o visual antes e depois de aplicar as transformações 2D.

resultado da aplicação de um grupo de transformações 2d a um visual

O que você precisa saber

Tecnologias

Pré-requisitos

  • C/C++
  • Microsoft Win32
  • COM (Component Object Model)

Instruções

Etapa 1: Inicializar objetos DirectComposition

  1. Crie o objeto do dispositivo e o objeto de destino de composição.
  2. Crie um visual, defina seu conteúdo e adicione-o à árvore visual.

Para obter mais informações, consulte Como inicializar o DirectComposition.

Etapa 2: Criar a matriz do grupo de transformação

IDCompositionTransform *pTransforms[3];

Etapa 3: criar os objetos de transformação, definir suas propriedades e adicioná-los à matriz do grupo de transformação

  1. Use os métodos IDCompositionDevice::CreateRotateTransform, ::CreateScaleTransform e ::CreateTranslateTransform para criar os objetos de transformação.
  2. Use as funções membro das interfaces IDCompositionRotateTransform, IDCompositionScaleTransform e IDCompositionTranslateTransform para definir as propriedades das transformações.
  3. Copie os ponteiros da interface de transformação para a matriz do grupo de transformação.
IDCompositionRotateTransform *pRotateTransform = nullptr;
IDCompositionScaleTransform *pScaleTransform = nullptr;
IDCompositionTranslateTransform *pTranslateTransform = nullptr;
IDCompositionTransform *pTransformGroup = nullptr;

// Create the rotate transform.
hr = pDevice->CreateRotateTransform(&pRotateTransform);

if (SUCCEEDED(hr))
{
    // Set the center of rotation to the center point of the visual.
    hr = pRotateTransform->SetCenterX(BITMAP_WIDTH/2.0f);
    
    if (SUCCEEDED(hr)) {
        hr = pRotateTransform->SetCenterY(BITMAP_HEIGHT/2.0f);
    }

    // Set the rotate angle to 180 degrees.
    if (SUCCEEDED(hr)) {
        hr = pRotateTransform->SetAngle(180.0f);
    }

    // Add the rotate transform to the transform group array.
    pTransforms[0] = pRotateTransform;

    // Create the scale transform.
    if (SUCCEEDED(hr)) {
        hr = pDevice->CreateScaleTransform(&pScaleTransform);
    }
}

if (SUCCEEDED(hr))
{
    // Set the scaling origin to the upper-right corner of the visual.
    hr = pScaleTransform->SetCenterX(0.0f);
    if (SUCCEEDED(hr)) {
        hr = pScaleTransform->SetCenterY(0.0f);
    }

    // Set the scaling factor to three for both the width and height. 
    if (SUCCEEDED(hr)) {
        hr = pScaleTransform->SetScaleX(3.0f);
    }
    if (SUCCEEDED(hr)) {
        hr = pScaleTransform->SetScaleY(3.0f);
    }

    // Add the scale transform to the transform group array.
    pTransforms[1] = pScaleTransform;

    // Create the translate transform.
    if (SUCCEEDED(hr)) {
        hr = pDevice->CreateTranslateTransform(&pTranslateTransform);
    }
}

if (SUCCEEDED(hr))
{
    // Move the visual 150 pixels to the right.
    hr = pTranslateTransform->SetOffsetX(150.0f);
    if (SUCCEEDED(hr)) {
        hr = pTranslateTransform->SetOffsetY(0.0f);
    }

    // Add the translate transform to the transform group array.
    pTransforms[2] = pTranslateTransform;
}

Etapa 4: Criar o objeto de grupo de transformação

Chame o método IDCompositionDevice::CreateTransformGroup para criar o objeto de grupo de transformação.

if (SUCCEEDED(hr))
{
    // Create the transform group.
    hr = pDevice->CreateTransformGroup(pTransforms, 3, &pTransformGroup);
}

Etapa 5: Aplicar o objeto de grupo de transformação ao visual

Use o método IDCompositionVisual::SetTransform para associar a propriedade Transform do visual ao objeto de grupo de transformação.

if (SUCCEEDED(hr))
{
    // Apply the transform group to the visual.
    hr = pVisual->SetTransform(pTransformGroup);
}

Etapa 6: Confirmar a composição

Chame o método IDCompositionDevice::Commit para confirmar as atualizações no visual para DirectComposition para processamento. O resultado da aplicação do grupo de transformações 2D aparece na janela de destino.

if (SUCCEEDED(hr))
{
    // Commit the composition.
    hr = pDevice->Commit();
}

Etapa 7: Liberar os objetos DirectComposition

Certifique-se de liberar o grupo de objetos de transformação 2D quando você não precisar mais deles. O exemplo a seguir chama a macro SafeRelease definida pelo aplicativo para liberar os objetos de transformação.

// Release the transform objects.
for (int i = 0; i < 3; i++)
{
    SafeRelease(&pTransforms[i]);
}

Lembre-se também de liberar o objeto do dispositivo, o objeto de destino de composição e os visuais antes da saída do aplicativo.

Exemplo completo

#define BITMAP_WIDTH  80.0
#define BITMAP_HEIGHT 80.0

HRESULT DemoApp::ApplyTransformGroup(IDCompositionDevice *pDevice, 
                                     IDCompositionVisual *pVisual)
{
    HRESULT hr = S_OK;

    if (pDevice == nullptr || pVisual == nullptr)
        return E_INVALIDARG; 
    
    IDCompositionTransform *pTransforms[3];

    IDCompositionRotateTransform *pRotateTransform = nullptr;
    IDCompositionScaleTransform *pScaleTransform = nullptr;
    IDCompositionTranslateTransform *pTranslateTransform = nullptr;
    IDCompositionTransform *pTransformGroup = nullptr;

    // Create the rotate transform.
    hr = pDevice->CreateRotateTransform(&pRotateTransform);

    if (SUCCEEDED(hr))
    {
        // Set the center of rotation to the center point of the visual.
        hr = pRotateTransform->SetCenterX(BITMAP_WIDTH/2.0f);
        
        if (SUCCEEDED(hr)) {
            hr = pRotateTransform->SetCenterY(BITMAP_HEIGHT/2.0f);
        }

        // Set the rotate angle to 180 degrees.
        if (SUCCEEDED(hr)) {
            hr = pRotateTransform->SetAngle(180.0f);
        }

        // Add the rotate transform to the transform group array.
        pTransforms[0] = pRotateTransform;

        // Create the scale transform.
        if (SUCCEEDED(hr)) {
            hr = pDevice->CreateScaleTransform(&pScaleTransform);
        }
    }

    if (SUCCEEDED(hr))
    {
        // Set the scaling origin to the upper-right corner of the visual.
        hr = pScaleTransform->SetCenterX(0.0f);
        if (SUCCEEDED(hr)) {
            hr = pScaleTransform->SetCenterY(0.0f);
        }

        // Set the scaling factor to three for both the width and height. 
        if (SUCCEEDED(hr)) {
            hr = pScaleTransform->SetScaleX(3.0f);
        }
        if (SUCCEEDED(hr)) {
            hr = pScaleTransform->SetScaleY(3.0f);
        }

        // Add the scale transform to the transform group array.
        pTransforms[1] = pScaleTransform;

        // Create the translate transform.
        if (SUCCEEDED(hr)) {
            hr = pDevice->CreateTranslateTransform(&pTranslateTransform);
        }
    }

    if (SUCCEEDED(hr))
    {
        // Move the visual 150 pixels to the right.
        hr = pTranslateTransform->SetOffsetX(150.0f);
        if (SUCCEEDED(hr)) {
            hr = pTranslateTransform->SetOffsetY(0.0f);
        }

        // Add the translate transform to the transform group array.
        pTransforms[2] = pTranslateTransform;
    }

    if (SUCCEEDED(hr))
    {
        // Create the transform group.
        hr = pDevice->CreateTransformGroup(pTransforms, 3, &pTransformGroup);
    }

    if (SUCCEEDED(hr))
    {
        // Apply the transform group to the visual.
        hr = pVisual->SetTransform(pTransformGroup);
    }

    if (SUCCEEDED(hr))
    {
        // Commit the composition.
        hr = pDevice->Commit();
    }

    // Release the transform objects.
    for (int i = 0; i < 3; i++)
    {
        SafeRelease(&pTransforms[i]);
    }

    // Release the transform group pointer.
    SafeRelease(&pTransformGroup);

    return hr;
}

Transformações