[ Next ] [ Previous ] | Chapter 10 | [ Contents ] [ Chapter 9: Introduction to Windows ] [ Chapter 11: Window Messages and Queues ]

### Window Management.

A window has many physical characteristics that are controlled both by the user and by the programmer. These characteristics include size, visibility, position, and order. A user can size a window by dragging the sizing border of the window; likewise, the programmer also can size the window by using a function call. A good application will not hinder the user from arranging the windows on the desktop in whatever manner he or she sees fit; however, an application also can provide the user with visual clues at to what actions can and cannot be performed. For example, a "Save" menu item may be disabled when the file is unchanged from its previous state, or a window may be inactive until the user has logged on successfully.
This chapter covers the following window characteristics:

- Visibility/invisible
- Active/inactive
- Sizing
- Z-order

The programming interfaces to change these characteristics are explained and two example programs are included: WINSAVE, a program designed to save the window characteristics at the time the application is closed, WINTRACK, a program that will maintain a minimum and maximum size requirement.

#### Visible, Invisible, Enabled, and Disabled Windows

Presentation Manager supports the idea of a "messy desktop" window arrangement. This means that several windows can be stacked upon each other similar to pieces of paper on a desk. A window that is visible is one that is currently visible on the desktop or that can be uncovered by moving a window that is on top of it. An invisible window is one with the WS_VISIBLE bit not set; the programmer must make it visible before it can be seen. WinShowWindow can be used to make an invisible window visible.

`BOOL WinShowWindow(HWND hwnd, BOOL fShow);`

The first parameter is the window to be made visible or invisible. A value of TRUE for the next parameter indicates the window is to be made visible. FALSE indicates the window is to be made invisible.
A window that is enabled is one that can respond so user input. An application can disable a window by using WinEnableWindow. Items on a dialog box can be disabled from being chosen if the choices are no longer applicable.

`BOOL WinEnableWindow(HWND hwnd, BOOL fEnable);`

The first parameter is the window to be enabled or disabled. A value of TRUE for the next parameter indicates the window is to be enabled. FALSE indicates the window is to be disabled.

#### Window Sizing

The CUA (Common User Access) guidelines recommend that a frame window let the user size and position the window to his or her own specifications. These guidelines are used to help maintain a consistent "look and feel" across all Presentation Manager applications. The CUA specifications are published by IBM and can help a user adapt more easily to a new OS/2 application.
Conveniently enough, Presentation Manager can handle most of this frame manipulation automagically. The frame control flag, FCF_SIZEBORDER. gives the frame window a "sizing border." The user can shape and size the window to his or her heart's content, and the programmer can kick back, relax and let Presentation Manager do all the work. But (there's always a but) the programmer should make sure that the WM_PAINT message processing adapts for the change in window real estate. There are a few ways to keep track of the window size.

- In the WM_PAINT processing, callto return the RECTL structure containing the window size.
- Keep track of the window size by processing the WM_SIZE messages. and store these values in a structure pointed to by a window word.

Suppose a client area contained a graphic that the .programmer wanted to be visible at all the times. One option is to resize automatically the window if the user sizes the window to a a smaller size. A less clumsy option is to restrict the size when the user is adjusting the the border. The following example shows just how to do this.

WINSIZE.C WINSIZE.MAK WINSIZE.DEF | Winsize.exe window

#### Device Independence, Almost

One new feature will be added to main in this example-a mini form of device independence. SVGA is very popular, and supporting both 1024 x 768 and 640 a 480 screen resolutions in your programs can be quite painful. Unfortunately. Presentation Manager does not guarantee that your programs will be dimensioned proportionally at both resolutions. The best way to make your program look great at any resolution is t to size your windows according to the screen size. "But how will I know how big the screen is?" you may ask. The answer Presentation Manager knows all, and you just have to know which questions to ask. WinQuerySysValue is used for exactly that reason.

> `LONG WinQuerySysValue(HWND hwndDesktop, LONG iSysValue);`

HwndDesktop is the desktop window handle, and iSysValue is a constant used to query a specific value. The constants available are too numerous to list here, but are listed in the documentation for WinQuerySysValue.

> `lWidth = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);`
> `lHeight = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);`

This function will provide lots of information about the dimensions of various system components. The values we are interested in are the height and width of the screen, SV_CXSCREEN and SV_CYSCREEN. The value returned from the function is the answer to your query.
Once we know the screen height and width, we use WinSetWindowPos to size and position the window accordingly.

#### Subclassing the Frame Window

`pfnNormalFrameProc = WinSubclassWindow(hwndFrame,`
`SubclassFrameProc);`
`WinSetWindowPtr(hwndFrame,`
`QWL_USER,`
`pFrameInfo);`
`pFrameInfo->lWidth = lWidth;`
`pFrameInfo->lHeight = lHeight;`
`pFrameInfo->pfnNormalFrameProc = pfnNormalFrameProc;`

The frame window must be subclassed in order to alter the default frame window behavior. For more information on subclassing, see Chapter 27. In this program, the old (in this case, the default) frame window procedure is saved, along with the minimum height and width, in the frame window word. Window words were covered in Chapter 9. Remember, some of the system control windows, such as the frame windows, have reserved space for a user-defined window word.

#### In Case of Error, Use the Class Default

> `hab = WinQueryAnchorBlock(hwndFrame);`
> `WinQueryClassInfo(hab,`
> `WC_FRAME,`
> `&classInfo);`
> `pfnNormalFrameProc = classInfo.pfnWindowProc;`
> `return ((*pfnNormalFrameProc)(hwndFrame,`
> `ulMsg,`
> `mpParm1,`
> `mpParm2));`

In case the window pointer is not found, the frame resorts back to its old window procedure. The path to the old window procedure is found by using two very useful functions, WinQueryAnchorBlock and WinQueryClassInfo.

> `HAB WinQueryAnchorBlock(HWND hwnd);`

WinQueryAnchorBlock has only one parameter, the window handle of the window for with to retrieve the anchor block handle. The function returns the handle to the anchor block.

> `BOOL APIENTRY WinQueryClassInfo(HAB hab,`
> `PSZ pszClassName,`
> `PCLASSINFO pClassInfo);`

This function has three parameters. hab is the anchor block handle, pszClassName is the name of the class for which to retrieve the information, and pClassInfo is a pointer to CLASSINFO structure.

> `typedef struct _CLASSINFO /* clsi */`
> `{ ULONG flClassStyle;`
> `PFNWP pfnWindowProc;`
> `ULONG cbWindowData;`
> `} CLASSINFO;`
> `typedef CLASSINFO *PCLASSINFO;`

The structure contains the class style flags, flClassStyle. A pointer to the window procedure, pfnWindowProc, and also the number of additional window words, cbWindowData.

WinQueryAnchorBlock is used to retrieve the anchor block for our message queue. Once we have the anchor block handle, WinQueryClassInfo is called to retrieve the default window procedure for the frame class. Then, this window procedure is executed rather than the subclassed frame window procedure.

#### Tracking the Frame

The WM_TRACKFRAME message controls the sizing of the frame. This message is sent from the title bar to the frame window. When the frame window receives this message, it sends a WM_QUERYTRACKINFO message to itself to query the TRACKINFO structure, which is used to define the boundaries of the tracking (moving or sizing) operation What the example program does is intercept the WM_QUERYTRACKINFO message, fill in the TRACKINFO structure, modify the tracking values that we want to limit, and return TRUE to let the tracking operation continue. The TRACKINFO structure looks like this.

> `typedef struct _TRACKINFO /* ti */`
> `{LONG cxBorder;`
> `LONG cyBorder;`
> `LONG cxGrid;`
> `LONG cyGrid;`
> `LONG cxKeyboard;`
> `LONG cyKeyboard;`
> `RECTL rclTrack;`
> `RECTL rclBoundary;`
> `POINTL ptlMinTrackSize;`
> `POINTL ptlMaxTrackSize;`
> `ULONG fs;`
> `} TRACKINFO;`
> `typedef TRACKINFO *PTRACKINFO;`

The default frame window procedure is called in order to get TRACKINFO structure that is already filled in.

> `pTrackInfo->ptlMinTrackSize.x = pFrameInfo->lWidth/2;`
> `pTrackInfo->ptlMinTrackSize.y = pFrameInfo->lHeight/2;`

Once we have this structure, we modify the ptlMinTrackSize.x and ptlMinTrackSize.y values. We use one-half the screen width and one-half the screen height as the new minimum tracking sizes. The last step is to return mrReply which will be TRUE in all cases, except for errors.

#### Saving Window Settings

Now we're ready to expand a little beyond the basic Presentation Manager program. When the user closes down an application, it is only polite to remember all the changes he or she has made to the frame window. In OS/2 2.0, the developers added two new functions to make it super-easy really to impress your customers - WinStoreWindowPos and WinRestoreWindowPos. These functions store the window size, position, and presentation parameters in OS2.INI file and then retrieve them on demand.

WINSAVE.C WINSAVE.MAK WINSAVE.DEF ####  | Winsave.exe restotes window position.

#### WinRestoreWindowPos

> `bReturn = WinRestoreWindowPos ( SAVE_NAME,`
> `SAVE_KEY,`
> `hwndFrame );`

WinRestoreWindowPos is called right after the frame window is created. This enables the saved changes to be visible right when the window is created.

> `BOOL APIENTRY WinRestoreWindowPos(PSZ pazAppName,`
> `PSZ pszKeyName,`
> `HWND hwnd);`

The first parameter is the application name, placed in the .INI tile. The second is the keyword used in conjunction with the application name. The last parameter is the window to apply the changes to.
If the call completes successfully, WinSetWindowPos will make the window visible and make it the active window.

> `BOOL APIENTRY WinSetWindowPos(HWND hwnd,`
> `HWND hwndInsertBehind,`
> `LONG x,`
> `LONG y,`
> `LONG cx,`
> `LONG cy,`
> `ULONG fl);`

WinSetWindowPos is a very handy function. It is used to position, size, activate, deactivate, maximize, minimize, hide, or restore a window. One of the nice aspects of WinSetWindowPos is its ability to consolidate several function calls into one.

> `WinSetWindowPos ( hwndFrame,`
> `HWND_TOP,`
> `0,`
> `0,`
> `0,`
> `0,`
> `SWP_ACTIVATE | SWP_SHOW ) ;`

hwndFrame is the window to adjust. The next parameter HWND_TOP indicates the position in the Z-order for the window. We've mentioned Z-order before; it's time for a little more detail.

#### X,Y,Z-Order

Presentation Manager supports a concept of piling windows (visually) one on top of another, known as Z-order. The active window and its children are always at the top of the Z-order. Children are ahead of their parents in their position in the Z-order. The window that is at the lop of the Z-order is one in which the user inputs keystrokes and mouse moves.
The next four parameters of WinSetWindowPos are the x coordinate, y coordinate, width, and height of the window. The last parameter is the value of the action flags OR'ed together. If SWP_MOVE is specified, the x, y coordinates are used to move the window to the requested position; if not, these two parameters are ignored. If SWP_SIZE is used, the window is resized to the new height and width; if not, these two parameters are ignored. We'll use SWP_ACTIVATE and SWP_SHOW to show the window, and also to make the frame window the active one.
Readers may wonder why they call these flags SW_. The reason is that a structure used in window positioning is a SWP (or "set window position") structure. The structure is as follows.

> `typedef struct _SWP /* swp */`
> `{`
> `ULONG fl;`
> `LONG cy;`
> `LONG cx;`
> `LONG y;`
> `LONG x;`
> `HWND hwndInsertBehind;`
> `HWND hwnd;`
> `ULONG ulReserved1;`
> `ULONG ulReserved2;`
> `} SWP;`
> `typedef SWP *PSWP;`

After calling WinRestoreWindowPos, either WinShowWindow or WinSetWindowPos with the SWP_SHOW flag should be called.

#### Saving State

> `case WM_SAVEAPPLICATION:`
> `WinStoreWindowPos ( SAVE_NAME,`
> `SAVE_KEY,`
> `WinQueryWindow ( hwndWnd, QW_PARENT )) ;`
> `break ;`

Presentation Manager sends a special message at application shutdown time for the sole purpose of giving the programmer a chance to save the options and settings the user has customized to reflect his or her preferences. This is the WM_SAVEAPPLICATION message. Catchy name. This is the time to call WinStoreWindowPos.

> `BOOL APIENTRY WinStoreWindowPos(PCSZ pszAppName,`
> `PCSZ pszKeyName,`
> `HWND hwnd);`

The parameters for this function are exactly the same as WinRestoreWindowPos.

| Gotcha! One little note here: The settings for the frame window, not the client, are the ones to be retrieved.

[ Next ] [ Previous ] | Chapter 10 | [ Contents ] [ Chapter 9: Introduction to Windows ] [ Chapter 11: Window Messages and Queues ]