2014-02-26 62 views
2

我正在研究一段基本上通過多次調用TextOut在屏幕上繪製文本的代碼。這是一個C++ Win32應用程序,我使用的是Visual Studio 2012.如何在Word在標記拼寫錯誤等時進行波浪下劃線?如何用Win32 TextOut繪製波浪形下劃線

TEXTMETRIC有一個名爲tmUnderlined的成員,適用於正常帶下劃線的文本,但不適用于波浪下劃線。我還發現微軟的RichEdit控件支持波浪下劃線,但我也無法使用它。

我當然可以使用簡單的正弦波創建路徑,但在此之前,我想檢查是否有更標準的方法來執行此操作。

+1

沒有任何方法可以通過'TextOut'來做到這一點。 –

+0

也許有其他的方法嗎? –

+0

剛剛檢查了GDI +的DrawString方法。有一個名爲FontStyle的枚舉,其中包含FontStyleUnderline,但沒有波浪形下劃線... –

回答

4

我自己實現了它。下面是任何人的情況下將代碼感興趣:

BOOL SomeClass::drawWavyUnderline (WPPoint ptTextPos, int nWidth, COLORREF col) 
    // Draws a wavy underline below the position a run of text at the given 
    // position and of the given width would occupy. This method consults the 
    // height of the currently selected font in order to find the baseline where 
    // the underline is drawn. 
    // NOTE: The method will fail to find the correct position of the underline 
    // if the current text alignment is not set to TA_LEFT! 
    // @param ptTextPos (in): TextOut reference point. 
    // @return: TRUE on success, FALSE on failure. 
    { 
    BOOL bResult = FALSE; 
    Gdiplus::Graphics *pGfx = NULL; 
    Gdiplus::Pen *pPen = NULL; 
    Gdiplus::PointF *arrPts = NULL; 
    // Determine the number of points required. 
    static const float fNumPixelsPerSample = 1.2f; 
    int nNumPts = (int)(nWidth/fNumPixelsPerSample); 
    if (nNumPts <= 1) 
     { 
     goto outpoint; // width too small or even negative! 
     } 
    // Retrieve information about the current GDI font. 
    TEXTMETRIC tm; 
    if (!::GetTextMetrics (/* HDC... */, &tm)) 
     { 
     goto outpoint; // failed to retrieve TEXTMETRIC! 
     } 
    // Create points array. 
    arrPts = new Gdiplus::PointF [nNumPts]; 
    if (arrPts == NULL) 
     { 
     goto outpoint; // out of mem! 
     } 
    // Fill points array. 
    static const float fYOffset = 1.0f; 
    static const float fAmp = 1.5f; 
    Gdiplus::PointF *pScan = arrPts; 
    for (int i = 0; i < nNumPts; i++, pScan++) 
     { 
     pScan->X = (Gdiplus::REAL)(ptTextPos.x + (float) i * nWidth/(nNumPts - 1)); 
     // The amplitude is computed as a function of the absolute position x rather 
     // than the sample index i in order to make sure the waveform will start at 
     // the correct point when two runs are drawn very near each-other. 
     float fValue = (float)(fAmp * sin ((pScan->X/fNumPixelsPerSample)*(M_PI/3.0))); 
     pScan->Y = (Gdiplus::REAL)(ptTextPos.y + tm.tmAscent + tm.tmDescent*0.5f + fYOffset + fValue); 
     } 
    // Create GDI+ graphics object. 
    HDC hdc = /* code to retrieve the HDC... */ ; 
    if (hdc == NULL) 
     { 
     goto outpoint; // missing HDC 
     } 
    pGfx = new Gdiplus::Graphics (hdc); 
    if (pGfx == NULL) 
     { 
     goto outpoint; // out of mem! 
     } 
    // Draw the lines. 
    pPen = new Gdiplus::Pen (Gdiplus::Color (GetRValue (col), GetGValue (col), GetBValue (col))); 
    if (pPen == NULL) 
     { 
     goto outpoint; // out of mem! 
     } 
    pGfx->SetSmoothingMode (Gdiplus::SmoothingModeHighQuality); 
    if (pGfx->DrawLines (pPen, arrPts, nNumPts) != Gdiplus::Ok) 
     { 
     goto outpoint; // failed to draw the lines! 
     } 
    bResult = TRUE; 
    outpoint: 
    // Clean up. 
    if (pPen != NULL) delete pPen; 
    if (pGfx != NULL) delete pGfx; 
    if (arrPts != NULL) delete[] arrPts; 
    return bResult; 
    } 

P.S:如果你不喜歡goto方法,隨意改寫,而使用在try..catch!