Como executar testes de clique em um layout de texto

Fornece um breve tutorial sobre como adicionar testes de clique a um aplicativo DirectWrite que exibe texto usando a interface IDWriteTextLayout.

O resultado deste tutorial é um aplicativo que sublinha o caractere clicado no botão esquerdo do mouse, conforme mostrado na captura de tela a seguir.

captura de tela de

Esta é a maneira de conter as seguintes partes:

Etapa 1: criar um layout de texto.

Para começar, você precisará de um aplicativo que use um objeto IDWriteTextLayout . Se você já tiver um aplicativo que exibe texto com um layout de texto, vá para a Etapa 2.

Para adicionar um layout de texto, você deve fazer o seguinte:

  1. Declare um ponteiro para uma interface IDWriteTextLayout como um membro da classe .

    IDWriteTextLayout* pTextLayout_;
    
  2. No final do método CreateDeviceIndependentResources , crie um objeto de interface IDWriteTextLayout chamando o 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. Em seguida, você deve alterar a chamada para o método ID2D1RenderTarget::D rawText para ID2D1RenderTarget::D rawTextLayout , conforme mostrado no código a seguir.

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

Etapa 2: Adicionar um método OnClick.

Agora, adicione um método à classe que usará a funcionalidade de teste de clique do layout de texto.

  1. Declare um método OnClick no arquivo de cabeçalho de classe.

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. Defina um método OnClick no arquivo de implementação de classe.

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

Etapa 3: executar o teste de clique.

Para determinar onde o usuário clicou no layout de texto, usaremos o método IDWriteTextLayout::HitTestPoint .

Adicione o seguinte ao método OnClick que você definiu na Etapa 2.

  1. Declare as variáveis que passaremos como parâmetros para o método .

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    O método HitTestPoint gera os parâmetros a seguir.

    Variável Descrição
    hitTestMetrics A geometria que inclui totalmente o local de teste de ocorrência.
    isInside Indica se o local de teste de ocorrência está dentro da cadeia de caracteres de texto ou não. Quando FALSE, a posição mais próxima da borda do texto é retornada.
    isTrailingHit Indica se o local de teste de ocorrência está no lado à esquerda ou à direita do caractere.
  2. Chame o método HitTestPoint do objeto IDWriteTextLayout .

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

    O código neste exemplo passa as variáveis x e y para a posição sem nenhuma modificação. Isso pode ser feito neste exemplo porque o layout de texto tem o mesmo tamanho que a janela e se origina no canto superior esquerdo da janela. Se esse não fosse o caso, você teria que determinar as coordenadas em relação à origem do layout de texto.

Etapa 4: sublinhar o texto clicado.

Adicione o seguinte ao OnClick que você definiu na Etapa 2, após a chamada para o método HitTestPoint .

if (isInside == TRUE)
{
    BOOL underline;

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

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

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

Esse código faz o seguinte.

  1. Verifica se o ponto de teste de ocorrência estava dentro do texto usando a variável isInside .

  2. O membro textPosition da estrutura hitTestMetrics contém o índice baseado em zero do caractere clicado.

    Obtém o sublinhado para esse caractere passando esse valor para o método IDWriteTextLayout::GetUnderline .

  3. Declara uma variável DWRITE_TEXT_RANGE com a posição inicial definida como hitTestMetrics.textPosition e um comprimento de 1.

  4. Alterna o sublinhado usando o método IDWriteTextLayout::SetUnderline .

Depois de definir o sublinhado, redesenhe o texto chamando o método DrawD2DContent da classe .

DrawD2DContent();

Etapa 5: manipular a mensagem de WM_LBUTTONDOWN.

Por fim, adicione a mensagem WM_LBUTTONDOWN ao manipulador de mensagens do aplicativo e chame o método OnClick da classe .

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

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

GET_X_LPARAM e macros GET_X_LPARAM são declaradas no arquivo de cabeçalho windowsx.h. Eles recuperam facilmente a posição x e y do clique do mouse.