Ausführen von Treffertests für ein Textlayout

Enthält ein kurzes Tutorial zum Hinzufügen von Treffertests zu einer DirectWrite Anwendung, die Text mithilfe der IDWriteTextLayout-Schnittstelle anzeigt.

Das Ergebnis dieses Tutorials ist eine Anwendung, die das Zeichen unterstreicht, auf das mit der linken Maustaste geklickt wird, wie im folgenden Screenshot gezeigt.

Screenshot von "Auf diesen Text klicken"

Dies enthält die folgenden Teile:

Schritt 1: Erstellen eines Textlayouts.

Zunächst benötigen Sie eine Anwendung, die ein IDWriteTextLayout-Objekt verwendet. Wenn Sie bereits über eine Anwendung verfügen, die Text mit einem Textlayout anzeigt, fahren Sie mit Schritt 2 fort.

Gehen Sie wie folgt vor, um ein Textlayout hinzuzufügen:

  1. Deklarieren Sie einen Zeiger auf eine IDWriteTextLayout-Schnittstelle als Member der -Klasse.

    IDWriteTextLayout* pTextLayout_;
    
  2. Erstellen Sie am Ende der CreateDeviceIndependentResources-Methode ein IDWriteTextLayout-Schnittstellenobjekt, indem Sie die CreateTextLayout-Methode aufrufen.

    // 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. Anschließend müssen Sie den Aufruf der ID2D1RenderTarget::D rawText-Methode in ID2D1RenderTarget::D rawTextLayout ändern, wie im folgenden Code gezeigt.

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

Schritt 2: Hinzufügen einer OnClick-Methode.

Fügen Sie nun der -Klasse eine -Methode hinzu, die die Treffertestfunktion des Textlayouts verwendet.

  1. Deklarieren Sie eine OnClick-Methode in der Klassenheaderdatei.

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. Definieren Sie eine OnClick-Methode in der Klassenimplementierungsdatei.

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

Schritt 3: Ausführen von Treffertests.

Um zu bestimmen, wo der Benutzer auf das Textlayout geklickt hat, verwenden wir die IDWriteTextLayout::HitTestPoint-Methode.

Fügen Sie der OnClick-Methode, die Sie in Schritt 2 definiert haben, Folgendes hinzu.

  1. Deklarieren Sie die Variablen, die wir als Parameter an die -Methode übergeben.

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    Die HitTestPoint-Methode gibt die folgenden Parameter aus.

    Variable BESCHREIBUNG
    hitTestMetrics Die Geometrie, die die Treffertestposition vollständig umschließt.
    isInside Gibt an, ob sich die Treffertestposition innerhalb der Textzeichenfolge befindet oder nicht. Bei FALSE wird die Position zurückgegeben, die dem Rand des Texts am nächsten liegt.
    isTrailingHit Gibt an, ob sich die Treffertestposition an der führenden oder der nachseitigen Seite des Zeichens befindet.
  2. Rufen Sie die HitTestPoint-Methode des IDWriteTextLayout-Objekts auf.

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

    Der Code in diesem Beispiel übergibt die x- und y-Variablen für die Position ohne Änderungen. Dies kann in diesem Beispiel erfolgen, da das Textlayout die gleiche Größe wie das Fenster hat und aus der linken oberen Ecke des Fensters stammt. Wenn dies nicht der Fall wäre, müssten Sie die Koordinaten in Bezug auf den Ursprung des Textlayouts bestimmen.

Schritt 4: Unterstrichen Sie den angeklickten Text.

Fügen Sie dem OnClick-Befehl, den Sie in Schritt 2 definiert haben, nach dem Aufruf der HitTestPoint-Methode Folgendes hinzu.

if (isInside == TRUE)
{
    BOOL underline;

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

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

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

Dieser Code führt Folgendes aus.

  1. Überprüft mithilfe der IsInside-Variablen, ob sich der Treffertestpunkt im Text befindet.

  2. Das textPosition-Member der hitTestMetrics-Struktur enthält den nullbasierten Index des angeklickten Zeichens.

    Ruft den Unterstrich für dieses Zeichen ab, indem dieser Wert an die IDWriteTextLayout::GetUnderline-Methode übergeben wird.

  3. Deklariert eine DWRITE _ TEXT _ RANGE-Variable, bei der die Startposition auf hitTestMetrics.textPosition und eine Länge von 1 festgelegt ist.

  4. Umschaltet die Unterstreichung mithilfe der IDWriteTextLayout::SetUnderline-Methode.

Zeichnen Sie nach dem Festlegen der Unterstreichung den Text neu, indem Sie die DrawD2DContent-Methode der -Klasse aufrufen.

DrawD2DContent();

Schritt 5: Behandeln der _ WM-LBUTTONDOWN-Nachricht.

Fügen Sie abschließend die _ WM-LBUTTONDOWN-Nachricht dem Meldungshandler für Ihre Anwendung hinzu, und rufen Sie die OnClick-Methode der -Klasse auf.

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

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

GET _ X _ LPARAM- und GET _ _ X-LPARAM-Makros werden in der Headerdatei windowsx.h deklariert. Sie können die x- und y-Position des Mausklicks leicht abrufen.