How do I?- by Eric Slaats

Hi Again. Welcome to the second column on PM programming. In this column simple Presentation Manager programming problems and philosophies will be discussed. This Column is aimed at people who are interested in PM programming or are simply curious what makes PM programs tick. To understand this column, a little programming experience (preferably in C++) is recommended.

Last month we looked at the event paradigm. This means messages. It was also explained how messages are sent to and handled by windows. A few messages like WM_QUIT were mentioned in the previous column.

This time we'll take a closer look at some messages. While we're still in the process of setting up a basic application window, we'll take a look at two messages used in the creation of a frame window. The basic program we created last month will be used as a starting point for our new explorations. After this article we'll be able to create a simple control in our frame window (actually on the client area) and size/place it appropriately.

Get the message?

First let's refresh our memories. Messages are data-structures that are sent to a window procedure (queue at first) upon an event. For example, a button-click, a mouse-click on a window or the resizing of the window. Messages can also be sent to a certain window by a program, to invoke a certain action. For example, if we would like to know the currently used font in an MLE control (MLE is the Multi-Line-Edit control; it's the control the e.exe editor is build around), we could send the MLM_QUERYFONT message to that MLE. The message would return this information to us.

Most of the time however, messages are the result of an event and by letting our window procedure act upon these messages we can have some influence on how events are handled.

Creation messages

In our basic program we created a frame window (actually 5 windows that are glued together) with a call to WinCreateStdWindow. All the things that happen because of that call can be seen as events in the OS/2 system. This means there are messages we can act upon when a window is created.

We do have a choice in this: we don't have to handle the messages, there is always the possibility to let the default window procedure handle these messages. We will take a look at two messages that can play a key roll at window-creation time. (Note that there are more messages that we can use in the frame creation process. These messages are more complex and won't be discussed yet.)

1) WM_CREATE

The first message we discuss is a message that always occurs in frame window creation. This is the WM_CREATE message. This is the first message a window will receive after its initialization. At the moment this message is received, the window isn't visible yet and doesn't have a size or place on the desktop.

What do we normally do with the WM_CREATE message? Well, there are a number of possibilities.

What happens next? After the window has been created, it should be placed on the Desktop with a certain position and size. Mainly we're interested in the size. If we obtain the size, we're able to resize and position the button we created. If a window is resized (giving it its initial size is also resizing), the PM will send a WM_SIZE message.

2) WM_SIZE

The WM_SIZE message is mostly used to resize the controls in the client-area, but it can also be used to prevent a window from being sized beyond or over a certain size. The example we work out here is giving the button a size and place. We want the button in the center of the client area. This means we have to reposition the button every time the main window is resized. This is no problem because every time this happens a WM_SIZE is sent. So with one piece of code we can handle the creation situation as well as the resizing. If we used the info in CREATESTRUCT during WM_CREATE we would have to write two code pieces, one for creation and one for sizing!

Besides *placing the button in the middle of the client area* we want it to have a size 1/3 of the cx and cy of the client area.

The WM_SIZE message gives us just the information we need to do this. The WM_SIZE message passes the old window-size in mp1 and the new window-size in mp2. We're interested in the new window size. (Note: This is the size of the client-window, not the frame itself!)

In the previous article the MPARAM message parameters were discussed. These parameters were ULONG variables. (A ULONG is a 32 bit variable.) The cx and cy (x and y size) are shorts (16 bit). The mp1 and mp2 of the WM_SIZE are composed of two shorts and therefore make a ULONG. We can retrieve the two shorts out of this one ULONG with so-called helper-macros. The helpermacros we need are SHORT1FROMMP and SHORT2FROMMP. So *to get* the values for place (within the client area) and size of the button we can use these macros.

To set the position and size of the button we'll use the WinSetWindowPos API. Through this API a window can be sized, moved, made invisible etc. We will only use it to resize and move the Button. The complete code for our little experiment looks like this:

case WM_SIZE:
     {
     short x = SHORT1FROMMP(mp2)/3;
     short y = SHORT2FROMMP(mp2)/3;

     WinSetWindowPos(hwndButton,        // Place and size button
                     HWND_TOP,          // ONTOP in Z-order
                     x,                 // x coord
                     y,                 // y coord
                     x,                 // cx size
                     y,                 // cy size
                     SWP_SIZE|SWP_MOVE);// Change size|move en Show
     }
break;
Try to figure out how this works. It would be advisable to look up the precise working of WinSetWindowPos. This is a really great API.

To see how this code performs, take the example .exe file (ZIP, 13.7k) and resize the frame window in a number of different ways. You'll see that the Button always is displayed in the middle and that it's sized to 1/3 of the height and 1/3 of the width.

Concluding Notes

In this article we've seen a way to set up a control in a client window and size it according to the size of the frame window (client area). In most cases however, the client area will contain only one control, the main working space of you application. For example, an edit control, a spreadsheet control, a drawing control, etc. Dialog boxes that give applications the opportunity to have a specialized interaction with the user aren't created in the way we described in this article. (Usually dialogs can't be sized anyway!)

I hear some of you thinking, "how about menus, statusbars, toolbars, etc.?" Well, there are ways to implement these controls as part of the frame-window-conglomerate. This has the advantage that we don't have to provide the sizing, etc. In a future column I will take time to investigate and explain this.

Next month however, we will take a look at a way to add some extra controls to our frame window. This will be simple menus and scroll-bars. For now, if you have any comments, please let me know. Of course kudo's are also welcome (grin).


Eric Slaats holds a degree in Computer Science and teaches computer technology in Eindhoven. He is the creator of the Smalled utilities.

[Index]  [® Previous] - [Feedback] - [Next ¯]

[Our Sponsor: Best of OS/2 - News, demos, over 150 products, Hobbes Report and more!]


This page is maintained by Falcon Networking. We welcome your suggestions.

Copyright © 1996 - Falcon Networking