【问题标题】:Problem with drawing a clock with Direct2D使用 Direct2D 绘制时钟的问题
【发布时间】:2020-08-10 09:52:35
【问题描述】:

我正在尝试使用 Direct2D 绘制时钟。程序正确获取当前时间,但错误是 Direct2D 绘制时钟时,因为时钟似乎与当前时间过时。要获取当前时间,请使用GetLocalTime() 函数,然后映射值以将它们转换为角度,以便可以绘制它们。我该如何解决?

...

renderTarget->BeginDraw();
renderTarget->Clear(ColorF(ColorF::Black));

GetLocalTime(&sysTime);

wstring text = L"Hour: " + to_wstring(sysTime.wHour)
    + L"\nMinute: " + to_wstring(sysTime.wMinute)
    + L"\nSecond: " + to_wstring(sysTime.wSecond);

brush->SetColor(ColorF(ColorF::White));
renderTarget->DrawTextW(text.c_str(), text.length(), textFormat, textRect, brush);

D2D1_POINT_2F centerPoint = Point2F(320, 240);
FLOAT hourAngle = map(sysTime.wHour%12, 0, 12, 0, 360);
FLOAT minuteAngle = map(sysTime.wMinute, 0, 60, 0, 360);
FLOAT secondAngle = map(sysTime.wSecond, 0, 60, 0, 360);

brush->SetColor(ColorF(ColorF::DeepPink));
renderTarget->DrawEllipse(D2D1::Ellipse(centerPoint, 150, 150), brush, 5);

renderTarget->SetTransform(Matrix3x2F::Rotation(secondAngle, centerPoint));
brush->SetColor(ColorF(ColorF::Blue));
renderTarget->DrawLine(centerPoint,Point2F(centerPoint.x,centerPoint.y + 150*0.9), brush, 10,lineStrokeStyle);

renderTarget->SetTransform(Matrix3x2F::Rotation(minuteAngle, centerPoint));
brush->SetColor(ColorF(ColorF::White));
renderTarget->DrawLine(centerPoint,Point2F(centerPoint.x,centerPoint.y + 150*0.7), brush, 10, lineStrokeStyle);

renderTarget->SetTransform(Matrix3x2F::Rotation(hourAngle, centerPoint));
brush->SetColor(ColorF(ColorF::GreenYellow));
renderTarget->DrawLine(centerPoint, Point2F(centerPoint.x,centerPoint.y + 150*0.5), brush, 10,lineStrokeStyle);

renderTarget->SetTransform(Matrix3x2F::Identity());

HRESULT hrErr = renderTarget->EndDraw();

if (hrErr != S_OK) {
    MessageBox(hWnd, L"Direct2D Error", L"Direct2D Error", MB_OK | MB_ICONERROR);
    SafeRelease(&brush);
    SafeRelease(&renderTarget);
    SafeRelease(&factory);
}

...

【问题讨论】:

  • map() 是做什么的?
  • map 函数将时间线性映射到一个角度。我用这个函数把时分秒转换成0°到360°的角度。
  • 我使用了本页交易的公式:https://rosettacode.org/wiki/Map_range#C.2B.2B
  • 没有看到你的 map() 代码,我们怎么知道问题出在哪里?你检查过它返回的角度吗?

标签: c++ c winapi directx direct2d


【解决方案1】:

是的,您可以使用GetLocalTime 获取当前的本地日期和时间。问题可能在于将时间映射到一个角度。

但是这些都可以解决,因为MSDN里有很详细的例子。

我们可以计算角度,然后应用旋转变换,而不是计算线条的坐标。下面的代码显示了一个绘制一个时钟指针的函数。 fAngle 参数给出手的角度,以度为单位。

void Scene::DrawClockHand(float fHandLength, float fAngle, float fStrokeWidth)
{
    m_pRenderTarget->SetTransform(
        D2D1::Matrix3x2F::Rotation(fAngle, m_ellipse.point)
            );

    // endPoint defines one end of the hand.
    D2D_POINT_2F endPoint = D2D1::Point2F(
        m_ellipse.point.x,
        m_ellipse.point.y - (m_ellipse.radiusY * fHandLength)
        );

    // Draw a line from the center of the ellipse to endPoint.
    m_pRenderTarget->DrawLine(
        m_ellipse.point, endPoint, m_pStroke, fStrokeWidth);
}

此代码绘制一条垂直线,从钟面的中心开始,到点 endPoint 结束。通过应用旋转变换,该线围绕椭圆的中心旋转。旋转的中心点是构成钟面的椭圆的中心。

void Scene::RenderScene()
{
    m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));

    m_pRenderTarget->FillEllipse(m_ellipse, m_pFill);
    m_pRenderTarget->DrawEllipse(m_ellipse, m_pStroke);

    // Draw hands
    SYSTEMTIME time;
    GetLocalTime(&time);

    // 60 minutes = 30 degrees, 1 minute = 0.5 degree
    const float fHourAngle = (360.0f / 12) * (time.wHour) + (time.wMinute * 0.5f);
    const float fMinuteAngle =(360.0f / 60) * (time.wMinute);

    DrawClockHand(0.6f,  fHourAngle,   6);
    DrawClockHand(0.85f, fMinuteAngle, 4);

    // Restore the identity transformation.
    m_pRenderTarget->SetTransform( D2D1::Matrix3x2F::Identity() );
}

参考:Drawing Clock Hands

调试:

整个代码示例:

【讨论】:

  • 很抱歉,但需要回答才能回答问题。这只是你的平均“试试这个,它有效”,完全忽略了这个问题。一个高质量的答案需要说明问题是什么,以及建议的答案如何解决它。
猜你喜欢
  • 2017-05-30
  • 2014-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
相关资源
最近更新 更多