TweetFollow Us on Twitter

MacApp and C++ 2
Volume Number:6
Issue Number:9
Column Tag:Jörg's Folder

Related Info: TextEdit

C++ and MacApp, Part II

By Jörg Langowski, MacTutor Editorial Board

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

C++ and MacApp, Part II

Last month’s example was meant to give you an impression of the structure of a larger MacApp program in C++ and of some specific problems which arise when using the MacApp libraries from C++. We will now look into the structure of MacApp 2.0 applications in more detail, to see what happens at each point in a program.

We’ll start with a very simple example, the ‘nothing’ program that simply displays a window with the text ‘MacApp®’ in it. This program (from the Apple C++ examples) is printed in listing 1. The ‘main program’ consists simply of a few lines: First, most of the essential toolbox managers are initialized by a call to InitToolBox(). This procedure - through a call to the low-level routine DoRealInitToolBox() - calls InitGraf, InitFonts, InitWindows, FlushEvents, InitMenus, TEInit, and InitDialogs. It also sets a number of global MacApp variables, most of which won’t concern us here; an important one is gConfiguration, which is the configuration record that defines the system environment and allows us later to test whether we have a math coprocessor, the Script Manager, or other essential things.

ValidateConfiguration tests the configuration record against a number of global constants the values of which you can define at compile time in your program, if it requires the presence of certain system services or hardware options. Since we haven’t set any of those constants, our program will run on all machines. Nevertheless, we do the test, in case additions are made later. If, for instance, your program would need a floating point processor, you have to include at the beginning of the program:

 #defineqNeedsFPU1

If the program is then run on a machine without FPU, ValidateConfiguration(&gConfiguration) will return false and the program abort with an error dialog.

If the configuration is correct, the main code will be executed starting with a call to InitUMacApp(8); this will allocate 8 blocks of master pointers. Furthermore, various internal variables of MacApp will be initialized. If you intend to print from your program, you must also call InitPrinting(). This routine initializes more MacApp variables that are used in printing, and in particular creates one object of the class TStdPrintHandler. This object is assigned to the global gPrintHandler.

You then create a new instance of your application class, in this case TNothingApplication. Since there exist no constructors in Object Pascal, we have to define our application’s initialization code in an initialization method. First we check whether the object was successfully constructed by calling FailNIL(gNothingApplication), which will abort with an error message if the handle passed is NIL. If everything worked out, we can call our initialization method INothingApplication. As a parameter to this method we pass the four-character identification of the application’s main file type. In our case, the initialization code basically calls IApplication; this routine, besides various other things, initializes the application’s menu bar. The remaining code in INothingApplication is needed to prevent the linker from stripping the class code for TDefaultView.

What does this mean? In larger applications with complicated view and document structures, you tell the system how to create your views and documents explicitly by overriding TDocument::DoMakeViews and TApplication::DoMakeDocument. These methods will be called by MacApp when a new document is created (see below). However, you may alternatively use a mechanism of view creation from templates. MacApp will create a default view of type ‘dflt’ when starting the application if DoMakeViews has not been overridden. If we register our view class TDefaultView under the type name like ‘dflt’, MacApp will create a default view that contains the methods of TDefaultView according to our own definition.

As you see, everything happens at run time, thus the methods will be called by late binding. The linker doesn’t know that TDefaultView’s code will ever be called. Since we have an intelligent linker, it will try to save space and not include that code in the final application, which will result in a run time error when we’re trying to find TDefaultView’s methods. The resort is to create one instance of TDefaultView, as shown in the listing. If you initialize your own views by overriding TDocument:: DoMakeViews, this wouldn’t be necessary. Last month, I erroneously included the ‘dead code strip suppression’ part in my example; those lines may be omitted without consequences.

After all the preambles we can now call gNothingApplication->Run(), which enters the main event loop. Most of the user actions that have not explicitly been defined by overriding methods will now be handled automatically by MacApp. That is, one new document will be created with the default view inside, that view can be scrolled and the window resized, and the Apple, File and Edit menus function as you would expect them to.

The only method that we override is TDefaultView::Draw(Rect *area). This method does the actual drawing for our view - it simply draws the text ‘MacApp®’ surrounded by a gray border. Printing and saving of this document is handled by MacApp.

TEDemo - last month’s example

You will now need to pull last month’s MacTutor out of the chaos on your desk, or borrow a copy from a friend. That example was much longer and more complicated; you see, however, that the main program remains almost identical, we only had to add a call to InitUTEView() to be able to use a Text Edit view in our program. The actual behavior of the program is implemented in all the methods that are overridden by our definitions, and as you see, there are lots of them. First, the initialization method has grown somewhat. TEApplication::ITEApplication() now initializes the arrays of different text colors and icon rectangles in the icon palette. It still calls IApplication() (from the superclass); this call is always required, and it sets up the menu bar.

When the application starts, it will open one new document of its standard type. The routine that creates the document is TTEApplication::DoMakeDocument, and this is called by TApplication::OpenNew, which in turn gets called by TApplication:: HandleFinderRequest. The latter routine is called once on entering the Run() method of the application. DoMakeDocument, in turn, initializes the document by calling ITEDocument.

The reason that we see our desired view(s) in the document window is because TApplication:: OpenNew also calls the DoMakeViews method of the newly created document. This method has been defined in the program, and it creates a palette view at the top of the window which contains some icons, and a text view for the remaining part of the window. It also creates the standard print handler.

The DoRead and DoWrite methods of TTEDocument have been explained in part last month - it was here where we had to deal with the problem of passing procedure parameters in C++. These methods get called when the Open and Save items in the File menu are activated. The menu handler is called from the main event loop, which is part of the application’s default Run method; no need to write explicit menu handlers here.

The methods of TPaletteView handle the icon selections in the palette at the top of the window. DoMouseCommand looks which icon we clicked in, highlights the palette appropriately and sets the variable fIconSelected to the number of the icon selected. This variable is then later used to determine the cursor shape and the behavior of the text view on mouse clicks and keystrokes.

In the methods of TTEView, we have to override the menu handling since we have a new menu that determines the text color. Thus, the menu behavior is defined in the methods DoSetupMenus and DoMenuCommand. DoSetupMenus is called regularly by MacApp to make sure that changes to menus are made visible. DoMenuCommand is called when a menu item is selected.

DoMouseCommand will draw a box in the window if the ‘drawing tool’ is selected by methods from the Sketcher class which is defined further below; otherwise, it calls the method inherited from the superclass, which in this case implements TextEdit behavior for setting the caret position and selecting text.

TSketcher is the class of objects that draw rounded rectangles (TBoxes) in the window. An object of this class gets instantiated when the mouse is clicked in the window while the drawing tool icon is selected. The ‘Sketcher’ then tracks the mouse and creates a new TBox object at the position given by the result of the mouse tracking.

TBox, finally, draws itself inside the window as a rounded rectangle.

I hope this explanation has made clear at least approximately how a MacApp application sets itself up and uses the classes and methods defined in the program. We shall see more examples in the near future. Meanwhile, I would like to ask the remaining Forth believers to stay tuned; next month it’s your turn again.

Happy hacking.

Listing 1: nothing.cp 

#include <UMacApp.h>
#include <UPrinting.h>
#include <Fonts.h>

const OSType kSignature = ‘SS01’;
const OSType kFileType = ‘SF01’;

class TNothingApplication : public TApplication {
public:
 virtual pascal void 
 INothingApplication(OSType itsMainFileType);
};

class TDefaultView : public TView {
public:
 virtual pascal void Draw(Rect *area);
};

pascal void 
TNothingApplication::INothingApplication
 (OSType itsMainFileType)
{IApplication(itsMainFileType);
 RegisterStdType(“\pTDefaultView”, ‘dflt’);
 if (gDeadStripSuppression)
 { TDefaultView *aDfltView;
 aDfltView = new TDefaultView;
 }
}

pascal void TDefaultView::Draw(Rect *)
{Rect itsQDExtent;
 
 PenNormal();    PenSize(10, 10);
 PenPat(qd.dkGray);
 GetQDExtent(&itsQDExtent);
 FrameRect(&itsQDExtent);
 TextFont(applFont); TextSize(72);
 MoveTo(45, 90); DrawString(“\pMacApp®”);
 PenNormal();
}

TNothingApplication *gNothingApplication;

int main()
{InitToolBox();
 if (ValidateConfiguration(&gConfiguration))
 { InitUMacApp(8);
 InitPrinting();
 gNothingApplication = new TNothingApplication;
 FailNIL(gNothingApplication);
 gNothingApplication->INothingApplication(kFileType);
 gNothingApplication->Run();
 }
 else StdAlert(phUnsupportedConfiguration);
 return 0;
}

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links... | Read more »
Blue Archive heads for nature in New Yea...
Continuing the Blue Archive trend of releasing seasonal events to the Western version of the game nowhere near when they actually happened, the Cyber New Year March update has arrived. It brings with it a story centring around New Year, which it... | Read more »
Once Human conquers maths to be one hotl...
It feels like Once Human has been in development for about ten years at this point, but that has clearly not blunted the excitement for NetEases’ upcoming open-world survival game. As a matter of fact, it seems things have never been better, as... | Read more »
Watcher of Realms celebrates its first a...
It has been one year since Moonton Games kicked off the fantasy RPG Watcher of Realms, and there are a lot of celebrations to mark the occasion. You could take part in a brand-new mode, earn some skins, and recruit some of the strongest characters... | Read more »
Tarisland finally launches and celebrate...
It has felt like a lifetime, as it always does when it comes to waiting, but now Level Infinites’ anticipated MMORPG Tarisland is available across mobiles and Windows. It is time to pick your favourite of the nine classes, customise them to your... | Read more »
Reverse: 1999 offer Reality teams a mout...
Bluepoch Games has confirmed that Phase 2 of Reverse:1999s Version 1.6 has launched, and brings with it a lot to get your teeth into. Along with some sign-in rewards and a bunch of stories to enjoy, as well as a new 6-star character who just might... | Read more »
Uncharted Waters Origin unveils its late...
LINE Games, Motif, and KOEI Tecmo have announced the latest raft of updates for their seafaring adventure title Uncharted Waters Origin, and if you've played for a while you know what to expect. A new Admiral, new mates, and some new story, the... | Read more »
Wrecking Golf is a casual physics-based...
In case you missed it, Dusan Popovic has officially launched Wrecking Golf on iOS and Android, the indie developer's casual golf game on mobile presented with charming pixel-art visuals. Featuring physics-based mechanics and simple controls, the... | Read more »
Blue Archive is striking out to Anime Ex...
At this point in my writing career, I have seen quite a few press releases come about, and it feels like one of the most frequently updated games there is Blue Archive. It is, of course, great to see a game have a life like this, and now Nexon is... | Read more »
Grab a Grammy-inspired Backbone One with...
There are so many mobile controllers on the market that it could be a little difficult to know which to go for. If you are someone who goes for a good old celebrity endorsement, however, then the new Backbone One might be for you, created as it... | Read more »

Price Scanner via MacPrices.net

Walmart continues to sell clearance 13-inch M...
Walmart continues to offer clearance, but new, Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBooks... Read more
Apple is offering steep discounts, up to $600...
Apple has standard-configuration 16″ M3 Max MacBook Pros available, Certified Refurbished, starting at $2969 and ranging up to $600 off MSRP. Each model features a new outer case, shipping is free,... Read more
Save up to $480 with these 14-inch M3 Pro/M3...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
Amazon has clearance 9th-generation WiFi iPad...
Amazon has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80-$100 off MSRP, starting only $249. Their prices are the lowest available for new iPads anywhere: – 10″ 64GB WiFi iPad (Space Gray or... Read more
Apple is offering a $50 discount on 2nd-gener...
Apple has Certified Refurbished White and Midnight HomePods available for $249, Certified Refurbished. That’s $50 off MSRP and the lowest price currently available for a full-size Apple HomePod today... Read more
The latest MacBook Pro sale at Amazon: 16-inc...
Amazon is offering instant discounts on 16″ M3 Pro and 16″ M3 Max MacBook Pros ranging up to $400 off MSRP as part of their early July 4th sale. Shipping is free. These are the lowest prices... Read more
14-inch M3 Pro MacBook Pros with 36GB of RAM...
B&H Photo has 14″ M3 Pro MacBook Pros with 36GB of RAM and 512GB or 1TB SSDs in stock today and on sale for $200 off Apple’s MSRP, each including free 1-2 day shipping: – 14″ M3 Pro MacBook Pro (... Read more
14-inch M3 MacBook Pros with 16GB of RAM on s...
B&H Photo has 14″ M3 MacBook Pros with 16GB of RAM and 512GB or 1TB SSDs in stock today and on sale for $150-$200 off Apple’s MSRP, each including free 1-2 day shipping: – 14″ M3 MacBook Pro (... Read more
Amazon is offering $170-$200 discounts on new...
Amazon is offering a $170-$200 discount on every configuration and color of Apple’s M3-powered 15″ MacBook Airs. Prices start at $1129 for models with 8GB of RAM and 256GB of storage: – 15″ M3... Read more
Amazon is offering a $200 discount on 14″ M3...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $150-$200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go, so be sure to check their site often if the model you... Read more

Jobs Board

Solutions Engineer - *Apple* - SHI (United...
**Job Summary** An Apple Solution Engineer's primary role is tosupport SHI customers in their efforts to select, deploy, and manage Apple operating systems and Read more
*Apple* / Mac Administrator - JAMF Pro - Ame...
Amentum is seeking an ** Apple / Mac Administrator - JAMF Pro** to provide support with the Apple Ecosystem to include hardware and software to join our team and Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.