模拟仪表盘类






4.17/5 (8投票s)
2000年1月19日

115911

5090
一个将数值显示为模拟仪表盘的控件
最近,我参与了一个仪器项目,其中使用一个单独的显示(CView)来呈现测量结果以及一些传感器的状态。 希望将所有内容放在一个可以最大化的“窗口”中,并且无需处理重叠的窗口或对话框即可查看所有相关信息。
作为图形化显示传感器状态的一种方法,开发了一个“模拟仪表”类,该类可用于任何显示上下文中的任何正方形矩形中。 因此,可以在应用程序的 CView 派生类中确定一个正方形区域 (CRect),并且可以在此 CRect 中根据需要显示和更新仪表。
绘制仪表有些微不足道,但是平滑(且快速)地动画化此类仪表则有所不同。 为此,我回顾了我在 示波器/条形图控件 中使用的“三重缓冲”方法。 在这种方法中,我创建了三个位图:一个用于底层“网格”(饼形楔形,标题和数值限制值),一个用于“指针”,另一个用于在 BitBlt'ing 到目标显示上下文之前临时存储指针和网格组合的“结果”。
为了提高动画的速度,这些位图仅在“需要时”更新。 例如,仅当仪表的矩形已更改时才重绘网格位图,并且仅当指针的位置已更改时才重绘指针位图。 此外,位图的组合在基于内存的结果中执行,然后在显示之前执行,以提供更快的性能。
可以基于以下步骤使用模拟仪表
- 将仪表添加到您的类中
- 根据您的特定需求初始化仪表的属性。
- 在所需的显示上下文中确定一个正方形矩形。
- 显示仪表。
- 根据需要更新仪表。
以下详细概述了这些步骤
- 在仪表的拥有者(例如,您的 CView 派生类)中,添加您的仪表。
- 初始化仪表属性。
- 确定仪表的位置(正方形矩形)并显示它。
- 根据需要更新指针位置。
- 其他注意事项
- SetRange (GetMaxRange,GetMinRange)
- SetRangeDecimals (GetRangeDecimals)
- SetValueDecimals (GetValueDecimals)
- SetTitle (GetTitle)
- 提示:您必须调用 ShowMeter 才能在调用“Set”函数后看到效果。
建立 CRect 成员变量来跟踪仪表的位置也可能很有用。
class CAnalogMeterTestView : public CView { public: CRect m_rectLeftMeter ; CRect m_rectRightMeter ; CAnalogMeter m_meterLeft ; CAnalogMeter m_meterRight ; } // end CAnalogMeterTestView
最好在仪表所有者的构造函数中进行调整。
CAnalogMeterTestView::CAnalogMeterTestView() { // setup the Left meter properties m_meterLeft.SetRange (-5.0, 5.0) ; m_meterLeft.SetRangeDecimals(1) ; m_meterLeft.SetValueDecimals(3) ; m_meterLeft.SetTitle("Channel A") ; // setup the Right meter properties m_meterRight.SetRange (-10.0, 10.0) ; m_meterRight.SetRangeDecimals(1) ; m_meterRight.SetValueDecimals(3) ; m_meterRight.SetTitle("Channel B") ; } // end CAnalogMeterTestView constructor
最好在仪表所有者的 OnDraw 函数中进行调整。
void CAnalogMeterTestView::OnDraw(CDC* pDC) { // determine the meter rectangle(s) - make sure they are square // fill in the member variable CRect's accordingly // show the meters in their respective rectangles m_meterLeft.ShowMeter (pDC, m_rectLeftMeter) ; m_meterRight.ShowMeter (pDC, m_rectRightMeter) ; } // end OnDraw
我使用的方法是根据计时器定期更新指针位置。
void CAnalogMeterTestView::OnTimer(UINT nIDEvent) { double dLeftValue, // the new meter values to be shown dRightValue ; CClientDC dcClient(this) ; // get a client dc for the updated meter // determine the new values // update the meters m_meterLeft.UpdateNeedle (&dcClient, dLeftValue) ; m_meterRight.UpdateNeedle (&dcClient, dRightValue) ; // call the base class, as the Class Wizard says I should CView::OnTimer(nIDEvent); } // end OnTimer
自定义
如上面的步骤2所示,可以轻松修改仪表范围、标题和数值上的小数位数。但是,应该注意的是,您必须在进行这些更改后调用 ShowMeter 才能“看到”效果。 可以更改这些属性(通过“Set”函数)或检索这些属性(通过“Get”函数)。 公共属性修改/访问函数是
“仪表内部”的自定义
CAnalogMeter 构造函数包含一些可能提供一些有趣的自定义项的区域,特别是在颜色方面。 尝试修改成员变量:m_colorGrid、m_colorNeedle 和 m_colorValue。
此外,仪表的“饼图切片”的宽度基于 CAnalogMeter::DrawGrid() 函数中指定的角度。 该角度通过变量 dLimitAngleDeg 设置。
在您向我发送令人讨厌的电子邮件之前,请阅读此内容...(在发送友好的电子邮件之前,您不必阅读此内容)
该仪表旨在用于 CView 派生类中,并且已使用我的打印机和剪贴板功能进行了测试。 我没有尝试在其他区域(例如对话框中的控件)中使用它。 我确信可以添加这些功能,或者可以将这种方法应用于这些其他区域,但是我现在没有时间这样做。