Mastering Dialog Windows in Xbase++ Part 1 - Terminology And Window Types Copyright © 2002-2008 Clayton Jones |
by Clayton
Jones (with thanks to Greg Doran for his assistance with research) Revised November 19, 2008 |
Introduction |
One
of the great things about Xbase++ is how it presents the underlying
Windows API to us in a more simplified and easier to use interface.
This is never more true than when working with dialog windows. In
WIN32 API SuperBible by Richard Simon1, the introduction
to Chapter 3 "Creating Windows" states "There is only one function needed
to create windows, the CreateWindow function, which is the most
complex function in the Windows API". An attempt to
study the chapter will validate his statement - it is quite complex and
challenging to grasp. Fortunately for us, Xbase++ distills this complexity down to several basic parent/owner configurations and some optional attributes, with which we can easily create many different kinds of interfaces in our applications. However, these window types are not as clearly documented as they could be, and as a result there is some confusion and misunderstanding on this subject in the Xbase++ community. When I first began working with Xbase++ (summer, 1997), I had a very difficult time understanding the different types of windows and how they worked. Many of the terms used in discussion groups were not defined in the documentation and were often used in more than one context. Nowhere in the documentation was there a thorough explanation of the window hierarchy. It was very confusing and it took a long time to grasp the concepts - much longer than it should have. Since that time, in addition to writing applications, my involvement
with Xbase++ has included the development of Top-Down Library and its
Tutorial, writing articles, conducting training sessions, and speaking at
developer conferences in Europe and the US. All of these activities have involved teaching, in one form or another.
I saw that new people beginning to use Xbase++ were
having the same difficulties I had. A great many of us are not C/C++
programmers, and I was motivated to find a
way to make an easier transition into the language for "the common mortal". Over time, as I
learned more and developed new methods, I kept searching for new and better ways of explaining the
concepts and techniques. |
The First USA DevCon, New Hampshire, 2001 |
When I was asked to
speak at the DevCon I knew immediately what the subject would be. I
had developed good techniques for controlling window behavior and, most
importantly, a set of terms had evolved during training sessions which had proven very effective for conveying
the concepts. I pulled all the pieces
together into a presentation for the conference and it received a very
positive and enthusiastic response.
With urging from several people who
attended the DevCon, I decided to expand the material into a
series of web page articles, with the hope that it will help to clarify
the subject and help new users get productive more quickly. |
The Articles |
The series of articles will cover the mechanics of windows, the concepts of control, and the role of threads and event loops. Included will be techniques, tips and tricks for achieving the ultimate goal: being able to open as many layers of windows as we need, in any style of architecture, with complete control and predictable behavior. Part 1,this article, discusses the terminology and the definitions of
the six window types. |
AppDeskTop() and SetAppWindow() |
Before getting into the window terminology,
some clarification is needed for these two functions. Because they
are used in the definitions of the different window types, it is important
to define them clearly. |
AppDesktop() |
The AppDeskTop() function returns a reference to
the invisible implicit window (XbpIWindow) which is created by the Xbase++
runtime engine at startup. This is commonly referred to as
"the application desktop" or "the
desktop window". Even though we cannot see it, it plays a
crucial role in the windows hierarchy. |
SetAppWindow() |
There is some confusion about this function
because it serves different purposes in GUI and CRT applications.
The function acts primarily as a Get/Set function, where a dialog window
is passed into it as a parameter. Calling the function later without a
parameter retrieves a reference to the window. In CRT, SetAppWindow() serves an additional purpose of allowing the "set" window to display output. Therefore, it is necessary to pass into it each window that receives focus. This, however, ruins its ability to serve as a Main window reference, since the "set" window is always changing. Since a reference to the Main window is needed for various purposes, it is common to have a separate user defined Get/Set function for that. This is commonly named RootWindow(). In GUI, the Main application window is passed into SetAppWindow() during startup. After that, there is no need to send any other window into it. Therefore, SetAppWindow() serves as the Get/Set function for the Main window throughout the life of the application, and a RootWindow() function is unnecessary. This use is implied in the Xbase++ documentation where there are countless code samples using SetAppWindow() as a reference to Main. Because of the general lack of clarity on the subject of window control, some developers who have moved from CRT to GUI erroneously continue to send different windows into SetAppWindow() in an attempt to control window behavior. Some needlessly convoluted application designs have resulted from doing this. Part 2 of the series will show how this practice is unnecessary, and how complete control of window behavior can be achieved without resorting to it. Once the principles are understood, application design becomes very simple and straightforward. For the remainder of the series, it is assumed that SetAppWindow() always returns a reference to the Main application window. |
Terminology - Sorting Out The Confusion |
Some of the terms presented here are
not "official" terms from any reference book or Microsoft documentation
(those that are, are so noted).
They are strictly for use in the context of Xbase++. Some of them
come from common use, some I made up or adopted. This list is not
presented as an authoritative technical reference, but is offered here solely for the purpose of
giving Xbase++ developers a precise vocabulary so that we can communicate
effectively. |
Top-Level |
The term "top-level" refers to any window that has AppDeskTop()
as both parent and owner.
There can be more than one top-level window open in an application.
Top-level, therefore, is a general term referring to any window with that
parent/owner configuration. It is a good, intuitive term for these windows
since they are the highest ones in the windows hierarchy that are
visible. Top-level is used in this context in a MSDN article by Kyle
Marsh2. Referring to top-level windows, the Xbase++ documentation states that a GUI application can have "several application windows" (bottom paragraph in the topic "Windows and Relationships"). So "application window" is the only documented term synonymous with top-level. However, it has never caught on in common use as a general term. "The application window", as if there is only one, is often used to refer specifically to the primary controlling window of the application, usually called the Main window. |
Main and SubMain |
While there can be more than one top-level window open at
once, only one of them is the primary controlling window
which is created at startup, and which is programmed to terminate the
application when it is closed. This window usually has a menu bar or buttons to launch
other parts of the program. There is an important distinction
between this window and any other top-level windows, and we need some
dedicated terms to indicate which we are referring to. |
Child |
The next primary window type is one that is called from a
top-level window (either Main or SubMain), and has as parent and owner the drawingarea
of the top-level window. The Xbase++ documentation uses the term "MDI
Client" to
describe this window (see
the topic XbpDialog), but it has never caught on. Instead, the term
"Child" has been universally used. Indeed, "Child" is
the name used for this window in Simon, Marsh and Petzold. |
Modal |
The third primary window type is one which has AppDeskTop() as parent and
SetAppWindow() as owner, along with some
other characteristics. The term "modal" is universally
used for this type of window. Unfortunately, because it takes more
than just the parent/owner configuration to make a Modal window, the term
is often used to refer to windows that are not truly Modal.
A general description for Modal windows is found in the Xbase++
documentation for :SetModalState() under the topic for XbpWindow. A
more detailed definition is given in the outline below. |
StepChild |
Main, Child and Modal are the three primary window types
commonly used in applications. In addition, SubMain can be used for
certain purposes. The next secondary type is another variation which has special
characteristics and is used for particular purposes. It has the
same parent/owner configuration as a Modal, but lacks the other conditions
which would make it a Modal window. |
Layered Sibling |
One of the important
techniques discussed in Part 2 of the series is where we call a Child
window from within an existing Child. Technically, these two windows
are identical - they both have the same parent/owner configuration and
behavior.
In actual use, however, there is a difference. Therefore we
need a term which specifically means a Child window used in this manner, as
opposed to one that is called from a top-level window. The term "sibling" is used in the Xbase++ documentation to refer to any Xbase Parts which have the same parent. By definition this includes dialog windows, and it is used similarly in Marsh. So I have adopted the term "Layered Sibling" to describe this special way of using Child windows. This is the last of the secondary window category. |
Stream |
"Stream" is a
term used to describe a group of layered windows running in a
separate thread. Beginning with a Child, any number of Layered Siblings may be called below it, one Sibling calling the next, hence a "stream" of windows emanating from the first one. Any number of Streams may exist at one time. The distinguishing element is that each Stream must exist in its own thread. |
Conclusion |
Top-level, Main, SubMain, Child, Stepchild, Modal, Layered Sibling, Stream |
A
diverse
collection of terms. Together they provide a precise vocabulary
for communication and discussion of window techniques in Xbase++.
With them we can express our ideas clearly and precisely and expect to be
understood. Below is an outline of the window types and
their definitions.
The next article in the series will discuss the pros and cons of
various techniques for achieving multiple Streams of layered windows.
It will encompass the use of these window types and the role of
threads and event loops. |
Six Types of Windows in GUI Applications |
Three Primary Types - Main, Child, Modal |
1)
Definition of the Main Window
Parent = appDeskTop() Parent =
setAppWindow():drawingarea
The primary purpose of a Modal is to disable the rest of the application
Note: In the original version of this article I had a
3rd condition listed here, stating that Modals require event loops.
However, it was brought to my attention that technically this is not correct
and I have
removed it. But it is an important subject and deserves some
explanation. While it
is technically correct that Modal windows do not need event loops (the Main
window is disabled but its event loop continues to process events for the
Modal window), for most practical purposes Modals do need event loops.
The reason for this is that in most cases Modals must behave in a procedural
manner (the flow of program execution must halt where the Modal window is
called and resume when it Returns). An event loop is required for this
behavior. A good example of this is a
dialog which asks the user which of two courses of action to take during a
sequential routine.
AboutBoxes and other Modals called from the Main Menu can do without an
event loop, but this is a small minority of typical Modal windows in a
database program. In addition, there is no harm in having an event
loop in that type of Modal (because a Modal, by definition, is the only
active window, so it doesn't matter). Therefore, for the purpose of these
articles it should be assumed that Modal windows have event loops and behave
procedurally. In real-world day-to-day programming I have found it to
be a
non-issue, and all of my Modals have event loops. I don't even think
about it, it's just a given. |
Three Secondary Types - StepChild, SubMain and Layered Sibling |
4)
StepChild Window - this window is sometimes incorrectly called a Modal or a Child, and
sometimes is called an "owned" window (confusing, because all windows are owned by something).
I chose this name because it describes it well - like a Child, it is
usually called from
Main, but Main is not its real parent, hence, StepChild).
Parent = appDeskTop() Note: This is the same parent/owner configuration as a Modal, only it
does not set the ModalState, b) Cannot be used along with a Child window inside
the Main borders because it covers a Child, c) A StepChild is not disabled by a Modal
(because it is not a child of Main), but it can be d) There are more cautions about this window which
will be covered in Part 2, but
suffice it to say 5) SubMain Window - I chose this name because it is
much like a Main window, but is called Parent = appDeskTop() This has the same parent/owner configuration as the Main window, and both are top-level windows. A SubMain, however, is called from within the Main window and has these constraints and features: a) It must run in a separate thread and have its own event loop or else events get mixed up between b) It is closed automatically if Main is closed
(assuming that Main is programmed to Quit the c) Can be covered up by Main unless the StayOnTop attribute is set. d) It can perform like an independent application
in this manner: 2) It gets a task bar button. 3) It can have a menu. 4) It can have its own child windows using this parent/owner configuration: Parent =
subMain:drawingarea 5) Modals can be called
which disable a SubMain, if it is specified as the owner of the Modal. b) Special purpose routines, such as a print preview window, which can run full-screen and give the |
Part1 - The End |
1
Windows NT Win32 API Superbible, Richard J. Simon, Waite Group Press 2 "Win32 Window Hierarchy and Styles", Kyle Marsh, MSDN Technology Group 3 Programming Windows, Fifth Edition, Charles Petzold, Microsoft Press |
Copyright © 2002-2008 Clayton Jones |
Return to: Articles Page |Top-Down Page | Software And Services
| Home