![]() |
Contents page Previous | Next |
This tutorial focuses on some of the technical and syntactical issues for working with TeeChart and Microsoft's Visual C++. Most TeeChart documentation is written using Visual Basic examples but hopefully by the end of this tutorial you should find it easy enough to 'port' those examples and apply them to Visual C++ (of course VC++ then has a few tricks of its own !).
Applied examples in this tutorial originate with MFC in mind.
void CMyDlg::OnButton1() { //Add this include to the implementation file #include "Series.h" // Add a Bar Series, (constants are discussed later in the tutorial) m_Chart1.AddSeries(1); // Fill with random data m_Chart1.Series(0).FillSampleValues(10); }
Compile the project and select the button to populate a Bar Series on the Chart.
Please read the whole of this section before commencing to upgrade your VC++ project to TeeChart ActiveX Control v2017. The following describes manual steps and a semi-automated upgrade using the TeeChart Upgrade utility.
Manual upgradeThe differences between TeeChart Pro AX v8 and TeeChart Pro AX v2017 to be considered when upgrading v8 projects are as follows:
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
//prevents the following compile error type: tchart.h(29) : error C2017: 'CTChart' : 'class' type redefinition..or add the directives to all header files before compiling the project as a preventative measure.
For most conventional project types the TeeChart Upgrade utility (accessible via the TeeChart Program Manager group) can do the majority of the routine work of the upgrade.
To use the upgrade tool, start it from the icon below the TeeChart Program Manager group. Select the VC++ tab and select the workspace you wish to upgrade.
See the Upgrading from TeeChart v5 Word document, in the 'Docs' folder, for more information about upgrading projects from TeeChart v5.
To change Chart properties at design time, right mouseclick on the Chart on the Form and select 'Properties' from the menu to display the properties window. Select the 2nd tab, TeeChart Pro Editor to display the Chart Editor. You can make changes to the Chart as described in previous tutorials.
*Note
Do not use the Chart Editor accessible via 'TeeChart Pro ActiveX Control Object' from the Mouse right Button menu when clicking on the Chart in a Form. If you Edit in this way and not via 'Properties' as described in the previous paragraph, modified properties are not permanently saved for runtime.
Adding an event for the Chart on the Dialog Form is fairly straightforward. Right click on the Chart in the Form and select Events from the menu. Developer Studio offers you a list of TeeChart events. Select the event you wish to add from the list and the 'Add and Edit' button. This will add the handler and the function to the implementation file.
MS VC++ adds the TeeChart classes to the project as per the steps outlined in Quick start. These can be viewed with the ClassView window. The Chart itself, here named as m_Chart1, can be accessed without further modification to the implementation file. To work with any other Class you will need to add it as an #include to the file. Take the following example, we are modifying the Chart Panel Gradient. We need to include the Classes for Panel and Gradient.
void CMyDlg::OnButton1() { //Add includes #include "Panel.h" #include "Gradient.h" //Enable Panel Gradient m_Chart1.GetPanel().GetGradient().SetVisible(true); }
Note the key difference to code described for Visual Basic in the online help file. VC++ requires the Get and Set of each property. In effect we are 'getting' each Class (Panel and Gradient) and 'setting' the property. The structure remains the same.
MS VC++ v7 makes coding considerably easier as you are now prompted with all properties and methods that relate to a Class as you type the code. You still need the header #include though.
The Online help contains a listing of declarations of Classes, Properties,
Methods, Constants and Events. These can be applied with reasonable uniformity
to different programming environments. TeeChart coded examples, for all
environments, can be found in the
Examples
folder. The Online help also includes some examples, mostly written for
Visual Basic. Due to space constraints there are far more examples in VB than VC++
but all principles used in VB can be applied in VC++. All new concepts are
presented in the TeeChart AX Feature Demo accessible via the TeeChart
Program Manager menu group. The following table translates some of the VB coded
expressions used in the demo to VC++.
VB Expression |
VC++ equivalent |
Add methodTChart1.Series(0).Add 3, "Pears", vbRed |
#include "series.h" m_Chart1.Series(0).Add(3,"Pears",RGB(255,0,0)); |
Axis TitleTChart1.Axis.Left.Title.Caption="My left axis" |
#include "axes.h" #include "axis.h" #include "axisTitle.h" m_Chart1.GetAxis().GetLeft().GetTitle().SetCaption("My Left Axis"); |
Chart TitleWith Chart1.Header.Text .Clear .Add("ACME Monthly Sales") .Add("Year: 2017") End with |
#include "Titles.h" #include "Strings.h" COleVariant var1(CString ("ACME Monthly Sales")); COleVariant var2(CString ("Year: 2017")); CTitles hd = m_Chart.GetHeader(); hd.GetText().Clear(); hd.GetText().Add(*(LPCVARIANT)var1); hd.GetText().Add(*(LPCVARIANT)var2); //if items (header lines) already in list (+ alternative COleVariant declare syntax) m_Chart1.GetHeader().GetText().SetItem(0, COleVariant("ACME Monthly Sales")); m_Chart1.GetHeader().GetText().SetItem(1, COleVariant("Year: 2017")); |
Canvas drawTChart1.Canvas.MoveTo(0,0) TChart1.Canvas.LineTo(100,100) TChart1.Canvas.TextOut(50,50,"My output text) |
#include "Canvas.h" m_Chart1.GetCanvas().MoveTo(0,0); m_Chart1.GetCanvas().LineTo(100,100); m_Chart1.GetCanvas().TextOut(50,50,"My output text"); |
OnGetAxisLabel event'Add following text to Bottom Axis Labels If aAxis = atBottom Then LabelText = "Period " + LabelText End If |
CString strLabel(*LabelText); strLabel += " Period"; strLabel.SetSysString(LabelText); |
OnGetNextAxisLabel eventIf Axis = atBottom Then MoreLabels = True 'Only label if following cases are true Select Case LabelIndex Case 0: LabelValue = 900 Case 1: LabelValue = 5000 Case 2: LabelValue = 10000 Case Else: MoreLabels = False End Select End If |
{ if (Axis == atLeft) { *MoreLabels = true; //Only label if following cases are true switch( LabelIndex ) { case 0: *LabelValue = 900; break; case 2: *LabelValue = 5000; break; case 1: *LabelValue = 10000; break; default: *MoreLabels=false; } } } |
Outputting numeric information with Canvas TextOut
Dim value1, value2, total As Integer value1 = 4 value2 = 6 total = value1 + value2 TChart1.Canvas.TextOut 10, 10, total |
CString text; int value1,value2,total; value1 = 4; value2 = 6; total = value1+value2; text.Format(_T("Serie : %d"),total); m_Chart1.GetCanvas().TextOut(10,10,text)); |
Series as Datasource for Function' Using Series datasource as an interface ' permits the input of Series from different ' Charts as Function datasource for a Chart Series With TChart1 .AddSeries (scBar) .AddSeries (scLine) .Series(0).FillSampleValues 50 .Series(1).SetFunction (tfAverage) '************************************ .Series(1).DataSource = "Series0" 'Or... .Series(1).DataSource = TChart1.Series(0) '************************************ .Series(1).CheckDataSource End With |
VARIANT SourceSeries; m_Chart1.AddSeries(scBar); m_Chart1.AddSeries(scLine); m_Chart1.Series(0).FillSampleValues(50); m_Chart1.Series(1).SetFunction(tfAverage); //*********************************************************** m_Chart1.Series(1).SetDataSource(COleVariant("Series0")); // Or.... SourceSeries.vt=VT_DISPATCH; CSeries InputSeries=m_Chart1.Series(0); SourceSeries.pdispVal=InputSeries; m_Chart1.Series(1).SetDataSource(SourceSeries); //*********************************************************** m_Chart1.Series(1).CheckDatasource(3); |
An observation on VC++/Windows 98 behaviour: When TeeChart is added to a dialog form, VC++ creates an IDC constant for the Chart, eg. IDC_TCHART1 = 1000. If your project later calls upon Windows 98 to assign Hwnd handles for TeeChart upon request, eg. via the GetDlgItem method then, if several TeeCharts reside on a form, Windows 98 4 digit (decimal) dynamically allocated handles may coincide with values of the IDC constants assigned to the Charts. That shouldn't be a problem, however VC++ treats the original constants as duplicate Hwnd handles only in the case where duplicity occurs in the same live form, overriding the true Hwnd handle for a Chart and recognising the conflicting IDC_ constant, as a conflicting Hwnd handle. To avoid this behaviour set IDC_TCHART constants to five digit values, eg. 10001. The 4 digit handles returned by Windows will therefore not coincide with the Chart constant.
The above behaviour is only limited to Windows 95 and 98 platforms. WinNT and Win2000 use a higher address range for Hwnd handles.
Please note that when creating a VC++ 7.0 (or greater) MFC Application project the TeeChart AX v2017 classes (*.cpp) and header files (*.h) have to be added manually. All the files necessary can be found under the New VC classes folder below the utilities folder; these files should be copied to your project folder (using Windows Explorer) and then should be added in to the project (in Solution Explorer -> right click over "Source Files" & "Header Files" folders -> Add Existing Item...).
MS VC++ doesn't natively support import of TeeChart constants. You need to create you own defines file and #include it in your project. We offer a pre built defines file in the
Examples\Visual C++ folder. Including the file in your project will allow you to use constants by name as matching the Enum declarations in the Online help file.
Generation of the TeeRect structure, as with CalenderSeries may give the following error messages:
// method 'RectCell' not emitted because of invalid return type or
parameter type
And
// method 'SeriesRect' not emitted because of invalid return type or
parameter type
The automatic code generator fails to define the structure. You can do it manually:
typedef struct tagTeeRect { long Left; // Left boundery value. long Top; // Top boundery value. long Right; // Right boundery value. long Bottom; // Bottom boundery value. } TeeRect; TeeRect CCalendarSeries::RectCell(long Column, long Row) { static BYTE parms[] = VTS_I4 VTS_I4; VARIANT vtResult; InvokeHelper(0xb, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&vtResult, parms, Column, Row); return *(TeeRect*)vtResult.pvRecord; } TeeRect CCalendarSeries::GetSeriesRect() { VARIANT vtResult; InvokeHelper(0xd, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&vtResult, NULL); return *(TeeRect*)vtResult.pvRecord; }
The Calendar RectCell method should function correctly with the above definition for the structure. Thanks to Glyn Thomas for this contribution.
Canvas example
Canvas code placed in the OnAfterdraw event will draw after each Chart redraw thus allowing its use after Zoom or Scroll.
void CVCExampleDlg::OnOnAfterDrawTchart1() { // Draw line to 5th point and label it if (m_Chart1.Series(0).GetCount() > 4) { CCanvas cv = m_Chart1.GetCanvas(); CAxes ax = m_Chart1.GetAxis(); //Setup pen and brush //See section Constant defines for // how to define bsClear cv.GetPen().SetColor(RGB(0,0,0)); cv.GetBrush().SetStyle(bsClear); cv.TextOut(m_Chart1.Series(0).CalcXPos(5), m_Chart1.Series(0).CalcYPos(5), "HELLO"); cv.MoveTo(ax.GetLeft().GetPosition(), ax.GetTop().GetPosition()); cv.LineTo(m_Chart1.Series(0).CalcXPos(5), m_Chart1.Series(0).CalcYPos(5)); } }
ODBC example
This example connects to TeeChart ODBC test data and displays the Chart in the form of a Pie.
#include "series.h" #include "valuelist.h" #include "marks.h" void CVCExampleDlg::OnButton5() { // Add a Pie series and define the datasource m_Chart1.AddSeries(5); m_Chart1.Series(0).SetDataSource("DSN=TeeChart Pro Database; SQL=select * from employee"); m_Chart1.Series(0).GetYValues().SetValueSource("SALARY"); m_Chart1.Series(0).SetLabelsSource("LASTNAME"); m_Chart1.Series(0).GetMarks().SetVisible(false); }
TeeChart Pro AX v2017 includes several controls that may be added to a project to enhance runtime functionality of a Charting application.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
TeeListBox | TeeEditor | TeePreviewer | TeeCommander | TeePreviewPanel | ChartGrid |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
ChartGridNavigator | ChartPageNavigator | ChartEditorpanel | SeriesTextSource | SeriesXMLSource | CrossTabSource |
The controls are separately listed in the Registered Controls list when using Project & Add to Project so you will need to select and add them individually.
The ChartLink property connects the TeeCommander control bar to a TeeChart.
Examplem_Commander1.SetChartLink(m_Chart1.GetChartLink()); // Set the TeeCommander Editor to use TeeEditor1 // parameters when opening the Chart Editor m_Commander1.SetEditorLink(m_TeeEditor1.GetEditorLink()); // Set the TeeCommander Print Previewer to use TeePreviewer1 // parameters when showing Print Preview. m_Commander1.SetPreviewerLink(m_TeePreviewer1.GetPreviewerLink());
The ChartLink property connects the TeeEditor control bar to a TeeChart.
Examplem_TeeEditor1.SetChartLink(m_Chart1.GetChartLink()); // Disable the 'Add Series' and 'Help' buttons on the Editor m_TeeEditor1.GetOptions().SetAdd(false); m_TeeEditor1.GetOptions().SetHelp(false);
m_TeePreviewer1.SetChartLink(m_Chart1.GetChartLink());
m_TeeListBox1.SetChartLink(m_Chart1.GetChartLink());
m_TeePreviewPanel1.SetChartLink(m_Chart1.GetChartLink());
m_ChartGrid1.SetChartLink(m_Chart1.GetChartLink()); m_ChartGridNavigator1.SetGridLink(m_ChartGrid1.GetGridLink());
The SeriesTextSource component permits import of text file based data into a Chart Series.
Example// See the TeeChart VC++ examples for a full working // project with this code. // Use the SeriesTextSourceComponent to import data // from a text file. // It's sensitive to decimal type in text so we do a check // here on the machine locale. VARIANT SeriesIndex; LCID lcid; CHAR lpszLang[2]; lcid=GetThreadLocale(); int rc = GetLocaleInfo(lcid, LOCALE_SDECIMAL, lpszLang, 2); if (CString(&lpszLang[0]).Compare(CString(","))==0) { m_TextSource1.SetFilename("SurfaceDataComma.txt"); //use comma decimal separator } else { m_TextSource1.SetFilename("SurfaceDataPoint.txt"); //use point decimal separator } SeriesIndex.vt=VT_INT; SeriesIndex.intVal= m_Chart1.AddSeries(scTriSurface); // The following line only necessary if SeriesIndex as VT_INT. m_TextSource1.SetChartLink(m_Chart1.GetChartLink()); m_TextSource1.SetSeries(SeriesIndex); m_TextSource1.SetFieldSeparator(";"); m_TextSource1.AddField("x",1); m_TextSource1.AddField("y",2); m_TextSource1.AddField("z",3); m_TextSource1.SetActive(true);
The SeriesTextSource is non-visible at run-time. It allows data to be brought in from XML files to specified Chart series. Use this compenent's methods and properties to define or modify the data's fields and field delimiters and to set the location of the XML file as a path, URL or stream.
ExampleVARIANT SourceSeries; m_Chart1.AddSeries(1); SourceSeries.vt=VT_DISPATCH; CSeries InputSeries=m_Chart1.Series(0); SourceSeries.pdispVal=InputSeries; m_SeriesXMLSource1.SetFileName("http://www.steema.com/SampleData.xml"); //This can also be a local file m_SeriesXMLSource1.SetSeries(SourceSeries); m_SeriesXMLSource1.SetSeriesNode("USA"); m_SeriesXMLSource1.SetValueSource("Bar"); m_SeriesXMLSource1.Open();
The CrossTabSource is non-visible at run-time. CrossTabSource component connects to any dataset and automatically creates series from database data, using Group and Label fields and formula (sum or count values).
Examplevoid CAXv6VC60MFCDlg::OnShowWindow(BOOL bShow, UINT nStatus) { CDialog::OnShowWindow(bShow, nStatus); VARIANT SourceSeries; m_Chart1.AddSeries(1); SourceSeries.vt=VT_DISPATCH; CSeries InputSeries=m_Chart1.Series(0); SourceSeries.pdispVal=InputSeries; m_CrossTabSource1.SetSeries(SourceSeries); m_CrossTabSource1.SetGroupField("Terms"); m_CrossTabSource1.SetLabelField("Paymtype"); m_CrossTabSource1.SetValueField("Amntpaid"); m_CrossTabSource1.SetDataSet(COleVariant("DSN=TeeChart Pro System db; SQL=select * from orders")); m_CrossTabSource1.SetActive(true); m_Chart1.RefreshData(); } void CAXv6VC60MFCDlg::OnButton1() { CString tmp; tmp = m_CrossTabSource1.GetGroupField(); m_CrossTabSource1.SetGroupField(m_CrossTabSource1.GetLabelField()); m_CrossTabSource1.SetLabelField(tmp); m_CrossTabSource1.SetActive(true); m_Chart1.RefreshData(); }
![]() |
![]() |