Webocreation

Monday, November 23, 2009

Using GDI Objects

Using GDI Objects

This section describes the graphics user interface (GDI) objects that are used to draw output, their purpose, and how to use them. It also discusses creating your own GDI objects and shows how to use stock objects.

The tools used by the DC to draw output — regions, pens, brushes, fonts, bitmaps, and palettes — are encapsulated by MFC in classes that are derived from the CGdiObject base class. To see an illustration that shows some of the available GDI objects, click this icon.





The following table outlines the purpose and default values for each object.

Object Purpose Default value

CPen Used to draw lines and the border of all shapes, such as rectangles, polygons, and regions Solid black pen, one pixel wide


CBrush Used to fill in the interior of shapes such as polygons and regions Solid white brush
CFont Used to manipulate font characteristics System font
CBitmap Used to install and manipulate bitmaps None
CRgn Used to create, alter, and retrieve information about regions None
CPalette Used to create and manipulate palettes None

This section includes the following topics:

Creating Your Own GDI Objects

MFC provides classes for creating custom GDI objects. To define a GDI object, you simply create an object using the class constructor. If you use a constructor with no arguments, then one of the create functions should be called to initialize it. For example, the following example code shows two ways to define a pen object:

// Method number 1
CPen myPen1(PS_SOLID, m_penThickness, RGB(255,0,0));
// Method number 2
CPen myPen2;
myPen.CreatePen(PS_SOLID, 0, RGB(255,0,0));

The advantage of the latter method is that a constructor using no arguments will never throw an exception. However, each of the create functions returns a Boolean value that should be checked to determine whether the object was created successfully.

Default Attributes and Objects

When a CDC object is created, it gains a set of default attributes and GDI objects. These all reflect their system default values.

To manage these attributes, the CDC class contains a number of member functions. For example, CDC::GetTextColor and CDC::SetTextColor can be used to manage the color of text as it is drawn.

Overriding the Defaults

To change a GDI object from the default, you must select a new object into the DC. The CDC::SelectObject function is used to perform this selection. SelectObject selects the new object into the context and then returns the old object. Typically, this returned object is saved. When the drawing operation is complete, the original object is reselected into the DC.
CDC::SelectObject Functions

The following example code illustrates how various overloads of CDC::SelectObject support the GDI objects:

class CDC : public CObject
{ ...
CPen* SelectObject( CPen* pPen);
CBrush* SelectObject( CBrush* pBrush);
CFont* SelectObject( CFont* pFont);
CBitmap* SelectObject( CBitmap* pBitmap);
CRgn* SelectObject( CRgn* pRegion);
...
};

Note Palettes are selected into the DC using CDC::SelectPalette. Saving the Deselected Object

Save the deselected object so that it can be restored later. Three important reasons to do this are:
® It is good programming etiquette to restore the DC to its original state.
® To ensure that the data in the DC is valid, it must not be left pointing to a local GDI object (such as myBrush in the following example).
® Often a DC is shared between functions. Restoring the DC ensures that the next function to receive the DC will receive it in a known state.

The following example code shows how to create and use a GDI CBrush object:

void CMyView::OnDraw(CDC* pDC)
{
CBrush myBrush;
myBrush.CreateSolidBrush(RGB(0, 255, 0));
// Save the original brush.
CBrush *pOldBrush;
pOldBrush= pDC->SelectObject(&myBrush);
// Call drawing functions as required.
// ...
// Restore the old pen before exiting.
pDC->SelectObject(pOldBrush);
}

Using Stock Objects

Windows maintains a set of standard GDI objects for system and program use called stock objects. Stock objects include commonly used pens, brushes, and fonts. There are several advantages to using stock objects:

® Because they are built in, these stock objects do not need to be constructed or created.
® Multiple applications can use stock objects concurrently.
® Stock objects do not increase the number of resources used by the application.


CDC::SelectStockObject

Use CDC::SelectStockObject to request predefined fonts, pens, or brushes (or a default palette).

Note Remember that you are using an existing object, not creating a new one. The following table summarizes the types of stock objects available.


GDI category Stock object values

Fonts ANSI_FIXED_FONT

ANSI_VAR_FONT
DEVICE_DEFAULT_FONT
OEM_FIXED_FONT
SYSTEM_FONT
Pens BLACK_PEN
WHITE_PEN
NULL_PEN
Brushes BLACK_BRUSH
DKGRAY_BRUSH
GRAY_BRUSH
HOLLOW_BRUSH
LTGRAY_BRUSH
NULL_BRUSH
WHITE_BRUSH

Note Be sure to explicitly cast the CGdiObject pointer returned by SelectStockObject to a pointer of the proper type. Technically, a stock object does not have to be released because it is never really owned by your application. However, good programming etiquette dictates that you restore the previous GDI object, which releases the stock object.


To use a stock object
1. Create a pointer to the current object in the device context and select into the device context the object that your application will use to draw.

void CmyView::OnDraw(CDC* pDC)
{ //...
// save pointer to old Pen
CPen *pOldPen;
pOldPen = (CPen*)pDC->SelectStockObject(WHITE_PEN);
// Call drawing functions as required
// ...
2. Restore the old object before exiting.
// ...
pDC->SelectObject(pOldPen);
}

Using Pens

Pens, encapsulated in the CPen class, are used to draw lines, curves, and shapes. Pens have three characteristics: style, width, and color.

Styles

There are seven pen styles:

® PS_SOLID
® PS_DOT
® PS_DASH
® PS_DASHDOT
® PS_DASHDOTDOT
® PS_NULL
® PS_INSIDEFRAME



To see an illustration that shows examples of the first five pen styles, click this icon.



Use a PS_NULL pen style to draw a shape without a border. If you draw a line with a null pen, it will be invisible.

Use a PS_INSIDEFRAME pen style to draw inside the frame of closed shapes.

Width

The width of pen output is described in pixels. Use 0 to guarantee the narrowest possible width (1 pixel), regardless of the mapping mode. For more information about mapping modes, see Mapping Modes in this chapter. For values greater than 1, the pen style will always be PS_SOLID. If a different style is specified, it will be ignored.

Color

Use the RGB macro to create a COLORREF value for the color. For more information about COLORREF, see Setting Colors in this chapter.

Using Brushes

Brushes, encapsulated in the CBrush class, are used to fill areas. You can choose from three types, depending upon the kind of fill pattern you want — solid, a standard hatched pattern, or a bitmap pattern.

Unlike CFont and CPen, CBrush has multiple versions of the constructors and creation functions. This reflects the fact that brushes come in three main types.
Solid Brushes
Solid brushes require only a COLORREF argument.
Hatched Brushes
Hatched brushes require a hatch-style index and a COLORREF argument.
The standard hatch style indexes are:
® HS_BDIAGONAL
® HS_CROSS
® HS_DIAGCROSS
® HS_FDIAGONAL
® HS_HORIZONTAL
® HS_VERTICAL

To see an illustration that shows examples of the hatch styles, click this icon.


The following code example shows you how to create a blue hatched brush to fill a polygon. The hatch is aligned to the first point of the polygon by using the SetBrushOrg function.

// Construct and create the brush.
CBrush brush;
brush.CreateHatchBrush( HS_CROSS, RGB(0,0,255));
// set the bitmap origin.
pDC->SetBrushOrg(m_pts[0].x % 8, m_pts[0].y % 8);
CBrush* pOldBrush= pDC->SelectObject(&brush);
pDC->Polygon(m_pts, GetSize());
pDC->SelectObject(pOldBrush);

Bitmapped Brushes


A bitmapped brush requires a pointer to a bitmap; 8 x 8 pixels is the minimum size. This bitmap is tiled to fill the required area.

Using Fonts

MFC encapsulates fonts in the CFont class. A font is a set of characters of the same typeface (such as Courier), stroke weight (such as bold), and size (such as 10-point). To see an illustration that shows the various characteristics of a font,

click this icon.


Note The cell (or box) that surrounds each character determines the character spacing of a font.


A font family is made up of several fonts that may vary widely, but that have some common characteristic. The following table lists and describes the six font families defined by Windows.

Font family name Description

Decorative Novelty font; for example, Old English

Don't Care Generic family name

Modern Monospace font with or without serifs; for example, Pica, Elite, and Courier New

Roman Proportional font with serifs; for example, Times New Roman

Script Font designed to look like handwriting; for example, Script and Cursive

Swiss Proportional font without serifs; for example, Arial

Fixed-Pitch Fonts

In a fixed-pitch (monospace) font of a given size, each cell has the same dimensions, regardless of the width of the character that occupies it.

In the following example, note that every character in the second line falls exactly beneath a character in the previous line:

Example of a fixed-pitch font.

This is the TrueType font Courier New.



Software applications, such as source code editors, usually rely on fixed-pitch fonts because they allow easy vertical alignment of program constructs.

Proportional Fonts

In a proportional font, the cells vary in width, depending upon the relative width of the letter (l versus m, for example). The space between characters is designed to be optically pleasing, rather than uniform, and thus easier to read. This paragraph is set in Arial, a proportional font.

In addition to readability, proportional fonts offer the advantage of occupying less physical space.

Vector Fonts vs. Raster Fonts

Fonts can be stored and drawn by using one of two techniques:

® Vector fonts

Each font is stored as a mathematical description of the curves that compose each character. These descriptions are then used to draw a font of virtually any size. Microsoft TrueType and Adobe PostScript are the two best-known vector font technologies.

® Raster fonts

Each font character is stored as a bitmap pattern exactly as it would be displayed on an output device. Raster fonts are designed as sets for a specific point size, such as 6-point or 12-point font.
Though displaying vector fonts requires more computation, they are a more compact, flexible method for manipulating font information. In addition, vector fonts can also be rotated and stretched.
Because raster-font characters are stored and displayed as is, they can be quickly realized and output.

TrueType Fonts

A TrueType font character is a collection of line and curve commands, as well as a collection of hints. Windows uses the line and curve commands to determine the outline for a character or symbol. It uses the hints to adjust the length of lines and the shapes of curves so that a character will look as good as possible on a particular display.

TrueType fonts are easily resized, rotated, and stretched, but maintain a high quality of appearance that is comparable with a raster font.

Font Metrics

Because fonts are complicated entities, descriptions of them are also complicated. The standard data structure in Windows that is used to describe fonts is TEXTMETRIC, a data structure that contains 20 fields to describe the font.

You can use the CDC::GetTextMetrics function to retrieve information about the metrics for the currently selected font. This function places the information in a TEXTMETRIC data structure.

For TrueType fonts, a similar function, CDC::GetOutlineTextMetrics, can be used to fill in an OUTLINETEXTMETRIC structure.

The following code example shows how to use the TEXTMETRIC structure to set the range for a CScrollView class:

TEXTMETRIC tm;

pDC->GetTextMetrics(&tm);

CSize scrollRange;

scrollRange.cx = 100;

scrollRange.cy = tm.tmHeight * GetDocument()->GetSize();

SetScrollSizes( MM_TEXT, scrollRange);

Note All of the fonts that are installed on the system can be enumerated by using the ::EnumFonts and ::EnumFontFamiliesEx Windows SDK functions. However, these functions require the use of a callback function.

Logical Fonts vs. Physical Fonts

A logical font is a description of an ideal font. This ideal font may or may not actually exist on the system. A LOGFONT data type represents a logical font. (A LOGFONT data type is actually a typedef-defined structure to hold font information.)

A physical font is a font that is actually installed on the target system; therefore, it can be displayed. The TEXTMETRIC (or OUTLINETEXTMETRIC) data type represents it.

From the perspective of an application, a logical font represents the desired font, while the physical fonts represent the fonts available for actual use.

Using a Non-Stock Font

Using fonts other than the stock fonts can be very helpful when you need a specialized look.

To use non-stock fonts

1. Construct the font object.

2. Initialize the font using CFont::CreateFont, CFont::CreateFontIndirect, CFont::CreatePointFont, or CFont::CreateFontIndirect.

3. Select the font into the DC.



The following example code illustrates the creation of a font object using CFont::CreatePointFont:
CFont font;
font.CreatePointFont( 120 , ""); // 12 point, default typeface
LOGFONT logfont;
font.GetLogFont(&logfont); // retrieve specifics about the font.
CFont* pOldFont = pDC->SelectObject(&font);
// use font...



When an application requests the selection of a font into a DC, the font mapper portion of the Windows GDI is responsible for producing the closest match between the requested font and the available fonts. This process is called "font realization."

Using Bitmaps
A bitmap is an array of bits that contain data that describes the colors found in a rectangular region on the screen (or a rectangular region found on a page of printed paper).


MFC provides support for working with bitmaps through the CBitmap class and the CDC bitmap functions.

The two types of bitmaps are device-dependent bitmaps (DDBs) and device-independent bitmaps (DIBs). DDBs were common in versions before Windows 3.0. In fact, they were the only bitmaps available to developers. However, as display technology improved and as the variety of display devices increased among Windows users, certain inherent problems surfaced. For example, because there was no method of storing (or retrieving) the resolution of the display type on which a bitmap was created, a drawing application could not quickly determine whether a bitmap was suitable for the type of video display device on which the application was running. To solve this problem, beginning with Windows version 3.1, Microsoft started to use DIBs.
Device-Independent Bitmaps

A DIB contains the following color and dimension information:

® The color format of the device on which the rectangular image was created.

® The resolution of the device on which the rectangular image was created.

® The palette for the device on which the image was created.

® An array of bits that maps red, green, blue (RGB) triplets to pixels in the rectangular image.

® A data-compression identifier that indicates the data-compression scheme (if any) that is used to reduce the size of the array of bits.

The following example code creates a bitmap compatible with a specific DC:

CRect rect;
GetClientRect(&rect); // get the dimensions of the view
m_pBitmap = new CBitmap;
// create a bitmap compatible with the DC.
m_pBitmap->CreateCompatibleBitmap(
pDC, rect.Width(), rect.Height());

You can also load a bitmap file into your application, although this requires more work. For information, search for "LoadImage" in Visual C++ Help.

Using Regions
The CRgn class encapsulates a Windows GDI region. A region is an area built up from one or more elliptical or polygonal shapes. To use regions, use the member functions of the CRgn class with the clipping functions defined as members of the CDC class.


The following example code shows how to clip a view area to show only a complex elliptical subset of the rectangle:

// Create the complex, elliptic region.
CRgn rgn1, rgn2;
rgn1.CreateEllipticRgn(50,50,200,100);
rgn2.CreateEllipticRgn(100,25,50,300);
rgn2.CombineRgn(&rgn1, &rgn2, RGN_OR);
// Select it as the clip region
pDC->SelectClipRgn(&rgn2);
// Now draw the black rectangle.
CRect rect(0,0,400,400);
pDC->SelectStockObject(BLACK_BRUSH);
pDC->Rectangle(&rect);

For more information, search for "CRgn" in Visual C++ Help.

Using Palettes
The CPalette class encapsulates a Windows color palette. A palette provides an interface between an application and a color output device (such as a display device). The interface allows the application to take full advantage of the color capabilities of the output device without severely interfering with the colors that are displayed by other applications. Windows uses the application's logical palette (a list of needed colors), and the system palette (definitions of available colors) to determine the colors that are used.


A CPalette object provides member functions for manipulating the palette referred to by the object. You can construct a CPalette object and use its member functions to create the actual palette, a GDI object, and to manipulate its entries and other properties.

For more information, search for "CPalette" in Visual C++ Help

No comments:

Post a Comment