分类: C/C++
2008-09-14 19:57:20
Despite the rather vast array of tools that are provided with Visual C++ one area that seems to be somewhat ignored is that which is concerned with graphical data analysis. There seem to be millions of ways of showing, sorting and relating text and numbers but no good ways of graphically displaying them. (In my world, one decent plot is worth a thousand CRichEditCtrl
's.) Thus I'm always looking for a better way of graphically presenting information in an easily interpreted manner.
Historically, I've shown "live" gauge readings through the constant updating of a numerical value in a read-only edit control. However, apart from making the user seasick, this approach does not easily reveal subtle patterns or trends. This level of interpretation requires an "oscilloscope" or "strip chart" style display of historical data.
This OscopeCtrl is based on the bitmap shifting concept used in . It provides significant enhancements through the display of scaling information and plotting of double precision values. The user implementation is described below.
COScopeCtrl
. Name the control something that sounds technical, like "IDC_OSCOPE
".
COScopeCtrl
. class CTestOScopeDlg : public CDialog { // Construction ... protected: COScopeCtrl m_OScopeCtrl; ... }
BOOL CTestOScopeDlg::OnInitDialog() { ... // determine the rectangle for the control CRect rect; GetDlgItem(IDC_OSCOPE)->GetWindowRect(rect) ; ScreenToClient(rect) ; // create the control m_OScopeCtrl.Create(WS_VISIBLE | WS_CHILD, rect, this) ; ... }
BOOL CTestOScopeDlg::OnInitDialog() { ... // determine the rectangle for the control CRect rect; GetDlgItem(IDC_OSCOPE)->GetWindowRect(rect) ; ScreenToClient(rect) ; // create the control m_OScopeCtrl.Create(WS_VISIBLE | WS_CHILD, rect, this) ; // customize the control m_OScopeCtrl.SetRange(-10.0, 10.0, 1) ; m_OScopeCtrl.SetYUnits("Volts") ; m_OScopeCtrl.SetXUnits("Samples (Windows Timer: 100 msec)") ; m_OScopeCtrl.SetBackgroundColor(RGB(0, 0, 64)) ; m_OScopeCtrl.SetGridColor(RGB(192, 192, 255)) ; m_OScopeCtrl.SetPlotColor(RGB(255, 255, 255)) ; ... }
COScopeCtrl::SetPosition
function with the the data value to be appended to the plot. Subsequent calls to SetPosition will continue to shift the plot to the left. ... m_OScopeCtrl.AppendPoint(nRandom); ...
OScopeCtrl
optimizes the drawing of the plot for the sake of speed and smoothness of animation. In this approach, memory based device contexts and associated bitmaps are constructed for 1.) the underlying grid and 2.) the plot line segments. These two bitmaps are combined in another memory based display context to avoid flicker. During the painting of the control, the grid is BitBlt'd (as a SRCCOPY), the plot is then added by BitBlt'ing it as a "pattern" via SRCPAINT. The result is then BitBlt'd to the display (as SRCCOPY). (See the COScopeCtrl::OnPaint function for details.)
This approach is quite clean and fast for light colored plots and light colored grids which are to be displayed on dark colored backgrounds. For some light colored backgrounds, the plot and/or grid may not be displayed do to the OR'ing nature of the SRCPAINT-style BitBlt.
COScopeCtrl
draws the axis information text in a font which is 14 pixels high. The attributes for both the horizontal and vertical fonts can be modified in the COScopeCtrl::InvalidateCtrl()
function.
COScopeCtrl
constructor sets a most of the default behavior and is thoroughly documented. These values can be modified to achieve different styles of displays.
m_OScopeCtrl.SetRange(-10, 10, 1) ; m_OScopeCtrl.SetYUnits("Volts") ; m_OScopeCtrl.SetXUnits("Samples (Windows Timer: 100 msec)") ; m_OScopeCtrl.SetBackgroundColor(RGB(0, 64, 0)) ; m_OScopeCtrl.SetGridColor(RGB(192, 255, 192)) ; m_OScopeCtrl.SetPlotColor(RGB(255, 255, 255)) ;