Come eseguire hit test in un layout di testo

Fornisce una breve esercitazione su come aggiungere hit test a un'applicazione di DirectWrite che visualizza il testo usando l'interfaccia IDWriteTextLayout.

Il risultato di questa esercitazione è un'applicazione che sottolinea il carattere che viene fatto clic sul pulsante sinistro del mouse, come illustrato nella schermata seguente.

schermata di

Questa procedura contiene le parti seguenti:

Passaggio 1: Creare un layout di testo.

Per iniziare, sarà necessaria un'applicazione che usa un oggetto IDWriteTextLayout . Se si dispone già di un'applicazione che visualizza testo con un layout di testo, passare al passaggio 2.

Per aggiungere un layout di testo, è necessario eseguire le operazioni seguenti:

  1. Dichiarare un puntatore a un'interfaccia IDWriteTextLayout come membro della classe.

    IDWriteTextLayout* pTextLayout_;
    
  2. Alla fine del metodo CreateDeviceIndependentResources creare un oggetto interfaccia IDWriteTextLayout chiamando il metodo 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. È quindi necessario modificare la chiamata al metodo ID2D1RenderTarget::D rawText su ID2D1RenderTarget::DrawTextLayout , come illustrato nel codice seguente.

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

Passaggio 2: Aggiungere un metodo OnClick.

Aggiungere ora un metodo alla classe che userà la funzionalità di hit testing del layout di testo.

  1. Dichiarare un metodo OnClick nel file di intestazione della classe.

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. Definire un metodo OnClick nel file di implementazione della classe.

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

Passaggio 3: Eseguire hit testing.

Per determinare dove l'utente ha fatto clic sul layout di testo verrà usato il metodo IDWriteTextLayout::HitTestPoint .

Aggiungere quanto segue al metodo OnClick definito nel passaggio 2.

  1. Dichiarare le variabili che verranno passate come parametri al metodo.

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    Il metodo HitTestPoint restituisce i parametri seguenti.

    Variabile Descrizione
    hitTestMetrics Geometria che racchiude completamente la posizione di hit test.
    isInside Indica se la posizione di hit test è all'interno della stringa di testo o meno. Quando FALSE, la posizione più vicina al bordo del testo viene restituita.
    isTrailingHit Indica se la posizione di hit test si trova all'inizio o al lato finale del carattere.
  2. Chiamare il metodo HitTestPoint dell'oggetto IDWriteTextLayout .

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

    Il codice in questo esempio passa le variabili x e y per la posizione senza alcuna modifica. Questa operazione può essere eseguita in questo esempio perché il layout di testo è la stessa dimensione della finestra e ha origine nell'angolo superiore sinistro della finestra. In caso contrario, è necessario determinare le coordinate in relazione all'origine del layout di testo.

Passaggio 4: Sottolinea il testo fatto clic.

Aggiungere quanto segue al metodo OnClick definito nel passaggio 2, dopo la chiamata al metodo HitTestPoint .

if (isInside == TRUE)
{
    BOOL underline;

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

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

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

Questo codice esegue le operazioni seguenti.

  1. Verifica se il punto di hit-test era all'interno del testo usando la variabile isInside .

  2. Il membro textPosition della struttura hitTestMetrics contiene l'indice in base zero del carattere fatto clic.

    Ottiene la sottolineatura per questo carattere passando questo valore al metodo IDWriteTextLayout::GetUnderline .

  3. Dichiara una variabile DWRITE_TEXT_RANGE con la posizione iniziale impostata su hitTestMetrics.textPosition e una lunghezza di 1.

  4. Attiva la sottolineatura usando il metodo IDWriteTextLayout::SetUnderline .

Dopo aver impostato la sottolineatura, ridisegnare il testo chiamando il metodo DrawD2DContent della classe.

DrawD2DContent();

Passaggio 5: Gestire il messaggio di WM_LBUTTONDOWN.

Infine, aggiungere il messaggio di WM_LBUTTONDOWN al gestore messaggi per l'applicazione e chiamare il metodo OnClick della 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 macro GET_X_LPARAM vengono dichiarate nel file di intestazione windowsx.h. Recuperano facilmente la posizione x e y del clic del mouse.