Sample App in C++
Volume Number: 5
Issue Number: 12
Column Tag: Jörg's Folder
C++ Sample Application 
By Jörg Langowski, MacTutor Editorial Board
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
“C++ Sample Application”
As I am writing this, MPW C++ is shipping; version 3.1b1 is available through
APDA as of October 11. The following message could be found on Applelink:
“On Tuesday, October 3, 1989 Apple Computer, Inc announced MPW C++
v.3.1B1 and said MPW C++ was available for ordering immediately and would be
shipping later in October. ‘Later’ is here NOW! MPW C++ v.3.1B1 started shipping
on Wednesday, October 11, 1989!
To get your copy, call APDA at
1-800-282-2732 (U.S.)
1-800-637-0029 (Canada)
1-408-562-3910 (International)
ask for part number M0346LL/A. The price is $175 and the package includes one
Apple C++ Manual, three AT&T C++ manual (Product Reference, Library Manual, and
Selected Readings), MacApp 2.0B9 preliminary C++ interfaces (so you can use
MacApp from C++),and three 3.5" disks.
Tim Swihart
C++ Product Manager “
Thus, all people interested in C++ can now get their copies - and follow this
tutorial.
The example that I prepared for you this month is derived from one of the
samples on the Apple C++ disks. Apple’s samples include a rudimentary application
framework, some sort of a mini-MacApp, defined in the classes TApplication and
TDocument. After last month’s introduction to some essential features of C++, I’ll
show you this time how to use this framework to build a small application that opens
and closes a window in which some text is displayed and handles one custom menu in
addition to the Apple, File, and Edit menus.
Since the base classes, TApplication and TDocument, provide for MultiFinder
support, our application will also be fully MultiFinder compatible. I am not reprinting
the full TApplication and TDocument framework here, “for copyright reasons” - the
real reason being, of course, that it would make this article about ten pages longer, and
those of you who use C++ have those files, anyway. However, we’ll take a short look at
the main features of those two classes.
TApplication implements the basic behavior of a Macintosh application. This class
provides, among other methods, the constructor for instantiating a new application
object, and the public EventLoop routine:
{2}
class TApplication : HandleObject {
public:
TApplication(void);
void EventLoop(void);
etc.
}
Note here that this class is derived from the superclass HandleObject; this is a
special class particular to MPW C++, where space for the object is allocated through a
handle, not a pointer, to prevent memory fragmentation. Another ‘ special’ superclass
is PascalObject, which is used to access class definitions in Object Pascal from C++,
necessary for MacApp support. We’ll discuss these classes in a later column.
Most methods in TApplication are protected so that they can only be accessed by
derived classes. They include basic event handlers and initializers which are called
before and after the main event loop. Those methods are declared virtual which means
they don’t have to be defined within the class TApplication itself, and run-time binding
will be supported where necessary.
The behavior of our application will be completely determined by the way we
re-define TApplication’s methods. Of the base class, we only need the header file
TApplication.h to make its definitions available to our particular implementation; the
code for TApplication can be kept in a separate object file or a library.
A simple program would define its own application class, say TMacTutorApp, and
override some of the event handlers in TApplication. The main program then just
consist of calls to two methods, the constructor and the event loop:
{2}
int main (void)
{
gTheApplication = new TMacTutorApp;
if (gTheApplication == nil) return 0;
gTheApplication->EventLoop();
return 0;
}
A complete Macintosh application in five lines of C++ code! (I don’t count the
braces). Of course, this simplicity is deceptive; all the work is done in the methods
that determine the behavior of the event loop. Our application class, its associated
document class, and the methods are implemented in listing 1; the header file that
contains the definitions is shown in listing 2.
Our Application
Our application class re-defines TApplication’s constructor and six private
methods. Listing 1 contains the actual code. Let’s explain the methods as they are called
when the program is executed.
When the application object is constructed, first the constructor of the base
class, TApplication, is called. By default, this method initializes all the toolbox
managers, determines whether there is enough memory and the system environment is
OK to run the program, and does some other initializations. Then, TMacTutorApp’s
constructor is called (listing 1); this method sets up the menu bar and creates one new
document (DoNew()).
Any application created using the TApplication framework contains a list of
documents, whose maximum number is determined by the constant
kMaxOpenDocuments in our application’s class definition (Listing 2). The actual
handling of this document list is implemented in TApplication itself and need not
concern us here. As long as the number of open documents is less than
kMaxOpenDocuments, the New, and possibly Open, items in the File menu are enabled;
if the maximum number is reached, they will be disabled. This behavior is laid out in
the AdjustMenus method. That method is called once on every pass through the event
loop (also defined in the base class).
Mouse downs (and other events) are automatically passed on to their respective
handlers by TApplication. The routine that we need to override in our class definition
to handle menu selections is DoMenuCommand (Listing 1). Here, the basic apple, File
and Edit menu selection are treated in a more or less standard way; the fourth menu is
our own addition and contains four items to choose from. When one is selected, that
item will be checked while the others are unchecked (checking/ unchecking is done by
AdjustMenus). Furthermore, the number of the selected item, as well as a
corresponding string, are passed on to the open document. The document then knows
which message to display in its window.
Our Document
The basic methods that are defined in the TDocument class deal with document
display (i.e. window updating, growing/zooming, activate/deactivate), editing
(cut/paste, mouse down in content, key down), and file and print handling. All these
methods do nothing by default; they need to be overridden in our document’s class
definition.
Our document is called - what else - a TMacTutorDocument, and the methods we
redefine are the constructor, destructor, window draw (private) and update methods.
The constructor creates a new window and assigns an initial message to be displayed.
When you look at its code (Listing 1), you’ll notice that the first line looks somewhat
funny:
TMacTutorDocument::TMacTutorDocument
(short resID, StringPtr s) : (resID) { etc }
This form of a function call is particular to C++ constructors. When a
constructor is called, it will call the constructor of the base class first; this
constructor might need another set of parameters. This parameter list is therefore
given after the colon. In our case, we pass our window’s resource ID to the base class
constructor, which then creates a new window according to the resource information.
Thereafter our own constructor code is called, which initializes the message string and
makes the window visible.
The destructor will only hide our window; the actual deletion of the object
(DisposeWindow) is done in the base class, TDocument.
DoUpdate will call our definition of DrawWindow, embedded in calls to
BeginUpdate and EndUpdate. DrawWindow itself, which displays the message string in
the window, is private; all window re-drawing is handled through calls to DoUpdate.
Methods inside TMacTutorApp set and retrieve the selected menu item number in
our document, and set the message string. We therefore need access to these variables,
which are private to TMacTutorDocument. Such access is provided through the methods
SetDisplayString, GetItemSelected, and SetItemSelected, which are defined inline in the
header file (listing 3).
Taking all these definitions together, you have an object-oriented framework for
a very simple application. You see how easy it is to expand this framework to your own
needs, and how well-separated the different parts of an application are in an
object-oriented environment like C++. Application setup, menu handling (proper to
the application), and window handling (proper to the document), are clearly distinct,
as are the basic behavior (laid down in the application framework) and the
user-defined behavior (by overriding the basic methods).
I’ll leave it at that for this month; next time we’ll define our own family of
objects that can be displayed and manipulated in a document window. If you have
questions or comments regarding this column, interesting pieces of C++ code, or
suggestions for improvement, feel free to contact me via MacTutor or through the
network: LANGOWSKI@FREMBL51.BITNET.
Listing 1: MacTutorApp.cp - our application-specific class
implementations
/*--------------------------------------------------------
# MacTutorApp
#
# A rudimentary application skeleton
# based on an example given by Apple MacDTS
# © J. Langowski / MacTutor 1989
#
# This example uses the TApplication and TDocument
# classes defined in the Apple C++ examples
#
#--------------------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Constants, resource definitions, etc.
#define kMinSize 48 // min heap needed in K
#define rMenuBar 128 /* application’s menu bar */
#define rAboutAlert 128 /* about alert */
#define rDocWindow 128 /* application’s window */