Click here to Skip to main content
Click here to Skip to main content

Guide to WIN32 Regions

, 10 Mar 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
Guide to understanding how to create and use regions with the WIN32 SDK
<!-- Download Links --> <!-- Article image -->

Sample Image - preview.gif


Regions are a resource in windows that are very useful. They are device independent, which means that a device context (DC) is not need to create or use one. However, there are many functions in the WIN32 GDI that require a region.

Some of the useful places for a region are:

  • Update Region, Paint
  • Clipping, Paint
  • Hit Testing
  • Define window shape, Irregular Shaped Windows

Many of the functions that relate to regions are very simple, and need very little explanation, in fact the definition from MSDN is adequate enough to explain these functions. However, some of the functions are a little more difficult to understand and master, therefore extra details have been added to explain these functions. A few diagrams may accompany the explanation as well.

Region Creation

There are a number of ways to create a region. There are a number of functions that can be used create a region, from a simple shape such as a rectangle or an ellipse, to a complicated shape such as the outline of a string of text. Listed below is a table that describes each of the creation functions.

Function Description
CreateEllipticRgn Creates an elliptical region. As with drawing ellipses, elliptic regions are very large, and may slow your program down if you use a large number of them.
CreateEllipticRgnIndirect Creates an elliptical region from a RECT structure. As with drawing ellipses, elliptic regions are very large, and may slow your program down if you use a large number of them.
CreatePolygonRgn Creates a polygonal region.
CreatePolyPolygonRgn Creates a region consisting of a series of polygons.
CreateRectRgn Creates a rectangular region.
CreateRectRgnIndirect Creates a rectangular region from a RECT structure.
CreateRoundRectRgn Creates a rectangular region with rounded corners.
ExtCreateRegion Creates a region from the specified region and transformation data.
PathToRegion Creates a region from a WIN32 Path created in a DC.


There are a few operations that can be performed on a region in order to query, modify test its data.


After a few basic regions are created, it is possible to perform boolean operations on the regions in order to create more complex regions with CombineRgn. This function has five operations that can be performed in order to combine two different regions. Shown below is an example of each of the boolean operations that can be performed in CombineRgn:

Value Description Result
RGN_AND Creates the intersection of the two combined regions.
CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_AND);
RGN_COPY Creates a copy of the region identified by hrgnSrc1.
CombineRgn(hrgnDest, hrgnSrc1, NULL, RGN_COPY);
No Image
RGN_DIFF Combines the parts of hrgnSrc1 that are not part of hrgnSrc2.
CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_DIFF);
RGN_OR Creates the union of two combined regions.
CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_OR);
RGN_XOR Creates the union of two combined regions except for any overlapping areas.
CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_XOR);

One more thing to point out is that the destination region in CombineRgn can be one of the source regions. Therefore, if you continually modify a region by adding or subtracting a different region from it, you can perform one combine operation rather than worrying about copying the adjusted region. Here is an example:

HRGN hCacheRgn;
HRGN hUpdateRgn;


//C: Convoluted way.
//C: Initialize a temporary region.
HRGN hTemp = ::CreateRectRgn(0,0,0,0);
//C: Subtract teh update region from the Cache region. 
::CombineRgn(hTemp, hCacheRgn, hUpdateRgn, RGN_DIFF);
//C: Copy the Temp region back into the Cache region.
::CombineRgn(hCacheRgn, hTemp, NULL, RGN_COPY);
//C: Destroy the Temp region.

//C: Simple way
::CombineRgn(hCacheRgn, hCacheRgn, hUpdateRgn, RGN_DIFF);


The EqualRgn function checks the two specified regions to determine whether they are identical. The function considers two regions identical if they are equal in size and shape.

BOOL EqualRgn(
  HRGN hSrcRgn1,  // handle to first region
  HRGN hSrcRgn2   // handle to second region


The PtInRegion function determines whether the specified point is inside the specified region. This function is very useful for creating a hit-test region on your control. Such as a bitmap that has a hot-region that can be clicked by the user.

BOOL PtInRegion(
  HRGN hrgn,  // handle to region
  int X,      // x-coordinate of point
  int Y       // y-coordinate of point


The RectInRegion function is very similar to PtInRegion, except that it will determines whether any part of the specified rectangle is within the boundaries of a region.

BOOL RectInRegion(
  HRGN hrgn,         // handle to region
  CONST RECT *lprc   // pointer to rectangle


The GetRgnBox function retrieves the bounding rectangle of the specified region.

int GetRgnBox(
  HRGN hrgn,   // handle to a region
  LPRECT lprc  // bounding rectangle


The OffsetRgn function moves a region by the specified offsets.

int OffsetRgn(
  HRGN hrgn,     // handle to region
  int nXOffset,  // offset along x-axis
  int nYOffset   // offset along y-axis


The SetRectRgn function converts a region into a rectangular region with the specified coordinates.

BOOL SetRectRgn(
  HRGN hrgn,       // handle to region
  int nLeftRect,   // x-coordinate of upper-left corner of rectangle
  int nTopRect,    // y-coordinate of upper-left corner of rectangle
  int nRightRect,  // x-coordinate of lower-right corner of rectangle
  int nBottomRect  // y-coordinate of lower-right corner of rectangle

Paint Functions

WIN32 provides a number of functions that will allow a region handle to be used for painting affects. These effects include filling with a brush, outlining, and inverting the current contents


The FillRgn function fills a region by using the specified brush.

BOOL FillRgn(
  HDC hdc,    // handle to device context
  HRGN hrgn,  // handle to region to be filled
  HBRUSH hbr  // handle to brush used to fill the region


The FrameRgn function draws a border around the specified region by using the specified brush.

BOOL FrameRgn(
  HDC hdc,     // handle to device context
  HRGN hrgn,   // handle to region to be framed
  HBRUSH hbr,  // handle to brush used to draw border
  int nWidth,  // width of region frame
  int nHeight  // height of region frame


The InvertRgn function inverts the colors in the specified region.

BOOL InvertRgn(
  HDC hdc,    // handle to device context
  HRGN hrgn   // handle to region to be inverted


The PaintRgn function is similar to the FillRgn function, except that this function paints the specified region by using the brush currently selected into the device context.

BOOL PaintRgn(
  HDC hdc,    // handle to device context
  HRGN hrgn   // handle to region to be painted


The GetRegionData function fills the specified buffer with data desc

DWORD GetRegionData(
  HRGN hRgn,            // handle to region
  DWORD dwCount,        // size of region data bufferribing a region. 
This data includes the dimensions of the rectangles that make up the region.
  LPRGNDATA lpRgnData   // region data buffer

Region Data

A WIN32 region is really a set of rectangles managed in one object. The RGN_DATA structure manages this set of rectangles as well as some of the other data that is required to maintain the region. The RGN_DATA structure is accessible through the GetRegionData function. A region object can be created with a RGN_DATA structure with the ExtCreateRgn function. Here is a diagram to show the internal representation of a HRGN object. Each rectangle in the region is painted with an alternating colored brush.

Internal Representation of a region.


The ExtCreateRegion function creates a region from the specified region and transformation data.

HRGN ExtCreateRegion(
  CONST XFORM *lpXform,     // transformation data
  DWORD nCount,             // size of region data
  CONST RGNDATA *lpRgnData  // region data buffer

Something to be aware of, is that Windows 2000 will accept a region that has overlapping rectangles. If you try to create a region with data that contains overlapping rectangles on Windows NT4, this function will fail. Therefore if you create one of these regions on a Windows 2000 machine, and store the RGN_DATA of a region in a file or send the data across the network to a Windows NT4 machine, when you try to call ExtCreateRgn on the structure, it will fail.

The Windows 9x kernel dpes not support world transforms that involve either shearing or rotations. ExtCreateRegion fails if the transformation (XFORM) matrix has a scaling or translation of the region.


The program that has been created to demonstrate some of the possibilities for regions is an interactive window that allows the user to create two regions. The user can add new portions to either one of the source regions with a rectangle, ellipse or round rectangle tool. The polygon has been left out simply because of extra work related to the UI that would be required to incorporate this tool, however, a polygon is completely possible.

Here are the directions for creating a source region:

  1. Select the desired draw mode shape from the menu or the tool bar. There are three choices, Rectangle , Ellipse , or Round Rectangle .
  2. Select and area on the main window, and start dragging the region. A rubber-banding effect will show where the region will appear.
  3. Use the Left mouse button to draw a shape for the Source 1 region.
    Use the Right mouse button to draw a shape for the Source 2 region.
  4. At any time, you can hit the Escape key to cancel the drawing operation.
  5. Let go of the mouse button to update the region with the new shape that you have created.
  6. The Source 1 region will be drawn in RED, the Source 2 region will be drawn in Blue.

On the right-hand side of the window where the regions are drawn, there are four sub-views, where the different combine modes: RGN_AND, RGN_DIFF, RGN_OR, RGN_XOR are all demonstrated. As each source region is modified, these sub-views are updated. It is possible to replace one of the current source regions with one of the sub-view results simply by dragging the region to the window where the source regions are displayed. The Source 1 and Source 2 regions are displayed in Red and Blue respectively, just as in the main view, and the new combine region will be displayed in purple.

Here are the directions for moving the combine region to the source region.

  1. Simply decide which of the four sub-views that you would like to use.
  2. Click in the sub-view and drag the mouse to the main window. An icon will appear indicating that the item is being dragged.
  3. Use the Left mouse button to replace the combine region for the Source 1 region.
    Use the Right mouse button to replace the combine region for the Source 2 region.
  4. At any time, you can hit the Escape key to cancel the replace operation.
  5. Let go of the mouse button to replace the region with the combine region that you dragged..

You can delete the Source1, Source2 or both of the regions by selecting the appropriate menu item.

You can choose to view either the Source1 region, the Source2 region, or all of the regions by selecting the appropriate view from the menu. View All is the default selection.

One last operation in the RgnGuide program is to view the rectangles that compose the region in breakdown mode. You can do this by simply checking either the BreakDown Src 1 or BreakDown Src 2 menu item. The view will then show the selected region broken down into each of the rectangles that creates that region. Each rectangle will be painted with an alternating color. A plain reactangle will be pretty boring with one solid colored rectangle. An ellipse on the otherhand will contain a new rectangle on just about every other scanline.


Regions are a very powerful OS resource that you can use in your program. The demo program simply illustrates how to manage your resources, there are many other uses than the ones that have been described. WIN32 provides a rich set of functions that allows you to manage and manipulate your regions.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Paul M Watt
Architect L3 Communications
United States United States
I have been developing software for almost two decades. The majority of my expertise as well as my strongest language is C++ with the networking software as my domain of focus. I have had the opportunity to develop:
* Desktop applications (Data Layer, Business Layer, Presentation Layer)
* Application virtualization
* Web clients
* Mobile device management software
* Network Device drivers
* Embedded system software for
- IP routers
- ATM switches
- Microwave frequency radio/modems
* Distributed processing w/ parallel algorithms.
Over the years I have learned to value maintainable design solutions first. This has allowed me to adapt my projects to meet the challenges that inevitably appear during development, including:
* My own misjudgments
* Incomplete requirements
* Feature creep
* Poor decisions for which I have no control
I am a Mentor and frequent contributor to with tutorial articles that teach others about the inner workings of the Windows APIs.
I am the creator of an open source project on GitHub called Network Alchemy[^], which is a set of Network APIs that are focused on helping developers write robust network communication software.
I maintain my own repository and blog at[^], because code maintenance does not have to be a living hell.
Then for fun I will tinker with my ray-tracer when ever I upgrade my hardware to see what it is capable of doing.
Follow on   Twitter   LinkedIn

Comments and Discussions

QuestionRegion from FrameRgn Pinmembermcrawley3-Apr-12 8:05 
AnswerRe: Region from FrameRgn PinmemberPaul Watt6-Apr-12 20:46 
First, do you know the region that you are trying to manipulate from the Parent? This seems like the most difficult part to me, once you have the region, it is a matter of mapping between the different coordinate systems.
If you have not already discovered these functions, I suggest you check them out:
int MapWindowPoints(
  HWND hWndFrom,     // handle to source window
  HWND hWndTo,       // handle to destination window
  LPPOINT lpPoints,  // array of points to map
  UINT cPoints       // number of points in array
BOOL ClientToScreen(
  HWND hWnd,       // handle to window
  LPPOINT lpPoint  // screen coordinates
BOOL ScreenToClient(
  HWND hWnd,        // handle to window
  LPPOINT lpPoint   // screen coordinates
When I have attempted to perform similar operations to what you are describing, the coordinate system has been the most common reason for any issues I run into. The origin of the device context you are dealing with comes into play.
If your parent window is a top-level window, then it is basically a child of the desktop. So its coordinates will be relative to the upper-left corner of your screen. A child-window of that same parent window will have its coordinates relative to the client area of the parent. If the child window is the size of the entire client area, it will start at (0,0).
This 3rd window you mention, will either need to be a child window higher in the z-order than the child window I mentioned above, or possibly a popup window with the parent window as the owner. If it is a popup window, its origin will also start at the corner of your screen.
If you want to find the absolute screen coordinates of a child window, use the clientToScreen function. The value you receive will be very close to the parent windows offset, except it will include an offset for the height of the titlebar and the width of one border edge.
Finally, what sort of issue do I see when I realize I have a coordinate system issue? If I move my parent window to the upper left corner of my screen, and it appears to work, but then as I move the window further away all of my drawing code for the children seem to move in the same direction as the parent only twice as fast, your child window is painting with screen coordinates.
There are other possible issues and solutions, that is the most common one I run into. If this doesnt help, maybe you can provide some more detail of what you are seeing and I will try to give a few more suggestions.
Good Luck
All of my software is powered by a single Watt.

QuestionRegions Pinmembercrazymike193820-Dec-11 14:18 
AnswerRe: Regions PinmemberPaul Watt21-Dec-11 15:39 
GeneralMy vote of 5 Pinmembercrazymike193823-Oct-11 11:13 
GeneralRe: My vote of 5 PinmemberPaul Watt23-Oct-11 14:54 
GeneralMy vote of 5 Pinmemberrkjpsn7-Dec-10 12:52 
GeneralGood job! PinmemberJoeJiao12-Jul-10 7:36 
Questionhow to fill a region of independent block. Pinmemberfaju21-Apr-09 4:55 
AnswerRe: how to fill a region of independent block. PinmemberPaul Watt21-Apr-09 6:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150327.1 | Last Updated 11 Mar 2002
Article Copyright 2002 by Paul M Watt
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid