PMGuide - Painting and Drawing: Difference between revisions
Created page with "{{IBM-Reprint}} {{PMGuide}} This chapter describes presentation spaces, device contexts, and window regions, explaining how a PM application uses them for painting and drawing in windows. == About Painting and Drawing == An application typically maintains an internal representation of the data that it is manipulating. The information displayed in a screen, window, or printed copy is a visual representation of some portion of that data. This chapter introduces the conc..." |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 20: | Line 20: | ||
A window and its associated presentation space have three regions that control where drawing takes place in the window. These regions ensure that the application does not draw outside the boundaries of the window or intrude into the space of an overlapping window. | A window and its associated presentation space have three regions that control where drawing takes place in the window. These regions ensure that the application does not draw outside the boundaries of the window or intrude into the space of an overlapping window. | ||
| Region | {| class="wikitable" | ||
|- | ! Region !! Description | ||
| | |- | ||
| | | Update Region | ||
| | | This region represents the area of the window that needs to be redrawn. This region changes when overlapping windows change their z-order or when an application explicitly adds an area to the update region to force a window to be painted. | ||
|- | |||
| Clip Region | |||
| This region and the visible region determine where drawing takes place. Applications can change the clip region to limit drawing to a particular portion of a window. Typically, a presentation space is created with a clip region equal to NULL, which makes this region equivalent to the update region. | |||
|- | |||
| Visible Region | |||
| This region and the clip region determine where drawing takes place. The system changes the visible region to represent the portion of a window that is visible. Typically, the visible region is used to mask out overlapping windows. When an application calls the WinBeginPaint function in response to a WM_PAINT message, the system sets the visible region to the intersection of the visible region and the update region to produce a new visible region. Applications cannot change the visible region directly. | |||
|} | |||
Whenever drawing occurs in a window's presentation space, the output is clipped to the intersection of the visible region and clip region. | Whenever drawing occurs in a window's presentation space, the output is clipped to the intersection of the visible region and clip region. | ||
Line 54: | Line 61: | ||
==== WS_SYNCPAINT, CS_SYNCPAINT ==== | ==== WS_SYNCPAINT, CS_SYNCPAINT ==== | ||
Windows that have these styles receive WM_PAINT messages as soon as their update regions contain something; they are updated immediately (synchronously). | Windows that have these styles receive [[WM_PAINT]] messages as soon as their update regions contain something; they are updated immediately (synchronously). | ||
==== CS_SIZEREDRAW ==== | ==== CS_SIZEREDRAW ==== |
Latest revision as of 03:45, 6 May 2025
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
This chapter describes presentation spaces, device contexts, and window regions, explaining how a PM application uses them for painting and drawing in windows.
About Painting and Drawing
An application typically maintains an internal representation of the data that it is manipulating. The information displayed in a screen, window, or printed copy is a visual representation of some portion of that data. This chapter introduces the concepts and strategies necessary to make your PM application function smoothly and cooperatively in the OS/2 display environment.
Presentation Spaces and Device Contexts
A presentation space is a data structure, maintained by the operating system, that describes the drawing environment for an application. An application can create and hold several presentation spaces, each describing a different drawing environment. All drawing in a PM application must be directed to a presentation space.
Normally each presentation space is associated with a device context that describes the physical device where graphics commands are displayed. The device context translates graphics commands made to the presentation space into commands that enable the physical device to display information. Typical device contexts are the screen, printers and plotters, and off-screen memory bitmaps. By creating presentation spaces and associating them with particular device contexts, an application can control where its graphics output appears. Typically, a presentation space and device context isolate the application from the physical details of displaying graphics, so the same graphics commands can be used for many types of displays. This virtualization of output can reduce the amount of display code an application must include to support multiple output devices.
This chapter describes how an application sets up its presentation spaces and device contexts before drawing, and how to use window-drawing functions. Refer to the Graphics Programming Interface Programming Guide for the graphics functions available to PM applications.
Window Regions
A window and its associated presentation space have three regions that control where drawing takes place in the window. These regions ensure that the application does not draw outside the boundaries of the window or intrude into the space of an overlapping window.
Region | Description |
---|---|
Update Region | This region represents the area of the window that needs to be redrawn. This region changes when overlapping windows change their z-order or when an application explicitly adds an area to the update region to force a window to be painted. |
Clip Region | This region and the visible region determine where drawing takes place. Applications can change the clip region to limit drawing to a particular portion of a window. Typically, a presentation space is created with a clip region equal to NULL, which makes this region equivalent to the update region. |
Visible Region | This region and the clip region determine where drawing takes place. The system changes the visible region to represent the portion of a window that is visible. Typically, the visible region is used to mask out overlapping windows. When an application calls the WinBeginPaint function in response to a WM_PAINT message, the system sets the visible region to the intersection of the visible region and the update region to produce a new visible region. Applications cannot change the visible region directly. |
Whenever drawing occurs in a window's presentation space, the output is clipped to the intersection of the visible region and clip region.
The clip region includes the overlapped part of the back window, but the visible region excludes that portion of the back window. The system maintains the visible region to protect other windows on the screen; the application maintains the clip region to specify the portion of the window in which it draws. Together, these two regions provide safe and controllable clipping.
To further control drawing, both the system and the application manipulate the update region. For example, if a window's position is switched from back to front, several changes occur in the regions of both windows. The system adds the lower-right corner of the new front window to that window's visible region. The system also adds that corner area to the window's update region.
Window Styles for Painting
Most of the styles relating to window drawing can be set either for the window class (CS_ prefix) or for an individual window (WS_ prefix). The styles described in this section control how the system manipulates the window's regions and how the window is notified when it must be painted or redrawn.
WS_CLIPCHILDREN, CS_CLIPCHILDREN
All the windows with this style are excluded from their parent's visible region. This style protects windows but increases the amount of time necessary to calculate the parent's visible region. This style normally is not necessary, because if the parent and child windows overlap and both are invalidated, the parent window is drawn before the child window. If the child window is invalidated independently from its parent window, only the child window is redrawn. If the update region of the parent window does not intersect the child window, drawing the parent window does not disturb the child window.
WS_CLIPSIBLINGS, CS_CLIPSIBLINGS
Windows with this style are excluded from the visible region of sibling windows. This style protects windows with the same parent from being drawn accidentally, but increases the amount of time necessary to calculate the visible region. This style is appropriate for sibling windows that overlap.
WS_PARENTCLIP, CS_PARENTCLIP
The visible region for a window with this style is the same as the visible region of the parent window. This style simplifies the calculation of the visible region but is potentially hazardous, because the parent window's visible region usually is larger than the child window. Windows with this style should not draw outside their boundaries.
WS_SAVEBITS, CS_SAVEBITS
The system saves the bits beneath a window with this style when the window is displayed. When the window moves or is hidden, the system simply restores the uncovered bits. This operation can consume a great deal of memory; it is recommended only for transient windows such as menus and dialog boxes—not for main application windows. This style also is inappropriate for windows that are updated dynamically, such as clocks.
WS_SYNCPAINT, CS_SYNCPAINT
Windows that have these styles receive WM_PAINT messages as soon as their update regions contain something; they are updated immediately (synchronously).
CS_SIZEREDRAW
A window with this class style receives a WM_PAINT message; the window is completely invalidated whenever it is resized, even if it is made smaller. (Typically, only the uncovered area of a window is invalidated when a window is resized.) This class style is useful when an application scales graphics to fill the current window.
Strategies for Painting and Drawing
A PM application shares the screen with other windows and applications; therefore, painting and drawing must not interfere with those other applications and windows. When you follow these strategies, your application can coexist with other applications and still take full advantage of the graphics capabilities of the operating system.
Drawing in a Window
Ideally, all drawing in a window occurs as a result of an application's processing a WM_PAINT message. Applications maintain an internal representation of what must be displayed in the window, such as text or a linked list of graphics objects, and use the WM_PAINT message as a cue to display a visual representation of that data in the window.
To route all display output through the WM_PAINT message, an application must not draw on the screen at the time its data changes. Instead, it must update the internal representation of the data and call the WinInvalidateRect or WinInvalidateRegion functions to invalidate the portion of the window that must be redrawn. Sometimes it is much more efficient to draw directly in a window without relying on the WM_PAINT message—for example, when drawing and redrawing an object for a user who is using the mouse to drag or size the object.
If a window has the WS_SYNCPAINT or CS_SYNCPAINT style, invalidating a portion of the window causes a WM_PAINT message to be sent to the window immediately. Essentially, sending a message is like making a function call; the actions corresponding to the WM_PAINT message are carried out before the call that caused the invalidation returns—that is to say, the painting is synchronous.
If the window does not have the WS_SYNCPAINT or CS_SYNCPAINT style, invalidating a portion of the window causes the invalidated region to be added to the window's update region. The next time the application calls the WinGetMsg or WinPeekMsg functions, the application is sent a WM_PAINT message. If there are many messages in the queue, the painting occurs after the invalidation—that is, the painting is asynchronous. A WM_PAINT message is not posted to the queue in this case, so all invalidation operations since the last WM_PAINT message are consolidated into a single WM_PAINT message the next time the application has no messages in the queue.
There are advantages to both synchronous and asynchronous painting. Windows that have simple painting functions should be painted synchronously. Most of the system-defined control windows, such as buttons and frame controls, are painted synchronously because they can be painted quickly without interfering with the responsiveness of the program. Windows that require more time-consuming painting operations should be painted asynchronously so that the painting can be initiated only when there are no other pending messages that might otherwise be blocked while waiting for the window to be painted. Also, a window that uses an incremental approach to invalidating small portions of itself usually should allow those operations to consolidate into a single asynchronous WM_PAINT message, rather than a series of synchronous WM_PAINT messages. If necessary, an application can call the WinUpdateWindow function to cause an asynchronous window to update itself without going through the event loop. WinUpdateWindow sends a WM_PAINT message directly to the window if the window's update region is not empty.
The WM_PAINT Message
A window receives a WM_PAINT message whenever its update region is not NULL. A window procedure responds to a WM_PAINT message by calling the WinBeginPaint function, drawing to fill in the update areas, then calling the WinEndPaint function.
The WinBeginPaint function returns a handle to a presentation space that is associated with the device context for the window and that has a visible region equal to the intersection of the window's update region and its visible region. This means that only those portions of the window that need to be redrawn are drawn. Attempts to draw outside this region are clipped and do not appear on the screen.
If the application maintains its own presentation space for the window, it can pass the handle of that presentation space to WinBeginPaint, which modifies the visible region of the presentation space and passes the presentation-space handle back to the caller. If the application does not have its own presentation space, it can pass a NULL presentation-space handle and the system will return a cached-micro presentation space for the window. In either case, the application can use the presentation space to draw in the window.
The WinBeginPaint function takes a pointer to a RECTL structure, filling in this structure with the coordinates of the rectangle that encloses the area to be updated. The application can use this rectangle to optimize drawing, by drawing only those portions of the window that intersect with the rectangle. If an application passes a NULL pointer for the rectangle argument, the application draws the entire window and relies on the clipping mechanism to filter out the unneeded areas.
After the WinBeginPaint function sets the update region of a window to NULL, the application does the necessary drawing to fill the update areas. If an application handles a WM_PAINT message and does not call WinBeginPaint, or otherwise empty the update region, the application continues to receive WM_PAINT messages as long as the update region is not empty.
After the application finishes drawing, it calls the WinEndPaint function to restore the presentation space to its former state. When a cached-micro presentation space is returned by WinBeginPaint, the presentation space is returned to the system for reuse. If the application supplies its own presentation space to WinBeginPaint, the presentation space is restored to its previous state.
Drawing the Minimized View
When an application creates a standard frame window, it has the option of specifying an icon that the system uses to represent the application in its minimized state. Typically, if an icon is supplied, the system draws it in the minimized window and labels it with the name of the window. If the application does not specify the FS_ICON style for the window, the window receives a WM_PAINT message when it is minimized. The code in the window procedure that handles the WM_PAINT message can determine whether the frame window currently is minimized and draw accordingly. Notice that because the WS_MINIMIZED style is relevant only for the frame window, and not for the client window, the window procedure checks the frame window rather than the client window.
The following code fragment shows how to draw a window in both the minimized and normal states:
MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { HPS hps; RECTL rcl; ULONG flStyle; switch (msg) { case WM_PAINT: hps = WinBeginPaint(hwnd, (HPS) NULL, &rcl); /* Check whether the frame window (client's parent window) is minimized. */ flStyle = WinQueryWindowULong(WinQueryWindow(hwnd, QW_PARENT), QWL_STYLE); if (flStyle & WS_MINIMIZED) { /* Paint the minimized state. */ } else { /* Paint the normal state. */ } WinEndPaint(hps); return 0; } }
Drawing Without the WM_PAINT Message
An application can draw in a window's presentation space without having received a WM_PAINT message. As long as there is a presentation space for the window, an application can draw into the presentation space and avoid intruding into other windows or the desktop. Applications that draw without using the WM_PAINT message typically call the WinGetPS function to obtain a cached-micro presentation space for the window and call the WinReleasePS function when they have finished drawing. An application also can use any of the other types of presentation spaces described in the following sections.
Three Types of Presentation Spaces
All drawing must take place within a presentation space. The operating system provides three types of presentation spaces for drawing: normal, micro, and cached-micro presentation spaces. The normal presentation space provides the most functionality, allowing access to all the graphics functions of the operating system and enabling the application to draw to all device types. The normal presentation space is more difficult to use than the other two kinds of presentation spaces and it uses more memory. It is created by using the GpiCreatePS function and is destroyed by using the GpiDestroyPS function.
The micro presentation space allows access to only a subset of the operating system graphics functions, but it uses less memory and is faster than a normal presentation space. The micro presentation space also enables the application to draw to all device types. It is created by using the GpiCreatePS function and destroyed by using the GpiDestroyPS function.
The cached-micro presentation space provides the least functionality of the three kinds of presentation spaces, but it is the most efficient and easiest to use. The cached-micro presentation space draws only to the screen. It is created and destroyed by using either the WinBeginPaint and WinEndPaint functions or the WinGetPS and WinReleasePS functions.
The following sections describe each of the types of presentation spaces, in detail, and suggest strategies for using each type in an application. All three kinds of presentation spaces can be used in a single application. Some windows, especially if they never will be printed, are best served by cached-micro presentation spaces. Other windows might require the more flexible services of micro or normal presentation spaces.
Normal Presentation Spaces
The normal presentation space supports the full power of the operating system graphics, including retained graphics. The primary advantages of a normal presentation space over the other two presentation-space types are its support of all graphics functions and its ability to be associated with many kinds of device contexts.
A normal presentation space can be associated with many different device contexts. Typically, this means that an application creates a normal presentation space and associates it with a window device context for screen display. When the user asks to print, the application associates the same presentation space with a printer device context. Later, the application can reassociate the presentation space with the window device context. A presentation space can be associated with only one device context at a time, but the normal presentation space enables the application to change the device context whenever necessary.
When creating a normal presentation space, an application can associate it with a device context or defer the association to a later time. The GpiAssociate function associates a device context with a normal presentation space after the presentation space has been created. An application typically associates the normal presentation space with a device context when calling the GpiCreatePS function and, later, associates the presentation space with a different device context by calling GpiAssociate. To obtain a device context for a window, call the WinOpenWindowDC function. To obtain a device context for a device other than the screen, call the DevOpenDC function.
An application typically creates a normal presentation space during initialization and uses it until termination. Each time the application receives a WM_PAINT message, it passes the handle of the normal presentation space as an argument to WinBeginPaint; this prevents the system from returning a cached-micro presentation space. The system modifies the visible region of the supplied normal presentation space and returns the presentation space to the application. This method enables the application to use the same presentation space for all the drawing in a specified window. Normal presentation spaces created using GpiCreatePS must be destroyed by calling GpiDestroyPS before the application terminates. Do not call WinReleasePS to release a presentation space obtained using GpiCreatePS. Before terminating, applications also must use DevCloseDC to close any device contexts opened using DevOpenDC. No action is necessary for device contexts obtained using WinOpenWindowDC, because the system automatically closes these device contexts when destroying the associated windows.
Micro Presentation Spaces
The primary advantage of a micro presentation space over a cached-micro presentation space is that it can be used for printing as well as painting in a window. An application that uses a micro presentation space must explicitly associate it with a device context. This makes the micro presentation space useful for painting to a printer, a plotter, or an off-screen memory bitmap.
A micro presentation space does not support the full set of OS/2 graphics functions. Unlike a normal presentation space, a micro presentation space does not support retained graphics.
An application that must display graphics or text in a window and print to a printer or plotter typically maintains two presentation spaces: one for the window and one for the printing device. The following code fragment demonstrates how an application's graphics output can be routed through separate presentation spaces to produce a screen display and printed copy:
hdc = WinOpenWindowDC(...); hps = GpiCreatePS(..., hdc, ..., GPIA_ASSOC);
To create a micro presentation space for a device other than the screen, replace the call to the WinOpenWindowDC function with a call to the DevOpenDC function, which obtains a device context for a device other than the screen. Then the device context that is obtained by this call can be used as an argument to GpiCreatePS.
An application typically creates a micro presentation space during initialization and uses it until termination. Each time the application receives a WM_PAINT message, it should pass the handle of the micro presentation space as an argument to the WinBeginPaint function; this prevents the system from returning a cached-micro presentation space. The system modifies the visible region of the supplied micro presentation space and returns the presentation space to the application. This method enables the application to use the same presentation space for all drawing in a specified window.
Micro presentation spaces created by using GpiCreatePS should be destroyed by calling GpiDestroyPS before the application terminates. Do not call the WinReleasePS function to release a presentation space obtained by using GpiCreatePS. Before terminating, applications must use the DevCloseDC function to close any device contexts opened using the DevOpenDC function. No action is necessary for device contexts obtained using WinOpenWindowDC, because the system automatically closes these device contexts when destroying the associated windows.
Cached-Micro Presentation Spaces
The cached-micro presentation space provides the simplest and most efficient drawing environment. It can be used only for drawing on the screen, typically in the context of a window. It is most appropriate for application tasks that require simple window-drawing functions that will not be printed. Cached-micro presentation spaces do not support retained graphics.
After an application draws to a cached-micro presentation space, the drawing commands are routed through an implied device context to the current display. The application does not require information about the actual device context, because the device context is assumed to be the display. This process makes cached-micro presentation spaces easy for applications to use. The following code fragments illustrate this process:
HPS hps; case WM_PAINT: hps = WinBeginPaint(hwnd, NULL, NULL); /* * Use PS. */ WinEndPaint(hps);
or
HPS hps; case WM_PAINT: hps = WinGetPS(hwnd); /* * Use PS. */ WinReleasePS(hps);
There are two common strategies for using cached-micro presentation spaces in an application. The simplest strategy is to call the WinBeginPaint function during the WM_PAINT message, use the resulting cached-micro presentation space to draw in the window, then return the presentation space to the system by calling the WinEndPaint function. By using this method, the application interacts with the presentation space only when drawing in the presentation space. This method is most appropriate for simple drawing. A disadvantage of this method is that the application must set up any special attributes for the presentation space, such as line color and font, each time a new presentation space is obtained.
A second strategy is for the application to allocate a cached-micro presentation space during initialization, by calling the WinGetPS function and saving the resulting presentation-space handle in a static variable. Then the application can set attributes in the presentation space that exist for the life of the program. The presentation-space handle can be used as an argument to the WinBeginPaint function each time the window gets a WM_PAINT message; the system modifies the visible region and returns the presentation space to the application with its attributes intact. This strategy is appropriate for applications that need to customize their window-drawing attributes. A presentation space that is obtained by calling the WinGetPS function must be released by calling WinReleasePS when the application has finished using it, typically during program termination. A presentation space that is obtained by calling WinBeginPaint must be released by calling WinEndPaint, typically as the last part of processing a WM_PAINT message.