22. Device Contexts I: Overview

Page 371
  22. Device Contexts I: Overview  
   
  The key concept in the GDI is that of a device context. In an effort to make drawing (by which we will mean drawing both graphics and text) as device-independent as possible, Windows uses the idea of a device context. Device contexts are used to draw not only to physical devices such as the display or a printer, but also to an individual window or even a bitmap stored in memory.  
   
  The basic procedure when using a device context is as follows:  
   
  1. Obtain a device context, either by creating a new one or using an existing one. (As we will see, Windows maintains a stock of device contexts for our use.) For a window or the screen, we can use the GDI function GetDC or GetWindowDC. For a printer, we can use CreateDC. This process selects the device context into a device, such as a window, screen, printer, or memory block. (The Visual Basic hDC property also returns a handle to a device context. We will discuss this later in the chapter. Our attention now is focused on the Windows GDI.)  
   
  2. Set the device context's attributes and graphic objects, which may include its drawing pen, painting brush, font, and so on.  
   
  3. Apply drawing methods to the device context. This includes outputting text.  
   
  4. Destroy (using DeleteDC) or free (using ReleaseDC) the device context if appropriate.  
   
  We will go into these steps in more detail at the appropriate time. The important point to stress now is that device contexts provide a kind of device independence. In particular, drawing code that we create for one device context, such as the screen, can also be used in other device contexts just by changing the value of the device context argument to the drawing functions. Thus, we can use essentially the same code to draw on the screen as to print to the printer, for instance.  
Page 372
   
  For instance, the Ellipse function is used to draw an ellipse. It has five parameters, four of which specify the bounding rectangle that contains the ellipse and one of which specifies the device context into which to draw the ellipse. Thus, by changing one argument, we can draw the same ellipse in different contexts. (This will become clearer when we do some actual examples.)  
 
  How Windows Handles Window Painting  
   
  To understand the Windows GDI, we must understand how Windows decides when to paint (or repaint) a portion of a window. For this, we need to take a look at regions.  
   
  A Glossary of Regions  
   
  A region is an object that consists of a union of one or more rectangles, polygons, or ellipses. Regions have handles and can be filled, framed, moved, inverted, and so on.  
   
  To illustrate, we can create an elliptical region using the following function, which returns a handle to the region.  
 
  HRGN CreateEllipticRgn(
  int nLeftRect,   // x-coordinate of the upper-left corner of the
                   // bounding rectangle
  int nTopRect,    // y-coordinate of the upper-left corner of the
                   // bounding rectangle
  int nRightRect,  // x-coordinate of the lower-right corner of the
                   // bounding rectangle
  int nBottomRect  // y-coordinate of the lower-right corner of the
                   // bounding rectangle
);
 
   
  Incidentally, this should not be confused with drawing an ellipse in a window, which can be done using the Ellipse drawing function. This ellipse is referred to as an ellipse shape.  
   
  Regions are combined using the CombineRgn function:  
 
  int CombineRgn(
  HRGN hrgnDest,     // handle to destination region
  HRGN hrgnSrc1,     // handle to source region
  HRGN hrgnSrc2,     // handle to source region
  int fnCombineMode  // region combining mode
);
 
   
  The fnCombineMode parameter can assume one of the following values, which determine the precise action that takes place.  
Page 373
 
  RGN_AND
Outputs the intersection of the source regions.
 
 
  RGN_COPY
Copies the first region to the destination.
 
 
  RGN_DIFF
Outputs the portion of hrgnSrc1 that is not part of hrgnSrc2. (This is region1 region2.)
 
 
  RGN_OR
Outputs the union of the source regions.
 
 
  RGN_XOR
Outputs all portions of the union that are not in both regions. In set-theoretic language, this is the symmetric difference of the two regions.
 
   
  In addition to combining regions, a region can be filled, using the FillRgn or PaintRgn functions, inverted using InvertRgn, framed using FrameRgn, and moved using OffsetRgn.  
   
  The update region  
   
  The update region of a window is that region in a window that is currently out-of-date or invalid and therefore requires repainting.  
   
  The visible region  
   
  The visible region is generally the region that is visible to the user. However, the WS_CLIPCHILDREN and WS_CLIPSIBLINGS styles have an effect on what is considered the visible region. If a window has the WS_CLIPCHILDREN style, then the visible region does not include any child windows. If the window has the WS_CLIPSIBLINGS style, then the visible portion of the window does not include any portion that is obscured by sibling windows.  
   
  The clipping region  
   
  The clipping region is the subregion of the client area of a window in which drawing is currently permitted. Put another way, if we attempt to draw to a window, Windows will clip the drawing so that it does not extend beyond the clipping region.  
   
  As we will see, when an application receives a display device context through a call to one of the GDI functions BeginPaint, GetDC, or GetDCEx, the system sets the clipping region for the device context to the intersection of the visible region and the update region. In this way, the only portion of the window that is drawn is the portion that has visible changes.  
Page 374
   
  The window region  
   
  The term window region also appears in Microsoft's documentation as follows:  
  The window region determines the area within the window where the operating system permits drawing. The operating system does not display any portion of a window that lies outside of the window region.  
   
  This is not quite the same as the clipping region, because the window region is apparently not restricted to the client area of the window. In any case, it would not surprise me very much if the two terms were often mixed up in the documentation, so I would advise some caution here.  
   
  Functions That Affect Window Regions  
   
  The GDI API has a variety of functions that affect the various window regions (besides the functions for combining, filling, inverting, and moving regions discussed earlier).  
   
  GetUpdateRect and GetUpdateRgn  
   
  The GetUpdateRect function returns the coordinates of the smallest rectangle that completely encloses the update region of the specified window. The GetUpdateRgn function returns the actual update region of a window by copying it into a specified region object.  
   
  GetWindowRgn and SetWindowRgn  
   
  The GetWindowRgn function retrieves (makes a copy of) the window region of a window. The SetWindowRgn function sets the window region of a window.  
   
  The SetWindowRgn function can be used to create nonrectangular windows. More particularly, the function can be used to set the visible portion of a window to a nonrectangular shape. You can try this out very simply by creating a VB project with two forms: Form1 and Form2. Then place the following code behind a button on Form1 (you will need to add the necessary declarations, of course):  
 
  ' Load form2 and change window region
Dim hrgn As Long

hrgn = CreateEllipticRgn(0, 0, 100, 200)
Form2.Show

SetWindowRgn Form2.hWnd, hrgn, -1
 
   
  InvalidateRect and ValidateRect  
   
  The InvalidateRect function invalidates a rectangle by adding it to a window's update region. The ValidateRect function validates a rectangle by removing it from the update region.  
Page 375
   
  InvalidateRgn and ValidateRgn  
   
  The InvalidateRgn function invalidates a region by adding it to the window's update region. The ValidateRgn function validates a region by removing it from the update region.  
   
  RedrawWindow  
   
  The RedrawWindow function can be used to do a variety of things, including validating or invalidating a given region.  
   
  UpdateWindow  
   
  The UpdateWindow function updates the client area of a window by sending a WM_PAINT message to the window.  
   
  The Update Region and WM_PAINT Messages  
   
  As we have seen, the update region of a window is the region that is currently invalid and therefore requires repainting. Of course, this is constantly changing. For instance, if the user moves another window partially over the window in question, then Windows will add the covered portion to the update region. If a window is minimized, the entire window becomes invalid and is ''added to" the update region.  
   
  Indeed, when any action takes place that affects the contents of a window, such as when the window is first created, minimized, resized, or covered by another window, the window's contents are not saved. (It would take too many resources to save the contents of all such windows.) Instead, Windows invalidates the affected portion of the window and adds it to the update region. Then the system sends a WM_PAINT message to the window procedure of the window. Recall our discussion of how GetMessage handles WM_PAINT messages. In particular, WM_PAINT messages have very low priority and are bumped by both sent and posted messages.  
   
  Note that it is up to the programmer to include code in the window procedure to perform any necessary repainting of the update region of the window. The invalid region can be obtained through a call to GetUpdateRgn.  
   
  Even though Visual Basic takes care of this for us, it is worth looking a bit more closely at this issue.  
   
  Typically, a programmer will begin the WM_PAINT processing code with a call to BeginPaint. This function retrieves a device context, which is required by various painting API functions. We will discuss device contexts in detail very soon. However, the point here is that Windows sets the clipping region to the intersection of the update and visible regions. It then fills a PAINTSTRUCT structure with (among  
Page 376
   
  other things) the location of the update region. Then BeginPaint sets the update region to NULL, that is, it validates the update region, so that further WM_PAINT messages are not generated.  
   
  The nonclient area  
   
  As expected, Windows does nothing to help repaint the client area of a window, for it does not know the contents of that area. However, the story is different with respect to the nonclient area. The default window function DefWindowProc that is called at the end of the window procedure will redraw the nonclient area of the window. If, however, the application wants to assume this chore, it can process the WM_NCPAINT or WM_ERASEBKGND messages.  
 
  Device Contexts  
   
  A device context (or DC) is an object that is used to perform drawing (of both graphics and text) on a target device. Target devices may be virtual devices, such as a memory block or a window, or physical devices such as the screen or a printer.  
   
  Device contexts have attributes, such as the background color. Some attributes are graphic objects. The GDI graphic objects are listed below:  
   
  Bitmap object  
   
  Brush object  
   
  Palette object  
   
  Font object  
   
  Path object  
   
  Pen object  
   
  Region object  
   
  The process for associating a graphic object with a device context is simple:  
   
  1. Create a graphic object using an API function such as CreatePen, CreateBrushIndirect, or CreateBitmap, or use a stock object. (Windows maintains a collection of stock pens and stock brushes.) The properties of a graphic object are set when the object is created. For instance, the CreatePen function has parameters that determine the pen's width and color.  
   
  2. Select the object into the device context using SelectObject. (The analogy here is with selecting a pen with which to draw.)  
   
  We can use the GetCurrentObject and GetObject functions, in combination, to retrieve information about the currently selected object of a specified type in a device context. The GetCurrentObject function retrieves a handle to the currently.  
Page 377
   
  selected object, and the GetObject function fills a structure with information about the object whose handle was retrieved by the GetCurrentObject function.  
   
  Note that to change certain attributes currently used by a device context, such as the pen color, we need to create and select a new pen into the device context or use a different stock pen, destroying the previous pen. (Windows 2000 implements functions such as SetDCPenColor that can directly change the pen color of the currently selected pen, thus saving some hassle on the programmer's part.)  
   
  Using a Device Context  
   
  As we have mentioned, the basic procedure when using a device context is as follows:  
   
  1. Obtain a device context, either by creating a new one or using an existing one. For the client area of a window or the entire screen, we use GetDC. For an entire window (both client and nonclient areas) or the entire screen, we can use GetWindowDC. For a printer, we use CreateDC. When using device contexts obtained from Visual Basic's hDC property, save the current state of the DC. This process selects the device context into a device (window, screen, printer).  
   
  2. Set the device context's attributes and graphic objects (pens, brushes, or whatever).  
   
  3. Apply drawing methods to the device context.  
   
  4. Destroy (using DeleteDC) or free (using ReleaseDC) the device context if appropriate. When using device contexts obtained from Visual Basic's hDC property, restore the original state of the DC.  
   
  Figure 22-1 illustrates a device context.  
   
  To illustrate, the following procedure will draw a red ellipse with a black interior around a command button. Since drawing output is placed on a layer beneath standard controls, the command button appears on top of the ellipse.  
 
  Sub EllipseIt()

Dim hPen As Long
Dim hBrush As Long
Dim hDCForm As Long
Dim r As RECT
Dim iDC As Long

' Get device context for form
hDCForm = Form1.hdc

' Save it for later restoration
iDC = SaveDC(hDCForm)
 
Page 378
   
  0378-01.gif  
   
  Figure 22-1
A device context selected into a window
 
 
  ' Set brush (fill) to black
hBrush = GetStockObject(BLACK_BRUSH)
SelectObject hDCForm, hBrush

' And pen to red
hPen = CreatePen(PS_SOLID, 3, &HFF)
SelectObject hDCForm, hPen

' Get coordinates of rectangle surrounding button
r.Left = Command1.Left \ Screen.TwipsPerPixelX
r.Top = Command1.Top \ Screen.TwipsPerPixelY
r.Right = (Command1.Left + Command1.Width) \ Screen.TwipsPerPixelX
r.Bottom = (Command1.Top + Command1.Height) \ Screen.TwipsPerPixelY

' Draw rectangle
Ellipse hDCForm, r.Left - 50, r.Top - 50, r.Right + 50, r.Bottom + 50

' Refresh
Me.Refresh

' Delete pen
DeleteObject hPen

' Restore DC
RestoreDC hDCForm, iDC

End Sub
 
   
  Default Properties  
   
  To get some idea of the types of attributes possessed by a device context, Table 22-1 shows the default values that are given to a DC when it is first created. We will discuss some of these attributes later.  
Page 379
Table 22-1. Default Device Context Attribute Values
Attribute Default Value
Background color Background color setting from the Control Panel
Background mode OPAQUE
Bitmap None
Brush WHITE_BRUSH  (stock brush)
Brush origin (0,0)
Clipping region Entire window
Palette DEFAULT_PALETTE
Current pen position (0,0)
Device origin Upper-left corner of the window or the client area
Drawing mode R2_COPYPEN
Font SYSTEM_FONT
Intercharacter spacing 0
Mapping mode MM_TEXT
Pen BLACK_PEN  (stock pen)
Polygon-fill mode ALTERNATE
Stretch mode BLACKONWHITE
Text color Text color setting from Control Panel
Viewport extent (1,1)
Viewport origin (0,0)
Window extent (1,1)
Window origin (0,0)


   
  Device Context Modes  
   
  Device contexts have modes that affect how certain operations are performed. These are shown in Table 22-2.  
Table 22-2. Device Context Modes
Mode Description Set/Get
Background mode Specifies how background colors are mixed with existing window or screen colors when performing bitmap or text operations. SetBkMode, GetBkMode
Drawing mode Specifies how foreground colors are mixed with existing window or screen colors for pen, brush, bitmap, and text operations. SetROP2, GetROP2Mode
Mapping mode Specifies how graphics is mapped from logical coordinates to device coordinates. SetMapMode, GetMapMode


   
  (table continued on next page.)  
Page 380
   
  (table continued from previous page.)  
Table 22-2. Device Context Modes (continued)
Mode Description Set/Get
Polygon-fill mode Specifies how the brush patterns is used to fill the interior of complex regions. SetPolyFillMode, GetPolyFillMode
Stretching mode Specifies how bitmap colors are mixed with existing window or screen colors when the bitmap is scaled down. SetStretchBltMode, GetStretchBltMode


   
  Device Contexts and Visual Basic  
   
  Visual Basic forms and picture boxes have an hDC property that returns a private device context for the object (we will explain the term private later in Chapter 23, Device Contexts II: Types of Device Contexts). It is also possible to get a handle to a device context for these objects using the GetDC function. As we will see, the handles returned by hDC and GetDC may or may not be handles to the same DC. This depends on the setting of the AutoRedraw property.  
   
  Note that it is important to save the state of a VB device context obtained from hDC using the SaveDC function and then restore that state using RestoreDC when finished, as we did in the previous example.  
   
  The AutoRedraw property  
   
  As you probably know, the setting of the AutoRedraw property determines whether drawing output is automatically redrawn by Windows when necessary, for example, when the target window is resized or is covered and then uncovered by another window. (Unlike drawing output, child windows, such as controls, are always automatically redrawn.) When graphics are automatically redrawn, they are said to be persistent.  
   
  In order for Windows to have the capability of supporting persistent graphics, drawing output must be stored somewhere during the life of the application. This storage area is called a persistent bitmap and is kept in memory.  
   
  It is important to note that forms and picture boxes can have two memory bitmaps associated with them. One is a background bitmap that is used to "clear" the window. This will exist once the Picture property has been set for the form or control. When AutoRedraw is True, there is also a persistent bitmap that receives graphics output. Thus, the setting of this property has a profound effect on drawing. Let us look at this more closely.  
   
  The hDC property, GetDC, and drawing output  
   
  When AutoRedraw is True, a persistent bitmap exists. In this case, the hDC property refers to the device context for this persistent bitmap. When AutoRedraw is False, there is no persistent bitmap and the hDC property refers to the device  
Page 381
   
  context for the target window. In either case, the return value of GetDC is a handle to the device context for the target window (the API knows nothing about VB's persistent bitmaps).  
   
  It follows that the API drawing functions will always send their output to the target window, whereas the VB drawing functions send their output to the object referred to by the hDC property, which might be either the target window (when AutoRedraw is False) or the persistent bitmap (when AutoRedraw is True).  
   
  The HDCExample subroutine shown below demonstrates this. First, we turn on AutoRedraw and then use the hDC property of the pic picture box to select a white brush. Then we draw a rectangle (see Figure 22-2), which is filled with the white brush, as expected. Note that we must invoke the Refresh method for the picture box in order to get VB to move the output from the persistent bitmap to the picture box itself.  
   
  Next, we turn off AutoRedraw and draw two more rectangles one with the hDC property and one using the device context handle obtained from the GetDC function. In both cases, the rectangles do not use the white brush (see Figure 22-2), because we are using the device context of the picture box, not the persistent bitmap.  
 
  Private Sub HDCExample()

Dim hDCPic As Long

' Turn on AutoRedraw
pic.AutoRedraw = True

Debug.Print "hDC:" & pic.hdc

" Set brush to white
SelectObject pic.hdc, GetStockObject(WHITE_BRUSH)

' Draw rectangle to persistent bitmap
Rectangle pic.hdc, 0, 0, 100, 100

' Need this
pic.Refresh

' Turn off AutoRedraw
pic.AutoRedraw = False

' Get device context for window
hDCPic = GetD(pic.hwnd)
Debug.Print "GetDC:" & hDCPic

' Draw rectangles
Rectangle pic.hdc, 100, 100, 200, 200
Rectangle hDCPic, 200, 200, 300, 300

End Sub
 
Page 382
   
  The output from the Debug.Print statement is:  
 
  hDC:-469695987
GetDC:1946224922
 
   
  which shows that GetDC at least returns a different handle than hDC.  
   
  0382-01.gif  
   
  Figure 22-2.
AutoRedraw and GetDC
 
   
  It follows from this discussion that, when AutoRedraw is True, a problem arises if we try to draw with both the API drawing functions, through the device context handle obtained from GetDC and the VB drawing functions through the hDC property. Namely, Visual Basic will redraw the window from the persistent bitmap when it thinks necessary, thus erasing any graphics output that has gone directly to the window via the GetDC device context.  
   
  AutoRedraw and the Paint event  
   
  When a VB window, such as a picture box, needs redrawing for some reason (such as a change in size or being covered and uncovered, or as a result of a call to the Refresh method), VB will do one of two things. If AutoRedraw is True, then, as expected, VB will automatically redraw the window using the persistent bitmap. That is the whole point of the AutoRedraw property. Moreover, in this case, VB will not fire the Paint event for that window. On the other hand, if AutoRedraw is False, then VB instead simply fires the Paint event, leaving the programmer to deal with redrawing issues.  
   
  If we want to create persistent graphics when AutoRedraw is False,  
   
  we must place the drawing code in the Paint event of the target window.  
Page 383
   
  Note, however, that in the examples in the following discussion of GDI drawing, we will use a picture box whose AutoRedraw property is set to False, but we will not bother to place the drawing code in the Paint event for these examples.  
   
  The Picture and Image properties and the CLS method  
   
  By definition, the Picture property of a VB control always returns a handle to the background bitmap for the window. On the other hand, the Image property is intended to return a handle to the persistent bitmap. If this bitmap does not exist, then VB creates a persistent bitmap containing the same image as the background bitmap (but this is a different bitmap). The Image property then returns a handle to the newly created persistent bitmap.  
   
  Finally, we mention that the Visual Basic Cls method is based on the hDC property. Thus, when AutoRedraw is True, the persistent bitmap is cleared to the background color, and this change is also reflected in the window. When AutoRedraw is False, the window is cleared directly, and the persistent bitmap is drawn in that window.  
   
  Pens  
   
  Pens are graphic objects used to draw lines and curves. Many drawing functions require pens. For instance, the LineTo function is:  
 
  BOOL LineTo(
   HDC hdc,     // device context handle
   int nXEnd,   // x-coordinate of line's ending point
   int nYEnd    // y-coordinate of line's ending point
);
 
   
  This function draws a line using the pen that is currently selected into the device context.  
   
  The Windows GDI supports two types of pens: cosmetic and geometric.  
   
  Cosmetic pens  
   
  A cosmetic pen is used for quick drawing operations. Cosmetic pens use fewer resources than geometric pens, but have only three attributes: width, style, and color.  
   
  The functions CreatePen, CreatePenIndirect, or ExtCreatePen can be used to create a cosmetic pen. Windows also maintains three stock cosmetic pens, denoted by BLACK_PEN,WHITE_PEN, and DC_PEN (Windows 98/2000 only), which are accessible using the GetStockObject function.  
   
  The CreatePen function is:  
 
  HPEN CreatePen(
  int fnPenStyle,    // pen style
 
 

Page 384
 
  int nWidth,        // pen width
COLORREF crColor   // pen color
);
 
   
  where COLORREF is a 32-bit value of the form &Hbbggrr where the 16-bit value bb specifies the blue component of the color (from 0 to &HFF) and similarly for green and red. Thus, for example, &H0000FF is pure red.  
   
  In VB, we can use the declaration:  
 
  Declare Function CreatePen Lib "gdi32" (_
   ByVal fnPenStyle As Long, _
   ByVal nWidth As Long, _
   ByVal crColor As Long _
) As Long
 
   
  The fnPenStyle parameter is one of the following values:  
 
  PS_SOLID
Pen is solid.
 
 
  PS_DASH
Pen is dashed. (Valid only when the pen width is a single pixel.)
 
 
  PS_DOT
Pen is dotted. (Valid only when the pen width is a single pixel.)
 
 
  PS_DASHDOT
Pen has alternating dashes and dots. (Valid only when the pen width is a single pixel.)
 
 
  PS_DASHDOTDOT
Pen has alternating dashes and double dots. (Valid only when the pen width is a single pixel.)
 
 
  PS_NULL
Pen is invisible.
 
 
  PS_INSIDEFRAME
Pen is solid. When used with a drawing function that takes a bounding rectangle, such as the Ellipse function, the dimensions of the figure (ellipse) are shrunk so that it fits entirely within the bounding rectangle, taking into account the width of the pen. Applies only to geometric pens.
 
   
  The nWidth parameter specifies the width of the pen, in logical units (explained later). We can set this to 0 to create a line whose width is a single pixel.  
   
  Geometric pens  
   
  While cosmetic pens draw very quickly (about 3 to 10 times faster than geometric pens), geometric pens are more flexible, having the following properties: width, style, color, pattern, optional hatch, end style, and join style.  
Page 385
   
  A geometric pen is created using ExtCreatePen:  
 
  HPEN ExtCreatePen(
  DWORD dwPenStyle,     // pen style
  DWORD dwWidth,        // pen width
  CONST LOGBRUSH *lplb,   // pointer to structure for brush attributes
  DWORD dwStyleCount,     // length of array containing custom style bits
  CONST DWORD *lpStyle    // optional array of custom style bits
);
 
   
  This function permits the creation of cosmetic or geometric pens, determined by including the PS_COSMETIC or PS_GEOMETRIC bit style in the dwPenStyle argument.  
   
  Brushes  
   
  A brush is a graphic object that is used to paint the interior of polygons, ellipses, and paths.  
   
  Windows makes a distinction between a logical brush and a physical brush. The GDI functions that create a brush return a handle to a logical brush. However, when we select that brush into a device context using SelectObject, the device driver for the device creates a physical brush with which to do the actual painting. (After all, a black-and-white printer cannot use a red logical brush, for instance.)  
   
  The brush origin  
   
  It is important to understand the concept of the brush origin. Figure 22-3 illustrates the need for this concept.  
   
  The brush origin is that pixel in the brush that is placed at the starting pixel in the object to be painted when the painting begins. Figure 22-3 illustrates what happens when we want to paint a window and a control on the window, using the same brush. This involves two separate painting operations.  
   
  In Window1 of Figure 22-3, the brush origin is set at the upper-left-hand pixel in the brush for both painting operations. However, when the brush origin is aligned with the pixel at the upper-left corner of the control, to begin painting the control, the bit pattern on the control does not align properly with the pattern on the window.  
   
  As shown in Window2 of Figure 22-3, to get the patterns to align, all we need to do is change the brush origin when painting the control to the pixel in the second row and first column of the brush.  
   
  The brush origin can be set using the SetBrushOrgEx function:  
 
  BOOL SetBrushOrgEx(
  HDC hdc,       // handle of device context
 
Page 386
   
  0386-01.gif  
   
  Figure 22-3
Brush origin
 
 
    int nXOrg,     // x-coordinate of new origin
  int nYOrg,     // y-coordinate of new origin
  LPPOINT lppt   // points to previous brush origin
);
 
   
  Brush types  
   
  The Windows GDI implements four types of brushes: solid, stock, pattern, and hatch.  
   
  Solid brush. A solid brush is a logical brush that contains 64 pixels of a single color. Solid brushes are created using the CreateSolidBrush function.  
   
  Stock brush. The Windows GDI maintains seven predefined stock brushes. A GDI stock brush can be retrieved using the GetStockObject function:  
 
  HGDIOBJ GetStockObject(
   int fnObject    // type of stock object
);
 
Page 387
   
  The function returns a handle to a GDI object (HGDIOBJ). The fnObject parameter can assume one of the values in Table 22-3 (which includes the seven stock GDI brushes).  
   
  Table 22-3. Stock Object Types  
Value of fnObject Meaning
BLACK_BRUSH Black brush
DKGRAY_BRUSH Dark gray brush
DC_BRUSH Solid color brush (Windows 98/2000)
GRAY_BRUSH Gray brush
HOLLOW_BRUSH Same as NULL_BRUSH
LTGRAY_BRUSH Light gray brush
NULL_BRUSH Null brush
WHITE_BRUSH White brush
BLACK_PEN Black pen
DC_PEN Solid color pen (Windows 98/2000)
WHITE_PEN White pen
ANSI_FIXED_FONT Windows fixed-pitch system font
ANSI_VAR_FONT Windows variable-pitch (proportional) system font
DEVICE_DEFAULT_FONT Device-dependent font (Windows NT)
DEFAULT_GUI_FONT Default font for user interface objects, such as menus and dialog boxes
OEM_FIXED_FONT Original equipment manufacturer (OEM) dependent fixed-pitch font
SYSTEM_FONT System font (used to draw menus, dialog box controls, and text)
SYSTEM_FIXED_FONT Fixed-pitch system font used in Windows 3.0 and earlier
DEFAULT_PALETTE Default palette

   
  The Windows USER library also maintains a collection of 21 stock brushes. These brushes correspond to the colors of window elements, such as menus, scrollbars, and buttons. The GetSysColorBrush function is used to obtain a handle to one of these stock brushes.  
   
  Note that stock brushes do not need to be deleted when no longer needed, although it does not do any harm to do so.  
   
  Hatch brush. A hatch brush paints a pattern of vertical, horizontal, and/or diagonal lines. The Windows GDI maintains six predefined hash brushes.  
   
  Pattern brush. A pattern brush is created using a bitmap. To create a logical pattern brush, we must first create a bitmap and then call CreatePatternBrush or CreateDIBPatternBrushPt to create the pattern brush.  
Page 388
   
  Paths  
   
  A path is a sequence of one or more figures (or shapes) that are filled, outlined, or both. Note that, unlike a pen or brush, paths do not have handles and are not created and destroyed in the sense that the other graphic objects are created or destroyed.  
   
  One and only one path can be selected into a device context at a given time. When a new path is selected into a DC, the previous path is discarded.  
   
  To create a path and select it into a DC, we must first define the points that describe the path. This is a three-step process:  
   
  1. Call the BeginPath function.  
   
  2. Call the appropriate drawing functions.  
   
  3. Call the EndPath function.  
   
  This sequence of function calls is referred to as a path bracket.  
   
  The BeginPath function is:  
 
  BOOL BeginPath(
  HDC hdc      // handle to device context
);
 
   
  and the EndPath function is similar:  
 
  BOOL EndPath(
  HDC hdc      // handle to device context
);
 
   
  The drawing functions that can be used in a path bracket are shown in Table 22-4.  
   
  Table 22-4. Drawing Functions Allowed in a Path Bracket  
   
  AngleArc  
   
  LineTo  
   
  Polyline  
   
  Arc  
   
  MoveToEx  
   
  PolylineTo  
   
  ArcTo  
   
  Pie  
   
  PolyPolygon  
   
  Chord  
   
  PolyBezier  
   
  Polyline  
   
  CloseFigure  
   
  PolyBezierTo  
   
  Rectangle  
   
  Ellipse  
   
  PolyDraw  
   
  RoundRect  
   
  ExtTextOut  
   
  Polygon  
   
  TextOut  


   
  Once a path has been selected into a DC, we can perform various operations on that path, such as:  
   
  Drawing an outline of the path using the current pen  
   
  Filling the interior of the path using the current brush  
Page 389
   
  Converting the curves in the path to line segments  
   
  Converting the path to a clip path  
   
  Converting the path into a region  


WIN32 API Programming with Visual Basic
Win32 API Programming with Visual Basic
ISBN: 1565926315
EAN: 2147483647
Year: 1999
Pages: 31
Authors: Steven Roman

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net