Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Tools

A Presentation Manager Application Template


MAR89: A PRESENTATION MANAGER APPLICATION TEMPLATE

A PRESENTATION MANAGER APPLICATION TEMPLATE

Here's a PM application template that can be used as the starting point for your PM programs

Herbert Schildt

Herb Schildt is the author of more than two dozen computer books, with topics ranging from C to Modula-2. This article is an adaption from his book OS/2 Programming: An Introduction. He can be reached at RR #1, Box 130, Mahmomet, IL 61853.


Beginning with version 1.1, OS/2 has included the Presentation Manager (PM) as the default user interface. The Presentation Manager provides the user with a windowed, graphical interface in which much of the functionality of the system is readily displayed on the screen, thus making the operation of the computer more intuitive than that of the traditional command line interface. As you will see, however, the ease of end-user operation has a price: the extra time and effort it takes to create a PM-compatible program.

This article explains the general operation of a Presentation Manager application program and develops a Presentation Manager application template in C. Programs compatible with the Presentation Manager share a common structure. The elements shared by these PM-compatible programs are examined here. The PM application template shown at the end of this article can be used as the starting point for your own programs.

I chose C for this article, because C is the de facto language for OS/2 and Presentation Manager. There are two main reasons for this. First, C was the only language available when OS/2 was released. Second, the OS/2 API services strongly resemble the C standard library functions and appear to be optimized for it. The code in this article was compiled with Microsoft C, Version 5.1, using the Microsoft OS/2 Software Developer's Toolkit version of OS/2 and the Presentation Manager. With minor changes, however, the code should be able to be compiled using any OS/2-compatible C compiler.

What Is the Presentation Manager?

Technically, the Presentation Manager is a user-interface shell that runs on top of the OS/2 operating system base. From a programming point of view, however, the Presentation Manager virtually appears to be the operating system. This is because the Presentation Manager provides several hundred Application Program Interface (API) services, which, to a large extent, replace those provided by the basic OS/2 system. From the programmers's point of view, the Presentation Manager is one giant toolbox of interrelated services that allows the creation of application programs that share a common interface. For many PM-compatible programs, the original OS/2 API services are irrelevant.

The goal of the Presentation Manager is to enable an end user who has basic familiarity with the system to sit down and run virtually any application without prior training. So in theory, if you can run one Presentation Manager program, you can run them all. In actuality, of course, most useful programs will still require some sort of end-user instruction, but at least this instruction can be restricted to what the program does, not how the user must interact with it.

Not every program that runs under Presentation Manager will necessarily present the user with a PM-style interface. As the programmer, you can override the basic Presentation Manager philosophy; but if you do, you had better have a good reason, because otherwise the users of your programs will be disturbed. If you are writing application programs for OS/2, they should conform to the general PM application interface philosophy if they are to be successful in the marketplace.

One more important point: Because the Presentation Manager must have complete control of the screen, a PM-compatible program will not be able to use any of C's standard console input or output functions. This means, for example, that your PM-compatible programs should not call get( ) or printf( ). In fact, one reason there are many PM API services is that a large amount of the C standard library had to be rewritten when window support was introduced.

Let's look at a few of the more important features of the Presentation Manager.

The DeskTop Model

With few exceptions, the point of a window-based user interface is to provide the equivalent of a desktop on the screen. On a desktop you may find several pieces of paper, one on top of another, often with fragments of different pages visible beneath the top page. The equivalent of the desktop in the Presentation Manager is the screen. The equivalents of pieces of paper are windows on the screen. On a desk you can move pieces of paper about, maybe switching which piece of paper is on top or how much of another is exposed to view. Presentation Manager allows the same type of operations on its windows. By selecting a window you can make it current, which means putting it on top of all other windows. You can enlarge or shrink a window, or move it around on the screen. The Presentation Manager lets you control the surface of the screen the way you control the surface of your desk.

The Mouse

Unlike DOS and the original version of OS/2, the Presentation Manager allows the use of the mouse for almost all control, selection, and drawing operations. Of course, to say that it allows the use of the mouse is an understatement. The fact is that the PM interface was designed for mouse input: It allows the use of the keyboard! Although it is possible for an application program to ignore the mouse, it does so only in violation of a basic PM design philosophy principle.

In general, to activate a feature, move the mouse pointer to that feature and double-click the left mouse button. A double-click is achieved by pressing the button twice in rapid succession. Presentation Manager allows you to drag objects around by moving the mouse pointer to the object, pressing and holding the left button, and moving the mouse pointer and object to a new location.

Icons and Graphic Images

The Presentation Manager allows (but does not require) the use of icons and bit-mapped graphic images as a means of conveying information to the user. The theory behind the use of icons and graphic images is found in the old adage "A picture is worth a thousand words."

An icon, in OS/2 terminology, is a small symbol that is used to represent some function or program that can be activated by moving the mouse to the icon and double-clicking on it. A graphic image is generally used to simply convey information quickly to the user.

Menus and Dialog Boxes

In addition to standard windows, the Presentation Manager also provides special-purpose windows. The most common of these are the menu and dialog boxes. Briefly, a menu is a special window that contains only a menu from which the user makes a selection. Instead of having to provide the menu selection functions in your program, however, you simply create a standard menu window using PM services.

A dialog box is essentially a special window that allows more complex interaction with the application than that allowed by a menu. For example, your application might use a dialog box to input a filename. With few exceptions, nonmenu input is accomplished in the Presentation Manager via a dialog box.

General Operation of a PM Application

There is one important point that you must fix in your mind: A PM application program's flow is fundamentally different from a "normal" application. You will need to abandon any preconceived notions of how information moves in and out of your program as well as what constitutes a program's main loop. Before we look at any concrete PM services or examples, let's look at the theory behind all PM-compatible programs.

PM Application Theory

Programs that are compatible with the Presentation Manager share a common skeleton. In its most straightforward implementation, when the program begins, it performs the following functions, in the order shown.

  • Initializes the Presentation Manager relative to the program
  • Establishes a message queue
  • Registers a special function, referred to as the window function, which receives input from the Presentation Manager;
  • Creates a window of the registered class; and
  • Executes a loop, which reads messages from the queue and dispatches these messages to the window function, which takes appropriate action.

The window function (sometimes called wind-proc or windowproc) is a special function that is called only by the Presentation Manager, not by your program. It receives, in its parameters, a message from the message queue, established in the second step. It then takes different actions based upon the value of each message. (We will look at messages in a moment.)

In a very real way, a PM application program is functionally similar to an interrupt-driven program. At any point in time, the program may receive a message from the Presentation Manager to which it must respond. For example, your program might be told to refresh its screen or that the user has made a menu selection. The point is that a PM-compatible program is event driven. If you have never written interrupt-driven programs, then programming for the Presentation Manager will require that you adjust the way you think about your programs and their execution.

When a PM application ends, it must perform these three steps:

    1. Destroy the window.

    2. Destroy the message queue.

    3. Terminate the window environment relative to the application.

The Message Loop

Except for creating and destroying the windows required by your program, generally the only other thing that the main() function does is receive and dispatch messages. To accomplish this it uses a loop that looks something like this:

while (program is still running) {   get a message;   send the message to the proper window; }

Essentially, the Presentation Manager communicates with your program by putting messages into its message queue. Your program then extracts a message from the queue and dispatches it to the proper window by calling another PM service. This process continues until the program is terminated. For the most part, messages are the only way in which your program receives input. (Remember, a PM program cannot, for example, call scanf() to read input from the keyboard.) Although the form of a message varies somewhat, depending upon what type of message it is, all messages are integers. Now that you know some of the theory behind the Presentation Manager and its windows, let's look at some specifics.

Obtaining an Anchor Block Using WinInitialize

One of the first things that you will want your PM application to do is to obtain an anchor block handle by calling WinInitialize, whose prototype is shown here.

void far * WinInitialize (unsigned short handle)

Here, handle must be NULL. Notice that the function returns a void far pointer, which points to the region of memory used by the Presentation Manager to hold various bits of information about the window environment relative to the application program. This region of memory is called the anchor block, and the pointer to it is called the anchor block handle. If the system cannot be initialized, a NULL is returned. The anchor block handle is required as a parameter by many PM services.

Unlike the core API services, which generally return 0 for success, many of the PM services return 0 (NULL) on failure.

(The Microsoft OS/2 Software Developer's Kit has defined a great many type names. For example, they have defined USHORT as an unsigned short integer. I do not use the Microsoft-type names in this article, however, for two reasons. First, when learning about a new environment, it is important to know exactly what type of data you are dealing with. Although the type names defined by Microsoft are convenient, they disguise the nature of the actual data. Second, and more important, all the type names defined by Microsoft are copyrighted by Microsoft. Hence, other OS/2C compilers may not be able to provide them.)

Creating a Message Queue

After initializing the window system, all PM applications must create a message queue using WinCreateMsgQueue, which has this prototype:

  void far *WinCreateMsgQueue(void far *anchor_block, unsigned short size);

The anchor_block is the handle obtained using WinInitialize. The size of the queue is determined by the value of size, or, if size is NULL, then the system default is used. Generally, the system default queue size is acceptable.

Each element in the message queue is contained in a structure, called QMSG by Microsoft, defined like this:

  struct {
        void far *hwnd;               /* handle of the recipient window */
        unsigned short msg;           /* the message */
        void far *mp1;                /* additional message info */
        void far *mp2;                /* additional message info */
        unsigned long time;           /* time message was generated */

  POINTL ptl;                         /* position of mouse pointer */

  }QMSG;

The POINTL structure is defined like this:

    struct {
       long x;
       long y;
    } POINTL;

WinCreateMsgQueue returns a handle to the message queue or NULL if the request fails.

Registering a Window Class

Before you can actually create a window, you must register its class using WinRegisterClass, whose prototype is shown here:

  unsigned short WinRegisterClass (void far *anchor_block,
  char far *classname,
  (pascal far *window_func)(),
  unsigned long style,
  unsigned short storage_bytes)

Here, anchor_block is a pointer to the anchor block. The string pointed to by classname is the name of the window class being registered. This may be any name of your own choosing. The address of the window function must be passed as the third parameter. The style of the window is specified by style. Finally, the number of bytes of additional storage beyond that needed by the window is specified by storage_bytes. Your program may use this extra storage for its own purposes. For the example in this article, this field will be 0.

The sort of window being registered is described by the value of style. The only style that we will be using in this article has the value 4L and is defined as CS_SIZEREDRAW in the PMWIN.H header file provided by Microsoft. Using this style causes the Presentation Manager to inform your program each time the window is resized. The WinRegisterClass service returns nonzero if successful and NULL on failure.

Creating a Window

Once you have initialized the window system relative to your application, created a message queue, and registered the class, it is time to create a window.

All Presentation Manager windows begin with a frame, which is essentially a box. Onto this frame are added a number of optional, but desirable, additions. In OS/2 these additional features are actually windows in their own right, which are attached to the frame. It is easier, however, to think of them as options to the frame. Let's look at these options now.

There are two options that are virtually essential to all windows. The first is the border. The border is important because it allows the user to move or resize the window using the mouse. The second is the system menu. The system menu is a standard menu that, minimally, allows the user to perform the following operations: restore the window to its original size, move the window, resize the window, minimize or maximize the window, and close the window. Although the border allows a more convenient method of moving or resizing the window, these operations can also be activated from the system menu. When a window is minimized, it is shown in its iconic form and is moved to the icon region of the screen. Your program can specify what the iconic form of a window will look like or simply let the system decide. When a window is maximized, it takes over the entire screen. Closing a window removes it from the screen, and if this is the program's top-level window, it terminates the program.

Most of the time you will also want to add three other features to your windows: maximize icons, minimize icons, and a title that identifies the window. Although it is possible to maximize and minimize the window using the system menu, it is quicker if the maximize and minimize icons are available, because the user can activate them by clicking on them with the mouse. When the screen holds several windows, a title is almost necessary in order to remind the user which window is which.

Finally, if applicable to your program, you will want to add vertical and horizontal scroll bars to the window. By clicking on the appropriate points on these scroll bars, the user causes the contents of the window to scroll up, down, left, or right. The region enclosed by the frame and used by your application program is called the client area.

The organization of a standard PM window is shown in Figure 1. (Remember, not all options will necessarily be found on all windows.) Each PM-compatible program creates at least one main window. A main window is at the topmost level. The main window is the one that the user associates with the program. Closing the main window terminates the program.

There are two general categories of windows: parents and children. It is possible to create a window inside of another window. In this case the newly created window is a child of the main window and is enclosed by the parent. A Child window can, in turn, create a child of its own, and so on up to the limits imposed by the size of the screen.

Each window is associated with a class. There are several built-in classes, such as menus, frames, scroll bars, and the like. Windows that you create, however, will need to be given class names, and these classes must be registered with the Presentation Manager. All windows define the lower left corner as location 0,0. The maximum X and Y dimensions are dynamically defined as the window changes size and shape. The maximum, however, is determined by the resolution of the screen.

Using WinCreateStdWindow

The easiest way to create a window is to use WinCreateStdWindow Presentation Manager Service. Its prototype is shown here:

  void far *WinCreateStdWindow(void far *parent_handle,
      unsigned long style,
      void far *frame_data;
      char far *classname,
      char far *title,
      unsigned long client_style,
      unsigned module,
      unsigned short resource,
      void far **client_handle);

The parent_handle must be the handle of the parent window. When a program begins execution, its parent is the screen, which has 1 for its handle. Microsoft defines this value by the macro HWND_DESKTOP. The value of style determines how the window will first appear. Its most common values are shown in Figure 2, along with the macro names given them by Microsoft.

Figure 2: The most common values for the WinCreateStdWindow-style parameter.

  Macro Name               Value                       Meaning

--------------------------------------------------------------------

  WS_VISIBLE          0x80000000L           make window visible
  WS_MINIMIZED        0x01000000L           minimize window
  WS_MAXIMIZED        0x00800000L           maximize window

The value pointed to by frame_data sets various flags that detemine how the window will behave. This value can be any combination of the values shown in Figure 3, along with the macro names given them by Microsoft.

Figure 3: The values for the frame_data parameter to point to.

  Macro Name                Value              Meaning

---------------------------------------------------------------------------

  FCF_TITLEBAR          0x00000001L        include title bar
  FCF_SYSMENU           0x00000002L        include system menu
  FCF_MENU              0x00000004L        include user menu
  FCF_SIZEBORDER        0x00000008L        include sizing
  FCF_MINBUTTON         0x00000010L        include minimize icon
  FCF_MAXBUTTON         0x00000020L        include maximize icon
  FCF_MINMAX            0x00000030L        include both min and max icons
  FCF_VERTSCROLL        0x00000040L        include vertical scroll bar
  FCF_HORZSCROLL        0x00000080L        include horizontal scroll bar

The classname parameter points to the string that identifies the class. This should be the same string that was used in the call to WinRegisterClass. The string pointed to by title will be used as the title of the window for identification purposes. For most purposes the client_style parameter should be 0L, indicating that the client window should be of the same style as the window class.

The resource and module parameters are used to identify a resource module. For the examples in this chapter, no resource modules are needed, so these parameters should be NULL and 0, respectively. A handle to the client window is put in the handle pointed to by client_handle. The WinCreateStdWindow service returns a handle to the frame if successful and NULL on failure.

WinGetMsg and WinDispatchMsg

To process messages, your program will require the use of WinGetMsg and WinDispatchMsg. The WinGetMsg() prototype is shown here:

 unsigned short WinGetMsg(void far *anchor_block,
    QMSG far *message,
    void far *window,
    unsigned short first,
    unsigned short last)

The message retrieved from the queue is put in the queue structure pointed to by message. If window is not NULL, then it causes WinGetMsg to retrieve messages directed to only the specified window. Most of the time your application will want to receive all messages. In this case window should be NULL. All messages are integers. The first and last parameters determine the range of messages that will be accepted by defining the end points of that range. If you wish to receive all messages, then first and last should both be zero.

The return value of WinGetMsg is important. It returns true unless a termination message is received, in which case it returns false. This is the way your program will know it is being terminated.

In most situations, once a message has been received it is simply dispatched to the correct window without further processing by your program within the message loop. The service that sends messages along their way is WinDispatchMsg, whose prototype is shown here:

  void far *WinDispatchMsg(void far *anchor_block, QMSG far *message)

By calling this function the message will automatically be routed to the proper window function. WinDispatchMsg returns the value returned by the window function.

Program Termination

Before your program terminates, it must do three things: Close any active windows, close the message queue, and deactivate the window system interface created by the WinInitialize service. To accomplish these things the Presentation Manager provides the services WinDestroyWindow, WinDestroyMsgQueue, and WinTerminate. Their prototypes are shown here:

  unsigned long WinDestroyWindow(void far *handle_window);
  unsigned long WinDestroyMsgQueue(void far *handle_msgQ);
  unsigned long WinTerminate(void far *anchor-block);

Here, handle_window is the handle of the window to be closed. The handle_msgQ is the handle to the message queue to be destroyed. And the window system is disconnected by calling WinTerminate with the anchor block handle.

The Window Function

As mentioned earlier, all programs that are compatible with the Presentation Manager must pass to the PM the address of the window function that will receive messages. This function must be declared as shown here:

  void far * pascal far window_func(void far *handle,
       unsigned short message,
       void far *param1,
       void far *param2);

The window function receives the PM messages in its parameters. In essence, the PM sends your program a message by calling the window function. The value of handle is the handle of the window receiving the message. The message itself is contained in the integer message. Finally, some messages require further information, which is put into the param1 and param2 parameters.

The Presentation Manager can generate several different types of messages. Some of the more common ones are shown in Figure 4, along with the macro names assigned to them by Microsoft.

Figure 4: Some common messages.

  Macro name                     Value            Meaning

---------------------------------------------------------------

  WM_BUTTON1DOWN            0x0071        button 1 down
  WM_BUTTON1UP              0x0072        botton 1 up
  WM_BUTTON1DBLCLK          0x0073        double click on button 1
  WM_BUTTON2DOWN            0x0074        button 2 down
  WM_BUTTON2UP              0x0075        button 2 up
  WM_BUTTON2DBLCLK          0x0076        double click on button 2
  WM_BUTTON3DOWN            0x0077        button 3 down
  WM_BUTTON3UP              0x0078        button 3 up
  WM_BUTTON3DBLCLK          0x0079        double click on button 3
  WM_CHAR                   0x007A        keystroke occured
  WM_CREATE                 0x0001        window has been created
  WM_DESTROY                0x0002        window is being destroyed
  WM_ERASEBACKGROUND        0x004F        OK to erase background request
  WM_HSCROLL                0x0032        horizontal scroll
  WM_MOVE                   0x0006        window is being moved
  WM_MOUSEMOVE              0x0070        mouse has moved
  WM_PAINT                  0x0023        window display needs to be refreshed
  WM_SHOW                   0x0005        window is shown or removed from  the screen
  WM_SIZE                   0x0007        window is being resized
  WM_VSCROLL                0x0031        vertical scroll
  WM QUIT                   0x002A        window being terminated

The window function does not need to explicitly process all the messages that it receives. In fact, it is common for an application to process only a few types of messages. What happens, then, to the rest of the messages received by the window function? They are passed back to the PM for default processing using the WinDefWindowProc service. Its prototype is shown here:

  void far *WinDefWindowProc(void far *handle,
      unsigned short message,
      void far *param1,
      void far *param2)

As you probably guessed, the WinDefWindowProc simply passes back to the Presentation Manager the parameters with which it was called.

Putting Together the Pieces

Now that you have seen services needed to initialize and run a simple windowed application template, it is time to put together the pieces. The program shown in Listing One (page 81) creates a window that includes a system menu, a title, a sizing border, and scroll bars. You can move the window around the screen, minimize or maximize it, and change its shape. For the moment, don't concern yourself with the window function, window_func( ); it will be explained shortly.

The program can be compiled using Microsoft C, Version 5.1, using the OS/2 Software Developer's Kit. You may need to make some small changes if you are using a different compiler. Notice that the program defines INCL_WIN. This definition is needed to cause the prototypes and definitions for the window system to be loaded if you are using the Microsoft C compiler. Before you try to compile this program, read the next two sections.

The Definition File

A definition file is used to specify various options that affect your program. All definition files end with the .DEF extension. If you have been working with OS/2 for a while, then definition files are probably no stranger to you. (A detailed discussion of definition files is beyond the scope of this article, but the interested reader will find coverage of this topic in my book OS/2 Programming: An Introduction (Berkeley, Calif.: Osborne/McGraw-Hill, 1988). But unlike many non-PM-compatible programs for which a definition file is optional, you must define a definition file in the link line for any PM-compatible program you write. Aside from other reasons, the overriding reason for this is that you will need to specify more stack space for the PM application than it will receive by default. The Presentation Manager template in this article is allocated 4096 bytes, but real world applications may need more or less space. Also, it is a good idea to specify a heap size. Again, I allocated 4096 bytes for this purpose, but your programs may need a different amount of space. You must also include an EXPORTS statement in the file that specifies the name of the window function. The definition file for the template is shown in Listing Two (on page 81).

Compiling PM Programs

You will need to specify some different compiler options when compiling a Presentation Manager program than you did for a standard program. You can use this batch file if you are using the Microsoft C compiler:

  cl -c -G2sw %1.c
  link %l,,, os2, %1.def;

The -G2sw option tells the compiler to use a 32-bit address for all code and data references, to turn off stack checking, to assume that the value of the DS register is different from the one in SS, and to generate 80286 instructions. Because the Presentation Manager requires, minimally, an 80286 processor, there is no harm in generating 80286 instructions. (It is possible that you will have to use a different set of options even if you are using Microsoft C, because of future changes to the compiler or the PM environment.)

Understanding How the Template Works

The operation of the main( ) function is straightforward. It initializes the link between the Presentation Manager and the program, registers a new window class, creates a window, and executes its message loop. As messages are received they are dispatched to the window_func( ) by calling WinDispatchMsg. The message loop terminates when the WM_QUIT is received. This message is generated by choosing the close option in the window's system menu.

In a PM application, the most important single function is the window function. It receives the messages sent by the PM and takes appropriate action. The template shows entries in the switch statement for only the most common of the several messages that can be generated by the PM. (Keep in mind that any message that your program does not wish to process must be passed back to the PM via the WinDefWindowProc service.) Let's look at the meaning of some of these messages.

When a window is created, the WM_CREATE message is sent to the window function. This allows your program to initialize values or to perform other startup operations. As you know, the Presentation Manager allows the user to move and resize windows. It also allows the user to cover part of a window with another. These operations imply that all or part of the window must be redrawn at some point in time. The PM generates the WM_PAINT message whenever the contents of the window must be refreshed. One common misconception about the Presentation Manager is that it handles the reconstruction of a window that has been overlaid. The truth is that your program must reconstruct its own window whenever the WM_PAINT message is received.

The WM_ERASEBACKGROUND message tells your program that the window needs to be erased, perhaps because the window is being moved. By returning TRUE, you are allowing the PM to do this for you. Otherwise your program must do it.

Each time a key is pressed, the WM_CHAR message is generated. Each time the user requests a vertical scroll, the WM-VSCROLL message is generated. Each time a horizontal scroll is requested, the WM_HSCROLL message is generated. The mouse messages are self-explanatory.

When you run this program, a window will pop up. This window can be resized, moved, minimized, or maximized. Other than those basic window operations, the program does nothing else.

Because this program is a template for future applications, it does not do anything with the messages. But your applications will need to. Also, keep in mind that when your program does not actually need to concern itself with a message, such as a program that does not have scroll bars, its message can be removed from the switch statement. In this case the default processing will handle it.

_A PRESENTATION MANAGER APPLICATION TEMPLATE_ by Herbert Schildt

[LISTING ONE]

<a name="0086_001c">


/* A Presentation Manager Application skeleton. */

#define INCL_PM

#include <os2.h>
#include <stddef.h>  /* get definition of NULL */

void far * pascal far window_func(void far *, unsigned short,
           void far *, void far *);

char class[] = "MyClass";

main()
{
  void far *hand_ab;
  void far *hand_mq;
  void far *hand_frame, far *hand_client;
  QMSG q_mess;
  unsigned flags = FCF_SYSMENU |
        FCF_SIZEBORDER | FCF_TITLEBAR |
        FCF_VERTSCROLL| FCF_HORZSCROLL |
        FCF_MINMAX;

  hand_ab = WinInitialize(NULL);

  hand_mq = WinCreateMsgQueue(hand_ab, 0);

  if(!WinRegisterClass(hand_ab,   /* anchor block */
         class,     /* class name */
         window_func,   /* address of window function */
         CS_SIZEREDRAW, /* window style */
         0))        /* no storage reserved */
     exit(1);

  hand_frame = WinCreateStdWindow(HWND_DESKTOP,
        WS_VISIBLE,
        (void far *) &flags,
        (char far *) class,
        (char far *) "My Window",
        0L,   /* resource modules */
        NULL,
        0,
        &hand_client); /* client handle */

  /* message loop */
  while(WinGetMsg(hand_ab, &q_mess, NULL, 0, 0))
    WinDispatchMsg(hand_ab, &q_mess);

  WinDestroyWindow(hand_frame);

  WinDestroyMsgQueue(hand_mq);
  WinTerminate(hand_ab);
}

/* This is the window function. */
void far * pascal far window_func(void far *handle,
                 unsigned short mess,
                 void far *parm1,
                 void far *parm2)
{

  switch(mess) {
      case WM_CREATE:
   /* Perform any necessary initializations here. */
      break;

    case WM_PAINT:
   /* Refresh the window each time the WM_PAINT message
      is received.
        */
      break;

    case WM_ERASEBACKGROUND:
   /* By returning TRUE, the PM automatically erases
      the old window each time the window is resized
      or moved.   Without this, your program must
      manually handle erasing the window with it changes
      size or location.
   */
      return(TRUE);

    case WM_CHAR:
   /* Process keystrokes here. */
      break;

    case WM_HSCROLL:
   /* Process horizontal scroll request.  */
      break;

    case WM_VSCROLL:
   /* Process vertical scroll request. */
      break;

    case WM_MOUSEMOVE:
   /*  Process a mouse motion message. */
      break;

    case WM_BUTTON1DOWN:
   /* 1st mouse button is pressed. */
      break;

    case WM_BUTTON2DOWN:
   /* 2nd mouse button is pressed. */
      break;

    case WM_BUTTON3DOWN:
   /* 3rd mouse button is pressed. */
      break;

    /* If required by your application, you may also need to
       process these mouse messages:

      WM_BUTTON1UP
      WM_BUTTON1DBLCLK
      WM_BUTTON2UP
      WM_BUTTON2DBLCLK
      WM_BUTTON3UP
      WM_BUTTON3DBLCLK
    */
  }
  /* All messages not handled by the window_func,
     must be passed along to the PM for default
     processing.
  */
  return WinDefWindowProc(handle, mess, parm1, parm2);
}




<a name="0086_001d"><a name="0086_001d">
<a name="0086_001e">
[LISTING TWO]
<a name="0086_001e">

NAME skeleton
HEAPSIZE 4096
STACKSIZE 4096
EXPORTS window_func












Copyright © 1989, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.