次の方法で共有


テキスト レイアウトでヒット テストを実行する方法

IDWriteTextLayout インターフェイスを使用してテキストを表示するDirectWrite アプリケーションにヒット テストを追加する方法に関する簡単なチュートリアルを提供します。

このチュートリアルの結果は、次のスクリーン ショットに示すように、マウスの左ボタンでクリックされた文字に下線を引くアプリケーションです。

この方法では、次の部分を含めます。

手順 1: テキスト レイアウトを作成する。

まず、 IDWriteTextLayout オブジェクトを使用するアプリケーションが必要です。 テキスト レイアウトでテキストを表示するアプリケーションが既にある場合は、手順 2 に進みます。

テキスト レイアウトを追加するには、次の操作を行う必要があります。

  1. IDWriteTextLayout インターフェイスへのポインターを クラスのメンバーとして宣言します。

    IDWriteTextLayout* pTextLayout_;
    
  2. CreateDeviceIndependentResources メソッドの最後に、CreateTextLayout メソッドを呼び出して IDWriteTextLayout インターフェイス オブジェクトを作成します。

    // 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. 次に、次のコードに示すように 、ID2D1RenderTarget::D rawText メソッドの呼び出 しを ID2D1RenderTarget::D rawTextLayout に変更する必要があります。

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

手順 2: OnClick メソッドを追加します。

次に、テキスト レイアウトのヒット テスト機能を使用する メソッドを クラスに追加します。

  1. クラス ヘッダー ファイルで OnClick メソッドを宣言します。

    void OnClick(
        UINT x,
        UINT y
        );
    
  2. クラス実装ファイルで OnClick メソッドを定義します。

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

手順 3: ヒット テストを実行する。

ユーザーがテキスト レイアウトをクリックした場所を確認するには、 IDWriteTextLayout::HitTestPoint メソッドを 使用します。

手順 2 で定義した OnClick メソッドに以下を追加します。

  1. メソッドにパラメーターとして渡す変数を宣言します。

    DWRITE_HIT_TEST_METRICS hitTestMetrics;
    BOOL isTrailingHit;
    BOOL isInside; 
    

    HitTestPoint メソッドは、次のパラメーターを出力します。

    変数 説明
    hitTestMetrics ヒット テストの場所を完全に囲むジオメトリ。
    isInside ヒット テストの場所がテキスト文字列内にあるかどうかを示します。 FALSE の場合、テキストの端に最も近い位置が返されます。
    isTrailingHit ヒット テストの場所が文字の先頭と末尾のどちらにあるかを示します。
  2. IDWriteTextLayout オブジェクトの HitTestPoint メソッドを呼び出します。

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

    この例のコードでは、位置の x 変数と y 変数を変更せずに渡します。 これは、テキスト レイアウトがウィンドウと同じサイズで、ウィンドウの左上隅に表示されるため、この例で実行できます。 そうでない場合は、テキスト レイアウトの原点に関連する座標を決定する必要があります。

手順 4: クリックしたテキストに下線を引きます。

HitTestPoint メソッドの呼び出しの後に、手順 2 で定義した OnClick に以下を追加します。

if (isInside == TRUE)
{
    BOOL underline;

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

    DWRITE_TEXT_RANGE textRange = {hitTestMetrics.textPosition, 1};

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

このコードでは、次の処理を行います。

  1. isInside 変数を使用して、ヒット テスト ポイントがテキスト内にあったかどうかを確認します。

  2. hitTestMetrics 構造体の textPosition メンバーには、クリックした文字の 0 から始まるインデックスが含まれます。

    この値を IDWriteTextLayout::GetUnderline メソッドに渡して、この文字の下線を取得します。

  3. 開始位置が hitTestMetrics.textPosition に設定され、長さが 1 のDWRITE_TEXT_RANGE変数を宣言します。

  4. IDWriteTextLayout::SetUnderline メソッドを使用して下線を切り替えます。

下線を設定した後、 クラスの DrawD2DContent メソッドを呼び出してテキストを再描画します。

DrawD2DContent();

手順 5: WM_LBUTTONDOWN メッセージを処理します。

最後に、アプリケーションのメッセージ ハンドラーに WM_LBUTTONDOWN メッセージを追加し、 クラスの OnClick メソッドを呼び出します。

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

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

GET_X_LPARAM マクロと GET_X_LPARAM マクロは、windowsx.h ヘッダー ファイルで宣言されます。 マウス クリックの x 位置と y 位置を簡単に取得できます。