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.
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.
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.)
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.
WM_CREATE
message arrives, you'll know the window is being created. A number of settings your program uses can be retrieved at that time from the OS2.INI or a private INI file. These values can then be used in further processing.
WM_CREATE
message receives a pointer to a CREATESTRUCT
. This structure contains all the parameters that were involved in the creation of the window and a number of them we used in the WinCreateStdWindow
call. The CREATESTRUCT
looks like this:
typedef struct _CREATESTRUCT { PVOID pPresParams; // Presentation parameters. PVOID pCtlData; // Control data. ULONG id; // Window identifier. HWND hwndInsertBehind; // Window behind which the window is to be placed. HWND hwndOwner; // Window owner. LONG cy; // Window height. LONG cx; // Window width. LONG y; // Y-coordinate of origin. LONG x; // X-coordinate of origin. ULONG flStyle; // Window style. PSZ pszText; // Window text. PSZ pszClassName; // Registered window class name. HWND hwndParent; // Parent window handle. } CREATESTRUCT;We can use this information for further initiation if we want to. Note that all this information can be obtained by querying the window, but by caching it (keeping it at hand), you could achieve some performance improvements. (I should note here that I've seldom seen programs that do this.)
WM_CREATE
message contains a pointer to the so-called controldata (CTLDATA
). This structure has a different form for every window-class (control) OS/2 provides. It can be used to take a few shortcuts (save lines of code) when setting up controls like buttons etc. (Note: we're not that far yet, we're still in the process of creating a simple frame window.) In future columns the CTLDATA
will emerge again when we take a look at simple controls. The keyword here is LAZY. Don't do anything yourself which the system can do for you.
WM_CREATE
message is to set up controls in the client area. Most applications operate this way. ***In our example of this month we will set up a Button in the centre of the Client area. We can do this by using the following code:
WinCreateWindow(hwnd, // Parent handle (Client area) WC_BUTTON, // Window class (Button) "This is a button",// Window text WS_VISIBLE | BS_DEFAULT, // Button flags 0, 0, 0, 0, // client window has no size or position at this point hwnd, // Owner handle (Client area) HWND_TOP, // Z-order ontop 100, // Window ID 0, // Control 0); // Presentation ParametersThe API call used to do this is the
WinCreateWindow
API. This is call that will create a single button. (Note that the WinCraeteStdWindow
creates a complex set of windows.) Stuff like parents and owners as well as Z-order and Window ID's will be explained next month. For now it's essential that we notice that there are four 0's where the x, y, cx and cy parameters are. These parameters are used for sizing and placing a window. The client area at this point has no size or place, so giving the button a size or place in this window has no meaning at all. For example it could be placed out of the boundaries of the client window and thus be invisible and unreachable.WM_SIZE
message.
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.
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).
[Our Sponsor: Best of OS/2 - News, demos, over 150 products, Hobbes Report and more!]
Copyright © 1996 - Falcon Networking
This page is maintained by Falcon Networking. We welcome your suggestions.