Como executar o teste de colisão em um layout de texto
Fornece um breve tutorial sobre como adicionar deteção de ocorrências a uma aplicação DirectWrite que exibe texto usando a interface IDWriteTextLayout.
O resultado deste tutorial é um aplicativo que sublinha o caractere que é clicado pelo botão esquerdo do mouse, como mostrado na captura de tela a seguir.
Este guia contém as seguintes partes:
- Etapa 1: Criar um layout de texto.
- Etapa 2: Adicionar um método OnClick.
- Etapa 3: Execute o teste de acertos.
- Passo 4: Sublinhe o texto clicado.
- Etapa 5: Manipule a mensagem WM_LBUTTONDOWN.
Etapa 1: Criar um layout de texto.
Para começar, você precisará de um aplicativo que use um IDWriteTextLayout objeto. 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:
Declare um ponteiro para a interface IDWriteTextLayout como membro da classe.
IDWriteTextLayout* pTextLayout_;
No final do método CreateDeviceIndependentResources, crie um objeto de interface IDWriteTextLayout ao chamar 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. ); }
Em seguida, deve alterar a chamada para o método ID2D1RenderTarget::DrawText para ID2D1RenderTarget::DrawTextLayout conforme mostrado no código a seguir.
pRT_->DrawTextLayout( origin, pTextLayout_, pBlackBrush_ );
Etapa 2: Adicione um método OnClick.
Agora, adicione um método à classe que usará a funcionalidade de teste de ocorrências do layout de texto.
Declare um método OnClick no ficheiro de cabeçalho da classe.
void OnClick( UINT x, UINT y );
Defina um método OnClick no ficheiro de implementação da classe.
void DemoApp::OnClick(UINT x, UINT y) { }
Passo 3: Execute o teste de colisão.
Para determinar onde o usuário clicou no layout de texto, usaremos o IDWriteTextLayout::HitTestPoint método.
Adicione o seguinte ao método OnClick que definiu na Etapa 2.
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 produz os seguintes parâmetros.
Variável Descrição hitTestMetrics A geometria que completamente encerra a localização do teste de detecção. está dentro de Indica se o local do teste de acerto 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 do teste de acerto está no lado principal ou no lado inferior do personagem. 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 y para a posição sem qualquer modificação. Isso pode ser feito neste exemplo porque o layout do texto tem o mesmo tamanho da 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 do texto.
Passo 4: Sublinhe o texto clicado.
Adicione o seguinte ao OnClick que foi definido 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);
}
Este código faz o seguinte.
Verifica se o ponto de impacto estava dentro do texto usando a variável isInside.
O membro textPosition da estrutura hitTestMetrics contém o índice de base zero do caractere clicado.
Obtém o sublinhado para esse caractere passando esse valor para o IDWriteTextLayout::GetUnderline método.
Declara uma variável DWRITE_TEXT_RANGE com a posição inicial definida como hitTestMetrics.textPosition e um comprimento de 1.
Alterna o sublinhado utilizando o método IDWriteTextLayout::SetUnderline.
Depois de definir o sublinhado, redesenhe o texto chamando o DrawD2DContent método da classe.
DrawD2DContent();
Passo 5: Manipule a mensagem de WM_LBUTTONDOWN.
Finalmente, adicione a mensagem WM_LBUTTONDOWN ao manipulador de mensagens para a sua aplicação 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 GET_X_LPARAM macros são declaradas no arquivo de cabeçalho Windowsx.h. Eles recuperam facilmente a posição x e y do clique do mouse.