Compartir a través de


Cómo aplicar transformaciones 2D

Nota:

En el caso de las aplicaciones de Windows 10, se recomienda usar las API de Windows.UI.Composition en lugar de DirectComposition. Para obtener más información, consulta Modernize your desktop app using the Visual layer (Modernización de la aplicación de escritorio mediante la capa visual).

En este tema se muestra cómo aplicar transformaciones 2D a un objeto visual mediante Microsoft DirectComposition. El ejemplo de este tema aplica un grupo de transformaciones que:

  1. Girar el objeto visual en 180 grados.
  2. Escale verticalmente el objeto visual hasta tres veces su tamaño original.
  3. Traducir (mover) el objeto visual de 150 píxeles a la derecha de su posición original.

Las capturas de pantalla siguientes muestran el objeto visual antes y después de aplicar las transformaciones 2D.

resultado de aplicar un grupo de 2d transformaciones a un objeto visual

Lo que necesita saber

Tecnologías

Requisitos previos

  • C/C++
  • Microsoft Win32
  • Modelo de objetos componentes (COM)

Instrucciones

Paso 1: Inicializar objetos DirectComposition

  1. Cree el objeto de dispositivo y el objeto de destino de composición.
  2. Cree un objeto visual, establezca su contenido y agréguelo al árbol visual.

Para obtener más información, vea Cómo inicializar DirectComposition.

Paso 2: Creación de la matriz de grupos de transformación

IDCompositionTransform *pTransforms[3];

Paso 3: Crear los objetos de transformación, establecer sus propiedades y agregarlos a la matriz de grupos de transformación

  1. Use los métodos IDCompositionDevice::CreateRotateTransform, ::CreateScaleTransform y ::CreateTranslateTransform para crear los objetos de transformación.
  2. Use las funciones miembro de las interfaces IDCompositionRotateTransform, IDCompositionScaleTransform e IDCompositionTranslateTransform para establecer las propiedades de las transformaciones.
  3. Copie los punteros de interfaz de transformación a la matriz de grupos de transformación.
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;
}

Paso 4: Crear el objeto de grupo de transformación

Llame al método IDCompositionDevice::CreateTransformGroup para crear el objeto de grupo de transformación.

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

Paso 5: Aplicar el objeto de grupo de transformación al objeto visual

Use el método IDCompositionVisual::SetTransform para asociar la propiedad Transform del objeto visual con el objeto de grupo de transformación.

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

Paso 6: Confirmar la composición

Llame al método IDCompositionDevice::Commit para confirmar las actualizaciones del objeto visual en DirectComposition para su procesamiento. El resultado de aplicar el grupo de transformaciones 2D aparece en la ventana de destino.

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

Paso 7: Liberar los objetos DirectComposition

Asegúrese de liberar el grupo de objetos de transformación 2D cuando ya no los necesite. En el ejemplo siguiente se llama a la macro SafeRelease definida por la aplicación para liberar los objetos de transformación.

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

Recuerde también liberar el objeto de dispositivo, el objeto de destino de composición y los objetos visuales antes de que se cierre la aplicación.

Ejemplo 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;
}

Transformaciones