Functions that return GDI regions rarely actually return regions


For reasons I don't quite understand, the only functions in GDI and USER which create GDI regions are the functions with Create in their name, like Create­Rect­Rgn or Create­Polygon­Rgn. All the other functions which return a region require you to pass an existing region to use as the output.

I can see this being useful for Combine­Rgn, because you can set your output region to be equal to one of the input regions in order to update a region in place.

// hrgnTotal |= hrgnSegment
CombineRgn(hrgnTotal, hrgnTotal, hrgnSegment, RGN_OR);

// hrgnTotal &= hrgnClip
CombineRgn(hrgnTotal, hrgnTotal, hrgnClip, RGN_AND);

But for all of the Get functions, having to create an output region is usually just an annoyance.

// Create a dummy region - contents not important
HRGN hrgnClip = CreateRectRgn(0, 0, 0, 0);

// Ask for the clipping region to be copied to the dummy region
int status = GetClipRgn(hdc, hrgnClip);

I guess it lets you reuse a single dummy region over and over again, but in practice, you're just going to destroy the region when you're done to free up the GDI region memory.

Whatever the historical reason for this, we're stuck with it. It may be an ugly pattern, but at least it's a pattern.

The things I do for you: I asked a colleague who worked on Windows 3.0 if he knew the reason for this design pattern. He didn't know but suggested that I ask another person who retired from Microsoft many, many years ago. Fortunately, I happened to have his email address even though we aren't really that close. And the second person also didn't know. "This behavior was already in place when I joined the Windows 1.03 project. Maybe you can ask Rao." Unfortunately, I don't have Rao's email address, so the trail ran cold. But I burned a favor for you guys.

Comments (11)
  1. VIMH says:

    "But I burned a favor for you guys."

    And we are grateful for that, Raymond.

  2. Another Ben says:

    RaoR@CronusVentures.com

    The people need to know.

    [Good. You too can be somebody. -Raymond]
  3. Mark says:

    Could it be that the GetXxxRgn functions aren't allowed to run out of memory?

  4. Mark says:

    Alternatively, looking at the Word 1.1a code (which is now public), all calls to CreateRectRgn are done in init functions and appear to be long-lived, so perhaps the assumption of freeing it up isn't true?

  5. Daniel says:

    More like that the GetXxxRgn function aren't allowed to run out of handles.

    The size of region data depends a lot on the geometry of the region. So worst case is that you rotate a rectangle geometry: Original could be stored in a single RECT structure. The output however is a list of rectangles (internally probably handled as bitmap mask).

    (And no. Region Data is NOT vector data, no matter that this is what you would expect it to be on first sight)

  6. Pierre Lebeaupin says:

    Far be it from me to have the intent to start a flamewar, but the trail might even go up to Bill Atkinson, since QuickDraw region functions share that pattern.

  7. Willie says:

    This is the type of content that drew me to this blog.  It's so interesting to see the history behind these well known products.

  8. Just a guess says:

    This behavior is arisen in the dark era of insufficient RAM combined with "primitive" memory management. Intensive creating and destroying objects has probably fragmented the heap way too fast. The memory (de)allocation has never been really cheap operation, so performance difference might also become a part of the motivation.

  9. zonk says:

    Isn't it just naming convention, that Create**** calls always need corresponding Release**** call, and Get**** just shows you something not yours?

  10. Neil says:

    This reminds me of an undocumented function (which presumably no longer exists anyway) that I used in a screen-capturing program that I wrote; the function returned the internal region object corresponding to the visible part of a window, which was handy when I wanted to work out what I could capture. (Obviously it would have been a very bad idea to pass this region to one of the Get functions.)

  11. Joshua says:

    @Neil: My experiments on Win9x indicated that visibility of a window was handled directly as a set of rectangles and multiple WM_PAINT methods were generated: one for each visible rectangle.

    For the program that allowed me to notice I'm really glad I implemented the code for only repainting the visible region rather than the whole window (.5 seconds to repaint whole window is slooow).

Comments are closed.

Skip to main content