[ Next ] [ Previous ] | Chapter 10 |
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:
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.
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.
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.
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.exe window |
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.
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.
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.
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.
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.exe restotes window position. |
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.
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.
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 |