Cómo realizar pruebas de posicionamiento en un diseño de texto

Proporciona un breve tutorial sobre cómo agregar pruebas de posicionamiento a una aplicación de DirectWrite que muestra texto mediante la interfaz IDWriteTextLayout.

El resultado de este tutorial es una aplicación que subraya el carácter en el que se hace clic con el botón izquierdo del mouse, como se muestra en la siguiente captura de pantalla.

captura de pantalla de

Este procedimiento contiene las siguientes partes:

Paso 1: Crear un diseño de texto.

Para comenzar, necesitará una aplicación que use un objeto IDWriteTextLayout . Si ya tiene una aplicación que muestra texto con un diseño de texto, vaya al paso 2.

Para agregar un diseño de texto, debe hacer lo siguiente:

  1. Declare un puntero a una interfaz IDWriteTextLayout como miembro de la clase .

    IDWriteTextLayout* pTextLayout_;
    
  2. Al final del método CreateDeviceIndependentResources , cree un objeto de interfaz IDWriteTextLayout llamando al método 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. A continuación, debe cambiar la llamada al método ID2D1RenderTarget::D rawText a ID2D1RenderTarget::D rawTextLayout , como se muestra en el código siguiente.

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

Paso 2: Agregar un método OnClick.

Ahora agregue un método a la clase que usará la funcionalidad de prueba de posicionamiento del diseño de texto.

  1. Declare un método OnClick en el archivo de encabezado de clase.

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. Defina un método OnClick en el archivo de implementación de clase.

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

Paso 3: Realizar pruebas de posicionamiento.

Para determinar dónde ha clic el usuario en el diseño de texto, usaremos el método IDWriteTextLayout::HitTestPoint .

Agregue lo siguiente al método OnClick que definió en el paso 2.

  1. Declare las variables que pasaremos como parámetros al método .

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    El método HitTestPoint genera los parámetros siguientes.

    Variable Descripción
    hitTestMetrics Geometría que incluye completamente la ubicación de la prueba de posicionamiento.
    isInside Indica si la ubicación de la prueba de posicionamiento está dentro de la cadena de texto o no. Cuando es FALSE, se devuelve la posición más cercana al borde del texto.
    isTrailingHit Indica si la ubicación de la prueba de posicionamiento está en el lado inicial o final del carácter.
  2. Llame al método HitTestPoint del objeto IDWriteTextLayout .

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

    El código de este ejemplo pasa las variables x e y para la posición sin ninguna modificación. Esto se puede hacer en este ejemplo porque el diseño de texto tiene el mismo tamaño que la ventana y se origina en la esquina superior izquierda de la ventana. Si no fuera así, tendría que determinar las coordenadas en relación con el origen del diseño de texto.

Paso 4: Subrayado del texto en el que se ha hecho clic.

Agregue lo siguiente al onClick que definió en el paso 2, después de la llamada al método HitTestPoint .

if (isInside == TRUE)
{
    BOOL underline;

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

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

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

Este código hace lo siguiente.

  1. Comprueba si el punto de prueba de posicionamiento estaba dentro del texto mediante la variable isInside .

  2. El miembro textPosition de la estructura hitTestMetrics contiene el índice de base cero del carácter en el que se hace clic.

    Obtiene el subrayado de este carácter pasando este valor al método IDWriteTextLayout::GetUnderline .

  3. Declara una variable DWRITE_TEXT_RANGE con la posición inicial establecida en hitTestMetrics.textPosition y una longitud de 1.

  4. Alterna el subrayado mediante el método IDWriteTextLayout::SetUnderline .

Después de establecer el subrayado, vuelva a dibujar el texto llamando al método DrawD2DContent de la clase .

DrawD2DContent();

Paso 5: Controle el mensaje de WM_LBUTTONDOWN.

Por último, agregue el mensaje WM_LBUTTONDOWN al controlador de mensajes de la aplicación y llame al método OnClick de la clase .

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

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

GET_X_LPARAM y GET_X_LPARAM macros se declaran en el archivo de encabezado windowsx.h. Recuperan fácilmente la posición x e y del clic del mouse.