65.9K
CodeProject 正在变化。 阅读更多。
Home

CStatic 派生的 CSpeedoMeter 类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.96/5 (9投票s)

2005年1月23日

5分钟阅读

viewsIcon

106223

downloadIcon

4349

基于 CStatic 基类的简单速度计类。

Sample Image-SpeedoMeter.jpg

引言

这是一个速度计类,CSpeedoMeter v1.0。我找了一个多星期的速度计控件,但一直找不到。然后我决定自己尝试一下。我以为这会很简单,使用简单的三角函数进行旋转。如果你想知道为什么需要旋转计算,想象一下你在汽车仪表盘前。当你踩下油门时,你会看到东西在旋转,汽车突然开始加速。没错,你需要旋转指针!

基本上,我的方法是使用位图作为速度计的背景。不幸的是,将指针也做成位图有点麻烦。在 GDI API 中没有简单的方法来旋转位图。但是,我们可以直接将指针画成一条线。你只需要关注两个点,然后用一条直线连接它们。事实上,你实际上只控制一个点。这个点会被旋转,并绘制一条线段来表示在任何特定速度下的指针。够简单吧!

简单的数学

为了实现这一点,你需要校准你的速度计指针。我假设 0 度从 6 点钟方向开始。就像大多数真实的汽车速度计一样,指针最初设置在大约 7 点钟方向(顺时针比 6 点钟方向旋转 30 度。不过,我们的示例使用了 40 度的初始偏移)。记住,一个完整的圆代表 360 度。如果我们假设 1 度代表 1 公里/小时,那么一切都很容易。每增加 1 公里/小时,就会顺时针旋转 1 度。

因此,一旦我们能够计算旋转并能在任何特定角度绘制指针,那么差不多了,速度计离你的手就不远了。我们只需要做一些假设。所以,举个例子,让我们假设将指针更新到 240 公里/小时,你需要旋转 240 度 + 偏移量。记住我们使用了偏移量 = 40,这使得将指针设置为 240 公里/小时所需的旋转角度为 280 度。基本公式是

RotationAngle = OffsetAngle + NewSpeed;

我相信这足够简单易懂,所以我只会教你如何使用我的控件。另外值得一提的是,不要忘记绘制与你的假设相符的适当背景图像。在我这里,我创建了一个位图,其中 0 速度设置为从 6 点钟方向顺时针方向 40 度。我知道我的位图不是这个星球上最酷的,但作为开始,我觉得还不错,对吧!

使用代码

有几个文件需要复制到你的项目目录中。它们是:

  • matrix2x2.h & matrix2x2.cpp
  • vector2.h & vector2.cpp
  • speedometer.h & speedometer.cpp

matrix2x2vector2 也是我编写的,用于进行旋转操作。它们在我开发各种项目时,不时地派上用场。速度计类显然是速度计的核心引擎。

将它们放入项目目录后,创建一个 MFC 对话框项目并将上述文件添加到项目中。然后,只需构建项目。我确信它会失败。为什么?因为你还没有将你的项目链接到 winmm.lib。请通过转到 Project-><ProjectName> Properties… 来进行操作。

转到 Linker,然后在 Additional Dependencies 字段中添加 winmm.lib。我只是想告诉你,我使用 Visual Studio .NET 2003 来构建项目。对于 VS 6,请参考 VS 文档了解如何将库链接到你的项目。

接下来,你需要在对话框上创建一个静态控件。将其大小调整为 400x400 以适应我的位图背景。为静态控件添加一个控件变量,例如 m_speedometer。然后在你的 XXXDlg.h 下,将 m_speedmeter 控件的类型从 CStatic 更改为 CSpeedoMeter。不要忘记在你的 XXXDlg.h 文件的顶部添加 #include speedometer.h,以确保它理解 CSpeedoMeter 的作用。

等一下,你离使用该控件还有 2-3 步。下一步是初始化速度计。为了做到这一点,我更喜欢在你的 XXXDlg(在我的演示示例中是 CspeedoMeterDlg)类中创建一个初始化函数,例如 void InitializeSpeedoMeter()。在函数体内添加几行代码来设置位图、指针粗细和颜色。你应该在 OnInitDialog() 处理程序中调用初始化例程。

// Initialization code
void CSpeedoMeterDlg::InitSpeedoMeter()
{
    m_speedometer.SetBitmap(IDB_SPEEDOMETER);
    m_speedometer.SetNeedleThickness(5);
    m_speedometer.SetNeedleColor(RGB(255,0,0));
}

我假设你知道如何将位图导入到你的项目中。否则,只需在主菜单上转到 Project->Add Resource,然后导入位图。不要忘记为位图命名(例如,IDB_SPEEDOMETER)。最后但同样重要的是,在 OnInitDialog() 处理程序中调用 InitSpeedoMeter,就在 // TODO: Add extra initialization here 下方。

好的,现在你已准备好使用该控件。尝试该控件的一个简单方法是添加 OnMouseWheel(…) 处理程序。然后根据 zDelta 的值,通过 UpdateSpeed(float speed) 接口或 Accelerationg(float delta) 接口更新速度计速度。我的演示使用了 OnTimer(…) 处理程序来进行一个简单但有趣的模拟。

关注点

图形编程总是令人兴奋的,因为无论如何,你都会玩数学,如果你幸运的话,你还会玩物理。这太酷了!任何建设性的意见、评论和兴趣表达都可以发送到 我的电子邮件地址

历史

  • V1.0 - 可用的速度计。
© . All rights reserved.