【转载】FAQ: Window Regions
链接地址:
http://comrade.ownz.com/docs/regions.html
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
For exact information on the functions, see the official documentation.
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 SetWindowRgn
The 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 else
To 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:
- Guide to WIN32 Regions - this is a good tutorial, with C++ snippets. Describes how to create, combine, compare, save, and restore regions. Contains many helpful diagrams. Highly recommended.
- A Guide to WIN32 Clipping Regions - Guide to understand the three different types of clipping regions, and how they relate to the Device Context. I don't know what the hell this is about, but it seems to be using regions not for shaping windows, but rather controlling how painting is done.
- EdgeTracer - this is a document on the EdgeTracer tool's site on how to create irregularly shaped windows. More of a collection of reference than a tutorial, but it does include good examples for Borland C++, Delphi and VB.
- Produce Translucent Effects - an article by an MS MVP, Karl E. Peterson. This is more about translucent windows rather than irregularly shaped windows, but still a good read. He also posted an example VB program called WinRgn (mirrored here), and a VB class for translucent effects (mirrored here).
- Custom-Shaped and Transparent Windows - my tutorial from 2001. Some what poor writing by my today's standards :), but nevertheless it goes into quite a bit of detail and has good flow for reading.
- Transparent Button with Region and Anti-Aliased Edges - this dude made an example of some translucent and irregularly shaped buttons. Looks nice.
- Creating Bitmap Regions for Forms and Buttons - a tutorial on regions for C# .NET.
- Simple way to create non-rectangular shaped dialogs - a quick tutorial on regions using C++ and MFC.
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.