Contents page 
  Previous | Next 
 

Tutorial 15 - MS VC++ Applications


Contents
Introduction

Quick start

Adding TeeChart to your Project
Naming the Chart
Adding data to the Chart
Upgrading from TeeChart v8

Working with TeeChart in VC++

Changing Chart properties at design time
TeeChart events
Coding TeeChart for runtime
How to apply TeeChart Online help to VC++
Notes on use of TeeChart in Windows 98
Notes on use of TeeChart in Visual Studio.NET
Constant defines
Notes about the TeeRect Structure
Applied examples

Using the additional TeeChart Controls in VC++

TeeCommander
TeeEditor
TeePreviewer
TeeListBox
TeePreviewPanel
ChartGrid and ChartGridNavigator
SeriesTextSource
SeriesXMLSource
CrossTabSource


Introduction

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.


Quick start

Adding TeeChart to your Project


Upgrading from TeeChart v8

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 upgrade

The differences between TeeChart Pro AX v8 and TeeChart Pro AX v2017 to be considered when upgrading v8 projects are as follows:

Assisted upgrade

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.


Working with TeeChart in VC++

Changing Chart properties at design time

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.


TeeChart events

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.


Coding TeeChart for runtime

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.


How to apply TeeChart Online help to VC++

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 method
TChart1.Series(0).Add 3, "Pears", vbRed
 
#include "series.h"

m_Chart1.Series(0).Add(3,"Pears",RGB(255,0,0));
Axis Title
TChart1.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 Title
With 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 draw
TChart1.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 event
If 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);


Notes on use of TeeChart in Windows 98

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.


Notes on use of TeeChart in Visual Studio.NET

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...).


Constant defines

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.

Notes about the TeeRect Structure

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.

Applied examples

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);
}

Using the additional TeeChart Controls in VC++

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
TeeListBoxTeeEditorTeePreviewerTeeCommanderTeePreviewPanelChartGrid

ChartGridNavigator ChartPageNavigator ChartEditorPanel SeriesTextSource SeriesXMLSource CrossTabSource
ChartGridNavigator ChartPageNavigatorChartEditorpanelSeriesTextSource SeriesXMLSourceCrossTabSource

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.

TeeCommander

The ChartLink property connects the TeeCommander control bar to a TeeChart.

Example
m_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());

TeeEditor

The ChartLink property connects the TeeEditor control bar to a TeeChart.

Example
m_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);

TeePreviewer

Example
m_TeePreviewer1.SetChartLink(m_Chart1.GetChartLink());

TeeListBox

Example
m_TeeListBox1.SetChartLink(m_Chart1.GetChartLink());

TeePreviewPanel

Example
m_TeePreviewPanel1.SetChartLink(m_Chart1.GetChartLink());

ChartGrid and ChartGridNavigator

Example
m_ChartGrid1.SetChartLink(m_Chart1.GetChartLink());
m_ChartGridNavigator1.SetGridLink(m_ChartGrid1.GetGridLink());

SeriesTextSource

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);

SeriesXMLSource

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.

Example
VARIANT 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();

CrossTabSource

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).

Example
void 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();	
}



© 1998- Steema Software SL. All rights reserved.