c++ - 使用 Direct2D 绘制时钟的问题
问题描述
我正在尝试用 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);
}
...
解决方案
是的,您可以使用它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() );
}
参考:绘制时钟指针
调试:
整个代码示例:
推荐阅读
- c# - 如何在订阅者上实现 Prism EventAggregator 事件队列
- google-cloud-platform - GCP 指标资源管理器中的计数器指标
- javascript - 当浏览器/pwa 最小化时延迟 ServiceWorker 中的通知
- javascript - 在 highcharts 中叠加图表
- javascript - 使用 CLI 创建新项目后如何在 vue 3 中正确导入 Axios?
- java - 使用正则表达式将城市名称和可选的国家代码 (ISO-3166) 分成组
- sql - 将两个 group by 和 count 条件合二为一
- sed - Jenkinsfile,“查找”,忽略一些隐藏目录和其他文件夹
- java - H2 控制台在配置和使用嵌入式本地持久性时不显示 Spring Boot 创建的表,即使它们存在
- loopback4 - Loopback4 - 使用 OpenAPI 定义调用 REST API