This file contains the code for my OS/2 Developer Article: Issue: July/August 1994 Article: An Example OS/2 C++ Class Library System Page: 52 Author: Dean Roddey CompuServe: 72170,1614 This file kind of contains a grab bag of code examples with some explanatory text. Keep in mind that they are pulled out of context from a large, very integrated system so it might not always be obvious what is going on. But, since I came to computers via music, I can type a blue streak and so tend to comment pretty heavily. Also keep in mind that this is a work in eternal progress, so the comments might occasionally not perfectly reflect the code and there might be some incomplete functionality in places. Here are a few notes to help translate: 1) There are a number of .Dlls involved, but all of the code here will come from CIDLib.Dll and CIDGui.Dll (the kernel and GUI encapsulating Dlls.) 2) In my parlance, a Dll or Exe module is a Facility. For the most part a Dll is just passive code to be used but also often needs a proactive 'agent' that offers more proactive services. These are called 'Facility Objects', facCIDLib and facCIDGui in the examples. 3) All non class types exported from a facility are placed into a facility types structure, tCIDLib and tCIDGui in the examples. So they would be references (for example) as tCIDLib::CARD4 for a 4 byte cardinal value. 4) My class system has a single root (except for a very few small exceptions.) All derived classes override a couple of standard methods (via a macro called STDVPUBMETHODS) that provide my own style of runtime type identification. It provides the bIsA(), bIsDescendantOf(), bIsSortable, clsIsA(), and clsParent() methods. 5) The logging system is very integrated. When a message is logged and its severity is greater than APIFAILED, then it is stored on the THREAD object of the calling thread. The called method will return a FALSE, and the calling thread can examine the stored error if it cares why the failure occured. If the severity is PROCESS_FATAL or higher, then the log call will never return directly. Instead the logging method will throw the error object (CIDERROR) as an exception. If the exception is not handled, it will filter up to the start of the thead inside the THREAD class and terminate the application. All classes can format info about themselves to a string, so the logging system allows resource string loading, replacement of tokens in the message with actual object info, storing of the error on the THREAD, and exception throwing for fatal errors all in a single call. 6) WINDOW is the base class of the window system. All classes that are encapsulations of PM classes are derived from PMCTRLBASE. 7) All of the development is under CSet/2++ and its associated development tools (but not Workframe which I don't like.) 8) I am an ardent supporter of HPFS so all of the file names are long and mixed case. But, I understand that you might not be in the same position, so they have been renamed. The original names are in the headers of each file. So the files listed below are by the original names. For the zip file, I just tossed the CIDGui_ or CIDLib_ prefix and used as much of the rest of the file name as possible. Here is a list of the files in this directory: 1) CIDGui_Base.Hpp/Cpp These files contain the POINT and AREA classes. These are very simple but very useful. 2) CIDLib_Process.Hpp/Cpp These files contain the THREAD class. This is the kernel oriented thread class. GUITHREAD is derived from it, but just provides a small amount of extra functionality. 3) CIDLib_Exception_.Hpp/CIDLib_Exception.Cpp These files contain a nice exception handler that works in conjunction with the THREAD class. Each new class object installs this exception handler. It will trap serious exceptions and log them to disk along with a trace of all the calls that it took to get there. This is a semi- ripoff of an example on the Developers CD-ROM, but it is is very much slimmed down to what it practical to do in the field without debug info being available. 4) CIDGui_Paintbrush.Hpp/Cpp These files contain the PAINTBRUSH class, which is the wrapper around the PM Presentation Space. 5) CIDGui_Window.Hpp/Cpp These files contain the WINDOW class. 6) CIDGui_Dialog.Hpp/Cpp These files contain the DIALOGWND class discussed at length in the article. 7) Most classes have a nul reference defined, so WINDOW will have a define that is: #define NUL_WINDOW (*(WINDOW*)0) 8) There is a THREAD class and a GUITHREAD class, the latter of which is allowed to do GUI oriented stuff. facCIDLib will return a pointer to the calling thread's thread object as a THREAD. facCIDGui will return a pointer to the calling threads thread object as a GUITHREAD (or log a fatal error if the calling thread is not a GUI aware thread, which prevents a common OS/2 problem with non-GUI aware threads calling PM oriented APIs without being aware of it.) 9) I use hungarian notation (rare for C++ I guess.) However, the ability to derive classes makes it needlessly worrisome to create a new prefix for all derivatives (unless they offer radically unique functionality), so I tend to use 'family prefixes.' So I often use str for all string derivatives or wnd for all window derivatives. This is also necessary since the whole point of C++ is to use polymorphism to write to the lowest level class that provides the necessary functionality. 10) The ability to have a related popup menu is built into the WINDOW class so that all windows have that capability. 11) I don't use OS/2 or PM types directly outside of the facility that encapsulates them and seldom inside them either. They are are all redefined as enums or constants. 12) You might find my style very funkey. I have spent a lot of time on this issue and have never let habit drive the style of my system. It is oriented towards readability and getting everything lined up vertically as much as possible and getting everything on a tab stop when possible. Feel free to drop me a note. I might not respond if I get too bogged down with it, because this is just a funtime sideline for me and I can't afford to spend massive amounts of time on it. But, if you have a legitimate question and need help or want to offer suggestions, then feel free. This code is, of course, presented as is with no warranties of any kind. It cannot be used directly in a commercial product (difficult without the rest of the code anyway) but the ideas can freely be stolen for use.