Visual C++ and Object Oriented

Programming

James Canavan

E-Mail: jaco@donotenter.com
WWW: www.donotenter.com
© December, 1993

Introduction:

Visual C++ is as much a language of its own as is the code it helps to organize. Because most windows code needs to be transportable between applications a heavy use of library functions is used. From the programmers viewpoint this translates into categories of Objects which control the GUI constructs and processing of the application. A program is devided into three separate control subprograms - that is, any program written using the Class Wizard program included with Visual C++ has three main parts. Class Wizard creates the three control programs that the programmer uses to build a program. They are: the View, the Document, and Control. The View controls what the user sees, the Document controls all the programs variables, and the Control contains the functions for the main (user defined) Objects. The separate programs communicate with each other using a messaging system run by the Windows OS.

Getting a concept into a working program is a major cause of stress; and the more removed a person can become from the coding problems, simply, the easier it becomes to write the program. When a programmer can be relaxed and still find interest in climbing the pile of compiler manuals with enough faith in the concepts he brings along with him about the solution - the program gets written. And that is the purpose of programming - To write programs that solve problems - with as little work as possible.

Microsoft has developed a system of programming that allows the programmer to choose where to build the program. If an idea comes about while programming that requires an addition of a dialog box (for input or user notification) it can be added to the project very quickly. This keeps programming interesting and productive.

Consider for a moment the caveman, who invented the wheel. Did this animal-draped lad sit on a pile of well rounded but non-perfect stone wheels trying desperately to "get it right"? How round did the wheel need to be before it could roll? And wouldn't be more important to consider how thick the stone needed to be to carry a load? No, the caveman didn't quibble about a perfect eccentricity - "round pancake stones roll" - that's all that is needed to make a wheel. The caveman had a concept of "roll" and "round" - this was easy. But picking the correct stone, the correct size, and the tools needed to fashion the "roll" concept into a working object was a major task. Perhaps our caveman had a degree in stone carving, which would help in selecting the correct stone, the carving methods, etc.. OK, our caveman invented the wheel and has several prototypes ready for demonstration - now what?

Once a particular programming construct is developed using Visual C++ it can be used over and over. So simple buttons, dialog boxes, windows, tasks such as memory control and I/O may not seem functional by themselves - but they can be saved and used over again.

What cuts down on a programmers productivity is the need to follow the same coding steps to get to a familure solution. Many times code written for one application can not be converted to another application; so the only solution is to start from scratch. Again consider our nameless caveman - he has invented the wheel - but he has no place to roll his seemingly useless invention. A normal caveman might set his wheel aside and forget about it. But someone got the idea to connect the caveman's wheels together and transportation was invented. This brought it's own problems, of course, but that is not the point; importantly, the problem / solution process travels from concept to object, and then from object to object utilization.

Visual C++ allows the changing of a program from many directions. Updates are made between different programming tasks. For example, adding a menu bar to a program will update several files with the correct address values and function calls automaticaly by the enviornment. That is, Visual C++ handles variable cross-referencing. An icon's shape or an object's function can be changed quickly. Because the Windows OS uses the Microsoft Foundation Class (MFC) itself - using these classes saves time - so a programmer can concentrate on the main algorithm of the program.

Logic programming follows a similar path: define truths, define relations between truths, and then test new relations, add the outcome of the testing to the database of collected truths - continue. This process is dynamic - that is, to be worthwhile a PROLOG program (for example) needs to tell us something we didn't know. Dynamically, the program can proceed or backtrack according to what has been defined. An object-of-computation has been created - dynamically. Now notice that this Object takes on a non-discript form. It is no longer a tangible concept (like a wheel, linked list, or similar encapsulation), but a process of execution. And processes of execution are difficult (if not impossible) to map out and program - besides, that is why we have compilers.

Visual C++ is machine-like. A programmer is required to program down two paths: the view of what is done, and the process that is done behind the window pane. This goes right into selecting the sequence of the programming: An icon needs to be defined before it can be used, a variable that changes some value needs to be given a place in the queue of messages that will be sent to the main program, and a programmer must pull his mentality up from small definitions in order to determine if a new Class needs to be defined - or to look around for a defined Object.

A computer scientists escapes the need to count invariant values, predict backtracking states or halt conditions by employing a "machine mentality". That is, look at a real world problem as a machine and break it down into smaller machines. Here you might ask, "Wonderful, but how do I look at a problem as a machine?". The answer comes from working with enough problems (and there solutions to notice just how "machine like" problems are; after which, parts of a new problem can be noticed that seem similar to old problems already mapped into the machine mentality.

Consider the wavelength size of the electromagnetic spectrum - at some point we define it as very large - using a Real Number counting system - it is reduced until the wavelength size is reduced beyond our measuring ability. Just the same, it is very useful to know a waves frequency - the fact our definition extends below and beyond our ability to notice it does not matter. The difference between an X-ray and red light is real. In this case, we have abstracted a fuzzy demarcation for classifying electromagnetic radiation. The same classification holds true for Object Oriented programming - we classify what we need to define smaller (and larger) machines. And we stop when we feel we have gained enough utility out of our abstractions. In the problem / solution process we piece together our abstractions to flow together as one unit.

Windows NT developed by Microsoft Inc. has pushed the level of object dependence to the point of frustration. First, foremost, and at the head of the line, when installing this operating system one must consider the hardware platform that will be used. The frustration for a system administrator comes from using different vendor components - hardware and software. Until the number of components needed for this operating system are more standardized the problems will persist. For example, suppose I wish to use a Hewlett Packard Ethernet card with a Gateway 2000 486 computer, will it work? Can I put these two (problem/solution) objects together without needing something more? Do I need different network drivers - and must I buy stock in Compuserve just to download the correct drivers IF I can use them? Frustration stems from the selection and criteria needed to solve a problem. And as elegant as the Windows NT operating system is destined to become it is dependent on objects and the relations between them. Happily, Microsoft Windows NT is designed around objects.

Most obvious is the Windows GUI where the programmer performs his miracles, connects to the world, or just plays a leisurely game of solitaire. Microsoft's Visual C++ uses a heavily GUI environment to organize a programmers conceptualization of a program. Debugging is NOT just a task done after a program doesn't work, for example, as it is in UNIX, where the debugging code runs from an outer shell, but a REAL window linked to the ACTUAL code. For example, because of the heavy connection between the GUI and the code developing process, the Visual C++ debugger can be used to fix a program full of errors just by following the debugger suggestions ( in order of importance ) of the debuggers output. Yet, at any point a programmer can click the close box on the debugger window and go in different directions. So because of the Visual C++ GUI environment more programming directions are maintained.

The Programs:

Ramsey's Star (ram.exe):

The problem of coloring a graph with n points with n + k colors is taught using the "pigeon - hole" principle. But there is another theory behind this - Ramsey's Theory.

A number N has the (p,q) Ramsey property if and only if every graph G of N vertices, either G has a complete g-gon (complete graph of p vertices), or G has a complete g-gon.

The g-gons represent a different coloring of N vertices. While studying Petzold's textbook, I came across his "connect-the-dots" draw program ... I became interested in drawing on the client area of the screen.

RETURN TO TOP OF PAGE

Ram.exe:

Petzold's "connect-the-dots" program reads the mouse input and draws lines between the clicked locations. I changed this to release the line-drawing by the user:

for (i = 1; i < nCount ; i++)
        {
        MoveTo (hdc, points[nCount].x, points[nCount].y) ;
        LineTo (hdc, points[i].x, points[i].y) ;
        } 

I also added the ability for the user to select different colors for the lines,

and kept count of the vertices and edges. The program is simple to use - 'point and click', and to start over ( just like Petzold's "connect-the-dots" ), the left mouse button erases the client area.

Several more things could be added to this program that would be interesting:

  • Adding scroll to the client would allow for bigger star drawings.
  • Saving the point data would allow the algorithm to calculate how many n- gons (of different colors) could be calculated.
  • Linking a graph (G) to theory: "how many g-gons were "in there?"".

Ball bouncing program:

The ball program is composed of the following files that work together as one program:

* mainfrm.cpp & mainfrm.h:

Sets up the program from the highest level - composed of several other programs: ball.cpp which sets up the view, frame, and document classes, ball.h - the ball application's class definition, mainfrm.h - the header file for the program and it's resources.

* ballview.cpp & ballview.h:

The class functions for the "view" into the program - what the user sees. Here windows messages are sent - and handled. All the major activities for the program are handled here - I found this much easier (being new to this type of programming) than using the document file to do ball class (CBitBall) processing.

* balldoc.cpp & balldoc.h:

Normally used to process the program's data and dialog box processing - but after several weeks of being UNABLE to use this class - I decided to use the toolbar and menu for computer operator control. Although I should add that I recently learned of the exten statement in C++ that would allow variable sharing between programs (modules, classes, files) - but this is NOT the way Object Oriented program should be written - each file (except for the header {*.h}, and system files) is a class in itself - communication between classes is done with a message loop which polls the application's message Queue - data transfer between classes is normally done using something like a SendMessage( ) command.

RETURN TO TOP OF PAGE

* ball.rc & resource.h:

These files set up the GUI for the program - icons, menus, accelerator keys, and dialog boxes. Here is where using the sub-program APPWIZARD both complicates and simplifies writing code. Complicates programming because messages need to be considered when making the resources - this forces the programmer to step back from the inner development and connect the GUI to the code - statement for statement. But this is very helpful because it allows looking at the code connected to the result of its processing. Larger chunks - that is, more general characteristics of the connecting classes is apparent.

* ballball.h & ballball.cpp:

I added these files to define the class structure for a ball (ballball.h) and define the member functions for the ball. In these two files is where I learned most of what Object Oriented programming is all about.

What does the program do?:

ball.exe creates a window with standard controls - two methods of drawing a moving ball in this window are exemplified: Graphical Device Interface (GDI) drawing and Bitmap (Bitblit) drawing:

GDI method draws a ball then kills it by drawing another ball over it with the same color as the ball's background. It then calculates the position of the ball and re-draws the ball at this new position.

BitBlit drawing is a little different. It creates a bitmap memory storage for the whole client area (the white inside area) - it then copies a ball onto the position given by the same movement function as used in the GDI drawing method. But the ball is not drawn on the client area for the person watching - rather the entire client area is re-drawn for each ball movement. The program also allows the user to experiment with sound, size, velocity, and tracking. Tracking of the ball is done by canceling out the killball function by NOT erasing the ball before moving it - This, combined with changing the red, green, and blue values of the ball added some surprising results.

The use of objects in this program is best demonstrated by explaining the CBitBall class - this class defines a ball using variables and functions. Variables define the more "physical" aspects of a real ball; while the functions are used primarily to either get values ( such as color, position, and various Boolean flags ) - or set those values. Once the ball was successfully designed as a class structure, adding member functions was easy. Building the ball (B[1] as a variable) in the view object file connects the "ball" to the GUI of the program - the menu, drawing area - and user control. This encapsulation allows the application program (ballview, balldoc, and ball) files to control how the ball is manipulated.

Object (CBitBall) Control:

The functions that are part of the ball either transfer ball information to the main program or change these internal values. Menu messages are sent to the view object ... there the appropriate CBitBall class member functions are called - either to change or poll the ball variables... program control is then returned to the GUI - along with any output to the screen (client area) or speaker.

The view member functions update the GUI (tool bar status, timer control, or menu selections) each time any button is pushed. Since the update of the menu reflects the condition of the program the GUI is made more robust. For example, I had a problem when the user stopped a ball that was already stopped - an error occurred when the program tried to destroy an object that did not exist. But this problem was fixed by disabling the stop selection when the ball was not moving. Other "control masking" events were used to limit the messages from the GUI to the program - making the program more robust and "monkey free".

RETURN TO TOP OF PAGE

CBitBall Class:

// ****************************************
// CBitBall Class Start
class CBitBall 
{ 
public: 
        CBitBall(CWnd* pWnd, int xc, int yc ); // constructor 
        void Move(); // move the ball 
        void Draw(); // draw the ball
        void SetRadius(int radius); // set ball radius
        void SetVelocity(int velocity); // set ball velocity
        void SelectBallType(BOOL btype); // FALSE = GDI, TRUE = Bitmap
        BOOL GetBallType() { return bBitBall; }; // get ball type
        void SetNoise(BOOL bsound); // set noise flag
        BOOL GetBallNoise() {return bNoise; }; // get noise flag
        void KillBall(); // erase GDI ball
        void SetBallTracks(); // flip-flop BallTracks flag
        BOOL GetBallTracks() { return bBallTracks; }; // set tracks flip-flop 
        void SetBallMoving(BOOL bmoving); // set moving flag
        BOOL GetBallMoving() { return bBallMoving; }; // get moving flag 
        void SetBallColor(int ncolorselector); // colored ball
private: 
        int cxRadius, cyRadius; // how big are you?
        int xCenter, yCenter; // where is your center?
        int cxVel, cyVel; // how fast are you moving?
        BOOL bBitBall; // What kind of Ball do I have anyway? 
        // TRUE = BitBall, FALSE = GDI Ball
        CWnd* pBallWindow; // where all the action is .... 
        BOOL bNoise; // I can hear my ball too! 
        BOOL bBallTracks; // I know where the ball has been! 
        BOOL bBallMoving; // Is that ball moving? 
        int red; // red value of ball
        int green; // green value of ball
        int blue; // blue value of ball
}; // CBitBall Class End
// **************************************** 
RETURN TO TOP OF PAGE

Conclusion:

An object oriented mentality has seeped into the higher level software design process. During a computer scientist's most relaxed times - apart from software deadlines, office politics, and compiler errors - a conceptualization process takes place. Being relaxed, she may think of a novel solution to a problem haunting her for several days. This solution will not fly by as streams of code, ones or zeros, nor independent code segments - but it will power a belief in the solution by using conceptualizations. And so begins the computer scientist's mad circle - confident and relaxed that a solution is in sight - ready to start tapping the keys, open the cryptic symbolic compiler manuals which, of course, brings the stress and the need to relax again; where free from bouncing off the inner walls of her programming rut - she gains a new conceptualizations of the same problem - rested, the circle closes.

Bibliography:

1) Petzold, Charles, Programming Windows 3.1, Microsoft Press.
2) McCord, James, Windows Programmer's Reference, Que Corporation.
3) Andriamanalimanana, Bruno, Class Notes for CSC 585-1, Fall, 1993.
4) Applied Combinatorics, Fred Roberts, Prentice-Hall, 1984.
5) A Basis for Theoretical Computer Science, Arbib et. al. Springer-Verlag, 1984.
RETURN TO TOP OF PAGE

Programs:

Note: the following program are just "highest level programs" - ball.cpp for example does not have the functions. Look at the disk with the program for the full version of the programs.

ram.cpp

/*-----------------------------------------------------------
ram.cpp -- From "Connect-the-Dots Mouse Demo Program"
(c) Charles Petzold, 1992 
Used by and added to by: James Canavan, 1993
-----------------------------------------------------------*/
#include <windows.h> 
#include "ram.h"
#define MAXPOINTS 1000 // Max number of points in Ramsey' star
long FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG) ; 
static char szAppName[] = "ram" ; // name of all supporting files
enum color // what color do you want ???
        {
        red,green,blue, ltblue, purple, yellow ,black
        } color_it;
static HPEN hPenred, hPengreen, hPenblue, hPenblack;// handle to a pen 
static HPEN hPenpurple, hPenltblue, hPenyellow; 

// By the way, the following two lines are a very messed up way of doing
// this .... but it works!
char szBuffer [40]; // holds number of points.
char szBuffer2 [40]; // holds number of colors. 
char szBuffer3 [40]; // holds number of lines.
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance) 
{
        wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wndclass.lpfnWndProc = WndProc ;
        wndclass.cbClsExtra = 0 ;
        wndclass.cbWndExtra = 0 ;
        wndclass.hInstance = hInstance ;
        wndclass.hIcon = LoadIcon (hInstance, szAppName ) ;
        wndclass.hCursor = LoadCursor (NULL , IDC_ARROW ) ;
        wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
        wndclass.lpszMenuName = szAppName ; // Menu name
        wndclass.lpszClassName = szAppName ;
        RegisterClass (&wndclass) ;
}
// App Note: Version 1.0 - Oct. 17, 1993 
hwnd = CreateWindow (szAppName,
"Ramsey's Star 1.0",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
}
return msg.wParam ;
}
        long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT  wParam,
        LONG lParam)
{
static POINT points[MAXPOINTS] ;
static short nCount, nColor, nLine; 
HDC hdc ; // used to grab the device context
HMENU hMenu; // used to grab the menu
PAINTSTRUCT ps ;
short i; // used as a counter for point[i] increments
switch (message)
{ 
case WM_COMMAND:
        hMenu = GetMenu(hwnd);
        switch (wParam)
{ // pick a pen, but not any pen ! 
case IDM_RED:
        color_it = red; 
        nColor = nColor + 1; // increment pen-counter
        return 0;
case IDM_GREEN: 
        nColor = nColor + 1;
        color_it = green; 
        return 0;
case IDM_BLUE: 
        nColor = nColor + 1;
        color_it = blue;
        return 0; 
case IDM_LTBLUE: 
        nColor = nColor + 1;
        color_it = ltblue;
        return 0;
case IDM_PURPLE: 
        nColor = nColor + 1;
        color_it = purple;
        return 0;
case IDM_YELLOW: 
        nColor = nColor + 1;
        color_it = yellow;
        return 0; 
case IDM_BLACK: 
        nColor = nColor + 1;
        color_it = black;
        return 0; 
case ID_HELP_INSTRUCTIONS: 
        MessageBox( hwnd,"Left Mouse Button -----> Creates Point Right Mouse Button ----->
        Screen --Refresh", "Ramsey's Star .0", MB_ICONINFORMATION ); 
        return 0;
case ID_HELP_ABOUT:
        MessageBeep(0);
        MessageBox( hwnd, "Programmer: James Canavan (gjac1@sunyit.edu) October 18, 1993", 
        "...Just to let you know...", MB_OK);
        return 0;
        } 
        break;
case WM_CREATE: 
        // define pen using mixture of red, green, and blue.
        hPenred = CreatePen(PS_SOLID, 1, RGB(255,0,0));
        hPengreen = CreatePen(PS_SOLID, 1, RGB(0,255,0));
        hPenblue = CreatePen(PS_SOLID, 1, RGB(0,0,255));
        hPenpurple = CreatePen(PS_SOLID, 1, RGB(255,0,255));
        hPenltblue = CreatePen(PS_SOLID, 1, RGB(0, 255,255));
        hPenyellow = CreatePen(PS_SOLID, 1, RGB(255, 255, 0)); 
        hPenblack = CreatePen(PS_SOLID, 1, RGB(0, 0, 0 ));
        nLine = 3;
        nColor = 1; // got at least one color 
        return 0; 
case WM_SIZE: // if you resize the window - start over.
case WM_RBUTTONDOWN:
        nCount = 0 ; // Number of points.
        nColor = 1 ; // Number of colors.
        nLine = 3 ; // Number of lines total.
        InvalidateRect (hwnd, NULL, TRUE) ;
        return 0 ;
case WM_LBUTTONDOWN:
        if (wParam & MK_LBUTTON && nCount < 1000)
        { 
                nCount = nCount + 1;
                points [nCount] = MAKEPOINT (lParam) ;
                hdc = GetDC (hwnd) ;
                SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0L) ;
                ReleaseDC (hwnd, hdc) ;
        } 
        // This following section was pulled out of WM_RBUTTONDOWN 
        InvalidateRect (hwnd, NULL, FALSE) ;
        return 0 ; 
case WM_PAINT: 
        hdc = BeginPaint (hwnd, &ps) ; 
        switch (color_it) // color_it has menu color selection
        {
case red: SelectObject ( hdc, hPenred); break;
case green: SelectObject ( hdc, hPengreen); break;
case blue: SelectObject ( hdc, hPenblue); break; 
case ltblue: SelectObject ( hdc, hPenltblue);break;
case yellow: SelectObject ( hdc, hPenyellow);break;
case purple: SelectObject ( hdc, hPenpurple);break;
case black: SelectObject ( hdc, hPenblack); break;
        default: SelectObject ( hdc, hPenblack );break;
        } 
        for (i = 1; i < nCount ; i++)
        {
                MoveTo (hdc, points[nCount].x, points[nCount].y) ;
                LineTo (hdc, points[i].x, points[i].y) ;
        } 
        // Output info to Client Window
        TextOut (hdc, 3, 5, szBuffer,
        wsprintf (szBuffer, "Points: %d",nCount)); 
        if ( nColor > 7 )
                TextOut (hdc, 3, 23, szBuffer2, wsprintf (szBuffer2,"Colors: 7",nColor));
        else
                TextOut (hdc, 3, 23, szBuffer2,
                wsprintf (szBuffer2,"Colors: %d",nColor));
                if (nCount < 4)
                {
            if (nCount == 1) TextOut (hdc, 3, 40, szBuffer3, wsprintf (szBuffer3, "Lines: %d", 0 ));
            if (nCount == 2) TextOut (hdc, 3, 40, szBuffer3, wsprintf (szBuffer3, "Lines: %d", 1 ));
            if (nCount == 3) TextOut (hdc, 3, 40, szBuffer3, wsprintf (szBuffer3, "Lines: %d", 3 ));
                }
                else 
                {
                nLine = nLine+nCount-1; // Adding the number of lines we
                // already have plus the number 
                // of points we draw to.
                TextOut (hdc, 3, 40, szBuffer3, wsprintf (szBuffer3, "Lines: %d", nLine));
                }
        EndPaint (hwnd, &ps) ;
        return 0 ;
case WM_DESTROY: // take off !!
        DeleteObject(hPenred ); // get rid of created pen
        DeleteObject(hPengreen);
        DeleteObject(hPenblue);
        DeleteObject(hPenblack);
        DeleteObject(hPenltblue);
        DeleteObject(hPenyellow);
        DeleteObject(hPenpurple);
        PostQuitMessage (0) ;
        return 0 ;
        }
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

ball.cpp

// ************************************************************
// FILE NAME: ball.cpp
// PROGRAM: ball.exe version 5.0 
// PROGRAMMER: James Canavan - gjac1@sunyit.edu
// DATE: December, 1993
// PROGRAM DEPENDENCIES: ball.cpp, balldoc.cpp, ballview.cpp,
// ballball.cpp, mainfrm.cpp, stdfax.cpp 
// PURPOSE: 1) To draw two types of bouncing balls on the 
// screen - a GDI Ball and Bitmap Ball.
// 2) To practice Object Oriented programming
// ************************************************************
#include "stdafx.h"
#include "ball.h"
#include "mainfrm.h"
#include "balldoc.h"
#include "ballview.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBallApp
BEGIN_MESSAGE_MAP(CBallApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// // CBallApp construction CBallApp::CBallApp() { } ///////////////////////////////////////////////////////////////////////////// // The one and only CBallApp object CBallApp NEAR theApp; ///////////////////////////////////////////////////////////////////////////// // CBallApp initialization BOOL CBallApp::InitInstance() { SetDialogBkColor(); // set dialog background color to gray LoadStdProfileSettings(); // Load standard INI file options (including MRU) AddDocTemplate(new CSingleDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CBallDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CBallView))); // create a new (empty) document OnFileNew(); if (m_lpCmdLine[0] != '\0') { } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); enum { IDD = IDD_ABOUTBOX }; // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // App command to run the dialog void CBallApp::OnAppAbout() { CAboutDlg aboutDlg; aboutDlg.DoModal(); } ///////////////////////////////////////////////////////////////////////////// // CBallApp commands
RETURN TO TOP OF PAGE

Here is the author's E-mail address: jaco@donotenter.com