Starting the Visual C IDE

Chapter 23 - Windows Applications Using the MFC

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

A Bar Chart with Resources
The final application in this chapter, BARCHART.CPP, will draw a presentation-quality bar chart in the window’s client area. This application also makes use of several Windows resources, including a menu, an About dialog box, and a data entry dialog box.
The complete application is compiled and linked with four separate files. These files include the header file, BARCHART.H, the resource header file, BARCHARTR.H, the resource script file, BARCHART.RC and the source code file, BARCHART.CPP.
Enter each file carefully. You will also need to create a project file. Remember to mark this as a MFC application. The BARCHART.RC and BARCHART.CPP must be named in the project file’s list of files to include for the build. When all files have been entered, the application can be compiled and linked.
The BARCHART.H header file gives our class descriptions for CMainWnd, CTheApp, and CBarDataDialog. These classes are children of MFC library classes.
class CMainWnd : public CFrameWnd
{
public:
 CMainWnd( );
 afx_msg void OnPaint( );
 afx_msg void OnSize(UINT,int,int);
 afx_msg int  OnCreate(LPCREATESTRUCT cs);
 afx_msg void OnAbout( );
 afx_msg void OnBarData( );
 afx_msg void OnExit( );
 DECLARE_MESSAGE_MAP( )
};
class CTheApp : public CWinApp
{
public:
 virtual BOOL InitInstance( );
};

class CBarDataDialog : public CDialog
{
public:
 CBarDataDialog(CWnd
* pParentWnd=NULL)
               : CDialog(“BarDlgBox”,pParentWnd)
               {  }
 virtual void OnOK( );
};
The BARCHARTR.H resource header file contains the ID values that will be used for the menu and two dialog boxes:
#define IDM_ABOUT    10
#define IDM_INPUT    20
#define IDM_EXIT     30
#define DM_TITLE    300
#define DM_XLABEL   301
#define DM_YLABEL   302
#define DM_P1       303
#define DM_P2       304
#define DM_P3       305
#define DM_P4       306
#define DM_P5       307
#define DM_P6       308
#define DM_P7       309
#define DM_P8       310
#define DM_P9       311
#define DM_P10      312
The BARCHART.RC resource script file defines the application’s menu and dialog boxes:
//Microsoft Developer Studio generated resource script.
//
#include “resource.h”
#include “barchartr.h”

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include “windows.h”
#undef APSTUDIO_HIDDEN_SYMBOLS
#include “afxres.h”
/////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////
//
// Menu
//
BARMENU MENU DISCARDABLE
BEGIN
 POPUP “Bar_Chart”
 BEGIN
   MENUITEM “About Box...”, IDM_ABOUT
   MENUITEM “Bar Values...”, IDM_INPUT
   MENUITEM “Exit”, IDM_EXIT
 END
END
        
/////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUTDLGBOX DIALOG DISCARDABLE  14, 22, 200, 75
STYLE WS_POPUP | WS_CAPTION
CAPTION “About Box”
BEGIN
 CTEXT “A Bar Chart Application”,-1,30,5,144,8
 CTEXT “A Simple MFC Windows Application”,-1,30,17,144,8
 CTEXT “By William H. Murray and Chris H. Pappas”,
        -1,28,28,144,8
 CTEXT “(c) Copyright 1998",-1,68,38,83,8
 DEFPUSHBUTTON   ”OK",IDOK,84,55,32,14,WS_GROUP
END

BARDLGBOX DIALOG DISCARDABLE  42, 65526, 223, 209
STYLE WS_POPUP | WS_CAPTION
CAPTION “Bar Chart Data”
BEGIN
 GROUPBOX “Bar Chart Title:”,100,5,11,212,89,WS_TABSTOP
 GROUPBOX “Bar Chart Heights”,101,5,105,212,90,WS_TABSTOP
 LTEXT “Title: ”,-1,43,35,28,8,NOT WS_GROUP
 EDITTEXT DM_TITLE,75,30,137,12
 LTEXT “x-axis label:”,-1,15,55,55,8,NOT WS_GROUP
 EDITTEXT DM_XLABEL,75,50,135,12
 LTEXT “y-axis label:”,-1,15,75,60,8,NOT WS_GROUP
 EDITTEXT DM_YLABEL,75,70,135,12
 LTEXT “Bar #1: ”,-1,45,125,40,8,NOT WS_GROUP
 LTEXT “Bar #2: ”,-1,45,140,40,8,NOT WS_GROUP
 LTEXT “Bar #3: ”,-1,45,155,40,8,NOT WS_GROUP
 LTEXT “Bar #4: ”,-1,45,170,40,8,NOT WS_GROUP
 LTEXT “Bar #5: ”,-1,45,185,40,8,NOT WS_GROUP
 LTEXT “Bar #6: ”,-1,130,125,40,8,NOT WS_GROUP
 LTEXT “Bar #7: ”,-1,130,140,40,8,NOT WS_GROUP
 LTEXT “Bar #8: ”,-1,130,155,40,8,NOT WS_GROUP
 LTEXT “Bar #9: ”,-1,130,170,40,8,NOT WS_GROUP
 LTEXT “Bar #10:”,-1,130,185,45,8,NOT WS_GROUP
 EDITTEXT DM_P1,90,120,30,12
 EDITTEXT DM_P2,90,135,30,12
 EDITTEXT DM_P3,90,150,30,12
 EDITTEXT DM_P4,90,165,30,12
 EDITTEXT DM_P5,90,180,30,12
 EDITTEXT DM_P6,180,120,30,12
 EDITTEXT DM_P7,180,135,30,12
 EDITTEXT DM_P8,180,150,30,12
 EDITTEXT DM_P9,180,165,30,12
 EDITTEXT DM_P10,180,180,30,12
 PUSHBUTTON “OK”,IDOK,54,195,24,14
 PUSHBUTTON “Cancel”,IDCANCEL,124,195,34,14
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
 “resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
 ”#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
 “#include ”"windows.h""\r\n"
 “#undef APSTUDIO_HIDDEN_SYMBOLS\r\n”
 “#include ”"afxres.h""\r\n"
 “\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
 ”\r\n"
 “\0"
END

#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//

/////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
It took a while to get here, but we’re now ready to look at the source code for the BARCHART.CPP application. Examine this code and note the inclusion of various resources such as menus, dialog boxes, etc.
//
//  barchart.cpp
//  A Presentation Quality Bar Chart Application
//  using the MFC Library.
//  Copyright (c) William H. Murray and Chris H. Pappas, 1998
//

#include <afxwin.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include “barchartr.h”   // resource IDs
#include “barchart.h”
#define maxnumbar 10
char szTString[80]="(bar chart title area)";
char szXString[80]="x-axis label";
char szYString[80]="y-axis label";
int iBarSize[maxnumbar]={20,10,40,50};
int m_cxClient,m_cyClient;

CTheApp theApp;

CMainWnd::CMainWnd( )
{
 Create((AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,
       LoadCursor(NULL,IDC_CROSS),
       (HBRUSH) GetStockObject(WHITE_BRUSH),NULL)),
       “Bar Chart Application with the MFC”,
       WS_OVERLAPPEDWINDOW,rectDefault,NULL,"BarMenu");
}

void CMainWnd::OnSize(UINT,int x,int y)
{
 m_cxClient=x;
 m_cyClient=y;
}

void CMainWnd::OnPaint( )
{
 CPaintDC dc(this);
 static DWORD dwColor[10]={RGB(0,0,0),        //black
                           RGB(245,0,0),      //red
                           RGB(0,245,0),      //green
                           RGB(0,0,245),      //blue
                           RGB(245,245,0),    //yellow
                           RGB(245,0,245),    //magenta
                           RGB(0,245,245),    //cyan
                           RGB(0,80,80),      //blend 1
                           RGB(80,80,80),     //blend 2
                           RGB(245,245,245)}; //white
 
 CFont newfont;
 CFont* oldfont;
 CBrush newbrush;
 CBrush* oldbrush;
 int i,iNBars,iBarWidth,iBarMax;
 int ilenMaxLabel;
 int x1,x2,y1,y2;
 int iBarSizeScaled[maxnumbar];
 char sbuffer[10],*strptr;
 iNBars=0;
 for (i=0;i<maxnumbar;i++) {
   if(iBarSize[i]!=0) iNBars++;
 }

 iBarWidth=400/iNBars;

 // Find bar with maximum height and scale
 iBarMax=iBarSize[0];
 for(i=0;i<iNBars;i++)
   if (iBarMax<iBarSize[i]) iBarMax=iBarSize[i];

 // Convert maximum y value to a string
 strptr=_itoa(iBarMax,sbuffer,10);
 ilenMaxLabel=strlen(sbuffer);

 // Scale bars in array.  Highest bar = 270
 for (i=0;i<iNBars;i++)
   iBarSizeScaled[i]=iBarSize[i]*(270/iBarMax);
 // Create custom viewport and map mode
 dc.SetMapMode(MM_ISOTROPIC);
 dc.SetWindowExt(640,400);
 dc.SetViewportExt(m_cxClient,m_cyClient);
 dc.SetViewportOrg(0,0);

 // Draw text to window if large enough
 if (m_cxClient > 200) {
 newfont.CreateFont(12,12,0,0,FW_BOLD,
                    FALSE,FALSE,FALSE,OEM_CHARSET,
                    OUT_DEFAULT_PRECIS,
                    CLIP_DEFAULT_PRECIS,
                    DEFAULT_QUALITY,
                    VARIABLE_PITCH|FF_ROMAN,
                    “Roman”);
 oldfont=dc.SelectObject(&newfont);
 dc.TextOut((300-(strlen(szTString)*10/2)),
             15,szTString,strlen(szTString));
 dc.TextOut((300-(strlen(szXString)*10/2)),
             365,szXString,strlen(szXString));
 dc.TextOut((90-ilenMaxLabel*12),70,strptr,ilenMaxLabel);
 // delete font objects
 dc.SelectObject(oldfont);
 newfont.DeleteObject( );
 newfont.CreateFont(12,12,900,900,FW_BOLD,
                    FALSE,FALSE,FALSE,
                    OEM_CHARSET,OUT_DEFAULT_PRECIS,
                    CLIP_DEFAULT_PRECIS,
                    DEFAULT_QUALITY,
                    VARIABLE_PITCH|FF_ROMAN,
                    “Roman”);
 oldfont=dc.SelectObject(&newfont);
 dc.TextOut(50,200+(strlen(szXString)*10/2),
            szYString,strlen(szYString));
 // delete font objects
 dc.SelectObject(oldfont);
 newfont.DeleteObject( );
 }

 // Draw coordinate axis
 dc.MoveTo(99,49);
 dc.LineTo(99,350);
 dc.LineTo(500,350);
 dc.MoveTo(99,350);
 // Initial values
 x1=100;
 y1=350;
 x2=x1+iBarWidth;

 // Draw Each Bar
 for(i=0;i<iNBars;i++) {
   newbrush.CreateSolidBrush(dwColor[i]);
   oldbrush=dc.SelectObject(&newbrush);
   y2=350-iBarSizeScaled[i];
   dc.Rectangle(x1,y1,x2,y2);
   x1=x2;
   x2+=iBarWidth;
   // delete brush objects
   dc.SelectObject(oldbrush);
   newbrush.DeleteObject( );
 }
}
int CMainWnd::OnCreate(LPCREATESTRUCT)
{
 UpdateWindow( );
 return (0);
}

void CMainWnd::OnAbout( )
{
 CDialog about(“AboutDlgBox”,this);
 about.DoModal( );
}

void CBarDataDialog::OnOK( )
{
 GetDlgItemText(DM_TITLE,szTString,80);
 GetDlgItemText(DM_XLABEL,szXString,80);
 GetDlgItemText(DM_YLABEL,szYString,80);
 iBarSize[0]=GetDlgItemInt(DM_P1,NULL,0);
 iBarSize[1]=GetDlgItemInt(DM_P2,NULL,0);
 iBarSize[2]=GetDlgItemInt(DM_P3,NULL,0);
 iBarSize[3]=GetDlgItemInt(DM_P4,NULL,0);
 iBarSize[4]=GetDlgItemInt(DM_P5,NULL,0);
 iBarSize[5]=GetDlgItemInt(DM_P6,NULL,0);
 iBarSize[6]=GetDlgItemInt(DM_P7,NULL,0);
 iBarSize[7]=GetDlgItemInt(DM_P8,NULL,0);
 iBarSize[8]=GetDlgItemInt(DM_P9,NULL,0);
 iBarSize[9]=GetDlgItemInt(DM_P10,NULL,0);
 CDialog::OnOK( );
}

void CMainWnd::OnBarData( )
{
 CBarDataDialog dlgBarData(this);
 if (dlgBarData.DoModal( )==IDOK) {
   InvalidateRect(NULL,TRUE);
   UpdateWindow( );
 }
};

void CMainWnd::OnExit( )
{
 DestroyWindow( );
}
BEGIN_MESSAGE_MAP(CMainWnd,CFrameWnd)
 ON_WM_PAINT( )
 ON_WM_SIZE( )
 ON_WM_CREATE( )
 ON_COMMAND(IDM_ABOUT,OnAbout)
 ON_COMMAND(IDM_INPUT,OnBarData)
 ON_COMMAND(IDM_EXIT,OnExit)
END_MESSAGE_MAP( )

BOOL CTheApp::InitInstance( )
{
 m_pMainWnd=new CMainWnd( );
 m_pMainWnd->ShowWindow(m_nCmdShow);
 m_pMainWnd->UpdateWindow( );
 return TRUE;
}
When all of these files are entered, build the application with the Visual C++ Project utility.
The BARCHART.H Header File
This application will use many of the features of the previous application. For example, note the similar function declarations in CMainWnd and the message map:
afx_msg void On Paint( );
afx_msg void OnSize(UINT,int,int);
afx_msg int  OnCreate(LPCREATESTRUCT cs);
afx_msg void OnAbout( );
afx_msg void OnBarData( );
afx_msg void OnExit( );
The creation of the About and data entry dialog boxes parallels the last example. In this application, however, the data entry dialog box will process more user input than in the previous example. You may want to review the information dealing with dialog boxes in the previous example at this time.
The Resource Files
The BARCHARTR.H and BARCHART.RC files are combined by the Microsoft Resource Compiler into a single compiled Windows resource, BARCHART.RES.
The BARCHARTR.H resource header file contains three menu identification values: IDM_ABOUT, IDM_INPUT, and IDM_EXIT.
Thirteen identification values are also included for use by the modal dialog box. Three are for the title and labels: DM_TITLE, DM_XLABEL, and DM_YLABEL. The remaining ten values, DM_P1 to DM_P10, are for retrieving the height of the individual bars. They will be represented with integer values.
The resource script file, BARCHART.RC, contains a description of the application’s menu and dialog boxes. The menu is shown in Figure 23-9. Compare the menu title and features to the text used to create the menu in the resource file.
Figure 23-9: The application’s menu during construction
The application contains two dialog boxes. The About box is almost identical to that used in the previous application. The data entry dialog box is a bit more complex, and is shown in Figure 23-10.
Figure 23-10: The application’s data entry dialog box during construction
The resource editor was used to construct both the About dialog box and the data entry dialog box.
The BARCHART.CPP Source Code File
This section concentrates on those features of the bar chart application that were not addressed in the applications developed earlier in this chapter. The BARCHART.CPP application will allow the user to draw a presentation-quality bar chart in the client area of a window. With the use of a modal dialog box, the user can specify a chart title, axis labels, and the heights of up to ten bars. The chart will then be correctly scaled to the window, with each bar’s color selected from an array of predefined values.
The maximum number of bars, maxnumbar, is set to ten at the start of the application:
#define maxnumbar 10
This value can be changed slightly, but remember that a good bar chart doesn’t crowd too many bars onto a single chart.
As you can see in the following code, global data types hold initial bar chart values for titles, axis labels, and bar heights:
char szTString[80]="(bar chart title area)";
char szXString[80]="x-axis label";
char szYString[80]="y-axis label";
int iBarSize[maxnumbar]={20,10,40,50};
The size of the client area will also be saved as a global value. These are the same variable names used in the previous example:
int m_cxClient,m_cyClient;
Because the application keeps track of the client area size, this bar chart can be scaled to fit the current window size.
Bar colors are selected from the dwColor array in a sequential manner. If the bar chart has three bars, they will be black, red, and green. Colors can be exchanged if you so desire.
The CFont and CBrush classes permit a font or brush object to be passed to any CDC (base class for display context) member function. New fonts will be needed to draw the chart title and axis labels. Brushes were discussed earlier in this chapter. Here is the syntax used to create a new font and brush object:
CFont newfont;
CFont
* oldfont;
CBrush newbrush;
CBrush
* oldbrush;
Manipulating Bar Data
Before plotting a bar chart, it is first necessary to determine how many bar values are being held in the global array iBarSize. This can be determined by counting values until the first zero value is encountered:
iNBars=0;
for (i=0;i<maxnumbar;i++)
{
 if(iBarSize[i]!=0) iNBars++;
}
Data values are returned to this array whenever the data entry dialog box is closed. The width of each bar drawn in the chart is dependent upon the total number of bars. The chart will always be drawn to the same width. Individual bar width is determined with this calculation:
iBarWidth=400/iNBars;
The height of each bar is determined relative to the largest bar value entered by the user. The largest bar value is always drawn to the same chart height. The size of the largest bar value is easy to determine:
// Find bar with maximum height and scale
iBarMax=iBarSize[0];
for(i=0;i<iNBars;i++)
 if (iBarMax<iBarSize[i]) iBarMax=iBarSize[i];
This chart will also print the height of the largest bar value next to the vertical axis. The _itoa( ) function is used to convert this value to a string:
// Convert maximum y value to a string
strptr=_itoa(iBarMax,sbuffer,10);
ilenMaxLabel=strlen(sbuffer);
The remaining bars in the array are then scaled to the largest bar’s value:
// Scale bars in array. Highest bar = 270
for (i=0;i<iNBars;i++)
 iBarSizeScaled[i]=iBarSize[i]
*(270/iBarMax);
Preparing the Window
Before the application begins drawing in the window’s client area, the mapping mode, window extent, viewport extent, and origin are set with the following portion of code:
// Create custom viewport and map mode
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(640,400);
dc.SetViewportExt(m_cxClient,m_cyClient);
dc.SetViewportOrg(0,0);
This same action was taken in the previous example to ensure that when the window changes size, the chart will remain proportional to the window size. See the previous application for additional details on these function calls.
Drawing Text to the Window
The previous application drew text to the screen using the Windows default font. When several fonts or orientations are required, various font functions must be used. This application requires several font sizes and orientations. Let’s look at how these can be created. There are actually two ways to create and manipulate fonts in Windows: CreateFont( ) and CreateFontIndirect( ). This example uses the CreateFont( ) function.
What Is a Font?
A font can be defined as a complete set of characters of the same typeface and size. Fonts include letters, punctuation marks, and additional symbols. The size of a font is measured in points. For example, 12-point Arial, 12-point Times New Roman, 14-point Times New Roman, and 12-point Lucida Bright are all different fonts. A point is the smallest unit of measure used in typography. There are 12 points in a pica and 72 points (6 picas) in an inch.
A typeface is a basic character design that is defined by a stroke width and a serif (a smaller line used to finish off a main stroke of a letter, as you can see at the top and bottom of the uppercase letter “M”). As mentioned above, a font represents a complete set of characters from one specific typeface, all with a certain size and style, such as italics or bold. Usually, the system owns all of the font resources and shares them with application programs. Fonts are not usually compiled into the final executable version of a program.
Applications such as BARCHART.CPP treat fonts like other drawing objects. Windows supplies several fonts: System, Terminal, Courier, Helvetica, Modern, Roman, Script, and Times Roman, as well as several TrueType fonts. These are called GDI_supplied fonts.
The CreateFont( ) Function Syntax
The CreateFont( ) function is defined in the WINDOWS.H header file. This function selects a logical font from the GDI’s pool of physical fonts that most closely matches the characteristics specified by the developer in the function call. Once created, this logical font can be selected by any device. The syntax for the CreateFont( ) function is
CreateFont(Height,Width,Escapement,Orientation,Weight,
          Italic,Underline,StrikeOut,CharSet,
          OutputPrecision,ClipPrecision,Quality,
          PitchAndFamily,Facename)
Using CreateFont( ), with its 14 parameters, requires quite a bit of skill. Table 23-1 gives a brief description of the CreateFont( ) parameters.
Table 23-1: CreateFont() Parameters
CreateFont( ) Parameters
Description
(LONG) Height
Desired font height in logical units
(LONG) Width
Average font width in logical units
(LONG) Escapement
Angle (in tenths of a degree) for each line written in the font
(LONG) Orientation
Angle (in tenths of a degree) for each character’s baseline
(LONG) Weight
Weight of font (from 0 to 1,000); 400 is normal, 700 is bold
(BYTE) Italic
Italic font
(BYTE) Underline
Underline font
(BYTE) StrikeOut
Struck out fonts (redline)
(BYTE) CharSet
Character set (ANSI-CHARSET, OEM-CHARSET)
(BYTE) OutputPrecision
How closely output must match the requested specifications (OUT-CHARACTER PRECIS, OUT-DEFAULT-PRECIS, OUT-STRING-PRECIS, OUT-STROKE-PRECIS)
(BYTE) ClipPrecision
How to clip characters outside of clipping range (CLIP-CHARACTER PRECIS, CLIP-DEFAULT-PRECIS, CLIP-STROKE-PRECIS)
(BYTE) Quality
How carefully the logical attributes are mapped to the physical font (DEFAULT-QUALITY, DRAFT-QUALITY, PROOF-QUALITY)
(BYTE) PitchAndFamily
Pitch and family of font (DEFAULT-PITCH, FIXED-PITCH, PROOF-QUALITY, FF-ROMAN, FF-SCRIPT, FF-DECORATIVE, FF-DONTCARE, FF-MODERN, FF-SWISS)
(CHAR) Facename
A string pointing to the typeface name of the desired font
The first time the CreateFont( ) function is called by the application, the parameters are set to the following values:
Height = 12
Width  = 12
Escapement = 0
Orientation = 0
Weight = FW_BOLD
Italic = FALSE
Underline = FALSE
StrikeOut = FALSE
CharSet = OEM_CHARSET
OutputPrecision = OUT_DEFAULT_PRECIS
ClipPrecision = CLIP_DEFAULT_PRECIS
Quality = DEFAULT_QUALITY
PitchAndFamily = VARIABLE_PITCH|FF_ROMAN
Facename = “Roman”
An attempt will then be made by Windows to find a font to match the preceding specifications. This font will be used to print a horizontal string of text in the window. The next time CreateFont( ) is called, the parameters are set to the following values:
Height = 12
Width  = 12
Escapement = 900
Orientation = 900
Weight = FW_BOLD
Italic = FALSE
Underline = FALSE
StrikeOut = FALSE
CharSet = OEM_CHARSET
OutputPrecision = OUT_DEFAULT_PRECIS
ClipPrecision = CLIP_DEFAULT_PRECIS
Quality = DEFAULT_QUALITY
PitchAndFamily = VARIABLE_PITCH|FF_ROMAN
Facename = “Roman”
Again, an attempt will be made by Windows to find a match to the preceding specifications. Examine the listing and notice that only Escapement and Orientation were changed. Both of these parameters use angle values specified in tenths of a degree. Thus, 900 represents an angle of 90.0 degrees. The Escapement parameter rotates the line of text from horizontal to vertical. Orientation rotates each character, in this application, by 90.0 degrees. This font will be used to print a vertical axis label in the application.
Here is how the vertical axis label was printed in this application:
newfont.CreateFont(12,12,900,900,FW_BOLD,
                  FALSE,FALSE,FALSE,
                  OEM_CHARSET,
                  OUT_DEFAULT_PRECIS,
                  CLIP_DEFAULT_PRECIS,
                  DEFAULT_QUALITY,
                  VARIABLE_PITCH|FF_ROMAN,
                  “Roman”);
oldfont=dc.SelectObject(&newfont);
dc.TextOut(50,200+(strlen(szXString)
*10/2),
         szYString,strlen(szYString));
When you develop your own applications, be sure to examine the online documentation on the CreateFont( ) function and the additional typefaces that may be available for your use.
Drawing the Axes and Bars
Simple x and y coordinate axes are drawn with the use of the MoveTo( ) and LineTo( ) functions:
// Draw coordinate axis
dc.MoveTo(99,49);
dc.LineTo(99,350);
dc.LineTo(500,350);
dc.MoveTo(99,350);
The program then prepares for drawing each bar. As the following code shows, the first bar always starts at position 100,350 on the chart, as defined by x1 and y1. The width of the first bar and all subsequent bars is calculated from the last drawing position and the width of each bar. The second x value is defined by x2.
// Initial values
x1=100;
y1=350;
x2=x1+iBarWidth;
Bars are drawn (by the program) by retrieving the scaled bar height value from iBarSizeScaled. This scaled value, saved in y2, is used in the Rectangle( ) function. Since the Rectangle( ) function draws a closed figure, the figure will be filled with the current brush color. The color value selected from the array is incremented during each pass through the loop. Here is a portion of code to show how this is achieved:
// Draw Each Bar
for(i=0;i<iNBars;i++)
{
 newbrush.CreateSolidBrush(dwColor[i]);
 oldbrush=dc.SelectObject(&newbrush);
 y2=350-iBarSizeScaled[i];
 dc.Rectangle(x1,y1,x2,y2);
 x1=x2;
 x2+=iBarWidth;
}
After each bar is drawn, the values in x1 and x2 are updated to point to the next bar’s position. This process is repeated in the for loop until all the bars are drawn.
Running BARCHART
Compile the BARCHART application within the Project utility. When you execute the application, a default bar chart similar to the one in Figure 23-11 will be drawn in the window. You can create a custom bar chart, as shown in Figure 23-12, by entering a chart title, axis labels, and unique bar values.
Figure 23-11: The default chart for the BARCHART application
Figure 23-12: A custom bar chart
You can continue the development of this application by adding axis tick marks, a legend, and so on. Customization is limited only by your imagination.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net