Graphical Device Interface

   

The graphical device interface (GDI), supported by the gdi32.dll dynamic link library, provides the capability for a window to draw and to print. This includes drawing lines, text, font service, and color management.

One of the key elements to the GDI is the device context . A device context (DC) represents a data structure defining a set of graphic objects, attributes, and output modes. DCs are created using the CreateDC() and GetDC() functions. There is a myriad of other DC functions that are commonly used as well. In all, seven types of GDI objects can be selected into a device context (see Table 14.6).

Table 14.6. The Seven Types of GDI Object

Feature

Description

Bitmap

Used for copying or scrolling parts of the screen.

Brush

Used for painting and filling the interior of polygons, ellipses, and paths.

Font

Used for identifying type, size , and style of a type font.

Palette

Used for defining the set of available colors.

Path

Used for painting and drawing operations.

Pen

Used for line drawing.

Region

Used for clipping and other operations.

There are more than 330 GDI routines available in current versions of Windows . Use Borland's impdef command-line tool or DLL LIB Util , described in the Tip earlier, to determine the full list of the available Windows GDI functions supported by the gdi32.dll .

The Windows GDI can be extremely useful for providing 2D graphic rendering and visualization for business applications. Borland's VCL wraps much of the GDI functionality within the TImage and TCanvas classes. Because the VCL provides a solid encapsulation of the GDI, the benefit of using the raw Win32 GDI is not all that substantial for the C++Builder developer.

The biggest debilitating factor with the GDI, whether used directly or through the VCL, is that its performance is marginal at best. Using the GDI to display real-time, high-speed graphic images often provides a lesson in frustration for both developers and users. In regards to frames per second, it's slow, even with the best hardware. Fortunately, the DirectDraw API, which is part of Microsoft's DirectX Game SDK, provides a much-improved library alternative for 2D graphics display. For those requiring high-performance 2D rendering, DirectDraw is the answer. Although DirectX is considered an extension of the Win32 API because it is supported by Windows 9x, 2000, and XP, it is not within the scope of this chapter.

Discussion and examples specific to the Windows GDI are provided in the Graphics and Multimedia section, see Chapter 15. However, there are some other elements of the GDI that we can explore, which can be used to affect the look of a windows form.

Shaping Your Applications

Manipulating forms and making them do cool and interesting things like we did earlier with animation can help applications be less boring. In this section, we will explore the concept of regions and cover a handful of related functions such as CombinRgn() , CreateEllipticRgn() , and GetClientRect() . These functions can control how windows look. Instead of the same old rectangle window look, regions can change the look of a window, which are part of the GDI. C++Builder makes combining the Win32 API functions to create regions on your system very easy. These and other APIs are located in the WINGDI.H header file.

At this point you might be asking, "What's a region?" A region is an area that bounds the window. Anything outside the region is not considered part of the window. The window clips anything else outside the region, giving the window a different look.

Let's now look at some of these special GDI region Win32 API calls.

CreateRoundRectRgn()

This function will create a rectangular window with rounded edges.

The CreateRoundRectRgn() function has the following parameters:

 HRGN CreateRoundRectRgn(      int nLeftRect, // x-coordinate of the region's upper-left corner      int nTopRect, // y-coordinate of the region's upper-left corner      int nRightRect, // x-coordinate of the region's lower-right corner      int nBottomRect, // y-coordinate of the region's lower-right corner      int nWidthEllipse, // height of ellipse for rounded corners      int nHeightEllipse // width of ellipse for rounded corners     ); 
  • nLeftRect specifies the x coordinate of the upper-left corner of the region.

  • nTopRect specifies the y coordinate of the upper-left corner of the region.

  • nRightRect specifies the x coordinate of the lower-right corner of the region.

  • nBottomRect specifies the y coordinate of the lower-right corner of the region.

  • nWidthEllipse specifies the width of the ellipse used to create the rounded corners.

  • nHeightEllipse specifies the height of the ellipse used to create the rounded corners.

The following example illustrates how to create a round-edged window:

 RECT R  = GetClientRect();  HRGN MyRegion = CreateRoundRectRgn(0,0,150,110,15,10);  SetWindowRgn(Handle , MyRegion , true); 

This is a relatively easy thing to do; The only difficult part is determining the coordinates. It's often necessary to play with them a bit to make the windows look the way you want, but that is the only drawback.

CreateEllipticRgn()

If you want an even more different look, there's another function called CreateEllipticRgn() that gives your window an oval-shaped appearance. It will actually make a window round or oval, depending on the parameters to the function. CreateEllipticRgn() has the following parameters:

 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     ); 
  • nLeftRect specifies the x coordinate of the upper-left corner of the bounding rectangle of the ellipse.

  • nTopRect specifies the y coordinate of the upper-left corner of the bounding rectangle of the ellipse.

  • nRightRect specifies the x coordinate of the lower-right corner of the bounding rectangle of the ellipse.

  • nBottomRect specifies the y coordinate of the lower-right corner of the bounding rectangle of the ellipse.

The parameters are somewhat similar to the CreateRoundRectRgn() function, except that you only specify the whole width of the circle. The following example illustrates the use of the CreateEllipticRgn() function:

 HRGN HRegion  HRegion = CreateEllipticRgn(0,0,Form1->Width, Form1->Height);  SetWindowRgn(Handle , hRgn1 , true); 

This example code changes your form to a semiround circle (an oval). We started at Left(0) Top(0) and worked our way to the form's width and height, yielding a result that looks like an oval.

CombineRgn()

CombineRgn() function is a powerful function. CombinRgn() can actually take the regions that you specify and merge them together. A number of the programs these days that have the irregular window shapes usually use the CombineRgn() function. Along with the CreateEllipticRgn() , CreateRoundRect() , and CreatePolygonRgn() functions, you can specify regions to make your windows look even more glamorous.

CombineRgn() has the following parameters:

 int CombineRgn(      HRGN hrgnDest,    // handle to destination region      HRGN hrgn1,    // handle to source region      HRGN hrgn2,    // handle to source region      int fnCombineMode     // region combining mode     ); 
  • hrgnDest identifies a new region with dimensions defined by combining two other regions. (This region must exist before CombineRgn() is called.)

  • hrgn1 identifies the first of two regions to be combined.

  • hHrgn2 identifies the second of two regions to be combined.

  • fnCombineMode specifies a mode indicating how the two regions will be combined. This parameter can be one of the values in Table 14.7.

Table 14.7. CombineRgn() Flags

Flags

Values

RGN_AND

Creates the intersection of the two combined regions.

RGN_COPY

Creates a copy of the region identified by hrgnSrc1 .

RGN_DIFF

Combines the parts of hrgnSrc1 that are not part of hrgnSrc2 .

RGN_OR

Creates the union of two combined regions.

RGN_XOR

Creates the union of two combined regions except for any overlapping areas.

The return value specifies the type of the resulting region. It can be one of the values shown in Table 14.8.

Table 14.8. CombineRgn() Return Values

Return Value

Description

NULLREGION

The region is empty.

SIMPLEREGION

The region is a single rectangle.

COMPLEXREGION

The region is more than a single rectangle.

ERROR

No region is created.

Interestingly enough, the regions do not need to be distinct. For example, if you pass three regions ( Region1 , Region1 , and Region2 ) as the parameters, you can see that Region1 , the original region already passed, will be destined to hold the final region, which is completely okay. However, if you do pass another region separate from the other declared regions, you must pass an already declared region before calling this API.

The following is an example of using CombineRgn() function. Hopefully, the example will clarify any issues you might have and give you a better understanding of how to use the function.

 HRGN Region1, Region2;  Region1 = CreateRectRgn(0, 0, 100, 100);  Region2 = CreateRectRgn(50, 50, 150, 150);  CombineRgn(Region1, Region1, Region2, RGN_XOR);  SetWindowRgn(Handle , hRgn1 , true); 

Using this example, you will see your form turn into two boxes with a box hole in the middle of it. The hole is there because the RGN_XOR flag was used. The two regions overlap, but do not combine with the intersecting regions. If we use the RGN_OR flag, you will see they now intersect and combine.

Also, we used Region1 as the destination and a created region. Why did we do this? Well, remember that we need a destination region, and Region1 and Region2 combined will overwrite Region1 . Because we passed the parameter, the function knows the coordinates and sends them to the Region1 destination.

But let's not stop here. Earlier, we mentioned something about the CreatePolygonRgn() function. Let's go over that because it's another region function that's quite interesting.

CreatePolygonRgn() function has the following parameters:

 HRGN CreatePolygonRgn(      CONST POINT *lppt,    // pointer to array of points      int cPoints,    // number of points in array      int fnPolyFillMode     // polygon-filling mode     ); 
  • lppt points to an array of POINT structures that define the vertices of the polygon. The polygon is presumed closed. Each vertex can be specified only once.

  • CPoints specifies the number of points in the array.

  • fnPolyFillMode specifies the fill mode used to determine which pixels are in the region. This parameter can be one of the values shown in Table 14.9.

Table 14.9. Possible fnPolyFillMode Modes

Parameter

Value

ALTERNATE

Selects alternate mode (fills area between odd-numbered and even-numbered polygon sides on each scan line)

WINDING

Selects winding mode (fills any region with a nonzero winding value)

To pass the proper parameters to the CreatePolygonRgn() function, we can both use the Win32 API and C++Builder's POINT structure. This function relies on point pixel locations to create a region. This is similar to connect the dots, where the function will create the region based on these dots.

The POINT structure is a structure that defines the x and y coordinates of an object. You simply fill it in. To create a multiple-point coordinate, simply declare a POINT structure variable with an array.

We've only covered the basics of regions here to give you a better understanding of how regions work with C++Builder. If you want to learn more about creating windows with regions, visit Microsoft's MSDN Web site at http://www.microsoft.com/msdn. Perform a search for window regions or irregular windows .


   
Top


C++ Builder Developers Guide
C++Builder 5 Developers Guide
ISBN: 0672319721
EAN: 2147483647
Year: 2002
Pages: 253

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