这为我省去了很多麻烦,谢谢,所以这是我没有 goto 的解决方案,还有一些优化:
#include <gdiplus.h>
#include <corecrt_math_defines.h>
#include <vector>
bool drawWavyUnderline(HDC hDC, const POINT& 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|TA_TOP.
// @param ptTextPos (in): TextOut reference point.
// @return: TRUE on success, FALSE on failure.
{
bool bResult = false;
// Determine the number of points required.
const float fNumPixelsPerSample = 1.2f;
const int nPts = (int)(nWidth / fNumPixelsPerSample);
if (nPts > 1) {
try {
// Retrieve information about the current GDI font.
TEXTMETRIC tm;
if (::GetTextMetrics(hDC, &tm)) {
// Fill points array.
const float fAmp = 1.5f;
const float fYOffset = ptTextPos.y + tm.tmAscent + tm.tmDescent * 0.5f + 1.0f;
float xOffset = 0.0;
std::vector< Gdiplus::PointF> arrPts;
arrPts.resize(nPts);
for (auto& pt : arrPts) {
pt.X = (Gdiplus::REAL)(ptTextPos.x + xOffset++ * nWidth / (nPts - 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.
const float fValue = (float)(fAmp * sin((pt.X / fNumPixelsPerSample) * (M_PI / 3.0)));
pt.Y = (Gdiplus::REAL)(fYOffset + fValue);
}
// Draw the wavy line:
Gdiplus::Graphics gfx(hDC);
Gdiplus::Pen pen(Gdiplus::Color(GetRValue(col), GetGValue(col), GetBValue(col)));
gfx.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
bResult = gfx.DrawLines(&pen, arrPts.data(), nPts) == Gdiplus::Ok;
}
}
catch (...) {
}
}
return bResult;
}