This book is a guide to the lesser-documented and less-well-known aspects of OWL, such as multiple threads, TThread , thread-synchronization objects, .HLP files, the CLASSLIB support libraries, Doc/View, and more. We also talk a bit about how OWL can integrate with other languages, such as Visual Basic (VB) or Delphi, and how you can make debugging your OWL applications easier.
If you're a bit disappointed that this book doesn't cover some of the more "hard-core" OWL classes in greater detail, take heart--this book is being released concurrently with its companion volume, Core OWL 5.0, which investigates those classes which are in 99% of all OWL programs: TModule , TApplication , TWindow , the various OWL 5.0 controls, and so forth. This in turn leaves this book to focus on the aspects of OWL that are undocumented, but are still useful and highly (in my opinion) underutilized. If it seems that I've chosen a fairly shallow subject for this book, don't be deceived--there's still a lot that I didn't cover in either book, for reasons of space available. What you hold in your hands is, I believe (along with Core OWL 5.0), the finest "after-the-basics" book on OWL available on the market.
This book is organized as follows:
Chapter 1 is a simple reintroduction to OWL, and the benefits to be gained by using OWL versus doing things the old, hard, C/SDK way. This is really more of a warm-up than anything else, and helps to set the tone for the rest of the book. I also take a few moments to explain where and how all of the new material I discuss in this book might fit into our Hello, World application.
Chapter 2 is a comprehensive dive into the OWL support libraries, ClassLib and WinSys. We talk about the subdivision of OWL into the user-interface, ClassLib, WinSys, and Services components, and go over some of the lesser-known classes in ClassLib and WinSys in greater detail. Some of the ClassLib components, such as multithreading objects, we save for later.
Chapter 3 brings up the subject of C++ mixin classes and moves into the OWL mixins. Mixins are components reused by inheritance, and, while more or less unknown, OWL provides some pretty interesting mixins that may make your application that little bit more powerful.
Chapter 4 takes a left turn into the wonderful world of Help. Specifically, context-sensitive help. Along with the rules and regs on how to make OWL's context-sensitive help system respond to your whims, we also explore the neglected art of how to build a WinHelp file, and talk briefly about how this will change for future versions of Windows and NT.
Chapter 5 explores the possibilities of multithreaded programs and the OWL support for them. We investigate the OWL synchronization objects, thread objects, and discuss the ramifications of this preemptive multitasking message-based GUI operating system we're all stuck with. This chapter will be inapplicable to users still coding under Win16.
Chapter 6 takes us into the realm of menus and TMenu . Considered by some user-interface experts to be something of an anachronism, menus and menubars are still considered an essential part of any serious Windows application. In this chapter, we'll dive into what makes a menu a menu, and how we can customize the appearance of your menus to make your users shiver every time they fire up your app.
Chapter 7 examines a few of the undocumented OWL classes, ones that generally don't get much press or much of the glory. Some will deal with error modes, some will deal with user-interface painting, and some will deal with multimedia capabilities.
Chapter 8 peers into the murky waters of the OWL Doc/View architecture. This is probably the most widely misunderstood portion of OWL, and will probably elicit the most amount of confusion in your OWL applications, but once you understand the Doc/View model and how OWL applies it, your applications will become easier to understand and far more powerful to extend.
Chapter 9 talks about that lovely subject of debugging your OWL applications, and provides a variety of tricks and ideas that you may or may not have known when you picked up this book. We also talk about exception handling, both at the language level and the OS level.
Chapter 10 makes a stab at world peace by showing you how OWL can be made to get along with other languages and other technologies. In an increasingly interconnected world of computer networks, it is no longer acceptable to isolate yourself in one language or one environment; here we'll talk about how you can integrate your OWL code with Delphi, Visual Basic, even Java, as well as take advantage of Win32 remote procedure calls (RPC) to build true client/server apps.
Chapter 11 is a collection of questions and answers (ones which I thought might be bothering you but not worth the email bandwidth to ask about). Loosely grouped into sections, this chapter has no other order to it than the order in which I thought of the questions.
Finally, the various appendices provide some "supplemental" text, such as the new features of C++ (since version 2.1), and how to build the BIDS and OWL libraries. Certainly not required reading, but you may want to sto by, take a look, and see if anything catches your eye.
What's not covered
Many times, it is as important to know what isn't covered in a book as to know what is. In this case, due to size limitations, several key technologies from OWL are not covered: none of the graphic display interface (GDI) classes ( TBrush , TPen , etc.) are covered, nor is printing, nor print preview. While there may be some who immediately set this book back on the shelf for my decision to skip those two subjects, this was a conscious decision on my part. I couldn't cover everything. OWL is a huge system, and there's only so much this 2-volume book can cover. I tend not to use GDI or printing in my professional work (the last three projects I've done have all been client/server with a graphical user interface (GUI) frontend and a database backend), and while this may not be the world's most scientific study, empirical and anecdotal evidence seem to tell me that GDI isn't something that all OWL developers use; controls and windows and dialogs and menus and applications are.
This is not the place to find discussions of the heart and soul of OWL 5.0. The place for that is Core OWL 5.0, the companion volume to this book. (The accompanying CD contains all the source code for both books, just to give you a quick glance at what's covered in the other book.) Naturally, this doesn't stop us from taking a deep look into a particular class or system if it relates directly to our discussions in this one, so you needn't fear that you have to own both books in order to make sense of this one.
A brief history
It always helps to know where you've been before you can know where you're going.
Time: Fall 1985 Windows 1.0 is released to the public, to a tremendous yawn, or belly-flop, if you prefer. In a time when 80286/12MhZ machines with a full 1MB RAM are top of the line, Windows is an incredible memory hog, not to mention slower than a snail in low gear headed uphill in an avalanche. Nobody's really interested, except maybe Petzold, and it takes him two years to produce the first Programming Windows edition.
Meanwhile, a language expert at AT&T has just made the first external release of a new language, C++. It is greeted with some speculation, some excitement, some trepidation. By his own estimation, Bjarne Stroustrup estimated that about 500 people were using C++ at this point. Not exactly what you'd call a tidal wave of users, but still 499 more than when he began work in October 1979.
Time: Spring 1990 Windows 3.0 is released to a tremendous explosion of interest. Over the next several years, sales of Windows 3.0 will break every software sales record the industry recognizes. Microsoft begins its domination of the software industry. Petzold releases a new version of Programming Windows, and becomes a programmer's household name. Entire generations of programmers are ingrained in the ways of WndProc and WNDCLASS , and Windows programming is hard. Very hard, to be exact. Remember to lock your blocks. Don't use large model. Oh, and don't forget your MakeProcInstance() calls.
At the same time, Borland makes its first commercial release of Turbo C++. Good timing, too, because Stroustrup estimates about 150,000 people are using his new language. The Annotated Reference Manual, or the Brown Book, the C++ bible, releases in the same month, describing C++ 2.0, which was released the previous June.
Some visionaries have already started thinking about how best to mix C++ and Windows, but it's still on the drawing board. A few forays are made, but nothing really takes steam.
Time: Spring 1992 Windows 3.1 is released to the public, and the sales records keep breaking. Petzold makes his new edition available, and his position as the father of all Windows programmers is reinforced. Stroustrup estimates 400,000 people were using C++ in 1991; he stops counting at that point. Windows programmers, ingrained by repetition, are still locking their memory blocks and minding their ProcInstance() calls and hand-crafted files. But by this point, Microsoft has also made a C++ compiler release, Microsoft C/C++ 7.0, and with it ships the MFC1.0, consisting of sixty-three classes that closely map to the Windows API. Borland, not to be outdone, has already released OWL 1.0 which offers the same promise that MFC 1.0 offers: "Use us. We'll help you forget all about those nasty Windows programming details that you shouldn't have to worry about." Only a few programmers pay attention, and so most of the Windows world continues along the C-driven course, unaware of the power and promise given by C++.
Time: Summer 1993 Windows NT 3.1 is released to the public, to another tremendous yawn. Petzold doesn't even bother writing Programming Windows NT: Joe User is not interested in upgrading his 386/33 with 4MB RAM to a 486/50 with 16MB RAM. Windows 3.1 is still growing, and the C++/Windows wars are taking on a new bent. Borland releases OWL 2.0 with Borland C++ 4.0, and OWL 2.0 corrects what some (including this narrator) see to have been the fatal flaw in OWL 1.0: the Borland extension of Dynamic Dispatch Virtual Tables, a nonportable extension to the C++ syntax that may have made some OWL coding easier, but definitely confused and muddied the waters. MFC also exists in a 2.x version, both on the 16-bit and the 32-bit side. Visual C++ 1.0 was broken into two distinct products, one for 16-bit development and the other for 32-bit development. Microsoft, backed by powerful voices in the C/C++ development media, appears to be winning over Borland and OWL. But the nature of C++ is still transitory, and new extensions are being adopted into the language even as Borland and Microsoft struggle for Windows C++ class library supremacy.
Time: Late 1994, Early 1995 Windows95 is still called "Chicago," and just about everybody and their grandmother has a beta copy. Microsoft shifts its research and development efforts in MFC from the 16-bit side to the 32-bit side, shipping MFC 3.1 with Visual C++ 2.1, the first 32-bit C++ release that didn't simply parallel what was being developed on the 16-bit side. Borland, meanwhile, releases Borland C++ 4.5 and OWL 2.5, but it simply introduces the OCF, which is designed to ease object linking and embedding (OLE) development. Now, somewhat behind Microsoft, Borland struggles to extend and improve OWL to catch up to the perceived gap between the two frameworks. But those who see the potential in OWL, the power in OWL over MFC, quietly work on. They can see OWL's inherent object-oriented design: it has been ported to OS/2, and could easily be ported to other platforms if the demand were there. Microsoft tries the same thing with MFC to the Macintosh and, in this narrator's view, fails horribly, mostly due to the API-wrapping that is the foundation of MFC that fails to allow for a different underlying mechanism to be successfully encapsulated. It doesn't end the hooting of the MFC-proponents, but those who have discovered OWL stick to their guns and wait.
Time: Summer 1996 Windows95 ships, in an almost anticlimactic fervor. Newsweek and Time start carrying Windows95 polls and statistics. One can walk into a fast-food joint just about anywhere in the nation and hear people talking about files and storage and realize they're talking about computers and not those metal things that hold paper. C++ nears standardization, but a new trend starts to emerge, one that is independent of C++, but could have a tremendous impact on the language and its uses. In early 1995, Design Patterns is published, bringing to the average C++ programmer the power of the emerging idea of patterns. Microsoft shipped Visual C++ 4.0 and MFC 4.0 (so named because the new release was "so good as to warrant a jump in the version numbers"), and Borland's answer only now comes forth. Borland C++ 5.0, codenamed Vulcan, ships, and OWL 5.0 answers every challenge laid down by MFC 4.0, as well as issuing a few of its own. Unlike Microsoft, which introduces nonstandard C++ syntax within Visual C++ to cover its own problems within MFC, [1] Borland relies only on standard C++, and even breaks itself into separate layers to make OWL more portable to other compilers and other architectures.
Suddenly, Windows programming isn't so hard anymore. Matter of fact, it is downright ... fun.
Time: Now The heresy begun in 1993 with OWL 1.0 gains strength. OWL 5.0 stands as a classic example of encapsulation and architecture-hiding, being inherently portable between both Windows 3.1 and Win32 (Windows95 and WindowsNT), something not even MFC can claim. (16-bit MFC development ceased in July 1995.) OWL 5.0 finds a loyal flock eagerly awaiting the chance to plumb its depths and explore its capabilities and to push it to the edge of the envelope.
A final word
As you begin to flip through the book and absorb what I have written here, remember that I, like any other human being on the face of this planet, am not perfect. If something I've done seems to contradict your experience, by all means, doubt me. Test the code, walk it through the debugger, and arrive at your own conclusions. My goals in writing this book were simple: to help the average OWL developer open his or her eyes and see beyond the basics that most OWL books feel inclined to present. There are places where I stray off the beaten path, just to show that it can be done. Some of the techniques and ideas presented here may not be of immediate assistance to you, but it's my hope that showing you those techniques and ideas will help lead to a solution that enables you to fix that bug, work around that OWL limitation, or even add that feature that last week seemed impossible.
In the event that you do find a bug, or even want to contest an idea, feel free to contact me. I can be reached on the OWL mailing list, to which you can subscribe by sending email to netlab.cs.rpi.edu , which has a majordomo mailing list server running; this is probably the most reliable way of reaching me, and it's entirely possible (if not probable) that the other folks on the OWL list will be able to answer your questions. All levels of questions are welcome--from the most basic ("Um, what's a TFrameWindow ?") to the most technical ("What's that Capture member of TGadgetWindow used for, anyway?"). You should also be able to reach me through the book's Web page, at http://www.browsebooks.com .
As Jeffrey Richter said in Advanced Windows and Windows95: A Developer's Guide, although only his name appears on the front cover of his book, there are many others whose name should appear there. No truer words were ever penned by an author. In fact, if everybody's name that should be on the cover of this book were put there, there'd be no room left for the title, much less any cover art! And although an author's acknowledgments can often run longer than an Oscar speech, please bear with me and give me the moment I need to sufficiently thank all of them.
To begin with, I must thank my places of employment during the development of this book, Access Health Incorporated (Rancho Cordova, Calif.) and Ibex Technologies (El Dorado Hills, Calif.). The folks at both places were gracious and kind during difficult moments, and their support was greatly appreciated. Fabio, Ed, Keith, Bruce, is it time for basketball yet? Thanks also to the folks at Borland; without them, there'd be nothing to write about. Moreover, thanks specifically to Nan Borreson and Brian Meyers, who were kind enough to hear all my questions and struggle to find answers for them.
Thanks must also go to the folks at Manning: Marjan Bace, Ted Kennedy, Mary Piergies, all of whom struggled to work with this first-time author. Thanks, guys, for your patience and guidance. Your help and faith were invaluable.
Thanks, too, to the folks on the OWL mailing list; never once did they ever doubt that this would be a great book, and their confidence in me lifted my spirits right when it was needed. Not only that, but many were kind and gracious enough to allow code ideas of their's to be included in the CD at the back. If you're looking for a place to bring your OWL questions, the list is a great place to start. Rich, Gianni, Jack, Michael, Brian, Bruce, and many others, you are all great people, and I hope I've managed to live up to your expectations.
When I first began this project, I sent email to several book authors to see what sort of life book-writing was all about. One in particular responded to my queries in an eloquent and concise fashion, and now not only do I owe Bjarne Stroustrup a favor for inventing the C++ language, but for his comments and (repeated) answers to my questions. You'll be happy to know, Bjarne, that my marriage survived the book(s) and is doing well.
Thanks must also go to the men and women working the front lines at Lyon's Restaurants of Davis, Calif. (restaurant 469). Without them, you would be staring at the palm of your hand right now. When the time came to do writing, writing, and more writing, they kept me well-stocked with Diet Coke as I sat in the booth, laptop plugged into the ceiling, banging away at the keyboard, for hours on end. Thanks to Harry, Leonard, Damien, Janelle, Ben, Della, Barbara, Amy, Chad, Jennifer, Carolyn, and more. I couldn't have done it without you. Literally.
It seems that every author has to thank his parents, and I'm no different. What an author thanks them for, however, can be many things. I thank them for being who they are, so that they could rear me with the kind of love and affection and support they've shown me over all these years, not to mention their good consumer sense--sixteen years ago, it was a decision between an Apple Plus with 48K RAM, or a new Volvo. They came home with the Apple, and the rest is history. To my sister, JJ, also, I owe a great debt of gratitude--without the loan of her laptop computer, I really doubt I could have gotten the book written in time. To all of you out there looking for (or knowing somebody looking for) a wonderful actress and theater lead, I know just the woman.
Thanks must also go to Ron "The Younger" Reynolds, for many things, not the least of which is his ability to put up with me while I write a book. Without Ron's criticism and (mostly) constructive comments, this book would have been a much poorer work, and the code a lot buggier.
But most importantly, I must thank my wife, Charlotte, and my three-year-old son, Michael, for their unending support and love. With Michael, it was a little difficult at first adjusting to Daddy's constant "here-but-not-here" presence on the computer as I wrote the code, but once he discovered that computers can be fun too, he was a constant companion in the study. Sounds of Living Books' "Green Eggs and Ham" and "Dr. Seuss's A-B-C" wafted through the air to mingle with the sounds of tortured C++ code being hacked away. Thanks, Michael, and yes, Daddy can come read a story to you now. You've earned it. My wife, on the other hand, was forced to run the house by herself during the four months I was down at Lyon's pounding out page after page of text, and through it all her love and her support for the project was boundless. It has been said that behind every great man stands a great woman; in this case, behind this book stands a wonderful wife. I cannot express in words the gratitude and love I feel for this woman; I love you, honey, and thanks.
And now, on to the good stuff.
What is even more distressing is that this very case is already covered by C++'s currently existing syntax, using the placement new operator: CObject* ptr = new (ptr) CObject (arg1, arg2, arg3, ...);