This file is the start of a wxMac Developers Guide. Written by Cecil Coupe (ccoupe@simplot.com) with additions from Bill Hale and Tomaso Paoletti, and Matthew Flatt
Color QuickDraw
32 bit addressing - so you require a 68030/68040 or PowerPC.
Floating point hardware will help (probably a lot).
Enough memory for your C++ compiler to handle large programs.
You will want 20MB of free space in order to run the sample applications, 40MB free would be easier to deal with.
1. If you are lucky, you downloaded a self extracting stuffit archive. Simply double click on the icon and StuffIt will ask where to put the Folders and files.
2. If you don't have the .sea or .sit versions of the distribution, but instead have a file ending in .tar.Z, .tar.gz, or .ZIP (or .zip), you need to acquire the following programs for your Macintosh:
3. If you don't understand both steps 1 and 2, (and even if you don't need #2) you will have a extremely steep learning curve ahead of you. I'm sorry, but that is how it is in the cross platform world.
By now you've untarred/unzipped/unstuffed the archive, you might have read the README files, and you've already tried to build the system with CodeWarrior or Think-C++. MPW aficionados just modified the Makefile and tried it. You probably wouldn't be reading this unless you had a problem. Lets try it again, from the archive/zip/tar file (you did make a copy, right).
You should decide whether you want to use MPW, CodeWarrior, or ThinkC++. They can all coexist in the same set of folders, but life will be so much better and easier if you chose one now and stick with it throughout your wxWindows exploration.
For 68k compilation, you must make sure that the library and all applications are compiled with the same prefs settings. As distributed, the projects build for 4 byte ints, 8 byte doubles, and no floating pt HW (that is 4i/8d). If you wish to change this you will also have to add the appropriate libraries into the project in place of the 4i/8d's that are there.
If all works well (no fatal compile errors) you can try the sample programs located in the "samples" directories. Drill down into samples:hello. Loaded it - I happen to like using the Finder to open the :samples:hello: folder and double clicking on the hello.ppc.[[pi]].
Although, the 'minimal' program is even simpler than 'hello', if hello doesn't run for you, well its a long and winding road...
Louis Birk, Matthew Flatt, Scott Maxwell and Greg Whitehead joined the project, each with real applications that they wanted to port. Each contributed serious development effort for wxMac.
Given the different perspectives it should be no surprise that there are different stylistic tactics taken in various wxMac modules. So be it, We offer no apologies.
You must define a class that is publicly derived from wxApp. You can name this derived class whatever you want. For the following, I will name it "MyApp". In this class, you must declare a public method which will override the pure virtual method "OnInit" that is declared in the class wxApp. Then, at the minimum, we will have the following in a header file called "MyApp.h":
#include "wx_main.h" // should really be called "wx_app.h" class MyApp: public wxApp { public: wxFrame* OnInit(void); };
You must implement the publicly derived class of wxApp that you have just defined. At the minimum, we will have the following in a source file called "MyApp.cc":
#include "MyApp.h" wxFrame* MyApp::OnInit(void) { ... ... ... }You must finally declare and define a procedure "CreateApp" which the main program will call to create the object that you have derived from the class wxApp. You must use the name "CreateApp". It should be placed into the source file created in step B) above. The code that you need is as follows (where you should replace "MyApp" with the name of your derived class):
void CreateApp(void); void CreateApp(void) { new MyApp; }
As distributed, this workaround is not enabled. If you need it, in wx_main.cc, in the main() function is a line
// CreateApp(); // This procedure initializes the whole applicationSimply uncomment this, and apply the work around above to your application.
The purpose of the wxArea objects is to allow a parent wxWindow object to have different origins for its children wxWindow objects.
A wxWindow object contains wxArea objects. These wxArea objects are nested. Each wxArea object has margin values (left, top, right, and bottom) which specify where the next wxArea object is situated. Each wxArea object contains wxWindow objects. These wxWindow objects are positioned within the wxArea by an offset value (X, Y). The wxArea object is clipped by the inner sibling wxArea objects (not coded yet). The child wxWindow objects are clipped by the parent wxArea object.
The width and height of a wxArea object is calculated from the width and height of its parent wxWindow and from the margins of the outer sibling wxAreas.
Example:
width 200 ---------------------------------------------- | area A 2 | wxWindow parent | |---------------------------------------| | | | area B 20 | | | | | | |2 | |--------------------------------| | 2| | |10| area C |16 | | height 100 | | | | | | | | |--------------------------------| | | | | 5 | | | |---------------------------------------| | | 2 | |---------------------------------------------|
Suppose the wxWindow parent has width 200 and height 100.
Suppose the area A has (l, t, r, b) = (2, 2, 2, 2).
Suppose the area B has (l, t, r, b) = (10, 20, 16, 5).
Let area C be the automatically generated client area, with (l, t, r, b) = (0, 0, 0, 0).
Then, the width and height of area A is 200 and 100. The width and height of area B is 196 and 96. The width and height of area C is 170 and 71.
Children wxWindow objects of area A are positioned with respect to area A origin; children wxWindow objects of area B objects are positioned with respect to area B origin; and, likewise, for area C. In effect, these children wxWindow objects of the parent wxWindow have different origins within the wxWindow parent.
You can look at the code for wxText (best) and wxFrame for examples of creating areas for a wxWindow object in addition to the automatic client area.
So, wxWindows contain areas and pointers to areas. Some Areas contain pointers to wxWindows. Be aware that the order of destructors is somewhat confusing and problematical.
Up until wxMedia, wxCanvas always managed the scrollbars for you. If your drawing extended far enough, the scroll bars kicked in, and scroll bar actions were automatically excuted on the drawing area.
Unfortunately, this doesn't work well enough for editing text documents. The first reason is that scroll steps need to be correlated with lines of text. The second reaosn is that the size of a text document can easily exceed the short-integer-based drawing areas of many platforms.
SetScrollbars is supposed to configure properties of the scrollbar that are used for automatic scrolling. It is also the way to turn scrollbars on or off. So, we added the extra Bool flag to SetScrollbars to turn the scrollbars on without turning on automatic management.
The new methods - SetScrollPos, SetScrollRange, etc. - were added to give direct control over the scrollbars. Why wasn't SetScrollbars sufficient? I don't remember.
Finally, OnScroll was added to allow manual handling of scrollbar events.
In simple terms, this hack detects that your program creates a "Help" menu with a wxMenuItem of "About" and that you added this menu to the menubar with something like: menubar->Append(help_menu, "Help"); Yes, this is not inter-nationalized, just English.
When wxMenuBar::Append sees this, it saves away the wxMenu ptr and the Mac Item Number. These are used in the wxApp::doMacInMenuBar() [wx_app.cc] to trigger whatever callback function you set up to handle Help/About. I'm actually proud of this, but I know that it is weak. You can disable a couple of lines in wx_app.cc to remove its effects, although the additional memory lingers.
If you really want to find leaks (and they are there), and if you have access to MPW's canon tool, you can replace calls to 'new' with calls to DebugNew's 'NEW', set the appropropriate #define and recompile. You should do this on a copy of the project, because your doing a global search and replace and they can be troublesome to undo. See the CodeWarrior Doc for DebugNew (probably on the CD).
There is a library project, wxMac161 PPC (debug) that can be used for leak testing. It uses a different .pch file, 'wxDebugHeaders.pch) which builds the library and one of two precompiled headers, either 'wxDebugHeadersPPC' or 'wxDebugHeaders68K'. Then in the project for the application set preferences/C++ Language/prefix file: to be wxDebugHeadersPPC (or 68K). 12 leaks is normal for minimal.cc and 25 leaks for hello.cc To help track drown other leaks I've included a file of patches to make to Metroworks DebugNew. See file DebugNew.patch and Hello.cc which has lots of code that trys force and or find leaks. Ugly but effective.
SetSize() for wxWindows and its subclasses is a little mysterious and has significant implications if you want to write or understand the controls (wxButtons, wxListBoxs ...) The only SetSize() you need is in wx_win.cc (for class wxWindow). wxItems (buttons, etc.) should not define this function!!! Instead a window or item needs to define an OnClientAreaDSize() method. It works like this - When an application like hello.cc calls SetSize(), the method in wxWindow is used (because no one overrides it). wxWindow::SetSize() ventures off into the wxArea's code and eventually the Window's or Item's OnClientAreaDSize() method is called. This is where the control (ie wxItem) needs to modify its position and size according to the semantics of wxMac and OnClientAreaDSize().
Paint() is a method of many classes. By default (wb_win.h,) Paint() calls OnPaint() so for the application developer, Paint() is just a way to trigger OnPaint(). Starting with the 'a5' release, there should not be any methods named Paint() either inside wxMac or your app either. Inside wxmac the various wxItems' OnPaint() methods depend upon being able to call wx_win.cc/OnPaint() and they do so with an explicit scope operation.