Click here to Skip to main content
15,860,972 members
Articles / Desktop Programming / MFC
Article

CStatic derivative CSpeedoMeter class

Rate me:
Please Sign up or sign in to vote.
3.96/5 (9 votes)
22 Jan 20055 min read 103.9K   4.3K   37   6
A simple SpeedoMeter class based on CStatic base class.

Sample Image-SpeedoMeter.jpg

Introduction

Here is a Speedometer class, CSpeedoMeter v1.0. I had been looking for a speedometer control out there for a while but I couldn’t find one. Then I decided to give it a try. I thought it would be pretty simple, using simple trigonometric calculation to do rotation. If you are wondering why you need a rotation calculation, imagine you are in front of your car's dashboard. When you press the pedal you will see something rotating and suddenly your car starts accelerating. Exactly, you need to rotate a needle!

Basically, my approach is to have the background of the speedometer as a bitmap. Unfortunately, to make the needle as a bitmap is a bit messy. There is not an easy way to rotate bitmap in GDI API. But, we can just draw the needle as a line. You only need to take care of two points, while you connect with a straight line. In fact, you are actually controlling only one point. That point will be rotated and a line segment will be drawn representing the needle at any particular speed. Simple enough!

The Simple Mathematics

To make it happen, you need to calibrate your Speedo's needle. I am assuming the 0 degree start from 6 o’clock. As with most of the real Speedo controls in a real car, the needle is initially set at about 7:00 o’clock direction (30 degree clock-wise from 6 o’clock. Our example however uses initial offset at 40 degree). Remember, one full circle would represent 360 degrees. If let’s say, we assume one degree will represent 1 km/h, then life is easy. For each 1 km/h delta, it will represent a rotation of 1 degree clock-wise.

Therefore, once we can calculate the rotation and are able to draw the needle at any particular angle, then that’s about it, a speedometer is not far away from your hand. We just need to make some assumptions. So, for example let’s say, updating the needle to 240 km/h, you need to rotate the needle by 240 degrees + offset. Remember we use offset = 40, which makes the rotation required to set the needle to 240 km/h, to 280 degrees. The basic formula is:

RotationAngle = OffsetAngle + NewSpeed;

I am sure it is simple enough to be understood, so I would just teach you how to use my control. Another thing worth mentioning is, don’t forget about drawing the appropriate background image that is consistent with your assumption. In my case, I created a bitmap with the 0 speed set at 40 degrees from 6 o’clock clock-wise. I know my bitmap is not the coolest in this planet, but to make a start I think it is not too bad, yeah!

Using the code

There are a few files you need to copy to your project directory. They are:-

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

The matrix2x2 and vector2 are also written by me for doing the rotation stuff. They become so handy from time to time when I develop various projects. The speedometer class is obviously the core engine of the Speedo.

After you put them in your project directory, create a dialog MFC project and add the above files to the project. Then, just build the project. I am sure it will fail. Why? Because you haven’t linked your project with winmm.lib. Please do so by going to Project-><ProjectName> Properties…

Go to linker and add winmm.lib on Additional Dependencies field. Just wanna inform you, I use Visual Studio .NET 2003 to build the project. For VS 6, please refer to VS documentation on how to link libraries to your project.

Next, you need to create a static control on your dialog. Size it to 400x400 to fit my bitmap background. Add a control variable to the static control, say m_speedometer. Then under your XXXDlg.h, change the type of m_speedmeter control from CStatic to CSpeedoMeter. Don’t forget to add #include speedometer.h at the top of your XXXDlg.h file to make sure it understands what CSpeedoMeter does.

Wait a minute, you are still 2-3 steps away from using the control. The next step would be to initialize the speedometer. To do this, I prefer to create an initialization function in your XXXDlg (in my demo example, it is CspeedoMeterDlg) class, say void InitializeSpeedoMeter(). Add a few lines of code to the function body to set the bitmap, needle thickness, and its color. You should call the initialization routine inside the OnInitDialog() handler.

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

I am assuming that you know how to import a bitmap to your project. Otherwise, simply go to Project->Add Resource on the main menu, then import bitmap. Don’t forget to name the bitmap (e.g., IDB_SPEEDOMETER). Last but not the least, call InitSpeedoMeter in the OnInitDialog() handler, just under // TODO: Add extra initialization here.

OK, now you are ready to use the control. One easy way to try the control is to add OnMouseWheel(…) handler. Then based on the value of zDelta, you update the speedometer speed through UpdateSpeed(float speed) interface or Accelerationg(float delta) interface. My demo, uses OnTimer(…) handler to do a simple but interesting simulation.

Points of Interest

Doing graphics programming is always exciting because no matter what, you will play with math, and if you are lucky, you will play with physics. It is so cool!. Any, constructive input, comments and expression of interest can be sent to my email address.

History

  • V1.0 - Working speedometer.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
United States United States
Henry Tan was born in a small town, Sukabumi, Indonesia, on December 7th, 1979. He obtained his Bachelor of Computer System Engineering with first class honour from La Trobe University, VIC, Australia in 2003. During his undergraduate study, he was nominated as the most outstanding Honours Student in Computer Science. Additionally, he was the holder of 2003 ACS Student Award. After he finished his Honour year at La Trobe University, on August 2003, he continued his study pursuing his doctorate degree at UTS under supervision Prof. Tharam S. Dillon. He obtained his PhD on March 2008. His research interests include Data Mining, Computer Graphics, Game Programming, Neural Network, AI, and Software Development. On January 2006 he took the job offer from Microsoft Redmond, USA as a Software Design Engineer (SDE).


What he like most? Programming!Math!Physisc!Computer Graphics!Playing Game!

What programming language?
C/C++ but started to love C#.

Comments and Discussions

 
Questionthank you for the help Pin
Hayder Hussien25-Mar-22 2:50
Hayder Hussien25-Mar-22 2:50 
GeneralGDI Resource leakage Pin
darkhalf50129-Jan-06 10:23
darkhalf50129-Jan-06 10:23 
GeneralThe control is nice but a suggestion Pin
subash110721-Dec-05 20:34
subash110721-Dec-05 20:34 
GeneralThe name of the subclass Pin
Alex Evans19-Feb-05 18:25
Alex Evans19-Feb-05 18:25 
GeneralA Few Comments Pin
Rick York25-Jan-05 8:12
mveRick York25-Jan-05 8:12 
GeneralRe: A Few Comments Pin
Henry Tan Setiawan17-Mar-05 16:05
Henry Tan Setiawan17-Mar-05 16:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.