Objective Chart : PART I User’s Guide : Chapter 3 Design Overview of Objective Chart : Display Scheme
Display Scheme
To allow great flexibility from a single base class, the Objective Chart system uses an unconventional display scheme. Rather than having many window classes for various tasks, Objective Chart allows a single object (SRGraph) to take over the client area of any CWnd-based MFC window. A simple function call paints the chart data and all associated graphics using GDI calls to the device context that displays the window. This system allows the same code to be used to display charts in document views, in dialog controls, and even on buttons or menu items.
Drawing is performed in one of two modes. The default mode uses a back buffer to construct an image of the graph which is then block copied (BitBlt) to the screen overwriting the contents of the destination rectangle within the window. This method allows the draw cycle to complete invisibly, eliminating screen flicker. This method is visually pleasing and causes less eyestrain, but it has the disadvantages of requiring extra memory and slowing performance.
The second mode uses the device context surface directly and draws over the existing screen data. This method is less pleasing visually but it is quicker. It also has the advantage of being able to overlay chart data onto existing graphics. All chart components can be configured with a NO_FILL background to keep them from overwriting their backgrounds. Then pre-existing graphics can serve as background for the chart’s data. This mode is selected by calling SRGraph::SetBackgroundDraw(FALSE).
The window that is displaying the chart normally initiates the drawing process. In the OnDraw() or OnPaint() message handler, the CWnd object calls the DrawComponentList() function of the SRGraph or derived object. SRGraph is supplied with a pointer to the device context or CDC object being used to paint the window and the address of the CWnd object itself. DrawComponentList() steps through the stored visual components one by one, calling their Draw() functions. Each component then draws itself onto the provided device context and, if necessary, takes window rectangle dimensions from the client area of the provided CWnd pointer.
During their draw cycles, some components may create additional temporary components on the heap or use components that they keep as member variables. The main component must pass along the current CDC and CWnd pointers to the sub-component or the draw process will fail. Furthermore, the text display components sometimes need to calculate character string sizes during their setup phases. Certain functions will fail if the CDC and CWnd are not known.
Some components also need to take references from the SRGraph object that owns the component. Therefore components have a member variable that must be correctly initialized [using SetParent()] to point to the parent graph to ensure correct operation. SetParent() is called automatically when a component is added to the SRGraph object’s component list.