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


Выполнение проверки попадания в макет текста

Краткое руководство по добавлению проверки попадания в приложение 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::D rawText на ID2D1RenderTarget::D rawTextLayout , как показано в следующем коде.

    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 Геометрия, полностью включающая место проверки попадания.
    isInside Указывает, находится ли расположение проверки попадания внутри текстовой строки. При значении 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 щелчка мыши.