共用方式為


如何在文字配置上執行點擊測試

提供一個簡短的教學課程,說明如何使用 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::DrawText 方法變更為 ID2D1RenderTarget::DrawTextLayout,如下列程式碼所示。

    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 幾何完整包圍測試位置。
    裡面 指出點擊測試位置是否在文字字串內。 當 FALSE 時,會傳回最接近文字邊緣的位置。
    isTrailingHit 指出命中測試位置是否位於字元的前置側或後置側。
  2. 呼叫 IDWriteTextLayout 物件的 HitTestPoint 方法。

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

    此範例中的程式代碼會傳遞位置的 xy 變數,而不需要任何修改。 這可以在此範例中完成,因為文字版面配置的大小與視窗相同,而且源自視窗左上角。 如果情況並非如此,您必須確定與文本佈局原點相關的座標。

步驟 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 成員包含所按字元從零開始的索引。

    將此值傳遞至 IDWriteTextLayout::GetUnderline 方法,以取得這個字元的底線。

  3. 宣告 DWRITE_TEXT_RANGE 變數,並將開始位置設定為 hitTestMetrics.textPosition,長度為 1。

  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_LPARAMGET_X_LPARAM 宏指令會在 windowsx.h 標頭檔案中宣告。 它們可以輕鬆地擷取滑鼠按兩下的 x 和 y 位置。