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


Как выполнить тестирование попаданий в текстовом макете

Предоставляется краткое руководство по добавлению тестирования попаданий в приложение DirectWrite, которое отображает текст с помощью интерфейса IDWriteTextLayout.

Результатом этого руководства является приложение, подчеркивающее символ, который нажимается левой кнопкой мыши, как показано на следующем снимке экрана.

снимок экрана с надписью

В этом руководстве содержатся следующие части:

Шаг 1. Создание текстового макета.

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

Чтобы добавить текстовый макет, необходимо выполнить следующее:

  1. Объявите указатель на интерфейс IDWriteTextLayout в качестве члена класса.

    IDWriteTextLayout* pTextLayout_;
    
  2. В конце метода CreateDeviceIndependentResources создайте объект интерфейса IDWriteTextLayout путем вызова метода CreateTextLayout.

    // Create a text layout using the text format.
    if (SUCCEEDED(hr))
    {
        RECT rect;
        GetClientRect(hwnd_, &rect); 
        float width  = rect.right  / dpiScaleX_;
        float height = rect.bottom / dpiScaleY_;
    
        hr = pDWriteFactory_->CreateTextLayout(
            wszText_,      // The string to be laid out and formatted.
            cTextLength_,  // The length of the string.
            pTextFormat_,  // The text format to apply to the string (contains font information, etc).
            width,         // The width of the layout box.
            height,        // The height of the layout box.
            &pTextLayout_  // The IDWriteTextLayout interface pointer.
            );
    }
    
  3. Затем необходимо изменить вызов метода ID2D1RenderTarget::DrawText на ID2D1RenderTarget::DrawTextLayout, как показано в следующем коде.

    pRT_->DrawTextLayout(
        origin,
        pTextLayout_,
        pBlackBrush_
        );
    

Шаг 2. Добавление метода OnClick.

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

  1. Объявите метод OnClick в файле заголовка класса.

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. Определите метод OnClick в файле реализации класса.

     void DemoApp::OnClick(UINT x, UINT y)
     {    
     }
    

Шаг 3. Выполнение тестирования на совпадения.

Чтобы определить, где пользователь щелкнул макет текста, мы будем использовать метод IDWriteTextLayout::HitTestPoint.

Добавьте это в метод OnClick, который вы определили на шаге 2.

  1. Объявите переменные, которые будут передаваться в метод в качестве параметров.

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    Метод HitTestPoint выводит следующие параметры.

    Переменная Описание
    hitTestMetrics Геометрия, полностью охватывающая расположение теста на попадание.
    находится внутри Указывает, находится ли расположение хит-теста внутри текстовой строки или нет. При значении FALSE возвращается положение, ближайшее к краю текста.
    isTrailingHit Указывает, находится ли расположение хит-теста в начале или в конце символа.
  2. Вызовите метод HitTestPoint объекта IDWriteTextLayout.

    pTextLayout_->HitTestPoint(
                    (FLOAT)x, 
                    (FLOAT)y,
                    &isTrailingHit,
                    &isInside,
                    &hitTestMetrics
                    );
    

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

Шаг 4. Подчеркнуть кликнутый текст.

Добавьте следующую команду в OnClick, определенной на шаге 2 после вызова метода HitTestPoint.

if (isInside == TRUE)
{
    BOOL underline;

    pTextLayout_->GetUnderline(hitTestMetrics.textPosition, &underline);

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

    pTextLayout_->SetUnderline(!underline, textRange);
}

В этом коде выполняется следующее.

  1. Проверяет, находится ли точка попадания внутри текста с использованием переменной isInside.

  2. Член textPosition структуры hitTestMetrics содержит индекс символа, на который был произведён щелчок, начиная с нуля.

    Метод IDWriteTextLayout::GetUnderline позволяет получить подчеркивание для этого символа, передав ему соответствующее значение.

  3. Объявляет переменную DWRITE_TEXT_RANGE с начальной позицией hitTestMetrics.textPosition и длиной 1.

  4. Переключает подчеркивание с помощью метода IDWriteTextLayout::SetUnderline.

После того как задали подчеркивание, перерисуйте текст, вызвав метод DrawD2DContent класса.

DrawD2DContent();

Шаг 5. Обработка сообщения WM_LBUTTONDOWN.

Наконец, добавьте сообщение WM_LBUTTONDOWN в обработчик сообщений для приложения и вызовите метод OnClick класса.

case WM_LBUTTONDOWN:
    {
        int x = GET_X_LPARAM(lParam); 
        int y = GET_Y_LPARAM(lParam);

        pDemoApp->OnClick(x, y);
    }
    break;

макросы GET_X_LPARAM и GET_X_LPARAM объявляются в файле заголовка windowsx.h. Они легко извлекают положение x и y щелчка мыши.