Feedback Search Top Backward Forward
EDM/2

Porting STEP02 to ICLUI

Written by Kenton W. Shaver

 

Introduction

This article describes the translation of Gavin Baker's STEP02.C to the IBM's C++ libraries for PM (ICLUI). Hopefully it will assist the programmer who is now learning these libraries or is attempting such ports of their own.

The result - CLOCK.EXE - requires the C-Set++ DLLs to run, as it is linked dynamically. A slightly modified copy of the original program that will compile under C-Set++ is also included so that the reader can conduct their own performance analysis and browsing sessions with the original program and the resulting port, if desired.

Scope

I'm assuming that you have read Gavin Baker's article in volume 1, issue 2,that you basically understand Presentation Manager programming, and that you have perused the recent articles here appearing about ICLUI [by Gordon Zeglinski, in volume 2, issue 1 - editor] detailing the IEvent, IWindow, and the IHandler classes, etc. Some important issues will be mentioned again for easier retention.

Overall Structure

In the ported program, a main window is created which in turn creates a client window, a menu window, and an object window for its own use; with the exception of the object window, this is what the original program does also. The object window launches a thread in charge of keeping time and updating the main window's client window at one second intervals. The messages exchanged between the frame window and its object window don't figure for much, though, especially since no easy method to thread the message processing loop of the class myObjectWindow is provided; this device is left in place for illustration.

The two other classes introduced here modify IFrameHandler so that it processes WM_SYSCOMMAND events and the creation of another IHandler class capable of processing WM_QUERYTRACKINFO events.

The program itself does basically the same thing as STEP02.C did, with the exceptions that it uses DosSleep() instead of WinTimer() to provide the timer support and it subclasses the frame window so that it cannot be resized below certain dimensions.

Subclassing

What do we mean when we say that our program uses subclassing? Do we mean subclass in the C++ sense, or in the PM sense? In the C++ sense, we might be indicating that we have used inheritance in our program, while in the PM sense, we are saying that we have replaced an existing window procedure, thus modifying the behavior of the object in question.

Our program does the latter, as illustrated by the following snippet:


Boolean mainWindow::trackAction(queryTrackEvent &qte)
{
   IWindow::defaultProcedure(qte);
   grabMinTrackSize(qte).x *= 3;
   grabMinTrackSize(qte).y *=5;
   return true; // don't call defaultProcedure again!! thanks
}

A member function of an IHandler derived class returns true when no further processing of an event is needed. This subclassing method returns true each time it is called because it has already called IWindow::defaultProcedure(), IBM's C++ equivalent of WinDefWindowProc().

Because of this method of subclassing, WinSubclassWindow() isn't needed - that's all there is to it.

Window Procedures in ICLUI

When looking at the definition of the myObjectWindow class, we see that it only needs a dispatchHandlerEvent() procedure to handle events. This member can make no assumptions about what type of events it will be getting.

In contrast, command() can assume that it will only be sent WM_COMMAND events, systemCommand() can be sure it will only get WM_SYSCOMMAND events, and trackAction() will only be called on to handle WM_QUERYTRACKINFO events. These methods don't need to look at the event ID, but in the case of myObjectWindow::dispatchHandlerEvent(), we have to actually look at the event ID and use a switch block.

The About Box

step02.gif

Figure 1) CLOCK.CPP about box

Modifying the original about box presents little trouble. First, STEP02.RES is loaded into the Dialog Editor. Be sure to specify MSGDEFINES.H as included in your resource file. We will rename STEP02.RC to CLOCK.RC to distinguish the old from the new.

Now, since we are not going to have any children of aboutBoxClass - the class we'll represent the about box with in our program, it would certainly be okay to inherit from IHandler and then define a new dispatchHandlerEvent() method to process the few messages that an about box is concerned with; since all of them will be WM_COMMAND messages anyway, we'll inherit handler functionality from the ICommandHandler class.

In either case, IHandler::handleEventsFor() initiates event processing.

General Porting Cautions

If you undertake a port of your own from C to C++ and the UI libraries, it might save time to note several items.

  • C++ has keywords that C doesn't, such as class. Be sure you leave the #include statement outside of extern "C" blocks that you create and that you have the \TOOLKT21\CPLUS\OS2H path specified in the environment variable INCLUDE. If you use the C includes in your program, you might encounter compile-time errors caused by leaving these additional reserved words in.
  • Be sure to include IHandler or an IHandler descendant along with such IWindow-derived classes as IObjectWindow and IFrameWindow, whether it be by ancestry or by membership.
  • If you register both IFrameHandler and ICommandHandler they will both call your command() method, and WM_COMMAND event processing will happen twice in instances where a false is returned indicating that the event wasn't processed. For example, if you just mark the occurrence of "Open file..." menu selections with squawk(), each selection of this menu item will be noted twice if both ICommandHandler and IFrameHandler are active.
  • It is a good idea to copy the #define statements showing the hexadecimal numbers of the messages that you are using in your program. "grep" or another such tool will easily extract definitions of the window messages such as WM_CLOSE from your \TOOLKT21\CPLUS\OS2H directory if need be.
  • The definition of the TRACKINFO is copied from the headers because it isn't included with what PM header information we use [this is included if you #define INCL_WINTRACKRECT before #include-ing . Copying from the header files should be avoided whenever possible to minimize the amount of program maintenance when the definitions change - editor].
  • Any programs that use the IThreadMemberFn<> template must be compiled and linked to handle templates. If you use this template class and tell C-Set++ to ignore template information, your program will compile and run as normal but it won't create the desired additional threads!