FAQ: Window Regions
I have tried to collect a lot of information on window regions and resources on them. If you think I should add something more, e-mail me.
What are window regions?
Window regions allow you to create non-square Windows. The "regions" themselves are represented as objects (HRGN), and can be assigned to a particular window (HWND) using the SetWindowRgn API.
The official documentation for regions can be found on MSDN site here: http://msdn.microsoft.com/library/en-us/gdi/regions_7ab7.asp.
How do I create a region?
You can use the following API to create a window region:
- CreateEllipticRgn
- CreateEllipticRgnIndirect
- CreatePolygonRgn
- CreatePolyPolgyonRgn
- CreateRectRgn
- CreateRectRgnIndirect
- CreateRoundRectRgn
- ExtCreateRegion
How do I create more complex regions?
To create complex regions, you can combine two regions using the CombineRgn function. The function allows you to take 2 regions, and combine them in various ways to produce a 3rd region (the destination region). For the list of possible combinations, see the official documentation.
How do I create regions out of images?
Creating a region out of an image means to create a window whose shape exactly matches the outline of a particular image. The image contains a region that is defined as transparency - meaning the window that shows that image should be transparent in those parts. To create such region manually, you can program a simple loop to subtract the transparent pixels from an initially rectangular region:
HRGN hRegion = CreateRectRgn(0, 0, width_of_image, height_of_image); for (int y = 0; y < height_of_image; y++) { for (int x = 0; x < width_of_image; x++) { if (image is transparent at (x, y)) { // create a dummy region for destination (it will be overwritten later anyway) HRGN hRegionDest = CreateRectRgn(0, 0, 1, 1); // create the region that represents the transparent pixel we want to subtract HRGN hRegionPixel = CreateRectRgn(x, y, x+1, y+1); // subtract the pixel from our current region, and save the new region into hRegionDest // essentially: hRegionDest = hRegion - hRegionPixel CombineRgn(hRegionDest, hRegion, hRegionPixel, RGN_XOR); // delete the old region, and substitute with the new destination region DeleteObject(hRegion); hRegion = hRegionDest; } } } // at this point, we have the region in hRegion, and we can assign it to a window using SetWindowRgnThe above algorithm is very slow, particularly for very large images. However, you can run it once, save the region data, and then restore it later. Check the Anything extra? category for optimizations to the algorithm.
How do I save/restore regions?
To save a region, retrieve its internal composition using the GetRegionData API. Save the binary data into a file, or some other location you like:
// we are given a region hRegion to save DWORD dwRegionSize = GetRegionData(hRegion, 0, NULL); LPRGNDATA lpRgnData = (LPRGNDATA) malloc(dwRegionSize); GetRegionData(hRegion, dwRegionSize, lpRgnData); // save lpRgnData into a file or somewhere elseTo restore a region from a saved location, use the ExtCreateRegion API (set lpXform to NULL, nCount to the size of the saved buffer in bytes, and lpRgnData to the pointer to the saved buffer):
// we are given a pointer to the region buffer lpRgnData, and its size in dwRegionSize HRGN hRegion = ExtCreateRegion(NULL, dwRegionSize, lpRgnData);So as you can see, GetRegionData and ExtCreateRegion are complements of each other - the former is used to convert a region into a binary data, and the latter to do the reverse.
How do I create transparent/translucent windows?
You want the SetLayeredWindowAttributes API.
In-depth tutorials?
Yes, there is plenty of stuff online. I noted some interesting ones, and here they are in no particular order:
Are there any tools/libraries to pre-create regions from images?
Yes, there are plenty. I have collected some links from the web over the years:
QvasiModo's MakeRegion
This is an excellent tool which I only find out about recently. The operation is pretty much self-explanatory: start MakeRegion.exe, go to Image -> Load, and pick an image. After that, choose what colour will be defined as the transparent colour. You can do so either by pointing to it in an image using the Image -> Pick transparent color tool, or by entering its explicit RGB value by going to Image -> Enter trans. color RGB. The program will then build the region data. You can save it by going to File -> Save As. It will offer you to save it as a .rgn file. In your own program, you can load this .rgn file straight in as binary data, and pass it through ExtCreateRegion API to get an hRegion out of it.
The tool even allows you to set tolerance levels, meaning it will except transparency colours that are not exactly what you picked, but are within a certain range. As well, the tool allows you to check the actual region composition as an array of rectangles.
It was first mentioned on the asmcommunity forums here.
The attachment is mirrored here.
The author is QvasiModo.
OnlyTools EdgeTracer
This is a commercial tool I found on Google. You can read more about it here. The screenshot looks nice - but the program costs $29.
The RGN Generator
A simple tool that lets you pick an image, enter the transparency colour and generate region data out of it. You can read it about it here, or download the mirrored version here.
comrade's Region Cutter
This is a small tool which I wrote many years ago to complement my tutorial on window regions. It is very simply: you pick a bitmap file, the destination region file, the transparency colour, and hit the Generate button.
You can download it here.
CContourBitmap Class
This is a C++ class for creating regions from bitmaps. It works by subtracting transparent pixels from a rectangular region. I have never tried it, but the author's name is Wolfgang, and you know that Mozart was one smart bloke.
CRegionCreater
This is a simple C++ class that implements a single function from converting a bitmap handle to a region.
CreateRegionFromFile
This is a function for converting a bitmap handle to a region, given some transparency colour.
Anything extra?
- f0dder's customshape sources - a hacker named f0dder took the time to optimize the region creation routine. The results are impressive: 20ms versus 871ms for the old algorithm (as described above).
- Useful functions for Regions - the dude made a CreateTileRegion and CreateStretchRegions functions, for tiling and stretching regions, respectively.
- Custom light-weight Regions - the guy didn't like the regular window region API, so he made C++ wrappers around it.
- Shapes and Regions (.NET) - some example for creating and testing regions in C# (.NET).
- Irregular shaped buttons - an example on how to combine regions and owner-drawning of buttons to create some crazy buttons. Pretty cool.
Comments
[an error occurred while processing this directive]