
Introduction
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. |
Operations
There are a few operations that can be performed on a region in order to query, modify
test its data.
CombineRgn
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;
...
HRGN hTemp = ::CreateRectRgn(0,0,0,0);
::CombineRgn(hTemp, hCacheRgn, hUpdateRgn, RGN_DIFF);
::CombineRgn(hCacheRgn, hTemp, NULL, RGN_COPY);
::DeleteObject(hTemp);
::CombineRgn(hCacheRgn, hCacheRgn, hUpdateRgn, RGN_DIFF);
EqualRgn
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,
HRGN hSrcRgn2
);
PtInRegion
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,
int X,
int Y
);
RectInRegion
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,
CONST RECT *lprc
);
GetRgnBox
The GetRgnBox function retrieves the bounding rectangle of the specified region.
int GetRgnBox(
HRGN hrgn,
LPRECT lprc
);
OffsetRgn
The OffsetRgn function moves a region by the specified offsets.
int OffsetRgn(
HRGN hrgn,
int nXOffset,
int nYOffset
);
SetRectRgn
The SetRectRgn function converts a region into a rectangular region
with the specified coordinates.
BOOL SetRectRgn(
HRGN hrgn,
int nLeftRect,
int nTopRect,
int nRightRect,
int nBottomRect
);
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
FillRgn
The FillRgn function fills a region by using the specified brush.
BOOL FillRgn(
HDC hdc,
HRGN hrgn,
HBRUSH hbr
);
FrameRgn
The FrameRgn function draws a border around the specified region by using the specified brush.
BOOL FrameRgn(
HDC hdc,
HRGN hrgn,
HBRUSH hbr,
int nWidth,
int nHeight
);
InvertRgn
The InvertRgn function inverts the colors in the specified region.
BOOL InvertRgn(
HDC hdc,
HRGN hrgn
);
PaintRgn
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,
HRGN hrgn
);
GetRegionData
The GetRegionData function fills the specified buffer with data desc
DWORD GetRegionData(
HRGN hRgn,
DWORD dwCount,
This data includes the dimensions of the rectangles that make up the region.
LPRGNDATA lpRgnData
);
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.
ExtCreateRgn
The ExtCreateRegion function creates a region from the specified region
and transformation data.
HRGN ExtCreateRegion(
CONST XFORM *lpXform,
DWORD nCount,
CONST RGNDATA *lpRgnData
);
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.
Demonstration
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:
- Select the desired draw mode shape from the menu or the tool bar. There are three
choices, Rectangle
, Ellipse
, or Round Rectangle
.
- Select and area on the main window, and start dragging the region. A rubber-banding effect
will show where the region will appear.
- 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.
- At any time, you can hit the Escape key to cancel the drawing operation.
- Let go of the mouse button to update the region with the new shape that you have created.
- 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.
- Simply decide which of the four sub-views that you would like to use.
- Click in the sub-view and drag the mouse to the main window. An icon will appear indicating
that the item is being dragged.
- 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.
- At any time, you can hit the Escape key to cancel the replace operation.
- 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.
Conclusion
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.
| You must Sign In to use this message board. |
|
|
 |
|
 |
I mean i have created a region something like this ≡ . Independent line/block but single region...
How to fill this single region with single / multiple color?
Is it possible to fill using single color?
Is it possible to fill using multiple color in a single region of independent line/blocks?
Thanks in advance
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I am not sure I understand your question.
If you want to fill the region with a single color, you can create a brush with a single color, then use that brush to fill the region:
HBRUSH hbr = ::CreateSolidBrush(RGB(0xFF, 0, 0)); // Red ::FillRgn(hDC, hRgn, hbr);
If you want to fill lines of the region, you could iterate and use FillRect in a similar way.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi there. Your article mentione you could combine text to regions somehow. I would like to remove text from a region - I can easily remove rectangular regions, ellipses etc, but how do you remove text? (ie. create a text "hole") ?
Thanks Paul
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi. I have following problem: My (MFC) program select/deselect some object with following code
BOOL MyObject::Intersects(const CRect& rect) { CRgn rgn, rgn1, rgn2; ... rgn1.CreatePolygonRgn( /*depending on MyObject*/, ALTERNATE); rgn2.CreatePolygonRgn( /*depending on MyObject, other than rgn1*/, ALTERNATE); int i = rgn.CombineRgn( &rgn1, &rgn2, RGN_OR ); //in my situation I always get i=COMPLEXREGION
return rgn.RectInRegion(rect); }
where rect is rectangle given from mouse.
In some special cases (with objects similiar "U" rotated 45dg clockwise) this function does not work correctly. I select rectangle by mouse outside object (but near to free ends of "U"). If this rectangle does not cross y-axis, then result is correct - RectInRegion and also MyObject::Intersects returns FALSE. If this rectangle has rect.left negative and rect.right positive then result is incorrect - RectInRegion (and also MyObject::Intersects) returns TRUE . This result does not depend on position of MyObject.
IMO, there is some mistake in RectInRegion algorithm. Or there are some specialties in CombineRgn or RectInRegion? Or is my program wrong? 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Good Article & got my 5,
I subclassed button (CButton) class. And used DrawItem to redraw the button shape. But I cannot use FillRgn or PaintRgn over there. I can use FillRect or other drawing functions there. My region data is valid, but not drawn/filled. Can u tell me why?
with regards, Nareen Neelamegam
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|
 |
|
 |
Some problems that I have had in the past when trying to paint with regions is related to the coordinate space that the region is trying to paint in.
What are you using to create the region for the button? Are you starting with the rectangle that came in the DRAWITEMSTRUCT, the rcItem rect? When regions dont paint properly for me, I usualy add a couple of lines of code right before where I am trying to paint the region. In the code I get a handle to teh Desktop DC, then use the exact same paint command with the desktop DC. I expect the region to be painted in the upper left hand corner with whatever offset I put into the control that I am trying to paint.
I cant think of anything in MFC or Win32 that would prevent you from using a region in that way. Try what I suggested and see if it helps you figure out your problem. Otherwise if you post the code for your OnDrawItem handler I will see if I can help out.
Good luck
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks alot Friend,
Anyhow, I got the solution at the time itself. The problem is I have created the region in my main dialog and gave it to the button's DrawItem handler. Hence the region created with the dialog's coordinate not matched with the button (since its size is smaller than its parent). In short, problem is with coordinates. FillRgn works actually, but not visible in the button area.
Now I have created the button with the window (dialog) size and set its region with the region I got from the dialog. Now it works well.
Thanks alot again.
with regards Nareen Neelamegam
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Sorry to bother you again. I have a baffling problem at hand. It somewhat pertains to my last thread.
Anywho; it seems CombineRgn, used in conjuntion with the "system region", doesn't work with all the available Modes. Here is a list of the working and non-working Modes:
RGN_AND - Works; no problems encountered. RGN_COPY - Haven't tried it but I will assume it works since it only copys. RGN_DIFF - Works; no problems encountered. RGN_OR - Does not work; the result is a bit strange, however, the result is way off. RGN_XOR - Does not work; the result is "exactly" the same as RGN_DIFF.
It's weird how some modes do work while others don't. Have you ran into this problem before? Is the problem due to maybe, CombineRgn was not meant to work with "system regions", but, only "application defined regions"? I'm at a total lost here.
Any help would be very appreciated. relient
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I have not run into any problems like you have described. My first inclination is to ask are you trying to modify the system region, or is it simply one of the source regions and you have a completely new region that accepts the results?
Maybe you can try copying the system region then or'ing the copied region to get your results.
I will spend a little more time on this this evening if you havent found a solution and I will let you know what I discover.
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I've build a simple little demonstration program, yet sufficient enough, to allow us to see how I arrived to my conclusions on my last thread.
HRGN sysRgn, desRgn, srcRgn; HDC hdc; PAINTSTRUCT ps; static int cnt = 1;
case WM_PAINT : sysRgn = CreateRectRgn(0, 0, 0, 0); GetUpdateRgn(hwnd, sysRgn, FALSE);
hdc = BeginPaint(hwnd, &ps);
srcRgn = CreateRectRgn(70, 70, 170, 170); FrameRgn(hdc, srcRgn, GetStockObject(LTGRAY_BRUSH), 1, 1);
desRgn = CreateRectRgn(0, 0, 0, 0); CombineRgn(desRgn, sysRgn , srcRgn, RGN_XOR);
SelectClipRgn(hdc, desRgn);
if ( cnt++ > 3 ) { FillRgn(hdc, desRgn, GetStockObject(GRAY_BRUSH)); FrameRgn(hdc, desRgn, GetStockObject(BLACK_BRUSH), 1, 1); } DeleteObject(sysRgn); DeleteObject(srcRgn); EndPaint(hwnd, &ps); return 0;
Here's what the demonstration program does:
1.When the window is first shown, you'll see a rectangle-frame of light gray color; with an all white background.
2.You're now supposed to position a window, of any size, halfway on top of the framed-rectangle and minimize-maximize this overlapped window 3 times to see the result. This 3 times; minimize-maximize is to assure we get 3 WM_PAINT's to allow, FillRgn and FrameRgn in the for() loop, to paint.
The region created with CombineRgn (destination region) will be painted in pure GRAY - not light gray, with a black frame around it.
Try this with all the RGN_XXX Modes and observe the results.
side note: I also tried obtaining the system region with GetRandomRgn, instead of GetUpdateRgn, and offset'ed the obtained region with OffsetRgn() and MapWindowPoints() to assure I get the right region coordinates for my system. The result was the same as using GetUpdateRgn. So I know that GetUpdateRgn is not the problem.
Thanks for reading, relient
-- modified at 13:47 Monday 12th September, 2005
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hey there. It's been a while since I last heard from you. I Hope everything's ok. I'm still in the same situation, if you've figured out what's the problem, please let me know.
Thanks, relient.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, I'm happy to report that I figured out the problem.
I would also like to point out that, although the update-region returned by BeginPaint is not the sytem region, it is Identical to that of the system region (in BeginPaint-EndPaint only) but technically; they're not the same thing. What is returned from BeginPaint is the system region that "is the intersection of the update region" plus other window factors . This was affirmed in Feng Yuangs book too.
Anyway. Without further ado; Here's the solution to my problem if you care to read:
http://www.it-faq.pl/mskb/118/472.HTM
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Possible? The only function I know of that can exclude part of a region is ExcludeClipRect. The problem with it is that if you want to exclude a region of an arbitrary size, you can't, because you're limited to rectangles only.
Is there any function similar to ExcludeClipRect but for excluding regions of arbitrary (not rectagular) size? If not, what other function/s could I use to accomplish this task, if any?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You can use SelectClipRgn to Set an arbitrary region.
If you want to add a region to the current clip region in the same way excludeClipRect does, simply call GetClipRgn to get the current region, then use CombineRegion to combine the current region with your new region, then finally call SelectClipRgn to replace the current region with the combination of your new region.
Coincidentally I wrote another article that describes tons of detail relating to clipping regions in the Win GDI. I describe all of the clipping region functions available to use, and info about all of the clipping planes that exist for a DC.
http://www.codeproject.com/gdi/cliprgnguide.asp[^]
Good luck
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
That did the job perfectly. Well, except that I used GetUpdateRgn instead since I needed the system region and not an application defined region to work with.
Again, Thanks and props.
relient
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
|
 |
|
 |
I'm familar with Regions, but for the novice windows progreammer this is a good article. How about following it up with an article on Paths?
Regards
Normski. - Professional Windows Programmer
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I was planning on that, that is why I did not add a description for the PathToRegion function. I felt that some background and explaination needed to be given for paths first.
The idea that I have for paths shows some impressive things that can be done.
|
| Sign In·View Thread·PermaLink | 1.50/5 |
|
|
|
 |
|
 |
Well-written, nicely formatted, slick diagrams... ...And a thorough explanation of something that (for me) has been very confusing. Nice job man!
And if words were wisdom, I'd be talking even more. The Offspring, I Choose
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
kilowatt wrote: Did you run the demo program? Was it insightful?
Yes! It gave me insight into how you made those cool little diagrams!
Seriously, it's a good demonstration, and complements the article very well. How long did it take you to put all this together?
And if words were wisdom, I'd be talking even more. The Offspring, I Choose
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I do not believe that I mentioned that the demonstration program requires WTL to build it. Sorry for any inconvenience.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|