[Next] [ Previous ] | Chapter9 - II |
A parent window performs many of the same duties that parents of human children perform. A parent window controls where the child can go. A child is "clipped' to the parent and will not be visible outside the parental boundaries. A child window can be moved outside these boundaries; however, the portion outside the parent window will not be visible. Also, a child will inherit all of the parent's styles. If a parent is visible, a child will be visible; if a parent is not visible, a child will not be visible. If a parent moves, the child moves alone with it. However, unlike a human parent, if a parent window is destroyed. all of its children are destroyed as well. If a parent window has two child windows, these children are considered siblings. When a family of windows is all visible at the same time, there is a power struggle for which window will be displayed on top. A child window always will be on top of the parent window. Some surprise, huh? |
However, siblings, and the whole windowing system as well, use a concept
known as 'Z-Order" to decide who gets on top. The sibling created last
usually is at the top of the "Z-Order". The programmer can change the order
using the function WinSetWindowPos. This function lets a window
be put on top or behind its other siblings. User interaction also
affects the "Z-Order." When the user clicks on one of the of the siblings,
that window will become the active window, and it will move to the top
of the '"Z-Order." The active window is usually the window that either
is or owns lime focus window. There is only one active window in the system
at any given time.
The other type of window relationship is an owner window. In the last
example, hwndFrame was also the owner of the other windows. An owner shares
some of the same duties a parent shares. When an owner is hidden, destroyed,
or minimized, the children are also. However, an owned window is not clipped
to its owner.
The other interesting features of owners is the level of communication
between owners and owned, or "control" windows. When an important event
happens to an owned window, the owner is sent a WM_CONTROL message.
The mpParm1 and mpParm2 parameters tell the owner which control
sent the message and what kind of event has occurred. A window does not
have to have an owner.
|
Figure 9.5 shows that the first 16 bits are used for the respective control window styles; the upper 16 bits are used for window styles. Since controls are also windows, both the control window styles and the basic window styles are designed to live together harmoniously. |
Value | Description |
WS_GROUP | Defines which items make up a group in a dialog box window. See Chapter 13 |
WS_TABSTOP | The user can use the tab key to move to this dialog item. See Chapter 13. |
WS_ANIMATE | Will create "exploding windows." |
WS_MAXIMIZED | Causes a window to he created fully maximized. |
WS_MINIMIZED | Causes a window to be created fully minimized. |
WS_SYNCPAINT | Causes a window to have paint messages generated immediately when an
area of
the window needs to be repainted. |
WS_SAVEBITS | Will save the screen area under a window and will restore the image when covered area has been uncovered. |
WS_PARENTCLIP | Will cause the parent's presentation space to be clipped to the child's presentation space, enabling the child to draw on the parent's presentation space. This can create some very interesting results, as the parent's visible presentation space usually is larger than or equal to the child's. Most often this style is not used. |
WS_CLIPSIBLINGS | Will prevent siblings from redrawing on top of each other |
WS_CLIPCHILDREN | Will cause the child window area to be excluded from the drawing region; in other words, the parent cannot paint over the child. Usually this style is not necessary because if both the parent and child windows need to be repainted and also overlap, the parent will be repainted first, and then the child window is repainted. |
WS_DISABLED | Will cause a window to be disabled upon creation. Thus this window will not respond to user input until the window is enabled. |
WS_VISIBLE | Will make a window visible at creation time. An invisible default window will be created. |
Table 9.7 presents class styles that can be specified at class registration
time.
Class Style | Description |
CS_MOVENOTIFY | WM_MOVE messages will be sent whenever the window is moved. |
CS_SIZEREDRAW | When a window has been sized, the window will be made completely invalid.
and a WM_PAINT message will be sent. This style is useful when an application centers text on the window or sizes an image to fill the window. |
CS_HITTEST | WM_HITTEST messages will be sent to the window whenever the mouse moves in the window. |
CS_FRAME | Specifies a frame window class. |
CS_CLIPCHILDREN | See above. |
CS_CLIPSIBLINGS | See above. |
CS_PARENTCLIP | See above. |
CS_SAVEBITS | See above. |
CS_SYNCPAINT | See above. |
WINDOW.CHere main has one small difference from main in the previous example. WIN1.C. The class style CS_SIZEREDRAW, is used for tle client window class. With this style, Presentation Manager will invalidate the window whenever the size changes. The text on the client area is dependent on the width of the window. Because we want to ensure that all the text is nicely formatted even when the window is resized, thus we use CS_SIZEREDRAW.
WINDOW.MAK
WINDOW.DEF
|
Presentation Manager windows use a different coordinate space from the one used by Microsoft Windows. (See Figure 9.6) The bottom left corner is coordinate 0,0. Most window drawing is done by specifying two sets of x,y coordinates that form the lower left and upper right corners of a "bounding rectangle." A structure RECTL,. contains the coordinates. It is a familiar parameter in most painting functions. The structure is defined:
typedef struct _RECTL /* rcl */
{
LONG xLeft;
LONG yBottom;
LONG xRight;
LONG yTop;
} RECTL;
typedef RECTL *PRECTL;
BOOL APIENTRY WinInvalidateRect(HWND hwnd,
PRECTL pwrc,
BOOL fIncludeChildren);
BOOL APIENTRY WinInvalidateRegion(HWND hwnd,
HRGN hrgn,
BOOL fIncludeChildren);
The first parameter for these functions is the window handle hwnd. The
next parameter is the area that is to be invalidated. The last parameter
indicates whether children are to be included in the invalid rectangle
or region.
Presentation Manager is very stingy in sending WM_PAINT messages. Only
that piece of the window that needs to be painted will be invalidated,
not the the entire window.
HPS APIENTRY WinBeginPaint(HWND hwnd,
HPS hps,
PRECTL prclPaint);
hwndWnd is the window the presentation space belongs to. Presentation
Spaces are covered in more detail later. The second parameter is used if
the user already has a presentation space obtained using WinGetPS or some
other means and wants to use that space for drawing If a NULLHANDLE is
specified, the system will provide a presentation space to be used. The
last parameter is a pointer to RECTL structure. The coordinates of the
invalidated region are placed in the structure. The invalidated region
is the region that needs to be painted.
BOOL WinEndPaint(HPS hps)WinEndPaint is used to terminate a paint procedure. There is only one parameter, hps, which is the presentation space returned from WinBeginPaint.
Once WinEndPaint is called, the region is validated, and any presentation
space returned from WinBeginPaint is released.
WinFillRect(hpsPaint,
&rclRect,
SYSCLR_WINDOW);
This function paints the region designated by the second parameter
with the specified color index. The first parameter is the presentation
space to paint.
BOOL APIENTRY WinFillRect(HPS hps,
PRECTL prcl,
LONG lColor);
A program can use a value such as CLR_BLUE or a system value such as SYSCLR_WINDOW that will fill the rectangle with the system default window color.
The WINDOW example is designed to draw some text on the client window
area; however, in a graphical user interface (GUI) environment, this is
not just a call to printf. Instead the developer
must provide the exact pixel location where the text is to be located.
Before we get around actually to drawing the text, we need to find some
information about the size of the font used in the client window. GpiQueryFontMetrics
is the function to provide all the needed information about a font.
BOOL APIENTRY GpiQueryFontMetrics(HPS
hps,
LONG lMetricsLength,
PFONTMETRICS pfmMetrics);
GpiQueryFontMetrics(hpsPaint,
sizeof(fmMetrics),
&fmMetrics);
The FONTMETRICS structure contains much data concerning the point size,
face name, height, and width of the current font. The variable lMaxBaselineExt
provides the height of the tallest character. We'll use this value as the
height-of-line line of text.
WinQueryWindowRect(hwndWnd,
&rclWindow);
liLineInfo.usxLeft = (USHORT)fmMetrics.lAveCharWidth;
liLineInfo.usxRight = rclWindow.xRight-(USHORT) fmMetrics.lAveCharWidth;
The next task is to find the current size of the window. Remember, a
window can be sized by the user at any time, and a program should be able
to adjust to such changes. WinQueryWindowRect will return
the size of a window in a RECTL. structure. We will define a right and
left margin that is equal to the average width of one character. Very conveniently,
the FONTMETRICS structure contains lAveCharWidth, which
is exactly that. With all this, we now know the height of our lines, the
x coordinate our lines will start at, and the x coordinate that is the
end of the line.
To position the first line of text at the top of the page and
create a one-line margin, the following math is done to move the bounding
rectangle down one line.
rclWindow.yTop = rclWindow.yTop-
liLineInfo.ulCharHeight;
rclWindow.yBottom = rclWindow.yTop-
liLineInfo.ulCharHeight;
Value | Description |
QW_NEXT | Returns the window below the specified window. |
QW_PREV | Returns the window above the specified window. |
QW_TOP | Returns the topmost child window. |
QW_BOTTOM | Returns the bottommost child window. |
QW_OWNER | Returns the owner of the specified window. |
QW_PARENT | Returns the parent of the specified window. |
QW_NEXTTOP | Returns the next window of the owner window hierarchy. |
QW_PREVTOP | Returns the previous window of the owner window hierarchy. |
QW_FRAMEOWNER | Returns the owner of the specified window that also shares the same parent as the specified window. |
WriteWindowInfo(hpsPaint,
hwndFrame,
&rclWindow,
&liLineInfo);
heEnum = WinBeginEnumWindows(hwndFrame);
hwndEnum = WinGetNextWindow(heEnum);
while (hwndEnum
!= NULLHANDLE)
{
WriteWindowInfo(hpsPaint,
hwndEnum,
&rclWindow,
&liLineInfo);
hwndEnum = WinGetNextWindow(heEnum);
}
/* end while hwndEnum */
WinEndEnumWindows(heEnum);
Presentation Manager lets users query all the descendants of a particular window by using the functions WinBeginEnumWindows and WinGetNextWindow. The window that is the head of the window family tree is the frame window, hwndFrame.
HENUM WinBeginEnumWindows(HWND hwnd);This window handle is passed to WinBeginEnumWindows, which passes back an enumeration handle, heEnum. This is a place holder to keep track of the last window that was returned. WinGetNextWindow takes heEnum and returns the next window in the window family tree. As each window is found, our own function, WriteWindowInfo , is used to display information about the window. The enumeration ends with a call to WinEndEnum Windows.
HWND WinGetNextWindow(HENUM henum);
BOOL WinEndEnumWindows(HENUM henum);
The first piece of information we'll retrieve from each window is the class name. Documentation refers to the system-defined class names as WC_FRAME and so on. However, the class name in reality, and returned by WinQueryClassName, is a string in the format "#1". Some help, huh? Public window class names are stored in powerful lookup tables known as atom tables. This format helps to cheek to see if a newly registered window class has the same name as one that is already registered. To convert from this cryptic format to something more readily deciphered, we define an array, pszClassNames, that maps the numeric class names to the documented class names. The string pszClass, returned from WinQueryClassName , is incremented by one to strip off the "#" and leave a value that can be converted to an integer index into the array.
If achClass is a nonnumeric value, we assume this to be an application-defined class, and keep the sting whole.
The second piece of information to retrieve is the parent and owner windows. WinQueryWindow is used to return the window handles of the parent and owner of the specified window. All this window detail is formatted into one string that will displayed on the client window by the user-function DrawString.
ulStyle = WinQueryWindowULong(hwndPaint,The other information we will output to the client area is the window styles. This is a value that is stored in the window word. Presentation Manager stores a lot of window information in window words. The next example covers this concept in more detail, WinQueryWindowULong will retrieve the window styles. The first parameter is the window we're inquiring about. The next parameter is a constant used to identify which piece of the window word we're after. The value QWL_STYLE designates that the window style is the ULONG is question. The example converts these values to meaningful text string and uses the function DrawString to display the formatted string on the client area.
QWL_STYLE);
LONG APIENTRY WinDrawText(HPS hpsPaint,We use the WinDrawText function in this example. The first parameter is the presentation space. The second parameter is the number of characters to output. A -1 indicates that the entire length of the null-terminated string is to be used. The string to write is pchString. The size of the text area is defined by passing a pointer to a RECTL structure that contains the designated coordinates. The next two parameters indicate the foreground and background color of the text. The last parameter is the formatting flag, a collection of formatting attributes that are ORed together. The attributes used in this example are DT_LEFT | DT_TEXTATTRS | DT_WORDBREAK. DTLEFT left-aligns the text horizontally, and DT_TEXTATTRS indicates that default window foreground and background colors will be used. If this flag is specified, the two previous parameters are ignored. The DT_WORDBREAK attribute will draw only the number of whole words that will fit inside the bounding rectangle. The number of characters drawn is returned. By enclosing this code in a loop and incrementing the string offset by the number of characters drawn, a very powerful routine that will be used often to print formatted text is created.
LONG lCount,
PCH pchString,
PRECTL prclRect,
LONG lForeColor,
LONG lBackColor,
ULONG flCmd);
while (!bFinished)
{
/* move down to next line
*/
usReturn = DropOneLine(prclRect,
pLineInfo->ulCharHeight);
/* if we can't move down any more, stop trying
to write any more */
if (!usReturn)
return ;
/* set the left and right drawing coordinates
*/
prclRect->xLeft = pLineInfo->usxLeft;
prclRect->xRight = pLineInfo->usxRight;
/* draw text that will fit
*/
usNumChars = WinDrawText(hpsPaint,
strlen(&pString[usOffset]),
&pString[usOffset],
prclRect,
0,
0,
DT_LEFT|DT_TEXTATTRS|DT_WORDBREAK);
if (!usNumChars || (usOffset+usNumChars == usStringLength))
/* if no characters were printed, or we are at the end
of the string, quit */
bFinished = TRUE;
else
/* offset string
to new position
*/
usOffset += usNumChars;
}
There is one last short function to explain, DropOneLine. This is a
user function that will take a pointer to a RECTL structure and decrement
the top and bottom y coordinates by the height of one line.
[Next] [ Previous ] | Chapter9 - II |