Поделиться через


Применение 2D-преобразований

Заметка

Для приложений в Windows 10 рекомендуется использовать API-интерфейсы Windows.UI.Composition вместо DirectComposition. Дополнительные сведения см. в Модернизации вашего настольного приложения с помощью визуального слоя.

В этом разделе показано, как применять 2D-преобразования к визуальному элементу с помощью Microsoft DirectComposition. В примере в этом разделе применяется группа преобразований, которые:

  1. Поверните визуальный элемент на 180 градусов.
  2. Увеличить изображение до трехкратного размера по сравнению с оригиналом.
  3. Переместите изображение на 150 пикселей вправо от его исходной позиции.

На следующих снимках экрана показано изображение до и после применения 2D-преобразований.

результат применения группы 2D-преобразований к визуальному

Что нужно знать

Технологии

Необходимые условия

  • C/C++
  • Microsoft Win32
  • Объектная модель компонента (COM)

Инструкции

Шаг 1. Инициализация объектов DirectComposition

  1. Создайте объект устройства и целевой объект композиции.
  2. Создайте визуальный элемент, задайте его содержимое и добавьте его в визуальное дерево.

Дополнительные сведения см. в разделе Как инициализировать DirectComposition.

Шаг 2. Создание массива групп преобразования

IDCompositionTransform *pTransforms[3];

Шаг 3. Создание объектов преобразования, задание их свойств и добавление их в массив групп преобразования

  1. Используйте методы IDCompositionDevice::CreateRotateTransform, ::CreateScaleTransformи ::CreateTranslateTransform для создания объектов преобразования.
  2. Используйте функции-члены интерфейсов IDCompositionRotateTransform, IDCompositionScaleTransformи IDCompositionTranslateTransform, чтобы задать свойства преобразований.
  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;
}

Шаг 4. Создание объекта группы преобразования

Вызовите метод IDCompositionDevice::CreateTransformGroup, чтобы создать объект группы преобразования.

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

Шаг 5. Применение объекта группы преобразования к визуальному элементу

Используйте метод IDCompositionVisual::SetTransform, чтобы связать свойство Transform визуального элемента с объектом группы преобразования.

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

Шаг 6. Фиксация композиции

Вызовите метод IDCompositionDevice::Commit, чтобы зафиксировать обновления визуала в DirectComposition для обработки. Результат применения группы 2D-преобразований отображается в целевом окне.

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

Шаг 7. Освобождение объектов DirectComposition

Не забудьте освободить группу объектов преобразования 2D, если они больше не нужны. В следующем примере вызывается определяемый приложением макрос SafeRelease, чтобы освободить объекты преобразования.

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

Кроме того, не забудьте освободить объект устройства, целевой объект композиции и визуальные элементы перед выходом приложения.

Полный пример

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

преобразования