Chapter 5
DLL
MFC Charting
Walk-Through
|
he following information demonstrates how to create your first Visual Studio Visual C++ MFC Charting implementation. It discusses installation, adding ProEssentials to a project, writing your first few lines of code, and shows the final results.
IMPORTANT: For help finding DLL specific features in our help system, click the Contents Tab at the top-left location, then near the bottom click ProEssentials Reference, and then see the Alphabetic Listing. The .Net Reference section is the best source for researching properties.
When installing ProEssentials, the setup program installs the ProEssentials DLLs into the System32 and SysWow64 folders. It also installs a header file and import library into the C:\ProEssentials10\VC directory. The relevant files are:
PEGRP64H.DLL
|
ProEssentials x64 64 bit DLL located in System32
|
PEGRP64H.LIB
|
ProEssentials x64 64 bit LIB File
|
PEGRPAPI.H
|
ProEssentials Header File
|
PEGRP32H.DLL
|
ProEssentials x86 32 bit DLL located in SysWow64
|
PEGRP32H.LIB
|
ProEssentials x86 32 bit LIB file
|
|
Creating the Project...
Launch Visual Studio and use the File / New... menu to launch the [New] project dialog. Within Tree select [
Visual C++ - - MFC
], select project template
[
MFC Application
], and supply a project name [MyFirstMfc] and project location.

Select a standard MFC style project and some favorite MFC options...

|
Project / Add Existing Item... menu
|
1) Copy "PEGRPAPI.H" and "PEGRP32H.LIB" from the C:\ProEssentials10\VC demo directory to where the [MyFirstMfc] project is located.
Note, for 64 bit, also copy PEGRP64H.LIB.
2) Use the [Project / Add Exiting Item...] menu to add "PEGRPAPI.H" and "PEGRP32H.LIB" to the [MyFirstMfc"] project.
The image shows the existing files being added to your project.

|
myfirstmfcview.cpp...
|
Adding ProEssentials Charting header file ...
|

|
3) Open the file "myfirstmfcview.cpp" and near the top add the line:
The include statement adds the ProEssentials header file which contains constants and function declarations.
|
myfirstmfcview.h...
|
Adding Window handle variable...
|

|
4) Open the file "myfirstmfcview.h" and add the line:
The variable
hPE is used to store the Window's handle for the ProEssentials chart control.
Each instance of MyFirstMfcView will have its own copy of this handle.
Then within file "myfirstmfcview.cpp"s constructor, initialize hPE to NULL.

|
Open Class Wizard for CMyFirstMfcView...
|

5) Left click Class View within the solution explorer. Right click CMyFirstMfcView and select Class Wizard...
Select the Messages Tab and double click the messages...
-
WM_CREATE
WM_DESTROY
WM_ERASEBKGND
WM_SIZE

Select the Virtual Functions Tab and double click the OnCommand function...
|
myfirstmfcview.cpp...
|
6) Within the recently added OnCreate, OnDestroy, OnSize, and OnCommand sections of MyFirstMfcView.cpp, add the following code that initializes an example chart. See images below for further reference.
OnCreate: initialze a chart after parent creates it's window
RECT r;
int s, p;
int dwColor;
float f[] = {10, 30, 20, 40, 30, 50, 15, 63, 74, 54, 25, 34};
GetClientRect(&r);
hPE = PEcreate(PECONTROL_GRAPH, 0, &r, this->m_hWnd, 1000);
PEszset(hPE, PEP_szMAINTITLE, TEXT("Hello World"));
PEszset(hPE, PEP_szSUBTITLE, TEXT(""));
PEnset(hPE, PEP_nSUBSETS, 2);
PEnset(hPE, PEP_nPOINTS, 6);
for (s=0; s<2; s++)
{
for (p=0; p<6; p++)
{ // (s*6)+p or (SubsetIndex * NumberPoints) + PointIndex
PEvsetcellEx(hPE, PEP_faYDATA, s, p, &f[(s*6)+p]);
}
}
// or Pass data in one call is much faster -> PEvset(hPE, PEP_faYDATA, f, 12);
PEvsetcell(hPE, PEP_szaPOINTLABELS, 0, TEXT("Jan"));
PEvsetcell(hPE, PEP_szaPOINTLABELS, 1, TEXT("Feb"));
PEvsetcell(hPE, PEP_szaPOINTLABELS, 2, TEXT("Mar"));
PEvsetcell(hPE, PEP_szaPOINTLABELS, 3, TEXT("Apr"));
PEvsetcell(hPE, PEP_szaPOINTLABELS, 4, TEXT("May"));
PEvsetcell(hPE, PEP_szaPOINTLABELS, 5, TEXT("June"));
PEvsetcell(hPE, PEP_szaSUBSETLABELS, 0, TEXT("For .Net Framework"));
PEvsetcell(hPE, PEP_szaSUBSETLABELS, 1, TEXT("or MFC, ActiveX, VCL"));
PEszset(hPE, PEP_szYAXISLABEL, TEXT("Simple Quality Rendering"));
PEszset(hPE, PEP_szXAXISLABEL, TEXT(""));
dwColor = PERGB(60, 0, 180, 0); PEvsetcell(hPE, PEP_dwaSUBSETCOLORS, 0, &dwColor);
dwColor = PERGB(180, 0, 0, 130); PEvsetcell(hPE, PEP_dwaSUBSETCOLORS, 1, &dwColor);
PEnset(hPE, PEP_nGRAPHPLUSTABLE, PEGPT_BOTH);
PEnset(hPE, PEP_nDATAPRECISION, 0);
PEnset(hPE, PEP_bLABELBOLD, TRUE);
PEnset(hPE, PEP_nPLOTTINGMETHOD, PEGPM_BAR);
PEnset(hPE, PEP_nGRADIENTBARS, 8);
PEnset(hPE, PEP_bBARGLASSEFFECT, TRUE);
PEnset(hPE, PEP_nLEGENDLOCATION, PELL_LEFT);
PEnset(hPE, PEP_nDATASHADOWS, PEDS_3D);
PEnset(hPE, PEP_nFONTSIZE, PEFS_LARGE);
PEnset(hPE, PEP_bPREPAREIMAGES, TRUE);
PEnset(hPE, PEP_bCACHEBMP, TRUE);
PEnset(hPE, PEP_nRENDERENGINE, PERE_DIRECT2D);
PEnset(hPE, PEP_bANTIALIASGRAPHICS, TRUE);
PEnset(hPE, PEP_bANTIALIASTEXT, TRUE);
PEnset(hPE, PEP_bALLOWDATAHOTSPOTS, TRUE);
PEnset(hPE, PEP_bBITMAPGRADIENTMODE, FALSE);
PEnset(hPE, PEP_nQUICKSTYLE, PEQS_LIGHT_SHADOW);
PEnset(hPE, PEP_bFIXEDFONTS, TRUE);
PEreinitialize(hPE);
PEresetimage(hPE, 0, 0);
|
|
OnDestroy: cleans up the chart resource at same time parent is cleaned up
OnSize: this causes chart to always fill client rect of parent
if (hPE)
{
RECT r; GetClientRect(&r);
::MoveWindow(hPE, 0, 0, r.right, r.bottom, FALSE);
}
|
|
OnCommand: this handles the hot spot event, showing a message box.
int wmId = LOWORD(wParam);
int wmEvent = HIWORD(wParam);
switch (wmEvent)
{
case PEWN_CLICKED:
HOTSPOTDATA hsd; TCHAR buffer[128]; float yvalue;
PEvget(hPE, PEP_structHOTSPOTDATA, &hsd);
if (hsd.nHotSpotType == PEHS_DATAPOINT)
{
PEvgetcellEx(hPE, PEP_faYDATA, hsd.w1, hsd.w2, &yvalue);
swprintf_s(buffer, TEXT("DataPoint %d value %.2f"), hsd.w2, yvalue);
::MessageBox(this->m_hWnd, buffer, TEXT("Hello World"), 0);
}
break;
}
|
|
MainTitle and SubTitle are set first. Note that setting SubTitle to an empty string hides the subtitle.
Subsets and Points define the amount of data you'll be passing.
Next, we pass some random data into the YData[s,p] two dimensional property array. PointLabels[0] sets the first data point label located below axis.
SubsetLabels[0]
sets the first subset label.
Next, we set various other properties controlling visual aspects, and enable flicker free updates with PrepareImages.
Finally PEreinitialize and PEresetimage tells ProEssentials to initialize and resetimage the image, in other words, you're done setting properties.
Your code window will look similar to below...

|
Run project: MFC Charting Results.
|
Congratulations...
|


|
Run your project and you'll see a similar application. Add tabs, right click the chart to make changes: change colors, hide legend, change plotting method, etc.
Congratulations, you've just completed your first MFC Charting ProEssentials implementation.
|
|